Spawning OS threads apparently works just fine from async
contexts. I was expecting there to be problems, similar to the way that invoking tokio
code outside the tokio
runtime results in spontaneous combustion or trying to create a Runtime
when you're already in a Runtime
tears a hole in the space time fabric.
fn get_runtime() -> tokio::runtime::Runtime { tokio::runtime::Builder::new_multi_thread() .enable_all() .build() .unwrap() } fn fun_with_explosives() { let rt = get_runtime(); rt.block_on(async { let inception = get_runtime(); rt.block_on(async { // TODO: add leonardo dicaprio implementation here }); }); }
But, no, apparently you can spawn threads just fine inside of the invisible walls of a Runtime
.
use tokio::sync::mpsc::{channel, Sender, Receiver}; fn get_runtime() -> tokio::runtime::Runtime { tokio::runtime::Builder::new_multi_thread() .enable_all() .build() .unwrap() } fn spawn_os_thread(tx: Sender<u64>) -> std::thread::JoinHandle<i32> { std::thread::spawn(move || { // do some work let mut x = 0u64; for i in 0..(1024 * 1024) { x += i; } // inside the thread, create another rt and use it // to execute async code let rt = get_runtime(); // send our message via an async channel using our new rt rt.block_on(async { tx.send(x) .await .expect("tx.send failed"); }); 123 }) } async fn f() { let (tx, mut rx) = channel(4); let thread = spawn_os_thread(tx); // await on message sent from os thread dbg!(rx.recv().await); // then also join the os thread dbg!(thread.join()); // tada } fn main() { let rt = get_runtime(); rt.block_on(f()); }
Playground results:
Compiling playground v0.0.1 (/playground)
Finished dev [unoptimized + debuginfo] target(s) in 2.11s
Running `target/debug/playground`
[src/main.rs:45] rx.recv().await = Some(
549755289600,
)
[src/main.rs:48] thread.join() = Ok(
123,
)
Sorry ... I just didn't expect that experiment to actually work.