diff options
author | Alice Ryhl <alice@ryhl.io> | 2020-04-24 16:16:46 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-04-24 10:16:46 -0400 |
commit | 3572ba5a7b15b83a4b25b21395e85425622ec0e6 (patch) | |
tree | c35268169ea185a9c2eac90e73c85a79c5dd3829 /tokio/src/task | |
parent | d8139fef7a555f99adaa37e139787d26e24daba3 (diff) |
task: update doc on spawn_blocking and block_in_place (#2436)
Diffstat (limited to 'tokio/src/task')
-rw-r--r-- | tokio/src/task/blocking.rs | 73 |
1 files changed, 62 insertions, 11 deletions
diff --git a/tokio/src/task/blocking.rs b/tokio/src/task/blocking.rs index f9be1ead..0ef60535 100644 --- a/tokio/src/task/blocking.rs +++ b/tokio/src/task/blocking.rs @@ -1,20 +1,37 @@ use crate::task::JoinHandle; cfg_rt_threaded! { - /// Runs the provided blocking function without blocking the executor. + /// Runs the provided blocking function on the current thread without + /// blocking the executor. /// /// In general, issuing a blocking call or performing a lot of compute in a /// future without yielding is not okay, as it may prevent the executor from - /// driving other futures forward. If you run a closure through this method, - /// the current executor thread will relegate all its executor duties to another - /// (possibly new) thread, and only then poll the task. Note that this requires - /// additional synchronization. + /// driving other futures forward. This function runs the closure on the + /// current thread by having the thread temporarily cease from being a core + /// thread, and turns it into a blocking thread. See the [CPU-bound tasks + /// and blocking code][blocking] section for more information. /// - /// # Note + /// Although this function avoids starving other independently spawned + /// tasks, any other code running concurrently in the same task will be + /// suspended during the call to `block_in_place`. This can happen e.g. when + /// using the [`join!`] macro. To avoid this issue, use [`spawn_blocking`] + /// instead. /// - /// This function can only be called from a spawned task when working with - /// the [threaded scheduler](https://docs.rs/tokio/0.2.10/tokio/runtime/index.html#threaded-scheduler). - /// Consider using [tokio::task::spawn_blocking](https://docs.rs/tokio/0.2.10/tokio/task/fn.spawn_blocking.html). + /// Note that this function can only be used on the [threaded scheduler]. + /// + /// Code running behind `block_in_place` cannot be cancelled. When you shut + /// down the executor, it will wait indefinitely for all blocking operations + /// to finish. You can use [`shutdown_timeout`] to stop waiting for them + /// after a certain timeout. Be aware that this will still not cancel the + /// tasks — they are simply allowed to keep running after the method + /// returns. + /// + /// [blocking]: ../index.html#cpu-bound-tasks-and-blocking-code + /// [threaded scheduler]: fn@crate::runtime::Builder::threaded_scheduler + /// [`spawn_blocking`]: fn@crate::task::spawn_blocking + /// [`join!`]: ../macro.join.html + /// [`thread::spawn`]: fn@std::thread::spawn + /// [`shutdown_timeout`]: fn@crate::runtime::Runtime::shutdown_timeout /// /// # Examples /// @@ -39,9 +56,43 @@ cfg_rt_threaded! { cfg_blocking! { /// Runs the provided closure on a thread where blocking is acceptable. /// - /// More information about the blocking threads is available at [CPU-bound tasks and blocking code][blocking]. + /// In general, issuing a blocking call or performing a lot of compute in a + /// future without yielding is not okay, as it may prevent the executor from + /// driving other futures forward. This function runs the provided closure + /// on a thread dedicated to blocking operations. See the [CPU-bound tasks + /// and blocking code][blocking] section for more information. + /// + /// Tokio will spawn more blocking threads when they are requested through + /// this function until the upper limit configured on the [`Builder`] is + /// reached. This limit is very large by default, because `spawn_blocking` is + /// often used for various kinds of IO operations that cannot be performed + /// asynchronously. When you run CPU-bound code using `spawn_blocking`, you + /// should keep this large upper limit in mind; to run your CPU-bound + /// computations on only a few threads, you should use a separate thread + /// pool such as [rayon] rather than configuring the number of blocking + /// threads. + /// + /// This function is intended for non-async operations that eventually + /// finish on their own. If you want to spawn an ordinary thread, you should + /// use [`thread::spawn`] instead. + /// + /// Closures spawned using `spawn_blocking` cannot be cancelled. When you + /// shut down the executor, it will wait indefinitely for all blocking + /// operations to finish. You can use [`shutdown_timeout`] to stop waiting + /// for them after a certain timeout. Be aware that this will still not + /// cancel the tasks — they are simply allowed to keep running after the + /// method returns. + /// + /// Note that if you are using the [basic scheduler], this function will + /// still spawn additional threads for blocking operations. The basic + /// scheduler's single thread is only used for asynchronous code. /// - /// [blocking]: ../index.html#cpu-bound-tasks-and-blocking-code + /// [`Builder`]: struct@crate::runtime::Builder + /// [blocking]: ../index.html#cpu-bound-tasks-and-blocking-code + /// [rayon]: https://docs.rs/rayon + /// [basic scheduler]: fn@crate::runtime::Builder::basic_scheduler + /// [`thread::spawn`]: fn@std::thread::spawn + /// [`shutdown_timeout`]: fn@crate::runtime::Runtime::shutdown_timeout /// /// # Examples /// |