Should JoinHandle<T> (from std::thread) implement Future?

I think it would sense for std::thread::JoinHandle to implement Future because it would simplify the interaction between async code and threading.

For example, this would be valid:

/// Do some tough problem without blocking the threadpool.
async fn do_something_expensive() -> Result<HardToComputeValue, Error> {
    thread::spawn(|| {
        // do something difficult ...
    }?.await;
}
1 Like

Although it does not do exactly what you mean, ::tokio_threadpool::blocking() offers functionality for a very similar need (the difference being in how and for what purpose the additional thread is spawned).

1 Like

This wouldn’t work in an efficient fashion since JoinHandle only supports a blocking wait. Which would mean the whole executor gets blocked until the thread finished when await is called.

To fix this JoinHandle and spawn() need to be changed to be able to interact with Wakers. That is extra overhead that isn’t required for projects which don’t use Futures.

Apart from that runtimes will also offer threadpools which offer the functionality you like to see. So there is no strong need to have this on the general purpose std::thread

3 Likes

Yeah, you can't do that because there is no async join API in pthreads.

You could maybe implement it using the pidfd API plus an epoll reactor in Linux, but it's not very efficient since it requires unnecessary system calls and also only works on recent Linux kernels and not portable to other POSIX systems.

Instead, create a oneshot future and have the spawned thread complete it, like this

let (c, p) = oneshot();

thread::spawn(|| {
    [...]
    c.complete(());
})?;

p.await