From 491f15827b8e228f2847c835232305687b0a95e1 Mon Sep 17 00:00:00 2001 From: David Kellum Date: Sun, 22 Jul 2018 13:35:30 -0700 Subject: [PATCH] General rustdoc improvements (#450) * Normalize links to docs.rs/CRATE/M.N/... docs.rs is smart enough to show docs for the latest M.N.P release when M.N is used in the link. For example: https://docs.rs/mio/0.6/mio/struct.Poll.html ..will show mio 0.6.14 and later docs. While using the `M.N.*` (ASTERISK) syntax also works, `M.N` is the more common usage, so standarize a few existing links to that format. * Fix missing or malformed rustdoc links * executor lib rustdoc minor format change * Promote tokio-threadpool crate level comments to rustdoc * Replace hidden tokio::executor::thread_pool docs with deprecation note * Fix typo/simplify util module rustdoc * Reuse some tokio::executor::thread_pool rustdoc for the crate Relates to #421 --- README.md | 2 +- src/executor/mod.rs | 75 +--------- src/lib.rs | 4 +- src/runtime/current_thread/mod.rs | 3 + src/timer.rs | 3 + src/util/mod.rs | 5 +- tokio-executor/src/lib.rs | 6 +- tokio-executor/src/park.rs | 2 +- tokio-fs/src/file/mod.rs | 4 +- tokio-io/src/codec/mod.rs | 4 +- tokio-threadpool/src/lib.rs | 236 ++++++++++++++++-------------- tokio-timer/src/timer/handle.rs | 1 + tokio-timer/src/timer/mod.rs | 1 + 13 files changed, 152 insertions(+), 194 deletions(-) diff --git a/README.md b/README.md index 4b7475f22..a6dbeb106 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ These components provide the runtime components necessary for building an asynchronous application. [net]: https://docs.rs/tokio/0.1/tokio/net/index.html -[reactor]: https://docs.rs/tokio/0.1.1/tokio/reactor/index.html +[reactor]: https://docs.rs/tokio/0.1/tokio/reactor/index.html [scheduler]: https://tokio-rs.github.io/tokio/tokio/runtime/index.html ## Example diff --git a/src/executor/mod.rs b/src/executor/mod.rs index 8e62bc54f..3f5b038b8 100644 --- a/src/executor/mod.rs +++ b/src/executor/mod.rs @@ -44,79 +44,10 @@ pub mod current_thread; #[deprecated(since = "0.1.8", note = "use tokio-threadpool crate instead")] -#[doc(hidden)] +/// Re-exports of [`tokio-threadpool`], deprecated in favor of the crate. +/// +/// [`tokio-threadpool`]: https://docs.rs/tokio-threadpool/0.1 pub mod thread_pool { - //! Maintains a pool of threads across which the set of spawned tasks are - //! executed. - //! - //! [`ThreadPool`] is an executor that uses a thread pool for executing - //! tasks concurrently across multiple cores. It uses a thread pool that is - //! optimized for use cases that involve multiplexing large number of - //! independent tasks that perform short(ish) amounts of computation and are - //! mainly waiting on I/O, i.e. the Tokio use case. - //! - //! Usually, users of [`ThreadPool`] will not create pool instances. - //! Instead, they will create a [`Runtime`] instance, which comes with a - //! pre-configured thread pool. - //! - //! At the core, [`ThreadPool`] uses a work-stealing based scheduling - //! strategy. When spawning a task while *external* to the thread pool - //! (i.e., from a thread that is not part of the thread pool), the task is - //! randomly assigned to a worker thread. When spawning a task while - //! *internal* to the thread pool, the task is assigned to the current - //! worker. - //! - //! Each worker maintains its own queue and first focuses on processing all - //! tasks in its queue. When the worker's queue is empty, the worker will - //! attempt to *steal* tasks from other worker queues. This strategy helps - //! ensure that work is evenly distributed across threads while minimizing - //! synchronization between worker threads. - //! - //! # Usage - //! - //! Thread pool instances are created using [`ThreadPool::new`] or - //! [`Builder::new`]. The first option returns a thread pool with default - //! configuration values. The second option allows configuring the thread - //! pool before instantiating it. - //! - //! Once an instance is obtained, futures may be spawned onto it using the - //! [`spawn`] function. - //! - //! A handle to the thread pool is obtained using [`ThreadPool::sender`]. - //! This handle is **only** able to spawn futures onto the thread pool. It - //! is unable to affect the lifecycle of the thread pool in any way. This - //! handle can be passed into functions or stored in structs as a way to - //! grant the capability of spawning futures. - //! - //! # Examples - //! - //! ```rust - //! # extern crate tokio; - //! # extern crate futures; - //! # use tokio::executor::thread_pool::ThreadPool; - //! use futures::future::{Future, lazy}; - //! - //! # pub fn main() { - //! // Create a thread pool with default configuration values - //! let thread_pool = ThreadPool::new(); - //! - //! thread_pool.spawn(lazy(|| { - //! println!("called from a worker thread"); - //! Ok(()) - //! })); - //! - //! // Gracefully shutdown the threadpool - //! thread_pool.shutdown().wait().unwrap(); - //! # } - //! ``` - //! - //! [`ThreadPool`]: struct.ThreadPool.html - //! [`ThreadPool::new`]: struct.ThreadPool.html#method.new - //! [`ThreadPool::sender`]: struct.ThreadPool.html#method.sender - //! [`spawn`]: struct.ThreadPool.html#method.spawn - //! [`Builder::new`]: struct.Builder.html#method.new - //! [`Runtime`]: ../../runtime/struct.Runtime.html - pub use tokio_threadpool::{ Builder, Sender, diff --git a/src/lib.rs b/src/lib.rs index b0d0b80a6..ea6582fd8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,7 +5,7 @@ //! provides a few major components: //! //! * A multi threaded, work-stealing based task [scheduler][runtime]. -//! * A [reactor][reactor] backed by the operating system's event queue (epoll, kqueue, +//! * A [reactor] backed by the operating system's event queue (epoll, kqueue, //! IOCP, etc...). //! * Asynchronous [TCP and UDP][net] sockets. //! * Asynchronous [filesystem][fs] operations. @@ -17,7 +17,7 @@ //! Guide level documentation is found on the [website]. //! //! [website]: https://tokio.rs/docs/getting-started/hello-world/ -//! [futures]: http://docs.rs/futures +//! [futures]: http://docs.rs/futures/0.1 //! //! # Examples //! diff --git a/src/runtime/current_thread/mod.rs b/src/runtime/current_thread/mod.rs index f0a927b9b..b0063f640 100644 --- a/src/runtime/current_thread/mod.rs +++ b/src/runtime/current_thread/mod.rs @@ -62,6 +62,9 @@ //! [rt]: struct.Runtime.html //! [concurrent-rt]: ../struct.Runtime.html //! [chan]: https://docs.rs/futures/0.1/futures/sync/mpsc/fn.channel.html +//! [reactor]: ../../reactor/struct.Reactor.html +//! [executor]: https://tokio.rs/docs/getting-started/runtime-model/#executors +//! [timer]: ../../timer/index.html mod builder; mod runtime; diff --git a/src/timer.rs b/src/timer.rs index 1147a5db6..2c4c7569a 100644 --- a/src/timer.rs +++ b/src/timer.rs @@ -76,6 +76,9 @@ //! [runtime]: ../runtime/struct.Runtime.html //! [tokio-timer]: https://docs.rs/tokio-timer //! [ext]: ../util/trait.FutureExt.html#method.deadline +//! [Deadline]: struct.Deadline.html +//! [Delay]: struct.Delay.html +//! [Interval]: struct.Interval.html pub use tokio_timer::{ Deadline, diff --git a/src/util/mod.rs b/src/util/mod.rs index 490d0cf6e..06f0fe500 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -1,8 +1,9 @@ //! Utilities for working with Tokio. //! //! This module contains utilities that are useful for working with Tokio. -//! Currently, this only includes [`FutureExt`][FutureExt]. However, this will -//! include over time. +//! Currently, this only includes [`FutureExt`], but this may grow over time. +//! +//! [`FutureExt`]: trait.FutureExt.html mod future; diff --git a/tokio-executor/src/lib.rs b/tokio-executor/src/lib.rs index 051d88855..4fbfdc795 100644 --- a/tokio-executor/src/lib.rs +++ b/tokio-executor/src/lib.rs @@ -7,8 +7,9 @@ //! //! 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. +//! 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: @@ -29,6 +30,7 @@ //! [`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 #![deny(missing_docs, missing_debug_implementations, warnings)] #![doc(html_root_url = "https://docs.rs/tokio-executor/0.1.2")] diff --git a/tokio-executor/src/park.rs b/tokio-executor/src/park.rs index ca03c237d..13713261c 100644 --- a/tokio-executor/src/park.rs +++ b/tokio-executor/src/park.rs @@ -42,7 +42,7 @@ //! [`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.13/mio/struct.Poll.html +//! [mio]: https://docs.rs/mio/0.6/mio/struct.Poll.html use std::marker::PhantomData; use std::rc::Rc; diff --git a/tokio-fs/src/file/mod.rs b/tokio-fs/src/file/mod.rs index b2b2ceed4..c3ae43112 100644 --- a/tokio-fs/src/file/mod.rs +++ b/tokio-fs/src/file/mod.rs @@ -190,7 +190,9 @@ impl File { /// /// # Panics /// - /// This function will panic if [`shutdown`] has been called. + /// This function will panic if `shutdown` has been called. + /// + /// [std]: https://doc.rust-lang.org/std/fs/struct.File.html pub fn into_std(mut self) -> StdFile { self.std.take().expect("`File` instance already shutdown") } diff --git a/tokio-io/src/codec/mod.rs b/tokio-io/src/codec/mod.rs index c4dab6564..8f7bc28a8 100644 --- a/tokio-io/src/codec/mod.rs +++ b/tokio-io/src/codec/mod.rs @@ -104,7 +104,7 @@ pub mod length_delimited { //! [`FramedRead`] adapts an [`AsyncRead`] into a `Stream` of [`BytesMut`], //! such that each yielded [`BytesMut`] value contains the contents of an //! entire frame. There are many configuration parameters enabling - //! [`FrameRead`] to handle a wide range of protocols. Here are some + //! [`FramedRead`] to handle a wide range of protocols. Here are some //! examples that will cover the various options at a high level. //! //! ## Example 1 @@ -370,7 +370,7 @@ pub mod length_delimited { //! [`AsyncRead`]: ../../trait.AsyncRead.html //! [`AsyncWrite`]: ../../trait.AsyncWrite.html //! [`Encoder`]: ../trait.Encoder.html - //! [`BytesMut`]: https://docs.rs/bytes/~0.4/bytes/struct.BytesMut.html + //! [`BytesMut`]: https://docs.rs/bytes/0.4/bytes/struct.BytesMut.html pub use ::length_delimited::*; } diff --git a/tokio-threadpool/src/lib.rs b/tokio-threadpool/src/lib.rs index 358c2c31a..d43bae0bc 100644 --- a/tokio-threadpool/src/lib.rs +++ b/tokio-threadpool/src/lib.rs @@ -1,117 +1,81 @@ -//! A work-stealing based thread pool for executing futures. - #![doc(html_root_url = "https://docs.rs/tokio-threadpool/0.1.5")] #![deny(warnings, missing_docs, missing_debug_implementations)] -// The Tokio thread pool is designed to scheduled futures in Tokio based -// applications. The thread pool structure manages two sets of threads: -// -// * Worker threads. -// * Backup threads. -// -// Worker threads are used to schedule futures using a work-stealing strategy. -// Backup threads, on the other hand, are intended only to support the -// `blocking` API. Threads will transition between the two sets. -// -// The advantage of the work-stealing strategy is minimal cross-thread -// coordination. The thread pool attempts to make as much progress as possible -// without communicating across threads. -// -// # Crate layout -// -// The primary type, `Pool`, holds the majority of a thread pool's state, -// including the state for each worker. Each worker's state is maintained in an -// instance of `worker::Entry`. -// -// `Worker` contains the logic that runs on each worker thread. It holds an -// `Arc` to `Pool` and is able to access its state from `Pool`. -// -// `Task` is a harness around an individual future. It manages polling and -// scheduling that future. -// -// # Worker overview -// -// Each worker has two queues: a deque and a mpsc channel. The deque is the -// primary queue for tasks that are scheduled to run on the worker thread. Tasks -// can only be pushed onto the deque by the worker, but other workers may -// "steal" from that deque. The mpsc channel is used to submit futures while -// external to the pool. -// -// As long as the thread pool has not been shutdown, a worker will run in a -// loop. Each loop, it consumes all tasks on its mpsc channel and pushes it onto -// the deque. It then pops tasks off of the deque and executes them. -// -// If a worker has no work, i.e., both queues are empty. It attempts to steal. -// To do this, it randomly scans other workers' deques and tries to pop a task. -// If it finds no work to steal, the thread goes to sleep. -// -// When the worker detects that the pool has been shut down, it exits the loop, -// cleans up its state, and shuts the thread down. -// -// # Thread pool initialization -// -// By default, no threads are spawned on creation. Instead, when new futures are -// spawned, the pool first checks if there are enough active worker threads. If -// not, a new worker thread is spawned. -// -// # Spawning futures -// -// The spawning behavior depends on whether a future was spawned from within a -// worker or thread or if it was spawned from an external handle. -// -// When spawning a future while external to the thread pool, the current -// strategy is to randomly pick a worker to submit the task to. The task is then -// pushed onto that worker's mpsc channel. -// -// When spawning a future while on a worker thread, the task is pushed onto the -// back of the current worker's deque. -// -// # Sleeping workers -// -// Sleeping workers are tracked using a treiber stack [1]. This results in the -// thread that most recently went to sleep getting woken up first. When the pool -// is not under load, this helps threads shutdown faster. -// -// Sleeping is done by using `tokio_executor::Park` implementations. This allows -// the user of the thread pool to customize the work that is performed to sleep. -// This is how injecting timers and other functionality into the thread pool is -// done. -// -// [1]: https://en.wikipedia.org/wiki/Treiber_Stack -// -// # Notifying workers -// -// When there is work to be done, workers must be notified. However, notifying a -// worker requires cross thread coordination. Ideally, a worker would only be -// notified when it is sleeping, but there is no way to know if a worker is -// sleeping without cross thread communication. -// -// The two cases when a worker might need to be notified are: -// -// 1) A task is externally submitted to a worker via the mpsc channel. -// 2) A worker has a back log of work and needs other workers to steal from it. -// -// In the first case, the worker will always be notified. However, it could be -// possible to avoid the notification if the mpsc channel has two or greater -// number of tasks *after* the task is submitted. In this case, we are able to -// assume that the worker has previously been notified. -// -// The second case is trickier. Currently, whenever a worker spawns a new future -// (pushing it onto its deque) and when it pops a future from its mpsc, it tries -// to notify a sleeping worker to wake up and start stealing. This is a lot of -// notification and it **might** be possible to reduce it. -// -// Also, whenever a worker is woken up via a signal and it does find work, it, -// in turn, will try to wake up a new worker. -// -// # `blocking` -// -// The strategy for handling blocking closures is to hand off the worker to a -// new thread. This implies handing off the `deque` and `mpsc`. Once this is -// done, the new thread continues to process the work queue and the original -// thread is able to block. Once it finishes processing the blocking future, the -// thread has no additional work and is inserted into the backup pool. This -// makes it available to other workers that encounter a `blocking` call. +//! A work-stealing based thread pool for executing futures. +//! +//! The Tokio thread pool supports scheduling futures and processing them on +//! multiple CPU cores. It is optimized for the primary Tokio use case of many +//! independent tasks with limited computation and with most tasks waiting on +//! I/O. Usually, users will not create a `ThreadPool` instance directly, but +//! will use one via a [`runtime`]. +//! +//! The `TheadPool` structure manages two sets of threads: +//! +//! * Worker threads. +//! * Backup threads. +//! +//! Worker threads are used to schedule futures using a work-stealing strategy. +//! Backup threads, on the other hand, are intended only to support the +//! `blocking` API. Threads will transition between the two sets. +//! +//! The advantage of the work-stealing strategy is minimal cross-thread +//! coordination. The thread pool attempts to make as much progress as possible +//! without communicating across threads. +//! +//! ## Worker overview +//! +//! Each worker has two queues: a deque and a mpsc channel. The deque is the +//! primary queue for tasks that are scheduled to run on the worker thread. Tasks +//! can only be pushed onto the deque by the worker, but other workers may +//! "steal" from that deque. The mpsc channel is used to submit futures while +//! external to the pool. +//! +//! As long as the thread pool has not been shutdown, a worker will run in a +//! loop. Each loop, it consumes all tasks on its mpsc channel and pushes it onto +//! the deque. It then pops tasks off of the deque and executes them. +//! +//! If a worker has no work, i.e., both queues are empty. It attempts to steal. +//! To do this, it randomly scans other workers' deques and tries to pop a task. +//! If it finds no work to steal, the thread goes to sleep. +//! +//! When the worker detects that the pool has been shut down, it exits the loop, +//! cleans up its state, and shuts the thread down. +//! +//! ## Thread pool initialization +//! +//! Note, users normally will use the threadpool created by a [`runtime`]. +//! +//! By default, no threads are spawned on creation. Instead, when new futures are +//! spawned, the pool first checks if there are enough active worker threads. If +//! not, a new worker thread is spawned. +//! +//! ## Spawning futures +//! +//! The spawning behavior depends on whether a future was spawned from within a +//! worker or thread or if it was spawned from an external handle. +//! +//! When spawning a future while external to the thread pool, the current +//! strategy is to randomly pick a worker to submit the task to. The task is then +//! pushed onto that worker's mpsc channel. +//! +//! When spawning a future while on a worker thread, the task is pushed onto the +//! back of the current worker's deque. +//! +//! ## Blocking annotation strategy +//! +//! The [`blocking`] function is used to annotate a section of code that +//! performs a blocking operation, either by issuing a blocking syscall or +//! performing any long running CPU-bound computation. +//! +//! The strategy for handling blocking closures is to hand off the worker to a +//! new thread. This implies handing off the `deque` and `mpsc`. Once this is +//! done, the new thread continues to process the work queue and the original +//! thread is able to block. Once it finishes processing the blocking future, the +//! thread has no additional work and is inserted into the backup pool. This +//! makes it available to other workers that encounter a [`blocking`] call. +//! +//! [`blocking`]: fn.blocking.html +//! [`runtime`]: https://docs.rs/tokio/0.1/tokio/runtime/ extern crate tokio_executor; @@ -128,6 +92,56 @@ extern crate log; #[cfg(feature = "unstable-futures")] extern crate futures2; +// ## Crate layout +// +// The primary type, `Pool`, holds the majority of a thread pool's state, +// including the state for each worker. Each worker's state is maintained in an +// instance of `worker::Entry`. +// +// `Worker` contains the logic that runs on each worker thread. It holds an +// `Arc` to `Pool` and is able to access its state from `Pool`. +// +// `Task` is a harness around an individual future. It manages polling and +// scheduling that future. +// +// ## Sleeping workers +// +// Sleeping workers are tracked using a [treiber stack]. This results in the +// thread that most recently went to sleep getting woken up first. When the pool +// is not under load, this helps threads shutdown faster. +// +// Sleeping is done by using `tokio_executor::Park` implementations. This allows +// the user of the thread pool to customize the work that is performed to sleep. +// This is how injecting timers and other functionality into the thread pool is +// done. +// +// ## Notifying workers +// +// When there is work to be done, workers must be notified. However, notifying a +// worker requires cross thread coordination. Ideally, a worker would only be +// notified when it is sleeping, but there is no way to know if a worker is +// sleeping without cross thread communication. +// +// The two cases when a worker might need to be notified are: +// +// 1. A task is externally submitted to a worker via the mpsc channel. +// 2. A worker has a back log of work and needs other workers to steal from it. +// +// In the first case, the worker will always be notified. However, it could be +// possible to avoid the notification if the mpsc channel has two or greater +// number of tasks *after* the task is submitted. In this case, we are able to +// assume that the worker has previously been notified. +// +// The second case is trickier. Currently, whenever a worker spawns a new future +// (pushing it onto its deque) and when it pops a future from its mpsc, it tries +// to notify a sleeping worker to wake up and start stealing. This is a lot of +// notification and it **might** be possible to reduce it. +// +// Also, whenever a worker is woken up via a signal and it does find work, it, +// in turn, will try to wake up a new worker. +// +// [treiber stack]: https://en.wikipedia.org/wiki/Treiber_Stack + pub mod park; mod blocking; diff --git a/tokio-timer/src/timer/handle.rs b/tokio-timer/src/timer/handle.rs index a09779483..d06ece1f2 100644 --- a/tokio-timer/src/timer/handle.rs +++ b/tokio-timer/src/timer/handle.rs @@ -33,6 +33,7 @@ thread_local!(static CURRENT_TIMER: RefCell> = RefCell::new(None) /// This function panics if there already is a default timer set. /// /// [`Delay`]: ../struct.Delay.html +/// [`Delay::new`]: ../struct.Delay.html#method.new pub fn with_default(handle: &Handle, enter: &mut Enter, f: F) -> R where F: FnOnce(&mut Enter) -> R { diff --git a/tokio-timer/src/timer/mod.rs b/tokio-timer/src/timer/mod.rs index 9043d476e..d9501a7c5 100644 --- a/tokio-timer/src/timer/mod.rs +++ b/tokio-timer/src/timer/mod.rs @@ -26,6 +26,7 @@ //! [`Delay`]: ../struct.Delay.html //! [`Now`]: trait.Now.html //! [`Now::now`]: trait.Now.html#method.now +//! [`SystemNow`]: struct.SystemNow.html // This allows the usage of the old `Now` trait. #![allow(deprecated)]