From 17d8c2b29d94550f504d8fd76d8d8aaf66095864 Mon Sep 17 00:00:00 2001 From: Alice Ryhl Date: Tue, 20 May 2025 18:37:41 +0100 Subject: [PATCH] runtime: various minor `LocalRuntime` improvements (#7346) --- tokio/src/runtime/builder.rs | 23 ++++++++++++--------- tokio/src/runtime/local_runtime/options.rs | 8 +++++++- tokio/src/runtime/local_runtime/runtime.rs | 2 +- tokio/tests/async_send_sync.rs | 8 ++++++++ tokio/tests/rt_local.rs | 24 ++++++++++++++++++++-- 5 files changed, 51 insertions(+), 14 deletions(-) diff --git a/tokio/src/runtime/builder.rs b/tokio/src/runtime/builder.rs index 93c67c5b5..a0207b3a0 100644 --- a/tokio/src/runtime/builder.rs +++ b/tokio/src/runtime/builder.rs @@ -895,34 +895,37 @@ impl Builder { } } - /// Creates the configured `LocalRuntime`. + /// Creates the configured [`LocalRuntime`]. /// - /// The returned `LocalRuntime` instance is ready to spawn tasks. + /// The returned [`LocalRuntime`] instance is ready to spawn tasks. /// /// # Panics - /// This will panic if `current_thread` is not the selected runtime flavor. - /// All other runtime flavors are unsupported by [`LocalRuntime`]. /// - /// [`LocalRuntime`]: [crate::runtime::LocalRuntime] + /// This will panic if the runtime is configured with [`new_multi_thread()`]. + /// + /// [`new_multi_thread()`]: Builder::new_multi_thread /// /// # Examples /// /// ``` - /// use tokio::runtime::Builder; + /// use tokio::runtime::{Builder, LocalOptions}; /// - /// let rt = Builder::new_current_thread().build_local(&mut Default::default()).unwrap(); + /// let rt = Builder::new_current_thread() + /// .build_local(LocalOptions::default()) + /// .unwrap(); /// - /// rt.block_on(async { + /// rt.spawn_local(async { /// println!("Hello from the Tokio runtime"); /// }); /// ``` #[allow(unused_variables, unreachable_patterns)] #[cfg(tokio_unstable)] #[cfg_attr(docsrs, doc(cfg(tokio_unstable)))] - pub fn build_local(&mut self, options: &LocalOptions) -> io::Result { + pub fn build_local(&mut self, options: LocalOptions) -> io::Result { match &self.kind { Kind::CurrentThread => self.build_current_thread_local_runtime(), - _ => panic!("Only current_thread is supported when building a local runtime"), + #[cfg(feature = "rt-multi-thread")] + Kind::MultiThread => panic!("multi_thread is not supported for LocalRuntime"), } } diff --git a/tokio/src/runtime/local_runtime/options.rs b/tokio/src/runtime/local_runtime/options.rs index ed25d9ccd..ef276e2c9 100644 --- a/tokio/src/runtime/local_runtime/options.rs +++ b/tokio/src/runtime/local_runtime/options.rs @@ -1,9 +1,15 @@ use std::marker::PhantomData; -/// `LocalRuntime`-only config options +/// [`LocalRuntime`]-only config options /// /// Currently, there are no such options, but in the future, things like `!Send + !Sync` hooks may /// be added. +/// +/// Use `LocalOptions::default()` to create the default set of options. This type is used with +/// [`Builder::build_local`]. +/// +/// [`Builder::build_local`]: crate::runtime::Builder::build_local +/// [`LocalRuntime`]: crate::runtime::LocalRuntime #[derive(Default, Debug)] #[non_exhaustive] pub struct LocalOptions { diff --git a/tokio/src/runtime/local_runtime/runtime.rs b/tokio/src/runtime/local_runtime/runtime.rs index 358a77195..c0cb327f2 100644 --- a/tokio/src/runtime/local_runtime/runtime.rs +++ b/tokio/src/runtime/local_runtime/runtime.rs @@ -92,7 +92,7 @@ impl LocalRuntime { pub fn new() -> std::io::Result { Builder::new_current_thread() .enable_all() - .build_local(&Default::default()) + .build_local(Default::default()) } /// Returns a handle to the runtime's spawner. diff --git a/tokio/tests/async_send_sync.rs b/tokio/tests/async_send_sync.rs index 4c291b3cc..aa668ce93 100644 --- a/tokio/tests/async_send_sync.rs +++ b/tokio/tests/async_send_sync.rs @@ -760,3 +760,11 @@ mod unix_asyncfd { async_assert_fn!(AsyncFd>::writable(_): !Send & !Sync & !Unpin); async_assert_fn!(AsyncFd>::writable_mut(_): !Send & !Sync & !Unpin); } + +#[cfg(tokio_unstable)] +mod unstable { + use super::*; + + assert_value!(tokio::runtime::LocalRuntime: !Send & !Sync & Unpin); + assert_value!(tokio::runtime::LocalOptions: !Send & !Sync & Unpin); +} diff --git a/tokio/tests/rt_local.rs b/tokio/tests/rt_local.rs index 5d276250b..4eb88d48a 100644 --- a/tokio/tests/rt_local.rs +++ b/tokio/tests/rt_local.rs @@ -73,7 +73,27 @@ fn test_spawn_local_from_guard() { } #[test] -#[should_panic] +#[cfg_attr(target_family = "wasm", ignore)] // threads not supported +fn test_spawn_from_guard_other_thread() { + let (tx, rx) = std::sync::mpsc::channel(); + + std::thread::spawn(move || { + let rt = rt(); + let handle = rt.handle().clone(); + + tx.send(handle).unwrap(); + }); + + let handle = rx.recv().unwrap(); + + let _guard = handle.enter(); + + tokio::spawn(async {}); +} + +#[test] +#[should_panic = "Local tasks can only be spawned on a LocalRuntime from the thread the runtime was created on"] +#[cfg_attr(target_family = "wasm", ignore)] // threads not supported fn test_spawn_local_from_guard_other_thread() { let (tx, rx) = std::sync::mpsc::channel(); @@ -94,6 +114,6 @@ fn test_spawn_local_from_guard_other_thread() { fn rt() -> tokio::runtime::LocalRuntime { tokio::runtime::Builder::new_current_thread() .enable_all() - .build_local(&LocalOptions::default()) + .build_local(LocalOptions::default()) .unwrap() }