From b7bfff2b32ea867cd4a5689fc45db7cd6398234d Mon Sep 17 00:00:00 2001 From: fakeshadow <24548779@qq.com> Date: Wed, 24 Mar 2021 04:56:13 -0700 Subject: [PATCH] add example of using multi-thread tokio runtime (#294) * add example of using multi-thread tokio runtime * Update multi_thread_system.rs Co-authored-by: Rob Ede --- actix-rt/examples/multi_thread_system.rs | 60 ++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 actix-rt/examples/multi_thread_system.rs diff --git a/actix-rt/examples/multi_thread_system.rs b/actix-rt/examples/multi_thread_system.rs new file mode 100644 index 0000000000..0ecd1ef1a0 --- /dev/null +++ b/actix-rt/examples/multi_thread_system.rs @@ -0,0 +1,60 @@ +//! 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(|| { + // build system with a multi-thread tokio runtime. + tokio::runtime::Builder::new_multi_thread() + .worker_threads(2) + .enable_all() + .build() + .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(); +}