tokio-executor-0.1.8/Cargo.toml.orig010064400007650000024000000012711350715307700156200ustar0000000000000000[package] name = "tokio-executor" # When releasing to crates.io: # - Remove path dependencies # - Update html_root_url. # - Update doc url # - Cargo.toml # - README.md # - Update CHANGELOG.md. # - Create "v0.1.x" git tag. version = "0.1.8" documentation = "https://docs.rs/tokio-executor/0.1.7/tokio_executor" repository = "https://github.com/tokio-rs/tokio" homepage = "https://github.com/tokio-rs/tokio" license = "MIT" authors = ["Carl Lerche "] description = """ Future execution primitives """ keywords = ["futures", "tokio"] categories = ["concurrency", "asynchronous"] [dependencies] crossbeam-utils = "0.6.2" futures = "0.1.19" [dev-dependencies] tokio = "0.1.18" tokio-executor-0.1.8/Cargo.toml0000644000000020500000000000000120550ustar00# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're # editing this file be aware that the upstream Cargo.toml # will likely look very different (and much more reasonable) [package] name = "tokio-executor" version = "0.1.8" authors = ["Carl Lerche "] description = "Future execution primitives\n" homepage = "https://github.com/tokio-rs/tokio" documentation = "https://docs.rs/tokio-executor/0.1.7/tokio_executor" keywords = ["futures", "tokio"] categories = ["concurrency", "asynchronous"] license = "MIT" repository = "https://github.com/tokio-rs/tokio" [dependencies.crossbeam-utils] version = "0.6.2" [dependencies.futures] version = "0.1.19" [dev-dependencies.tokio] version = "0.1.18" tokio-executor-0.1.8/CHANGELOG.md010064400007650000024000000020101350715307700145320ustar0000000000000000# 0.1.8 (June 2, 2019) ### Added - Add `executor::exit` to allow other executors inside `threadpool::blocking` (#1155). # 0.1.7 (March 22, 2019) ### Added - `TypedExecutor` for spawning futures of a specific type (#993). # 0.1.6 (January 6, 2019) * Implement `Unpark` for `Arc` (#802). * Switch to crossbeam's Parker / Unparker (#528). # 0.1.5 (September 26, 2018) * Implement `futures::Executor` for `DefaultExecutor` (#563). * Add `Enter::block_on(future)` (#646) # 0.1.4 (August 23, 2018) * Implement `std::error::Error` for error types (#511). # 0.1.3 (August 6, 2018) * Implement `Executor` for `Box` (#420). * Improve `EnterError` debug message (#410). * Implement `status`, `Send`, and `Sync` for `DefaultExecutor` (#463, #472). * Fix race in `ParkThread` (#507). * Handle recursive calls into `DefaultExecutor` (#473). # 0.1.2 (March 30, 2018) * Implement `Unpark` for `Box`. # 0.1.1 (March 22, 2018) * Optionally support futures 0.2. # 0.1.0 (March 09, 2018) * Initial release tokio-executor-0.1.8/LICENSE010064400007650000024000000020461346265360200137360ustar0000000000000000Copyright (c) 2019 Tokio Contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. tokio-executor-0.1.8/README.md010064400007650000024000000035071350715307700142140ustar0000000000000000# tokio-executor Task execution related traits and utilities. [Documentation](https://docs.rs/tokio-executor/0.1.8/tokio_executor) ## Overview 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`]: https://docs.rs/tokio-executor/0.1.8/tokio_executor/trait.Executor.html [`enter`]: https://docs.rs/tokio-executor/0.1.8/tokio_executor/fn.enter.html [`DefaultExecutor`]: https://docs.rs/tokio-executor/0.1.8/tokio_executor/struct.DefaultExecutor.html [`Park`]: https://docs.rs/tokio-executor/0.1.8/tokio_executor/park/trait.Park.html ## License This project is licensed under the [MIT license](LICENSE). ### Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in Tokio by you, shall be licensed as MIT, without any additional terms or conditions. tokio-executor-0.1.8/src/enter.rs010064400007650000024000000076301350715307700152100ustar0000000000000000use std::cell::Cell; use std::error::Error; use std::fmt; use std::prelude::v1::*; use futures::{self, Future}; thread_local!(static ENTERED: Cell = Cell::new(false)); /// Represents an executor context. /// /// For more details, see [`enter` documentation](fn.enter.html) pub struct Enter { on_exit: Vec>, permanent: bool, } /// An error returned by `enter` if an execution scope has already been /// entered. pub struct EnterError { _a: (), } impl fmt::Debug for EnterError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("EnterError") .field("reason", &self.description()) .finish() } } impl fmt::Display for EnterError { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { write!(fmt, "{}", self.description()) } } impl Error for EnterError { fn description(&self) -> &str { "attempted to run an executor while another executor is already running" } } /// Marks the current thread as being within the dynamic extent of an /// executor. /// /// Executor implementations should call this function before blocking the /// thread. If `None` is returned, the executor should fail by panicking or /// taking some other action without blocking the current thread. This prevents /// deadlocks due to multiple executors competing for the same thread. /// /// # Error /// /// Returns an error if the current thread is already marked pub fn enter() -> Result { ENTERED.with(|c| { if c.get() { Err(EnterError { _a: () }) } else { c.set(true); Ok(Enter { on_exit: Vec::new(), permanent: false, }) } }) } // Forces the current "entered" state to be cleared while the closure // is executed. // // # Warning // // This is hidden for a reason. Do not use without fully understanding // executors. Misuing can easily cause your program to deadlock. #[doc(hidden)] pub fn exit R, R>(f: F) -> R { // Reset in case the closure panics struct Reset; impl Drop for Reset { fn drop(&mut self) { ENTERED.with(|c| { c.set(true); }); } } ENTERED.with(|c| { debug_assert!(c.get()); c.set(false); }); let reset = Reset; let ret = f(); ::std::mem::forget(reset); ENTERED.with(|c| { assert!(!c.get(), "closure claimed permanent executor"); c.set(true); }); ret } impl Enter { /// Register a callback to be invoked if and when the thread /// ceased to act as an executor. pub fn on_exit(&mut self, f: F) where F: FnOnce() + 'static, { self.on_exit.push(Box::new(f)); } /// Treat the remainder of execution on this thread as part of an /// executor; used mostly for thread pool worker threads. /// /// All registered `on_exit` callbacks are *dropped* without being /// invoked. pub fn make_permanent(mut self) { self.permanent = true; } /// Blocks the thread on the specified future, returning the value with /// which that future completes. pub fn block_on(&mut self, f: F) -> Result { futures::executor::spawn(f).wait_future() } } impl fmt::Debug for Enter { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("Enter").finish() } } impl Drop for Enter { fn drop(&mut self) { ENTERED.with(|c| { assert!(c.get()); if self.permanent { return; } for callback in self.on_exit.drain(..) { callback.call(); } c.set(false); }); } } trait Callback: 'static { fn call(self: Box); } impl Callback for F { fn call(self: Box) { (*self)() } } tokio-executor-0.1.8/src/error.rs010064400007650000024000000027371350715307400152240ustar0000000000000000use std::error::Error; use std::fmt; /// 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" } } tokio-executor-0.1.8/src/executor.rs010064400007650000024000000125561350715307400157310ustar0000000000000000use futures::Future; use SpawnError; /// 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. /// /// This trait is primarily intended to implemented by executors and used to /// back `tokio::spawn`. Libraries and applications **may** use this trait to /// bound generics, but doing so will limit usage to futures that implement /// `Send`. Instead, libraries and applications are recommended to use /// [`TypedExecutor`] as a bound. /// /// # 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 /// [`TypedExecutor`]: ../trait.TypedExecutor.html 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 /// /// 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 /// # 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 + 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 Executor for Box { fn spawn( &mut self, future: Box + Send>, ) -> Result<(), SpawnError> { (**self).spawn(future) } fn status(&self) -> Result<(), SpawnError> { (**self).status() } } tokio-executor-0.1.8/src/global.rs010064400007650000024000000167111350715307400153300ustar0000000000000000use super::{Enter, Executor, SpawnError}; use futures::{future, Future}; use std::cell::Cell; /// Executes futures on the default executor for the current execution context. /// /// `DefaultExecutor` implements `Executor` and can be used to spawn futures /// without referencing a specific executor. /// /// When an executor starts, it sets the `DefaultExecutor` handle to point to an /// executor (usually itself) that is used to spawn new tasks. /// /// The current `DefaultExecutor` reference is tracked using a thread-local /// variable and is set using `tokio_executor::with_default` #[derive(Debug, Clone)] pub struct DefaultExecutor { _dummy: (), } impl DefaultExecutor { /// Returns a handle to the default executor for the current context. /// /// Futures may be spawned onto the default executor using this handle. /// /// The returned handle will reference whichever executor is configured as /// the default **at the time `spawn` is called**. This enables /// `DefaultExecutor::current()` to be called before an execution context is /// setup, then passed **into** an execution context before it is used. /// /// This is also true for sending the handle across threads, so calling /// `DefaultExecutor::current()` on thread A and then sending the result to /// thread B will _not_ reference the default executor that was set on thread A. pub fn current() -> DefaultExecutor { DefaultExecutor { _dummy: () } } #[inline] fn with_current R, R>(f: F) -> Option { EXECUTOR.with( |current_executor| match current_executor.replace(State::Active) { State::Ready(executor_ptr) => { let executor = unsafe { &mut *executor_ptr }; let result = f(executor); current_executor.set(State::Ready(executor_ptr)); Some(result) } State::Empty | State::Active => None, }, ) } } #[derive(Clone, Copy)] enum State { // default executor not defined Empty, // default executor is defined and ready to be used Ready(*mut Executor), // default executor is currently active (used to detect recursive calls) Active, } thread_local! { /// Thread-local tracking the current executor static EXECUTOR: Cell = Cell::new(State::Empty) } // ===== impl DefaultExecutor ===== impl super::Executor for DefaultExecutor { fn spawn( &mut self, future: Box + Send>, ) -> Result<(), SpawnError> { DefaultExecutor::with_current(|executor| executor.spawn(future)) .unwrap_or_else(|| Err(SpawnError::shutdown())) } fn status(&self) -> Result<(), SpawnError> { DefaultExecutor::with_current(|executor| executor.status()) .unwrap_or_else(|| Err(SpawnError::shutdown())) } } impl super::TypedExecutor for DefaultExecutor where T: Future + Send + 'static, { fn spawn(&mut self, future: T) -> Result<(), SpawnError> { super::Executor::spawn(self, Box::new(future)) } fn status(&self) -> Result<(), SpawnError> { super::Executor::status(self) } } impl future::Executor for DefaultExecutor where T: Future + Send + 'static, { fn execute(&self, future: T) -> Result<(), future::ExecuteError> { if let Err(e) = super::Executor::status(self) { let kind = if e.is_at_capacity() { future::ExecuteErrorKind::NoCapacity } else { future::ExecuteErrorKind::Shutdown }; return Err(future::ExecuteError::new(kind, future)); } let _ = DefaultExecutor::with_current(|executor| executor.spawn(Box::new(future))); Ok(()) } } // ===== global spawn fns ===== /// Submits a future for execution on the default executor -- usually a /// threadpool. /// /// Futures are lazy constructs. When they are defined, no work happens. In /// order for the logic defined by the future to be run, the future must be /// spawned on an executor. This function is the easiest way to do so. /// /// This function must be called from an execution context, i.e. from a future /// that has been already spawned onto an executor. /// /// Once spawned, the future will execute. The details of how that happens is /// left up to the executor instance. If the executor is a thread pool, the /// future will be pushed onto a queue that a worker thread polls from. If the /// executor is a "current thread" executor, the future might be polled /// immediately from within the call to `spawn` or it might be pushed onto an /// internal queue. /// /// # Panics /// /// This function will panic if the default executor is not set or if spawning /// onto the default executor returns an error. To avoid the panic, use the /// `DefaultExecutor` handle directly. /// /// # Examples /// /// ```rust /// # extern crate futures; /// # extern crate tokio_executor; /// # use tokio_executor::spawn; /// # pub fn dox() { /// use futures::future::lazy; /// /// spawn(lazy(|| { /// println!("running on the default executor"); /// Ok(()) /// })); /// # } /// # pub fn main() {} /// ``` pub fn spawn(future: T) where T: Future + Send + 'static, { DefaultExecutor::current().spawn(Box::new(future)).unwrap() } /// Set the default executor for the duration of the closure /// /// # Panics /// /// This function panics if there already is a default executor set. pub fn with_default(executor: &mut T, enter: &mut Enter, f: F) -> R where T: Executor, F: FnOnce(&mut Enter) -> R, { EXECUTOR.with(|cell| { match cell.get() { State::Ready(_) | State::Active => { panic!("default executor already set for execution context") } _ => {} } // Ensure that the executor is removed from the thread-local context // when leaving the scope. This handles cases that involve panicking. struct Reset<'a>(&'a Cell); impl<'a> Drop for Reset<'a> { fn drop(&mut self) { self.0.set(State::Empty); } } let _reset = Reset(cell); // While scary, this is safe. The function takes a // `&mut Executor`, which guarantees that the reference lives for the // duration of `with_default`. // // Because we are always clearing the TLS value at the end of the // function, we can cast the reference to 'static which thread-local // cells require. let executor = unsafe { hide_lt(executor as &mut _ as *mut _) }; cell.set(State::Ready(executor)); f(enter) }) } unsafe fn hide_lt<'a>(p: *mut (Executor + 'a)) -> *mut (Executor + 'static) { use std::mem; mem::transmute(p) } #[cfg(test)] mod tests { use super::{with_default, DefaultExecutor, Executor}; #[test] fn default_executor_is_send_and_sync() { fn assert_send_sync() {} assert_send_sync::(); } #[test] fn nested_default_executor_status() { let mut enter = super::super::enter().unwrap(); let mut executor = DefaultExecutor::current(); let result = with_default(&mut executor, &mut enter, |_| { DefaultExecutor::current().status() }); assert!(result.err().unwrap().is_shutdown()) } } tokio-executor-0.1.8/src/lib.rs010064400007650000024000000054621350715307700146420ustar0000000000000000#![deny(missing_docs, missing_debug_implementations, warnings)] #![doc(html_root_url = "https://docs.rs/tokio-executor/0.1.8")] // Our MSRV doesn't allow us to fix these warnings yet #![allow(rust_2018_idioms)] //! 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 spawns future object onto an executor. //! //! * The [`TypedExecutor`] trait spawns futures of a specific type onto an //! executor. This is used to be generic over executors that spawn futures //! that are either `Send` or `!Send` or implement executors that apply to //! specific futures. //! //! * [`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. //! //! # Implementing an executor //! //! Executors should always implement `TypedExecutor`. This usually is the bound //! that applications and libraries will use when generic over an executor. See //! the [trait documentation][`TypedExecutor`] for more details. //! //! If the executor is able to spawn all futures that are `Send`, then the //! executor should also implement the `Executor` trait. This trait is rarely //! used directly by applications and libraries. Instead, `tokio::spawn` is //! configured to dispatch to type that implements `Executor`. //! //! [`Executor`]: trait.Executor.html //! [`TypedExecutor`]: trait.TypedExecutor.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 crossbeam_utils; extern crate futures; mod enter; mod error; mod executor; mod global; pub mod park; mod typed; pub use enter::{enter, exit, Enter, EnterError}; pub use error::SpawnError; pub use executor::Executor; pub use global::{spawn, with_default, DefaultExecutor}; pub use typed::TypedExecutor; tokio-executor-0.1.8/src/park.rs010064400007650000024000000160051350715307400150210ustar0000000000000000//! Abstraction over blocking and unblocking the current thread. //! //! Provides an abstraction over blocking the current thread. This is similar to //! the park / unpark constructs provided by [`std`] but made generic. This //! allows embedding custom functionality to perform when the thread is blocked. //! //! A blocked [`Park`][p] instance is unblocked by calling [`unpark`] on its //! [`Unpark`][up] handle. //! //! The [`ParkThread`] struct implements [`Park`][p] using //! [`thread::park`][`std`] to put the thread to sleep. The Tokio reactor also //! implements park, but uses [`mio::Poll`][mio] to block the thread instead. //! //! The [`Park`][p] trait is composable. A timer implementation might decorate a //! [`Park`][p] implementation by checking if any timeouts have elapsed after //! the inner [`Park`][p] implementation unblocks. //! //! # Model //! //! Conceptually, each [`Park`][p] instance has an associated token, which is //! initially not present: //! //! * The [`park`] method blocks the current thread unless or until the token //! is available, at which point it atomically consumes the token. //! * The [`unpark`] method atomically makes the token available if it wasn't //! already. //! //! Some things to note: //! //! * If [`unpark`] is called before [`park`], the next call to [`park`] will //! **not** block the thread. //! * **Spurious** wakeups are permitted, i.e., the [`park`] method may unblock //! even if [`unpark`] was not called. //! * [`park_timeout`] does the same as [`park`] but allows specifying a maximum //! time to block the thread for. //! //! [`std`]: https://doc.rust-lang.org/std/thread/fn.park.html //! [`thread::park`]: https://doc.rust-lang.org/std/thread/fn.park.html //! [`ParkThread`]: struct.ParkThread.html //! [p]: trait.Park.html //! [`park`]: trait.Park.html#tymethod.park //! [`park_timeout`]: trait.Park.html#tymethod.park_timeout //! [`unpark`]: trait.Unpark.html#tymethod.unpark //! [up]: trait.Unpark.html //! [mio]: https://docs.rs/mio/0.6/mio/struct.Poll.html use std::marker::PhantomData; use std::rc::Rc; use std::sync::Arc; use std::time::Duration; use crossbeam_utils::sync::{Parker, Unparker}; /// Block the current thread. /// /// See [module documentation][mod] for more details. /// /// [mod]: ../index.html pub trait Park { /// Unpark handle type for the `Park` implementation. type Unpark: Unpark; /// Error returned by `park` type Error; /// Get a new `Unpark` handle associated with this `Park` instance. fn unpark(&self) -> Self::Unpark; /// Block the current thread unless or until the token is available. /// /// A call to `park` does not guarantee that the thread will remain blocked /// forever, and callers should be prepared for this possibility. This /// function may wakeup spuriously for any reason. /// /// See [module documentation][mod] for more details. /// /// # Panics /// /// This function **should** not panic, but ultimately, panics are left as /// an implementation detail. Refer to the documentation for the specific /// `Park` implementation /// /// [mod]: ../index.html fn park(&mut self) -> Result<(), Self::Error>; /// Park the current thread for at most `duration`. /// /// This function is the same as `park` but allows specifying a maximum time /// to block the thread for. /// /// Same as `park`, there is no guarantee that the thread will remain /// blocked for any amount of time. Spurious wakeups are permitted for any /// reason. /// /// See [module documentation][mod] for more details. /// /// # Panics /// /// This function **should** not panic, but ultimately, panics are left as /// an implementation detail. Refer to the documentation for the specific /// `Park` implementation /// /// [mod]: ../index.html fn park_timeout(&mut self, duration: Duration) -> Result<(), Self::Error>; } /// Unblock a thread blocked by the associated [`Park`] instance. /// /// See [module documentation][mod] for more details. /// /// [mod]: ../index.html /// [`Park`]: trait.Park.html pub trait Unpark: Sync + Send + 'static { /// Unblock a thread that is blocked by the associated `Park` handle. /// /// Calling `unpark` atomically makes available the unpark token, if it is /// not already available. /// /// See [module documentation][mod] for more details. /// /// # Panics /// /// This function **should** not panic, but ultimately, panics are left as /// an implementation detail. Refer to the documentation for the specific /// `Unpark` implementation /// /// [mod]: ../index.html fn unpark(&self); } impl Unpark for Box { fn unpark(&self) { (**self).unpark() } } impl Unpark for Arc { fn unpark(&self) { (**self).unpark() } } /// Blocks the current thread using a condition variable. /// /// Implements the [`Park`] functionality by using a condition variable. An /// atomic variable is also used to avoid using the condition variable if /// possible. /// /// The condition variable is cached in a thread-local variable and is shared /// across all `ParkThread` instances created on the same thread. This also /// means that an instance of `ParkThread` might be unblocked by a handle /// associated with a different `ParkThread` instance. #[derive(Debug)] pub struct ParkThread { _anchor: PhantomData>, } /// Error returned by [`ParkThread`] /// /// This currently is never returned, but might at some point in the future. /// /// [`ParkThread`]: struct.ParkThread.html #[derive(Debug)] pub struct ParkError { _p: (), } /// Unblocks a thread that was blocked by `ParkThread`. #[derive(Clone, Debug)] pub struct UnparkThread { inner: Unparker, } thread_local! { static CURRENT_PARKER: Parker = Parker::new(); } // ===== impl ParkThread ===== impl ParkThread { /// Create a new `ParkThread` handle for the current thread. /// /// This type cannot be moved to other threads, so it should be created on /// the thread that the caller intends to park. pub fn new() -> ParkThread { ParkThread { _anchor: PhantomData, } } /// Get a reference to the `ParkThread` handle for this thread. fn with_current(&self, f: F) -> R where F: FnOnce(&Parker) -> R, { CURRENT_PARKER.with(|inner| f(inner)) } } impl Park for ParkThread { type Unpark = UnparkThread; type Error = ParkError; fn unpark(&self) -> Self::Unpark { let inner = self.with_current(|inner| inner.unparker().clone()); UnparkThread { inner } } fn park(&mut self) -> Result<(), Self::Error> { self.with_current(|inner| inner.park()); Ok(()) } fn park_timeout(&mut self, duration: Duration) -> Result<(), Self::Error> { self.with_current(|inner| inner.park_timeout(duration)); Ok(()) } } // ===== impl UnparkThread ===== impl Unpark for UnparkThread { fn unpark(&self) { self.inner.unpark(); } } tokio-executor-0.1.8/src/typed.rs010064400007650000024000000123111350715307400152050ustar0000000000000000use 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. /// /// ```rust /// #[macro_use] /// extern crate futures; /// extern crate tokio; /// /// use futures::{Future, Stream, Poll}; /// use tokio::executor::TypedExecutor; /// use tokio::sync::oneshot; /// /// pub fn drain(stream: T, executor: &mut E) /// -> impl Future /// where /// T: Stream, /// E: TypedExecutor> /// { /// let (tx, rx) = oneshot::channel(); /// /// executor.spawn(Drain { /// stream, /// tx: Some(tx), /// }).unwrap(); /// /// rx.map_err(|_| ()) /// } /// /// // The background task /// pub struct Drain { /// stream: T, /// tx: Option>, /// } /// /// impl Future for Drain { /// type Item = (); /// type Error = (); /// /// fn poll(&mut self) -> Poll { /// loop { /// let item = try_ready!( /// self.stream.poll() /// .map_err(|_| ()) /// ); /// /// if item.is_none() { break; } /// } /// /// self.tx.take().unwrap().send(()).map_err(|_| ()); /// Ok(().into()) /// } /// } /// # pub fn main() {} /// ``` /// /// 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 { /// 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 /// # extern crate futures; /// # extern crate tokio_executor; /// # use tokio_executor::TypedExecutor; /// # use futures::{Future, Poll}; /// fn example(my_executor: &mut T) /// where /// T: TypedExecutor, /// { /// my_executor.spawn(MyFuture).unwrap(); /// } /// /// struct MyFuture; /// /// impl Future for MyFuture { /// type Item = (); /// type Error = (); /// /// fn poll(&mut self) -> Poll<(), ()> { /// println!("running on the executor"); /// Ok(().into()) /// } /// } /// # fn main() {} /// ``` 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 /// # extern crate futures; /// # extern crate tokio_executor; /// # use tokio_executor::TypedExecutor; /// # use futures::{Future, Poll}; /// fn example(my_executor: &mut T) /// where /// T: TypedExecutor, /// { /// 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 Item = (); /// type Error = (); /// /// fn poll(&mut self) -> Poll<(), ()> { /// println!("running on the executor"); /// Ok(().into()) /// } /// } /// # fn main() {} /// ``` fn status(&self) -> Result<(), SpawnError> { Ok(()) } } impl TypedExecutor for Box where E: TypedExecutor, { fn spawn(&mut self, future: T) -> Result<(), SpawnError> { (**self).spawn(future) } fn status(&self) -> Result<(), SpawnError> { (**self).status() } } tokio-executor-0.1.8/tests/executor.rs010064400007650000024000000012301350715307400162670ustar0000000000000000extern crate futures; extern crate tokio_executor; use futures::{future::lazy, Future}; use tokio_executor::DefaultExecutor; mod out_of_executor_context { use super::*; use tokio_executor::Executor; fn test(spawn: F) where F: Fn(Box + Send>) -> Result<(), E>, { let res = spawn(Box::new(lazy(|| Ok(())))); assert!(res.is_err()); } #[test] fn spawn() { test(|f| DefaultExecutor::current().spawn(f)); } #[test] fn execute() { use futures::future::Executor as FuturesExecutor; test(|f| DefaultExecutor::current().execute(f)); } } tokio-executor-0.1.8/.cargo_vcs_info.json0000644000000001120000000000000140540ustar00{ "git": { "sha1": "b4cb3226ab0c3cc6af272ba27ce176c84c79b73b" } }