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 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237
#![deny(missing_docs, missing_debug_implementations, warnings)] #![doc(html_root_url = "https://docs.rs/tokio-executor/0.1.5")] //! Task execution related traits and utilities. //! //! In the Tokio execution model, futures are lazy. When a future is created, no //! work is performed. In order for the work defined by the future to happen, //! the future must be submitted to an executor. A future that is submitted to //! an executor is called a "task". //! //! The executor is responsible for ensuring that [`Future::poll`] is called //! whenever the task is notified. Notification happens when the internal //! state of a task transitions from *not ready* to *ready*. For example, a //! socket might have received data and a call to `read` will now be able to //! succeed. //! //! This crate provides traits and utilities that are necessary for building an //! executor, including: //! //! * The [`Executor`] trait describes the API for spawning a future onto an //! executor. //! //! * [`enter`] marks that the current thread is entering an execution //! context. This prevents a second executor from accidentally starting from //! within the context of one that is already running. //! //! * [`DefaultExecutor`] spawns tasks onto the default executor for the current //! context. //! //! * [`Park`] abstracts over blocking and unblocking the current thread. //! //! [`Executor`]: trait.Executor.html //! [`enter`]: fn.enter.html //! [`DefaultExecutor`]: struct.DefaultExecutor.html //! [`Park`]: park/index.html //! [`Future::poll`]: https://docs.rs/futures/0.1/futures/future/trait.Future.html#tymethod.poll extern crate futures; mod enter; mod global; pub mod park; pub use enter::{enter, Enter, EnterError}; pub use global::{spawn, with_default, DefaultExecutor}; use futures::Future; use std::error::Error; use std::fmt; /// A value that executes futures. /// /// The [`spawn`] function is used to submit a future to an executor. Once /// submitted, the executor takes ownership of the future and becomes /// responsible for driving the future to completion. /// /// The strategy employed by the executor to handle the future is less defined /// and is left up to the `Executor` implementation. The `Executor` instance is /// expected to call [`poll`] on the future once it has been notified, however /// the "when" and "how" can vary greatly. /// /// For example, the executor might be a thread pool, in which case a set of /// threads have already been spawned up and the future is inserted into a /// queue. A thread will acquire the future and poll it. /// /// The `Executor` trait is only for futures that **are** `Send`. These are most /// common. There currently is no trait that describes executors that operate /// entirely on the current thread (i.e., are able to spawn futures that are not /// `Send`). Note that single threaded executors can still implement `Executor`, /// but only futures that are `Send` can be spawned via the trait. /// /// # Errors /// /// The [`spawn`] function returns `Result` with an error type of `SpawnError`. /// This error type represents the reason that the executor was unable to spawn /// the future. The two current represented scenarios are: /// /// * An executor being at capacity or full. As such, the executor is not able /// to accept a new future. This error state is expected to be transient. /// * An executor has been shutdown and can no longer accept new futures. This /// error state is expected to be permanent. /// /// If a caller encounters an at capacity error, the caller should try to shed /// load. This can be as simple as dropping the future that was spawned. /// /// If the caller encounters a shutdown error, the caller should attempt to /// gracefully shutdown. /// /// # Examples /// /// ```rust /// # extern crate futures; /// # extern crate tokio_executor; /// # use tokio_executor::Executor; /// # fn docs(my_executor: &mut Executor) { /// use futures::future::lazy; /// my_executor.spawn(Box::new(lazy(|| { /// println!("running on the executor"); /// Ok(()) /// }))).unwrap(); /// # } /// # fn main() {} /// ``` /// /// [`spawn`]: #tymethod.spawn /// [`poll`]: https://docs.rs/futures/0.1/futures/future/trait.Future.html#tymethod.poll pub trait Executor { /// Spawns a future object to run on this executor. /// /// `future` is passed to the executor, which will begin running it. The /// future may run on the current thread or another thread at the discretion /// of the `Executor` implementation. /// /// # Panics /// /// Implementers are encouraged to avoid panics. However, a panic is /// permitted and the caller should check the implementation specific /// documentation for more details on possible panics. /// /// # Examples /// /// ```rust /// # extern crate futures; /// # extern crate tokio_executor; /// # use tokio_executor::Executor; /// # fn docs(my_executor: &mut Executor) { /// use futures::future::lazy; /// my_executor.spawn(Box::new(lazy(|| { /// println!("running on the executor"); /// Ok(()) /// }))).unwrap(); /// # } /// # fn main() {} /// ``` fn spawn(&mut self, future: Box<Future<Item = (), Error = ()> + Send>) -> 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 /// # extern crate futures; /// # extern crate tokio_executor; /// # use tokio_executor::Executor; /// # fn docs(my_executor: &mut Executor) { /// use futures::future::lazy; /// /// if my_executor.status().is_ok() { /// my_executor.spawn(Box::new(lazy(|| { /// println!("running on the executor"); /// Ok(()) /// }))).unwrap(); /// } else { /// println!("the executor is not in a good state"); /// } /// # } /// # fn main() {} /// ``` fn status(&self) -> Result<(), SpawnError> { Ok(()) } } impl<E: Executor + ?Sized> Executor for Box<E> { fn spawn(&mut self, future: Box<Future<Item = (), Error = ()> + Send>) -> Result<(), SpawnError> { (**self).spawn(future) } fn status(&self) -> Result<(), SpawnError> { (**self).status() } } /// Errors returned by `Executor::spawn`. /// /// Spawn errors should represent relatively rare scenarios. Currently, the two /// scenarios represented by `SpawnError` are: /// /// * An executor being at capacity or full. As such, the executor is not able /// to accept a new future. This error state is expected to be transient. /// * An executor has been shutdown and can no longer accept new futures. This /// error state is expected to be permanent. #[derive(Debug)] pub struct SpawnError { is_shutdown: bool, } impl SpawnError { /// Return a new `SpawnError` reflecting a shutdown executor failure. pub fn shutdown() -> Self { SpawnError { is_shutdown: true } } /// Return a new `SpawnError` reflecting an executor at capacity failure. pub fn at_capacity() -> Self { SpawnError { is_shutdown: false } } /// Returns `true` if the error reflects a shutdown executor failure. pub fn is_shutdown(&self) -> bool { self.is_shutdown } /// Returns `true` if the error reflects an executor at capacity failure. pub fn is_at_capacity(&self) -> bool { !self.is_shutdown } } impl fmt::Display for SpawnError { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { write!(fmt, "{}", self.description()) } } impl Error for SpawnError { fn description(&self) -> &str { "attempted to spawn task while the executor is at capacity or shut down" } }