tokio_executor/
typed.rs

1use SpawnError;
2
3/// A value that spawns futures of a specific type.
4///
5/// The trait is generic over `T`: the type of future that can be spawened. This
6/// is useful for implementing an executor that is only able to spawn a specific
7/// type of future.
8///
9/// The [`spawn`] function is used to submit the future to the executor. Once
10/// submitted, the executor takes ownership of the future and becomes
11/// responsible for driving the future to completion.
12///
13/// This trait is useful as a bound for applications and libraries in order to
14/// be generic over futures that are `Send` vs. `!Send`.
15///
16/// # Examples
17///
18/// Consider a function that provides an API for draining a `Stream` in the
19/// background. To do this, a task must be spawned to perform the draining. As
20/// such, the function takes a stream and an executor on which the background
21/// task is spawned.
22///
23/// ```rust
24/// #[macro_use]
25/// extern crate futures;
26/// extern crate tokio;
27///
28/// use futures::{Future, Stream, Poll};
29/// use tokio::executor::TypedExecutor;
30/// use tokio::sync::oneshot;
31///
32/// pub fn drain<T, E>(stream: T, executor: &mut E)
33///     -> impl Future<Item = (), Error = ()>
34/// where
35///     T: Stream,
36///     E: TypedExecutor<Drain<T>>
37/// {
38///     let (tx, rx) = oneshot::channel();
39///
40///     executor.spawn(Drain {
41///         stream,
42///         tx: Some(tx),
43///     }).unwrap();
44///
45///     rx.map_err(|_| ())
46/// }
47///
48/// // The background task
49/// pub struct Drain<T: Stream> {
50///     stream: T,
51///     tx: Option<oneshot::Sender<()>>,
52/// }
53///
54/// impl<T: Stream> Future for Drain<T> {
55///     type Item = ();
56///     type Error = ();
57///
58///     fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
59///         loop {
60///             let item = try_ready!(
61///                 self.stream.poll()
62///                     .map_err(|_| ())
63///             );
64///
65///             if item.is_none() { break; }
66///         }
67///
68///         self.tx.take().unwrap().send(()).map_err(|_| ());
69///         Ok(().into())
70///     }
71/// }
72/// # pub fn main() {}
73/// ```
74///
75/// By doing this, the `drain` fn can accept a stream that is `!Send` as long as
76/// the supplied executor is able to spawn `!Send` types.
77pub trait TypedExecutor<T> {
78    /// Spawns a future to run on this executor.
79    ///
80    /// `future` is passed to the executor, which will begin running it. The
81    /// executor takes ownership of the future and becomes responsible for
82    /// driving the future to completion.
83    ///
84    /// # Panics
85    ///
86    /// Implementations are encouraged to avoid panics. However, panics are
87    /// permitted and the caller should check the implementation specific
88    /// documentation for more details on possible panics.
89    ///
90    /// # Examples
91    ///
92    /// ```rust
93    /// # extern crate futures;
94    /// # extern crate tokio_executor;
95    /// # use tokio_executor::TypedExecutor;
96    /// # use futures::{Future, Poll};
97    /// fn example<T>(my_executor: &mut T)
98    /// where
99    ///     T: TypedExecutor<MyFuture>,
100    /// {
101    ///     my_executor.spawn(MyFuture).unwrap();
102    /// }
103    ///
104    /// struct MyFuture;
105    ///
106    /// impl Future for MyFuture {
107    ///     type Item = ();
108    ///     type Error = ();
109    ///
110    ///     fn poll(&mut self) -> Poll<(), ()> {
111    ///         println!("running on the executor");
112    ///         Ok(().into())
113    ///     }
114    /// }
115    /// # fn main() {}
116    /// ```
117    fn spawn(&mut self, future: T) -> Result<(), SpawnError>;
118
119    /// Provides a best effort **hint** to whether or not `spawn` will succeed.
120    ///
121    /// This function may return both false positives **and** false negatives.
122    /// If `status` returns `Ok`, then a call to `spawn` will *probably*
123    /// succeed, but may fail. If `status` returns `Err`, a call to `spawn` will
124    /// *probably* fail, but may succeed.
125    ///
126    /// This allows a caller to avoid creating the task if the call to `spawn`
127    /// has a high likelihood of failing.
128    ///
129    /// # Panics
130    ///
131    /// This function must not panic. Implementers must ensure that panics do
132    /// not happen.
133    ///
134    /// # Examples
135    ///
136    /// ```rust
137    /// # extern crate futures;
138    /// # extern crate tokio_executor;
139    /// # use tokio_executor::TypedExecutor;
140    /// # use futures::{Future, Poll};
141    /// fn example<T>(my_executor: &mut T)
142    /// where
143    ///     T: TypedExecutor<MyFuture>,
144    /// {
145    ///     if my_executor.status().is_ok() {
146    ///         my_executor.spawn(MyFuture).unwrap();
147    ///     } else {
148    ///         println!("the executor is not in a good state");
149    ///     }
150    /// }
151    ///
152    /// struct MyFuture;
153    ///
154    /// impl Future for MyFuture {
155    ///     type Item = ();
156    ///     type Error = ();
157    ///
158    ///     fn poll(&mut self) -> Poll<(), ()> {
159    ///         println!("running on the executor");
160    ///         Ok(().into())
161    ///     }
162    /// }
163    /// # fn main() {}
164    /// ```
165    fn status(&self) -> Result<(), SpawnError> {
166        Ok(())
167    }
168}
169
170impl<E, T> TypedExecutor<T> for Box<E>
171where
172    E: TypedExecutor<T>,
173{
174    fn spawn(&mut self, future: T) -> Result<(), SpawnError> {
175        (**self).spawn(future)
176    }
177
178    fn status(&self) -> Result<(), SpawnError> {
179        (**self).status()
180    }
181}