From 70476f92772753a7964a4a64804fab44f8ad1f00 Mon Sep 17 00:00:00 2001 From: stefnotch Date: Mon, 14 Oct 2024 13:57:19 +0200 Subject: [PATCH] feat: add support for async-executor from smol-rs (#3090) --- any_spawner/Cargo.toml | 3 +++ any_spawner/src/lib.rs | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/any_spawner/Cargo.toml b/any_spawner/Cargo.toml index b18e25d095..bfaeb26208 100644 --- a/any_spawner/Cargo.toml +++ b/any_spawner/Cargo.toml @@ -9,6 +9,7 @@ description = "Spawn asynchronous tasks in an executor-independent way." edition.workspace = true [dependencies] +async-executor = { version = "1.13.1", optional = true } futures = "0.3.30" glib = { version = "0.20.0", optional = true } thiserror = "1.0" @@ -19,12 +20,14 @@ tracing = { version = "0.1.40", optional = true } wasm-bindgen-futures = { version = "0.4.42", optional = true } [features] +async-executor = ["dep:async-executor"] tracing = ["dep:tracing"] tokio = ["dep:tokio"] glib = ["dep:glib"] wasm-bindgen = ["dep:wasm-bindgen-futures"] futures-executor = ["futures/thread-pool", "futures/executor"] + [package.metadata.docs.rs] all-features = true rustdoc-args = ["--cfg", "docsrs"] diff --git a/any_spawner/src/lib.rs b/any_spawner/src/lib.rs index 297f9dccb0..758c5a4115 100644 --- a/any_spawner/src/lib.rs +++ b/any_spawner/src/lib.rs @@ -246,6 +246,44 @@ impl Executor { .map_err(|_| ExecutorError::AlreadySet)?; Ok(()) } + + /// Globally sets the [`async_executor`] executor as the executor used to spawn tasks, + /// lazily creating a thread pool to spawn tasks into. + /// + /// Returns `Err(_)` if an executor has already been set. + /// + /// Requires the `async-executor` feature to be activated on this crate. + #[cfg(feature = "async-executor")] + #[cfg_attr(docsrs, doc(cfg(feature = "async-executor")))] + pub fn init_async_executor() -> Result<(), ExecutorError> { + use async_executor::{Executor, LocalExecutor}; + + static THREAD_POOL: OnceLock = OnceLock::new(); + thread_local! { + static LOCAL_POOL: LocalExecutor<'static> = const { LocalExecutor::new() }; + } + + fn get_thread_pool() -> &'static Executor<'static> { + THREAD_POOL.get_or_init(Executor::new) + } + + SPAWN + .set(|fut| { + get_thread_pool().spawn(fut).detach(); + }) + .map_err(|_| ExecutorError::AlreadySet)?; + SPAWN_LOCAL + .set(|fut| { + LOCAL_POOL.with(|pool| pool.spawn(fut).detach()); + }) + .map_err(|_| ExecutorError::AlreadySet)?; + POLL_LOCAL + .set(|| { + LOCAL_POOL.with(|pool| pool.try_tick()); + }) + .map_err(|_| ExecutorError::AlreadySet)?; + Ok(()) + } } #[cfg(test)]