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}