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}