mirror of
https://github.com/tokio-rs/tokio.git
synced 2026-09-07 00:00:08 +02:00
task: move blocking fns into tokio::task (#1781)
This commit is contained in:
@@ -1,65 +1,7 @@
|
|||||||
//! Perform blocking operations from an asynchronous context.
|
//! Perform blocking operations from an asynchronous context.
|
||||||
|
|
||||||
mod pool;
|
mod pool;
|
||||||
pub(crate) use self::pool::{BlockingPool, Spawner};
|
pub(crate) use self::pool::{spawn_blocking, BlockingPool, Spawner};
|
||||||
|
|
||||||
mod schedule;
|
mod schedule;
|
||||||
mod task;
|
mod task;
|
||||||
|
|
||||||
use crate::task::JoinHandle;
|
|
||||||
|
|
||||||
/// Run the provided blocking function 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.
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// # async fn docs() {
|
|
||||||
/// tokio::blocking::in_place(move || {
|
|
||||||
/// // do some compute-heavy work or call synchronous code
|
|
||||||
/// });
|
|
||||||
/// # }
|
|
||||||
/// ```
|
|
||||||
#[cfg(feature = "rt-full")]
|
|
||||||
pub fn in_place<F, R>(f: F) -> R
|
|
||||||
where
|
|
||||||
F: FnOnce() -> R,
|
|
||||||
{
|
|
||||||
use crate::runtime::{enter, thread_pool};
|
|
||||||
|
|
||||||
enter::exit(|| thread_pool::block_in_place(f))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Run the provided closure on a thread where blocking is acceptable.
|
|
||||||
///
|
|
||||||
/// 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.
|
|
||||||
/// A closure that is run through this method will instead be run on a dedicated thread pool for
|
|
||||||
/// such blocking tasks without holding up the main futures executor.
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// # async fn docs() -> Result<(), Box<dyn std::error::Error>>{
|
|
||||||
/// let res = tokio::blocking::spawn_blocking(move || {
|
|
||||||
/// // do some compute-heavy work or call synchronous code
|
|
||||||
/// "done computing"
|
|
||||||
/// }).await?;
|
|
||||||
///
|
|
||||||
/// assert_eq!(res, "done computing");
|
|
||||||
/// # Ok(())
|
|
||||||
/// # }
|
|
||||||
/// ```
|
|
||||||
pub fn spawn_blocking<F, R>(f: F) -> JoinHandle<R>
|
|
||||||
where
|
|
||||||
F: FnOnce() -> R + Send + 'static,
|
|
||||||
R: Send + 'static,
|
|
||||||
{
|
|
||||||
pool::spawn(f)
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ const MAX_THREADS: u32 = 1_000;
|
|||||||
const KEEP_ALIVE: Duration = Duration::from_secs(10);
|
const KEEP_ALIVE: Duration = Duration::from_secs(10);
|
||||||
|
|
||||||
/// Run the provided function on an executor dedicated to blocking operations.
|
/// Run the provided function on an executor dedicated to blocking operations.
|
||||||
pub(super) fn spawn<F, R>(func: F) -> JoinHandle<R>
|
pub(crate) fn spawn_blocking<F, R>(func: F) -> JoinHandle<R>
|
||||||
where
|
where
|
||||||
F: FnOnce() -> R + Send + 'static,
|
F: FnOnce() -> R + Send + 'static,
|
||||||
{
|
{
|
||||||
|
|||||||
+1
-1
@@ -90,7 +90,7 @@ macro_rules! ready {
|
|||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
#[cfg(feature = "blocking")]
|
#[cfg(feature = "blocking")]
|
||||||
pub mod blocking;
|
pub(crate) mod blocking;
|
||||||
|
|
||||||
#[cfg(feature = "fs")]
|
#[cfg(feature = "fs")]
|
||||||
pub mod fs;
|
pub mod fs;
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ fn only_blocking() {
|
|||||||
let (block_tx, block_rx) = oneshot::channel();
|
let (block_tx, block_rx) = oneshot::channel();
|
||||||
|
|
||||||
pool.spawn(async move {
|
pool.spawn(async move {
|
||||||
crate::blocking::in_place(move || {
|
crate::task::block_in_place(move || {
|
||||||
block_tx.send(());
|
block_tx.send(());
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
@@ -72,7 +72,7 @@ fn blocking_and_regular() {
|
|||||||
let done_tx = Arc::new(Mutex::new(Some(done_tx)));
|
let done_tx = Arc::new(Mutex::new(Some(done_tx)));
|
||||||
|
|
||||||
pool.spawn(async move {
|
pool.spawn(async move {
|
||||||
crate::blocking::in_place(move || {
|
crate::task::block_in_place(move || {
|
||||||
block_tx.send(());
|
block_tx.send(());
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,62 @@
|
|||||||
|
use crate::blocking;
|
||||||
|
use crate::task::JoinHandle;
|
||||||
|
|
||||||
|
/// Run the provided blocking function 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.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use tokio::task;
|
||||||
|
///
|
||||||
|
/// # async fn docs() {
|
||||||
|
/// task::block_in_place(move || {
|
||||||
|
/// // do some compute-heavy work or call synchronous code
|
||||||
|
/// });
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
|
#[cfg(feature = "rt-full")]
|
||||||
|
pub fn block_in_place<F, R>(f: F) -> R
|
||||||
|
where
|
||||||
|
F: FnOnce() -> R,
|
||||||
|
{
|
||||||
|
use crate::runtime::{enter, thread_pool};
|
||||||
|
|
||||||
|
enter::exit(|| thread_pool::block_in_place(f))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Run the provided closure on a thread where blocking is acceptable.
|
||||||
|
///
|
||||||
|
/// 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.
|
||||||
|
/// A closure that is run through this method will instead be run on a dedicated thread pool for
|
||||||
|
/// such blocking tasks without holding up the main futures executor.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use tokio::task;
|
||||||
|
///
|
||||||
|
/// # async fn docs() -> Result<(), Box<dyn std::error::Error>>{
|
||||||
|
/// let res = task::spawn_blocking(move || {
|
||||||
|
/// // do some compute-heavy work or call synchronous code
|
||||||
|
/// "done computing"
|
||||||
|
/// }).await?;
|
||||||
|
///
|
||||||
|
/// assert_eq!(res, "done computing");
|
||||||
|
/// # Ok(())
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
|
pub fn spawn_blocking<F, R>(f: F) -> JoinHandle<R>
|
||||||
|
where
|
||||||
|
F: FnOnce() -> R + Send + 'static,
|
||||||
|
R: Send + 'static,
|
||||||
|
{
|
||||||
|
blocking::spawn_blocking(f)
|
||||||
|
}
|
||||||
@@ -1,5 +1,12 @@
|
|||||||
//! Asynchronous green-threads.
|
//! Asynchronous green-threads.
|
||||||
|
|
||||||
|
#[cfg(feature = "blocking")]
|
||||||
|
mod blocking;
|
||||||
|
#[cfg(feature = "rt-full")]
|
||||||
|
pub use blocking::block_in_place;
|
||||||
|
#[cfg(feature = "blocking")]
|
||||||
|
pub use blocking::spawn_blocking;
|
||||||
|
|
||||||
mod core;
|
mod core;
|
||||||
use self::core::Cell;
|
use self::core::Cell;
|
||||||
pub(crate) use self::core::Header;
|
pub(crate) use self::core::Header;
|
||||||
|
|||||||
@@ -268,7 +268,7 @@ fn blocking() {
|
|||||||
for _ in 0..4 {
|
for _ in 0..4 {
|
||||||
let block = block.clone();
|
let block = block.clone();
|
||||||
rt.spawn(async move {
|
rt.spawn(async move {
|
||||||
tokio::blocking::in_place(move || {
|
tokio::task::block_in_place(move || {
|
||||||
block.wait();
|
block.wait();
|
||||||
block.wait();
|
block.wait();
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user