//! An example on how to build a multi-thread tokio runtime for Actix System. //! Then spawn async task that can make use of work stealing of tokio runtime. use actix_rt::System; fn main() { System::with_tokio_rt(|| { // this cfg is needed when use it with io-uring, if you don't use io-uring // you can remove this cfg and last line in this closure #[cfg(not(feature = "io-uring"))] { // build system with a multi-thread tokio runtime. tokio::runtime::Builder::new_multi_thread() .worker_threads(2) .enable_all() .build() .unwrap() } // you can remove this two lines if you don't have tokio_uring feature enabled. // Note: tokio_uring is single thread and can't be multithreaded, // unless you spawn multiple of them #[cfg(feature = "io-uring")] tokio_uring::Runtime::new(&tokio_uring::builder()).unwrap() }) .block_on(async_main()); } // async main function that acts like #[actix_web::main] or #[tokio::main] async fn async_main() { let (tx, rx) = tokio::sync::oneshot::channel(); // get a handle to system arbiter and spawn async task on it System::current().arbiter().spawn(async { // use tokio::spawn to get inside the context of multi thread tokio runtime let h1 = tokio::spawn(async { println!("thread id is {:?}", std::thread::current().id()); std::thread::sleep(std::time::Duration::from_secs(2)); }); // work stealing occurs for this task spawn let h2 = tokio::spawn(async { println!("thread id is {:?}", std::thread::current().id()); }); h1.await.unwrap(); h2.await.unwrap(); let _ = tx.send(()); }); rx.await.unwrap(); let (tx, rx) = tokio::sync::oneshot::channel(); let now = std::time::Instant::now(); // without additional tokio::spawn, all spawned tasks run on single thread System::current().arbiter().spawn(async { println!("thread id is {:?}", std::thread::current().id()); std::thread::sleep(std::time::Duration::from_secs(2)); let _ = tx.send(()); }); // previous spawn task has blocked the system arbiter thread // so this task will wait for 2 seconds until it can be run System::current().arbiter().spawn(async move { println!("thread id is {:?}", std::thread::current().id()); assert!(now.elapsed() > std::time::Duration::from_secs(2)); }); rx.await.unwrap(); }