From a53f94ab61184be1fcd128da0f15a43ad30259e4 Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Fri, 6 Dec 2019 13:10:18 -0800 Subject: [PATCH] doc: expand on runtime / spawn docs (#1914) --- tokio/src/runtime/mod.rs | 10 ++++++ tokio/src/task/spawn.rs | 73 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) diff --git a/tokio/src/runtime/mod.rs b/tokio/src/runtime/mod.rs index 45c2bd5e3..9fb57e14a 100644 --- a/tokio/src/runtime/mod.rs +++ b/tokio/src/runtime/mod.rs @@ -161,6 +161,16 @@ //! This is done with [`Builder::enable_io`] and [`Builder::enable_time`]. As a //! shorthand, [`Builder::enable_all`] enables both resource drivers. //! +//! ## Lifetime of spawned threads +//! +//! The runtime may spawn threads depending on its configuration and usage. The +//! threaded scheduler spawns threads to schedule tasks and calls to +//! `spawn_blocking` spawn threads to run blocking operations. +//! +//! While the `Runtime` is active, threads may shutdown after periods of being +//! idle. Once `Runtime` is dropped, all runtime threads are forcibly shutdown. +//! Any tasks that have not yet completed will be dropped. +//! //! [tasks]: crate::task //! [driver]: crate::io::driver //! [executor]: https://tokio.rs/docs/internals/runtime-model/#executors diff --git a/tokio/src/task/spawn.rs b/tokio/src/task/spawn.rs index ab1356c80..131fca5b3 100644 --- a/tokio/src/task/spawn.rs +++ b/tokio/src/task/spawn.rs @@ -12,6 +12,10 @@ doc_rt_core! { /// different thread to be executed. The specifics depend on the current /// [`Runtime`](crate::runtime::Runtime) configuration. /// + /// There is no guarantee that a spawned task will execute to completion. + /// When a runtime is shutdown, all outstanding tasks are dropped, + /// regardless of the lifecycle of that task. + /// /// # Examples /// /// In this example, a server is started and `spawn` is used to start a new task @@ -45,6 +49,75 @@ doc_rt_core! { /// # Panics /// /// Panics if called from **outside** of the Tokio runtime. + /// + /// # Using `!Send` values from a task + /// + /// The task supplied to `spawn` must implement `!Send`. However, it is + /// possible to **use** `!Send` values from the task as long as they only + /// exist between calls to `.await`. + /// + /// For example, this will work: + /// + /// ``` + /// use tokio::task; + /// + /// use std::rc::Rc; + /// + /// fn use_rc(rc: Rc<()>) { + /// // Do stuff w/ rc + /// # drop(rc); + /// } + /// + /// #[tokio::main] + /// async fn main() { + /// tokio::spawn(async { + /// // Force the `Rc` to stay in a scope with no `.await` + /// { + /// let rc = Rc::new(()); + /// use_rc(rc.clone()); + /// } + /// + /// task::yield_now().await; + /// }).await.unwrap(); + /// } + /// ``` + /// + /// This will **not** work: + /// + /// ```compile_fail + /// use tokio::task; + /// + /// use std::rc::Rc; + /// + /// fn use_rc(rc: Rc<()>) { + /// // Do stuff w/ rc + /// # drop(rc); + /// } + /// + /// #[tokio::main] + /// async fn main() { + /// tokio::spawn(async { + /// let rc = Rc::new(()); + /// + /// task::yield_now().await; + /// + /// use_rc(rc.clone()); + /// }).await.unwrap(); + /// } + /// ``` + /// + /// Holding on to a `!Send` value across calls to `.await` will result in + /// an unfriendly compile error message similar to: + /// + /// ```text + /// `[... some type ...]` cannot be sent between threads safely + /// ``` + /// + /// or: + /// + /// ```text + /// error[E0391]: cycle detected when processing `main` + /// ``` pub fn spawn(task: T) -> JoinHandle where T: Future + Send + 'static,