tokio_executor/executor.rs
1use futures::Future;
2use SpawnError;
3
4/// A value that executes futures.
5///
6/// The [`spawn`] function is used to submit a future to an executor. Once
7/// submitted, the executor takes ownership of the future and becomes
8/// responsible for driving the future to completion.
9///
10/// The strategy employed by the executor to handle the future is less defined
11/// and is left up to the `Executor` implementation. The `Executor` instance is
12/// expected to call [`poll`] on the future once it has been notified, however
13/// the "when" and "how" can vary greatly.
14///
15/// For example, the executor might be a thread pool, in which case a set of
16/// threads have already been spawned up and the future is inserted into a
17/// queue. A thread will acquire the future and poll it.
18///
19/// The `Executor` trait is only for futures that **are** `Send`. These are most
20/// common. There currently is no trait that describes executors that operate
21/// entirely on the current thread (i.e., are able to spawn futures that are not
22/// `Send`). Note that single threaded executors can still implement `Executor`,
23/// but only futures that are `Send` can be spawned via the trait.
24///
25/// This trait is primarily intended to implemented by executors and used to
26/// back `tokio::spawn`. Libraries and applications **may** use this trait to
27/// bound generics, but doing so will limit usage to futures that implement
28/// `Send`. Instead, libraries and applications are recommended to use
29/// [`TypedExecutor`] as a bound.
30///
31/// # Errors
32///
33/// The [`spawn`] function returns `Result` with an error type of `SpawnError`.
34/// This error type represents the reason that the executor was unable to spawn
35/// the future. The two current represented scenarios are:
36///
37/// * An executor being at capacity or full. As such, the executor is not able
38/// to accept a new future. This error state is expected to be transient.
39/// * An executor has been shutdown and can no longer accept new futures. This
40/// error state is expected to be permanent.
41///
42/// If a caller encounters an at capacity error, the caller should try to shed
43/// load. This can be as simple as dropping the future that was spawned.
44///
45/// If the caller encounters a shutdown error, the caller should attempt to
46/// gracefully shutdown.
47///
48/// # Examples
49///
50/// ```rust
51/// # extern crate futures;
52/// # extern crate tokio_executor;
53/// # use tokio_executor::Executor;
54/// # fn docs(my_executor: &mut Executor) {
55/// use futures::future::lazy;
56/// my_executor.spawn(Box::new(lazy(|| {
57/// println!("running on the executor");
58/// Ok(())
59/// }))).unwrap();
60/// # }
61/// # fn main() {}
62/// ```
63///
64/// [`spawn`]: #tymethod.spawn
65/// [`poll`]: https://docs.rs/futures/0.1/futures/future/trait.Future.html#tymethod.poll
66/// [`TypedExecutor`]: ../trait.TypedExecutor.html
67pub trait Executor {
68 /// Spawns a future object to run on this executor.
69 ///
70 /// `future` is passed to the executor, which will begin running it. The
71 /// future may run on the current thread or another thread at the discretion
72 /// of the `Executor` implementation.
73 ///
74 /// # Panics
75 ///
76 /// Implementations are encouraged to avoid panics. However, panics are
77 /// permitted and the caller should check the implementation specific
78 /// documentation for more details on possible panics.
79 ///
80 /// # Examples
81 ///
82 /// ```rust
83 /// # extern crate futures;
84 /// # extern crate tokio_executor;
85 /// # use tokio_executor::Executor;
86 /// # fn docs(my_executor: &mut Executor) {
87 /// use futures::future::lazy;
88 /// my_executor.spawn(Box::new(lazy(|| {
89 /// println!("running on the executor");
90 /// Ok(())
91 /// }))).unwrap();
92 /// # }
93 /// # fn main() {}
94 /// ```
95 fn spawn(
96 &mut self,
97 future: Box<dyn Future<Item = (), Error = ()> + Send>,
98 ) -> Result<(), SpawnError>;
99
100 /// Provides a best effort **hint** to whether or not `spawn` will succeed.
101 ///
102 /// This function may return both false positives **and** false negatives.
103 /// If `status` returns `Ok`, then a call to `spawn` will *probably*
104 /// succeed, but may fail. If `status` returns `Err`, a call to `spawn` will
105 /// *probably* fail, but may succeed.
106 ///
107 /// This allows a caller to avoid creating the task if the call to `spawn`
108 /// has a high likelihood of failing.
109 ///
110 /// # Panics
111 ///
112 /// This function must not panic. Implementers must ensure that panics do
113 /// not happen.
114 ///
115 /// # Examples
116 ///
117 /// ```rust
118 /// # extern crate futures;
119 /// # extern crate tokio_executor;
120 /// # use tokio_executor::Executor;
121 /// # fn docs(my_executor: &mut Executor) {
122 /// use futures::future::lazy;
123 ///
124 /// if my_executor.status().is_ok() {
125 /// my_executor.spawn(Box::new(lazy(|| {
126 /// println!("running on the executor");
127 /// Ok(())
128 /// }))).unwrap();
129 /// } else {
130 /// println!("the executor is not in a good state");
131 /// }
132 /// # }
133 /// # fn main() {}
134 /// ```
135 fn status(&self) -> Result<(), SpawnError> {
136 Ok(())
137 }
138}
139
140impl<E: Executor + ?Sized> Executor for Box<E> {
141 fn spawn(
142 &mut self,
143 future: Box<dyn Future<Item = (), Error = ()> + Send>,
144 ) -> Result<(), SpawnError> {
145 (**self).spawn(future)
146 }
147
148 fn status(&self) -> Result<(), SpawnError> {
149 (**self).status()
150 }
151}