tokio-rs / tokio

A runtime for writing reliable asynchronous applications with Rust. Provides I/O, networking, scheduling, timers, ...
https://tokio.rs
MIT License
26.47k stars 2.44k forks source link

API proposal: `tokio::task::try_spawn_blocking` #4955

Open lkts opened 2 years ago

lkts commented 2 years ago

Is your feature request related to a problem? Please describe. Currently spawn_blocking queues tasks if there is no free threads to execute it in blocking thread pool. This behavior may not be suitable for some applications:

Describe the solution you'd like I propose a try_spawn_blocking API.

pub fn try_spawn_blocking<F, R>(f: F) -> Result<JoinHandle<R>, NoAvailableThreads>
where
    F: FnOnce() -> R + Send + 'static,
    R: Send + 'static 
{
}

struct NoAvailableThreads {}

Alternatively (i don't know if it makes more sense implementation-wise but i suspect so) try_spawn_blocking can return a special BlockingTaskJoinHandle which will expose the error.

Describe alternatives you've considered Having a semaphore-based limiter on top of Tokio works well. Motivation for adding this API to Tokio is that:

ipetkov commented 2 years ago

Worth noting that with #4823 we have fallible spawn methods on task::Builder.

4850 is tracking its stabilization

hawkw commented 2 years ago

Yeah, since, as @ipetkov pointed out, the task::Builder API will have fallible spawn methods, I think the best way to add support for attempting to spawn a blocking task only if it wouldn't be queued is something like this:

task::Builder::new()
    .disable_blocking_queue() // name, obviously, subject to bikeshedding)
    .spawn_blocking(|| { /* ... */ }

and, we would add a QueueDisabled (again, name subject to bikeshedding) variant to SpawnError, here: https://github.com/tokio-rs/tokio/blob/cf181e8b1b29802cf9ef89d2777b653c04417351/tokio/src/runtime/blocking/pool.rs#L86-L92