Repository: tokio-rs/tokio
File: tokio/src/task/blocking.rs (Rust)

Code before:
    /// The thread 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. When running many CPU-bound
    /// computations, a semaphore or some other synchronization primitive should be
    /// used to limit the number of computation executed in parallel. Specialized
    /// CPU-bound executors, such as [rayon], may also be a good fit.
    ///
    /// 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.
    ///
    /// Be aware that tasks spawned using `spawn_blocking` cannot be aborted
    /// because they are not async. If you call [`abort`] on a `spawn_blocking`
    /// task, then this *will not have any effect*, and the task will continue
    /// running normally. The exception is if the task has not started running
    /// yet; in that case, calling `abort` may prevent the task from starting.
    ///
    /// When you shut down the executor, it will attempt to `abort` all tasks
    /// including `spawn_blocking` tasks. However, `spawn_blocking` tasks
    /// cannot be aborted once they start running, which means that runtime
    /// shutdown will wait indefinitely for all started `spawn_blocking` to
    /// finish running. 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.  It is possible for a blocking task to be cancelled if it has
    /// not yet started running, but this is not guaranteed.
    ///
    /// Note that if you are using the single threaded runtime, this function will
    /// still spawn additional threads for blocking operations. The current-thread
    /// scheduler's single thread is only used for asynchronous code.
    ///
    /// # Related APIs and patterns for bridging asynchronous and blocking code
    ///
    /// In simple cases, it is sufficient to have the closure accept input
    /// parameters at creation time and return a single value (or struct/tuple, etc.).
    ///
    /// For more complex situations in which it is desirable to stream data to or from
    /// the synchronous context, the [`mpsc channel`] has `blocking_send` and
    /// `blocking_recv` methods for use in non-async code such as the thread created
    /// by `spawn_blocking`.
    ///
    /// Another option is [`SyncIoBridge`] for cases where the synchronous context
    /// is operating on byte streams.  For example, you might use an asynchronous
    /// HTTP client such as [hyper] to fetch data, but perform complex parsing
    /// of the payload body using a library written for synchronous I/O.
    ///
    /// Finally, see also [Bridging with sync code][bridgesync] for discussions
    /// around the opposite case of using Tokio as part of a larger synchronous
    /// codebase.
    ///

Review comment (suggestion):
```suggestion
    /// returns. It is possible for a blocking task to be cancelled if it has
```

Code after:
    /// The thread 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. When running many CPU-bound
    /// computations, a semaphore or some other synchronization primitive should be
    /// used to limit the number of computation executed in parallel. Specialized
    /// CPU-bound executors, such as [rayon], may also be a good fit.
    ///
    /// 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.
    ///
    /// Be aware that tasks spawned using `spawn_blocking` cannot be aborted
    /// because they are not async. If you call [`abort`] on a `spawn_blocking`
    /// task, then this *will not have any effect*, and the task will continue
    /// running normally. The exception is if the task has not started running
    /// yet; in that case, calling `abort` may prevent the task from starting.
    ///
    /// When you shut down the executor, it will attempt to `abort` all tasks
    /// including `spawn_blocking` tasks. However, `spawn_blocking` tasks
    /// cannot be aborted once they start running, which means that runtime
    /// shutdown will wait indefinitely for all started `spawn_blocking` to
    /// finish running. 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. It is possible for a blocking task to be cancelled if it has
    /// not yet started running, but this is not guaranteed.
    ///
    /// Note that if you are using the single threaded runtime, this function will
    /// still spawn additional threads for blocking operations. The current-thread
    /// scheduler's single thread is only used for asynchronous code.
    ///
    /// # Related APIs and patterns for bridging asynchronous and blocking code
    ///
    /// In simple cases, it is sufficient to have the closure accept input
    /// parameters at creation time and return a single value (or struct/tuple, etc.).
    ///
    /// For more complex situations in which it is desirable to stream data to or from
    /// the synchronous context, the [`mpsc channel`] has `blocking_send` and
    /// `blocking_recv` methods for use in non-async code such as the thread created
    /// by `spawn_blocking`.
    ///
    /// Another option is [`SyncIoBridge`] for cases where the synchronous context
    /// is operating on byte streams.  For example, you might use an asynchronous
    /// HTTP client such as [hyper] to fetch data, but perform complex parsing
    /// of the payload body using a library written for synchronous I/O.
    ///
    /// Finally, see also [Bridging with sync code][bridgesync] for discussions
    /// around the opposite case of using Tokio as part of a larger synchronous
    /// codebase.
    ///