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