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.4")]

//! 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 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
    ///
    /// Implementors 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. Implementors 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"
    }
}