From 1bfc33b6539bdad68413e248ef41393c61a81c07 Mon Sep 17 00:00:00 2001 From: "ADOMAS BEKERAS (from Dev Box)" Date: Thu, 26 Mar 2026 14:12:49 +0100 Subject: [PATCH 01/11] Make Spawner usable without features --- crates/anyspawn/src/handle.rs | 6 ++++++ crates/anyspawn/src/lib.rs | 4 ---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/crates/anyspawn/src/handle.rs b/crates/anyspawn/src/handle.rs index b8a37e15..4b74133f 100644 --- a/crates/anyspawn/src/handle.rs +++ b/crates/anyspawn/src/handle.rs @@ -25,6 +25,11 @@ pub(crate) enum JoinHandleInner { Tokio(::tokio::task::JoinHandle), #[cfg(feature = "custom")] Custom(oneshot::Receiver), + #[expect( + dead_code, + reason = "Unconstructable variant so the type compiles when no runtime feature are enabled." + )] + None, } impl Future for JoinHandle { @@ -36,6 +41,7 @@ impl Future for JoinHandle { JoinHandleInner::Tokio(jh) => Pin::new(jh).poll(cx).map(|res| res.expect("spawned task panicked")), #[cfg(feature = "custom")] JoinHandleInner::Custom(rx) => Pin::new(rx).poll(cx).map(|res| res.expect("spawned task panicked")), + JoinHandleInner::None => unreachable!("JoinHandleInner::None can not be constructed"), } } } diff --git a/crates/anyspawn/src/lib.rs b/crates/anyspawn/src/lib.rs index 7da88418..0c58981b 100644 --- a/crates/anyspawn/src/lib.rs +++ b/crates/anyspawn/src/lib.rs @@ -64,16 +64,12 @@ mod builder; #[cfg(feature = "custom")] mod custom; -#[cfg(any(feature = "tokio", feature = "custom"))] mod handle; -#[cfg(any(feature = "tokio", feature = "custom"))] mod spawner; #[cfg(feature = "custom")] pub use builder::CustomSpawnerBuilder; #[cfg(feature = "custom")] pub use custom::BoxedFuture; -#[cfg(any(feature = "tokio", feature = "custom"))] pub use handle::JoinHandle; -#[cfg(any(feature = "tokio", feature = "custom"))] pub use spawner::Spawner; From 4684cada99883ddb76aa93debda5c3d228cd2ee8 Mon Sep 17 00:00:00 2001 From: "ADOMAS BEKERAS (from Dev Box)" Date: Thu, 26 Mar 2026 15:10:57 +0100 Subject: [PATCH 02/11] Clippy --- crates/anyspawn/src/handle.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/crates/anyspawn/src/handle.rs b/crates/anyspawn/src/handle.rs index 4b74133f..6c2547e0 100644 --- a/crates/anyspawn/src/handle.rs +++ b/crates/anyspawn/src/handle.rs @@ -29,19 +29,25 @@ pub(crate) enum JoinHandleInner { dead_code, reason = "Unconstructable variant so the type compiles when no runtime feature are enabled." )] - None, + #[cfg(not(any(feature = "custom", feature = "tokio")))] + None(std::marker::PhantomData T>), } impl Future for JoinHandle { type Output = T; + #[cfg_attr( + not(any(feature = "custom", feature = "tokio")), + expect(unused_variables, reason = "cx is unused depending on features") + )] fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { match &mut self.get_mut().0 { #[cfg(feature = "tokio")] JoinHandleInner::Tokio(jh) => Pin::new(jh).poll(cx).map(|res| res.expect("spawned task panicked")), #[cfg(feature = "custom")] JoinHandleInner::Custom(rx) => Pin::new(rx).poll(cx).map(|res| res.expect("spawned task panicked")), - JoinHandleInner::None => unreachable!("JoinHandleInner::None can not be constructed"), + #[cfg(not(any(feature = "custom", feature = "tokio")))] + JoinHandleInner::None(_) => unreachable!("JoinHandleInner::None can not be constructed"), } } } From af2ce27c129c3246047765ce30ef669e99203c1d Mon Sep 17 00:00:00 2001 From: "ADOMAS BEKERAS (from Dev Box)" Date: Thu, 26 Mar 2026 15:27:19 +0100 Subject: [PATCH 03/11] Fix --- crates/anyspawn/src/spawner.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/crates/anyspawn/src/spawner.rs b/crates/anyspawn/src/spawner.rs index 4f24f948..cf9f1a41 100644 --- a/crates/anyspawn/src/spawner.rs +++ b/crates/anyspawn/src/spawner.rs @@ -126,6 +126,8 @@ enum SpawnerKind { #[cfg(feature = "custom")] Custom(CustomSpawner), ThreadAware(thread_aware::Arc), + #[cfg(not(any(feature = "custom", feature = "tokio")))] + None, } impl Spawner { @@ -274,6 +276,8 @@ impl Spawner { #[cfg(feature = "custom")] SpawnerKind::Custom(c) => JoinHandle(JoinHandleInner::Custom(c.call(work))), SpawnerKind::ThreadAware(ta) => ta.spawn(work), + #[cfg(not(any(feature = "custom", feature = "tokio")))] + SpawnerKind::None => unreachable!("SpawnerKind::None cannot be constructed"), } } } @@ -286,6 +290,8 @@ impl Debug for Spawner { #[cfg(feature = "custom")] SpawnerKind::Custom(c) => f.debug_tuple("Spawner").field(c).finish(), SpawnerKind::ThreadAware(_) => f.debug_tuple("Spawner").field(&"thread_aware").finish(), + #[cfg(not(any(feature = "custom", feature = "tokio")))] + SpawnerKind::None => unreachable!("SpawnerKind::None cannot be constructed"), } } } From 5d622093a3fffdbb18796e9afa3ae2aeb7c59d1b Mon Sep 17 00:00:00 2001 From: "ADOMAS BEKERAS (from Dev Box)" Date: Thu, 26 Mar 2026 16:28:28 +0100 Subject: [PATCH 04/11] Disable default features --- Cargo.lock | 1 - crates/anyspawn/Cargo.toml | 15 +++++++++++++-- crates/anyspawn/tests/builder.rs | 1 - crates/anyspawn/tests/handle.rs | 2 -- crates/anyspawn/tests/spawner.rs | 7 ------- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index accadecc..7d55a430 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -83,7 +83,6 @@ dependencies = [ "smol", "static_assertions", "thread_aware", - "tick", "tokio", ] diff --git a/crates/anyspawn/Cargo.toml b/crates/anyspawn/Cargo.toml index 3ca632af..73582833 100644 --- a/crates/anyspawn/Cargo.toml +++ b/crates/anyspawn/Cargo.toml @@ -27,7 +27,7 @@ allowed_external_types = [ all-features = true [features] -default = ["tokio", "custom"] +default = [] tokio = ["dep:tokio"] custom = ["dep:futures-channel"] @@ -43,9 +43,20 @@ insta.workspace = true opentelemetry = { workspace = true, features = ["futures"] } smol = "2" static_assertions.workspace = true -tick = { workspace = true, features = ["tokio"] } tokio = { workspace = true, features = ["macros", "rt-multi-thread", "sync"] } +[[test]] +name = "spawner" +required-features = ["tokio", "custom"] + +[[test]] +name = "handle" +required-features = ["tokio"] + +[[test]] +name = "builder" +required-features = ["tokio", "custom"] + [[bench]] name = "spawner" harness = false diff --git a/crates/anyspawn/tests/builder.rs b/crates/anyspawn/tests/builder.rs index 31358f96..dafafeb6 100644 --- a/crates/anyspawn/tests/builder.rs +++ b/crates/anyspawn/tests/builder.rs @@ -2,7 +2,6 @@ // Licensed under the MIT License. #![allow(missing_docs, reason = "test code")] -#![cfg(all(feature = "tokio", feature = "custom"))] #![cfg(not(miri))] // miri doesn't work well with `insta` snapshots //! Tests for `CustomSpawnerBuilder` naming and debug output. diff --git a/crates/anyspawn/tests/handle.rs b/crates/anyspawn/tests/handle.rs index 291d030e..f05bc42d 100644 --- a/crates/anyspawn/tests/handle.rs +++ b/crates/anyspawn/tests/handle.rs @@ -2,14 +2,12 @@ // Licensed under the MIT License. #![allow(missing_docs, reason = "test code")] -#![cfg(any(feature = "tokio", feature = "custom"))] //! Tests for `JoinHandle` implementations. use anyspawn::Spawner; #[cfg_attr(miri, ignore)] -#[cfg(feature = "tokio")] #[tokio::test] async fn join_handle_debug() { let spawner = Spawner::new_tokio(); diff --git a/crates/anyspawn/tests/spawner.rs b/crates/anyspawn/tests/spawner.rs index b941b689..1e047950 100644 --- a/crates/anyspawn/tests/spawner.rs +++ b/crates/anyspawn/tests/spawner.rs @@ -2,7 +2,6 @@ // Licensed under the MIT License. #![allow(missing_docs, reason = "test code")] -#![cfg(any(feature = "tokio", feature = "custom"))] #![cfg(not(miri))] // miri doesn't work well with `insta` snapshots //! Tests for `Spawner` implementations. @@ -11,7 +10,6 @@ use anyspawn::Spawner; static_assertions::assert_impl_all!(Spawner: Send, Sync); -#[cfg(feature = "tokio")] #[tokio::test] async fn tokio_spawn_and_await() { let spawner = Spawner::new_tokio(); @@ -19,7 +17,6 @@ async fn tokio_spawn_and_await() { assert_eq!(result, 42); } -#[cfg(feature = "tokio")] #[tokio::test] async fn tokio_spawn_fire_and_forget() { let spawner = Spawner::new_tokio(); @@ -34,7 +31,6 @@ async fn tokio_spawn_fire_and_forget() { assert_eq!(rx.await.unwrap(), 42); } -#[cfg(feature = "custom")] #[test] fn custom_spawn_and_await() { let spawner = Spawner::new_custom("threadpool", |fut| { @@ -45,7 +41,6 @@ fn custom_spawn_and_await() { assert_eq!(result, 42); } -#[cfg(feature = "custom")] #[tokio::test] async fn custom_spawn_fire_and_forget() { let spawner = Spawner::new_custom("threadpool", |fut| { @@ -63,7 +58,6 @@ async fn custom_spawn_fire_and_forget() { assert_eq!(rx.recv().unwrap(), 42); } -#[cfg(feature = "custom")] #[test] fn custom_spawner_debug() { let spawner = Spawner::new_custom("noop", |_| {}); @@ -71,7 +65,6 @@ fn custom_spawner_debug() { assert!(debug_str.contains("noop")); } -#[cfg(feature = "custom")] #[test] fn thread_aware_spawner_debug() { let spawner = Spawner::new_thread_aware((), |()| Spawner::new_custom("inner", |_| {})); From 8dd6ad9b4aa742b2bd2d6b60669708220425edd9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 27 Mar 2026 09:59:59 +0000 Subject: [PATCH 05/11] fix(anyspawn): fix grammar in handle.rs lint reason strings Agent-Logs-Url: https://github.com/microsoft/oxidizer/sessions/de7617ea-40d8-46bd-ab08-1adf6b7bbb65 Co-authored-by: AdomasBekeras <20183755+AdomasBekeras@users.noreply.github.com> --- crates/anyspawn/src/handle.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/anyspawn/src/handle.rs b/crates/anyspawn/src/handle.rs index 6c2547e0..0a998802 100644 --- a/crates/anyspawn/src/handle.rs +++ b/crates/anyspawn/src/handle.rs @@ -27,7 +27,7 @@ pub(crate) enum JoinHandleInner { Custom(oneshot::Receiver), #[expect( dead_code, - reason = "Unconstructable variant so the type compiles when no runtime feature are enabled." + reason = "Unconstructable variant so the type compiles when no runtime features are enabled." )] #[cfg(not(any(feature = "custom", feature = "tokio")))] None(std::marker::PhantomData T>), @@ -47,7 +47,7 @@ impl Future for JoinHandle { #[cfg(feature = "custom")] JoinHandleInner::Custom(rx) => Pin::new(rx).poll(cx).map(|res| res.expect("spawned task panicked")), #[cfg(not(any(feature = "custom", feature = "tokio")))] - JoinHandleInner::None(_) => unreachable!("JoinHandleInner::None can not be constructed"), + JoinHandleInner::None(_) => unreachable!("JoinHandleInner::None cannot be constructed"), } } } From 297e5a473a030d070e9cc44fc436b702534ada52 Mon Sep 17 00:00:00 2001 From: "ADOMAS BEKERAS (from Dev Box)" Date: Fri, 27 Mar 2026 11:20:03 +0100 Subject: [PATCH 06/11] Remove custom feature --- crates/anyspawn/Cargo.toml | 15 ++++--- crates/anyspawn/src/builder.rs | 18 ++++++--- crates/anyspawn/src/handle.rs | 15 ------- crates/anyspawn/src/lib.rs | 16 ++++---- crates/anyspawn/src/spawner.rs | 74 +++++++++++++++++----------------- 5 files changed, 64 insertions(+), 74 deletions(-) diff --git a/crates/anyspawn/Cargo.toml b/crates/anyspawn/Cargo.toml index f86ac2c0..743d1878 100644 --- a/crates/anyspawn/Cargo.toml +++ b/crates/anyspawn/Cargo.toml @@ -30,10 +30,9 @@ all-features = true [features] default = [] tokio = ["dep:tokio"] -custom = ["dep:futures-channel"] [dependencies] -futures-channel = { workspace = true, features = ["alloc"], optional = true } +futures-channel = { workspace = true, features = ["alloc"] } thread_aware = { workspace = true, features = ["derive"] } tokio = { workspace = true, features = ["rt"], optional = true } @@ -48,7 +47,7 @@ tokio = { workspace = true, features = ["macros", "rt-multi-thread", "sync"] } [[test]] name = "spawner" -required-features = ["tokio", "custom"] +required-features = ["tokio"] [[test]] name = "handle" @@ -56,16 +55,16 @@ required-features = ["tokio"] [[test]] name = "builder" -required-features = ["tokio", "custom"] +required-features = ["tokio"] [[bench]] name = "spawner" harness = false -required-features = ["tokio", "custom"] +required-features = ["tokio"] [[example]] name = "custom" -required-features = ["tokio", "custom"] +required-features = ["tokio"] [[example]] name = "tokio" @@ -73,11 +72,11 @@ required-features = ["tokio"] [[example]] name = "otel_context" -required-features = ["tokio", "custom"] +required-features = ["tokio"] [[example]] name = "thread_aware" -required-features = ["tokio", "custom"] +required-features = ["tokio"] [lints] workspace = true diff --git a/crates/anyspawn/src/builder.rs b/crates/anyspawn/src/builder.rs index a18a6027..3cda1466 100644 --- a/crates/anyspawn/src/builder.rs +++ b/crates/anyspawn/src/builder.rs @@ -28,10 +28,11 @@ use crate::custom::BoxedFuture; /// # Examples /// /// ```rust -/// use anyspawn::{BoxedFuture, CustomSpawnerBuilder}; -/// +/// # #[cfg(feature = "tokio")] /// # #[tokio::main] /// # async fn main() { +/// use anyspawn::{BoxedFuture, CustomSpawnerBuilder}; +/// /// let spawner = CustomSpawnerBuilder::tokio() /// .layer(|fut: BoxedFuture, spawn: &dyn Fn(BoxedFuture)| { /// spawn(Box::pin(async move { @@ -45,6 +46,8 @@ use crate::custom::BoxedFuture; /// let result = spawner.spawn(async { 42 }).await; /// assert_eq!(result, 42); /// # } +/// # #[cfg(not(feature = "tokio"))] +/// # fn main() {} /// ``` pub struct CustomSpawnerBuilder { spawn_fn: S, @@ -73,7 +76,7 @@ impl CustomSpawnerBuilder<()> { /// # } /// ``` #[cfg(feature = "tokio")] - #[cfg_attr(docsrs, doc(cfg(all(feature = "tokio", feature = "custom"))))] + #[cfg_attr(docsrs, doc(cfg(feature = "tokio")))] #[must_use] pub fn tokio() -> CustomSpawnerBuilder { CustomSpawnerBuilder { @@ -107,7 +110,7 @@ impl CustomSpawnerBuilder<()> { /// # } /// ``` #[cfg(feature = "tokio")] - #[cfg_attr(docsrs, doc(cfg(all(feature = "tokio", feature = "custom"))))] + #[cfg_attr(docsrs, doc(cfg(feature = "tokio")))] #[must_use] pub fn tokio_with_handle(handle: ::tokio::runtime::Handle) -> CustomSpawnerBuilder { CustomSpawnerBuilder { @@ -184,10 +187,11 @@ where /// # Examples /// /// ```rust - /// use anyspawn::{BoxedFuture, CustomSpawnerBuilder}; - /// + /// # #[cfg(feature = "tokio")] /// # #[tokio::main] /// # async fn main() { + /// use anyspawn::{BoxedFuture, CustomSpawnerBuilder}; + /// /// let spawner = CustomSpawnerBuilder::tokio() /// .layer(|fut: BoxedFuture, spawn: &dyn Fn(BoxedFuture)| { /// spawn(Box::pin(async move { @@ -198,6 +202,8 @@ where /// .build(); /// # let _ = spawner; /// # } + /// # #[cfg(not(feature = "tokio"))] + /// # fn main() {} /// ``` pub fn layer(self, layer_fn: L) -> CustomSpawnerBuilder where diff --git a/crates/anyspawn/src/handle.rs b/crates/anyspawn/src/handle.rs index 0a998802..e20c28ac 100644 --- a/crates/anyspawn/src/handle.rs +++ b/crates/anyspawn/src/handle.rs @@ -7,7 +7,6 @@ use std::fmt::Debug; use std::pin::Pin; use std::task::{Context, Poll}; -#[cfg(feature = "custom")] use futures_channel::oneshot; /// A handle to a spawned task that can be awaited to retrieve its result. @@ -23,31 +22,17 @@ pub struct JoinHandle(pub(crate) JoinHandleInner); pub(crate) enum JoinHandleInner { #[cfg(feature = "tokio")] Tokio(::tokio::task::JoinHandle), - #[cfg(feature = "custom")] Custom(oneshot::Receiver), - #[expect( - dead_code, - reason = "Unconstructable variant so the type compiles when no runtime features are enabled." - )] - #[cfg(not(any(feature = "custom", feature = "tokio")))] - None(std::marker::PhantomData T>), } impl Future for JoinHandle { type Output = T; - #[cfg_attr( - not(any(feature = "custom", feature = "tokio")), - expect(unused_variables, reason = "cx is unused depending on features") - )] fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { match &mut self.get_mut().0 { #[cfg(feature = "tokio")] JoinHandleInner::Tokio(jh) => Pin::new(jh).poll(cx).map(|res| res.expect("spawned task panicked")), - #[cfg(feature = "custom")] JoinHandleInner::Custom(rx) => Pin::new(rx).poll(cx).map(|res| res.expect("spawned task panicked")), - #[cfg(not(any(feature = "custom", feature = "tokio")))] - JoinHandleInner::None(_) => unreachable!("JoinHandleInner::None cannot be constructed"), } } } diff --git a/crates/anyspawn/src/lib.rs b/crates/anyspawn/src/lib.rs index 3063854a..36885e68 100644 --- a/crates/anyspawn/src/lib.rs +++ b/crates/anyspawn/src/lib.rs @@ -21,19 +21,22 @@ //! ## Using Tokio //! //! ```rust -//! use anyspawn::Spawner; -//! +//! # #[cfg(feature = "tokio")] //! # #[tokio::main] //! # async fn main() { +//! use anyspawn::Spawner; +//! //! let spawner = Spawner::new_tokio(); //! let result = spawner.spawn(async { 1 + 1 }).await; //! assert_eq!(result, 2); //! # } +//! # #[cfg(not(feature = "tokio"))] +//! # fn main() {} //! ``` //! //! ## Custom Runtime //! -//! ```rust,ignore +//! ```rust //! use anyspawn::Spawner; //! //! let spawner = Spawner::new_custom("threadpool", |fut| { @@ -54,23 +57,18 @@ //! //! # Features //! -//! - `tokio` (default): Enables the [`Spawner::new_tokio`] and +//! - `tokio`: Enables the [`Spawner::new_tokio`] and //! [`Spawner::new_tokio_with_handle`] constructors -//! - `custom`: Enables [`Spawner::new_custom`] and [`CustomSpawnerBuilder`] #![doc(html_logo_url = "https://media.githubusercontent.com/media/microsoft/oxidizer/refs/heads/main/crates/anyspawn/logo.png")] #![doc(html_favicon_url = "https://media.githubusercontent.com/media/microsoft/oxidizer/refs/heads/main/crates/anyspawn/favicon.ico")] -#[cfg(feature = "custom")] mod builder; -#[cfg(feature = "custom")] mod custom; mod handle; mod spawner; -#[cfg(feature = "custom")] pub use builder::CustomSpawnerBuilder; -#[cfg(feature = "custom")] pub use custom::BoxedFuture; pub use handle::JoinHandle; pub use spawner::Spawner; diff --git a/crates/anyspawn/src/spawner.rs b/crates/anyspawn/src/spawner.rs index 6ba69f36..6f44f14b 100644 --- a/crates/anyspawn/src/spawner.rs +++ b/crates/anyspawn/src/spawner.rs @@ -4,15 +4,12 @@ //! [`Spawner`] for plugging in runtime implementations. use std::fmt::{self, Debug}; -#[cfg(feature = "custom")] use std::sync::Arc; use thread_aware::{PerCore, ThreadAware}; -#[cfg(feature = "custom")] use crate::custom::{BoxedFuture, CustomSpawner}; use crate::handle::JoinHandle; -#[cfg(any(feature = "tokio", feature = "custom"))] use crate::handle::JoinHandleInner; /// Runtime-agnostic task spawner. @@ -27,22 +24,24 @@ use crate::handle::JoinHandleInner; /// Using Tokio: /// /// ```rust -/// use anyspawn::Spawner; -/// +/// # #[cfg(feature = "tokio")] /// # #[tokio::main] /// # async fn main() { +/// use anyspawn::Spawner; +/// /// let spawner = Spawner::new_tokio(); /// let handle = spawner.spawn(async { /// println!("Task running!"); /// }); /// handle.await; // Wait for task to complete -/// /// # } +/// # #[cfg(not(feature = "tokio"))] +/// # fn main() {} /// ``` /// /// ## Custom Runtime /// -/// ```rust,ignore +/// ```rust /// use anyspawn::Spawner; /// /// let spawner = Spawner::new_custom("threadpool", |fut| { @@ -60,14 +59,17 @@ use crate::handle::JoinHandleInner; /// Await the [`JoinHandle`](crate::JoinHandle) to retrieve a value from the task: /// /// ```rust -/// use anyspawn::Spawner; -/// +/// # #[cfg(feature = "tokio")] /// # #[tokio::main] /// # async fn main() { +/// use anyspawn::Spawner; +/// /// let spawner = Spawner::new_tokio(); /// let value = spawner.spawn(async { 1 + 1 }).await; /// assert_eq!(value, 2); /// # } +/// # #[cfg(not(feature = "tokio"))] +/// # fn main() {} /// ``` /// /// ## Handling Errors @@ -75,10 +77,11 @@ use crate::handle::JoinHandleInner; /// Return a `Result` from the task to propagate errors: /// /// ```rust -/// use anyspawn::Spawner; -/// +/// # #[cfg(feature = "tokio")] /// # #[tokio::main] /// # async fn main() { +/// use anyspawn::Spawner; +/// /// let spawner = Spawner::new_tokio(); /// /// let result = spawner @@ -96,6 +99,8 @@ use crate::handle::JoinHandleInner; /// Err(e) => eprintln!("Task failed: {e}"), /// } /// # } +/// # #[cfg(not(feature = "tokio"))] +/// # fn main() {} /// ``` /// /// # Thread-Aware Support @@ -123,11 +128,8 @@ pub struct Spawner(SpawnerKind); enum SpawnerKind { #[cfg(feature = "tokio")] Tokio(#[thread_aware(skip)] Option<::tokio::runtime::Handle>), - #[cfg(feature = "custom")] Custom(CustomSpawner), ThreadAware(thread_aware::Arc), - #[cfg(not(any(feature = "custom", feature = "tokio")))] - None, } impl Spawner { @@ -200,8 +202,6 @@ impl Spawner { /// std::thread::spawn(move || futures::executor::block_on(fut)); /// }); /// ``` - #[cfg(feature = "custom")] - #[cfg_attr(docsrs, doc(cfg(feature = "custom")))] pub fn new_custom(name: &'static str, f: F) -> Self where F: Fn(BoxedFuture) + Send + Sync + 'static, @@ -228,20 +228,22 @@ impl Spawner { /// # Examples /// /// ```rust + /// # #[cfg(feature = "tokio")] + /// # fn main() { /// use anyspawn::Spawner; - /// # use thread_aware::ThreadAware; - /// # use thread_aware::affinity::{MemoryAffinity, PinnedAffinity}; - /// # #[derive(Default, Clone)] - /// # struct Scheduler(Option); - /// # impl Scheduler { fn name(&self) -> String { format!("core-{}", self.0.unwrap_or(0)) } } - /// # impl ThreadAware for Scheduler { - /// # fn relocated(self, _: MemoryAffinity, dest: PinnedAffinity) -> Self { - /// # Self(Some(dest.processor_index())) - /// # } - /// # } + /// use thread_aware::ThreadAware; + /// use thread_aware::affinity::{MemoryAffinity, PinnedAffinity}; + /// #[derive(Default, Clone)] + /// struct Scheduler(Option); + /// impl Scheduler { fn name(&self) -> String { format!("core-{}", self.0.unwrap_or(0)) } } + /// impl ThreadAware for Scheduler { + /// fn relocated(self, _: MemoryAffinity, dest: PinnedAffinity) -> Self { + /// Self(Some(dest.processor_index())) + /// } + /// } /// - /// # #[tokio::main] - /// # async fn main() { + /// # let rt = tokio::runtime::Runtime::new().unwrap(); + /// # rt.block_on(async { /// let scheduler = Scheduler::default(); /// /// // Each core gets its own Spawner whose Scheduler carries the @@ -258,7 +260,10 @@ impl Spawner { /// /// let result = spawner.spawn(async { 1 + 1 }).await; /// assert_eq!(result, 2); + /// # }); /// # } + /// # #[cfg(not(feature = "tokio"))] + /// # fn main() {} /// ``` pub fn new_thread_aware(data: D, factory: fn(D) -> Self) -> Self where @@ -280,10 +285,11 @@ impl Spawner { /// # Examples /// /// ```rust - /// use anyspawn::Spawner; - /// + /// # #[cfg(feature = "tokio")] /// # #[tokio::main] /// # async fn main() { + /// use anyspawn::Spawner; + /// /// let spawner = Spawner::new_tokio(); /// /// // Await to get the result @@ -293,6 +299,8 @@ impl Spawner { /// // Or fire-and-forget by dropping the handle /// let _ = spawner.spawn(async { println!("background task") }); /// # } + /// # #[cfg(not(feature = "tokio"))] + /// # fn main() {} /// ``` pub fn spawn(&self, work: impl Future + Send + 'static) -> JoinHandle { match &self.0 { @@ -304,11 +312,8 @@ impl Spawner { }; JoinHandle(JoinHandleInner::Tokio(jh)) } - #[cfg(feature = "custom")] SpawnerKind::Custom(c) => JoinHandle(JoinHandleInner::Custom(c.call(work))), SpawnerKind::ThreadAware(ta) => ta.spawn(work), - #[cfg(not(any(feature = "custom", feature = "tokio")))] - SpawnerKind::None => unreachable!("SpawnerKind::None cannot be constructed"), } } } @@ -320,11 +325,8 @@ impl Debug for Spawner { SpawnerKind::Tokio(None) => f.debug_tuple("Spawner").field(&"tokio").finish(), #[cfg(feature = "tokio")] SpawnerKind::Tokio(Some(_)) => f.debug_tuple("Spawner").field(&"tokio(handle)").finish(), - #[cfg(feature = "custom")] SpawnerKind::Custom(c) => f.debug_tuple("Spawner").field(c).finish(), SpawnerKind::ThreadAware(_) => f.debug_tuple("Spawner").field(&"thread_aware").finish(), - #[cfg(not(any(feature = "custom", feature = "tokio")))] - SpawnerKind::None => unreachable!("SpawnerKind::None cannot be constructed"), } } } From c22e413e65c040bcf68c001ff948740b3419acd8 Mon Sep 17 00:00:00 2001 From: "ADOMAS BEKERAS (from Dev Box)" Date: Fri, 27 Mar 2026 11:26:38 +0100 Subject: [PATCH 07/11] Fix --- crates/anyspawn/tests/relocation.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/anyspawn/tests/relocation.rs b/crates/anyspawn/tests/relocation.rs index 54d4a5da..ae379c46 100644 --- a/crates/anyspawn/tests/relocation.rs +++ b/crates/anyspawn/tests/relocation.rs @@ -2,7 +2,6 @@ // Licensed under the MIT License. #![allow(missing_docs, reason = "test code")] -#![cfg(feature = "custom")] #![cfg(not(miri))] // miri does not support OS threads and CPU affinity helpers //! Tests for [`Spawner`] relocation behavior with [`ThreadAware`]. From 49f578baa2b490471a6948fa8daca19bd22e5ffb Mon Sep 17 00:00:00 2001 From: "ADOMAS BEKERAS (from Dev Box)" Date: Fri, 27 Mar 2026 11:41:30 +0100 Subject: [PATCH 08/11] Update readme --- crates/anyspawn/README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/anyspawn/README.md b/crates/anyspawn/README.md index 7cb4c6a7..aac8a011 100644 --- a/crates/anyspawn/README.md +++ b/crates/anyspawn/README.md @@ -59,9 +59,8 @@ details and examples. ## Features -* `tokio` (default): Enables the [`Spawner::new_tokio`][__link4] and +* `tokio`: Enables the [`Spawner::new_tokio`][__link4] and [`Spawner::new_tokio_with_handle`][__link5] constructors -* `custom`: Enables [`Spawner::new_custom`][__link6] and [`CustomSpawnerBuilder`][__link7]
From ae2164a3f13478919fa3ebcffa71f7254902bc2f Mon Sep 17 00:00:00 2001 From: "ADOMAS BEKERAS (from Dev Box)" Date: Fri, 27 Mar 2026 11:45:22 +0100 Subject: [PATCH 09/11] Update readme --- crates/anyspawn/README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/crates/anyspawn/README.md b/crates/anyspawn/README.md index aac8a011..d85f2f17 100644 --- a/crates/anyspawn/README.md +++ b/crates/anyspawn/README.md @@ -68,12 +68,10 @@ details and examples. This crate was developed as part of The Oxidizer Project. Browse this crate's source code. - [__cargo_doc2readme_dependencies_info]: ggGkYW0CYXSEGy4k8ldDFPOhG2VNeXtD5nnKG6EPY6OfW5wBG8g18NOFNdxpYXKEG9wiT4mviSlSG7bkeqiO1sYsG8AqKBp2b7sGG8q0eDukfWyeYWSCgmhhbnlzcGF3bmUwLjIuMIJsdGhyZWFkX2F3YXJlZTAuNi4y + [__cargo_doc2readme_dependencies_info]: ggGmYW0CYXZlMC43LjJhdIQbLiTyV0MU86EbZU15e0PmecoboQ9jo59bnAEbyDXw04U13GlhYvRhcoQb2kzPFSWDwP0bFmeuSlBPmOYbJhoG25idR60bDe4xDajaP_lhZIKCaGFueXNwYXduZTAuMi4wgmx0aHJlYWRfYXdhcmVlMC42LjI [__link0]: https://docs.rs/anyspawn/0.2.0/anyspawn/?search=Spawner [__link1]: https://docs.rs/thread_aware/0.6.2/thread_aware/?search=ThreadAware [__link2]: https://docs.rs/anyspawn/0.2.0/anyspawn/?search=Spawner::new_thread_aware [__link3]: Spawner#thread-aware-support [__link4]: https://docs.rs/anyspawn/0.2.0/anyspawn/?search=Spawner::new_tokio [__link5]: https://docs.rs/anyspawn/0.2.0/anyspawn/?search=Spawner::new_tokio_with_handle - [__link6]: https://docs.rs/anyspawn/0.2.0/anyspawn/?search=Spawner::new_custom - [__link7]: https://docs.rs/anyspawn/0.2.0/anyspawn/?search=CustomSpawnerBuilder From 016c8cbb60327a43c3c8ddb78189a9f7c98d63de Mon Sep 17 00:00:00 2001 From: "ADOMAS BEKERAS (from Dev Box)" Date: Fri, 27 Mar 2026 12:15:04 +0100 Subject: [PATCH 10/11] Rollback doctest --- crates/anyspawn/src/spawner.rs | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/crates/anyspawn/src/spawner.rs b/crates/anyspawn/src/spawner.rs index 6f44f14b..78c6b08f 100644 --- a/crates/anyspawn/src/spawner.rs +++ b/crates/anyspawn/src/spawner.rs @@ -229,21 +229,21 @@ impl Spawner { /// /// ```rust /// # #[cfg(feature = "tokio")] - /// # fn main() { + /// # #[tokio::main] + /// # async fn main() { /// use anyspawn::Spawner; - /// use thread_aware::ThreadAware; - /// use thread_aware::affinity::{MemoryAffinity, PinnedAffinity}; - /// #[derive(Default, Clone)] - /// struct Scheduler(Option); - /// impl Scheduler { fn name(&self) -> String { format!("core-{}", self.0.unwrap_or(0)) } } - /// impl ThreadAware for Scheduler { - /// fn relocated(self, _: MemoryAffinity, dest: PinnedAffinity) -> Self { - /// Self(Some(dest.processor_index())) - /// } - /// } + /// # use thread_aware::ThreadAware; + /// # use thread_aware::affinity::{MemoryAffinity, PinnedAffinity}; + /// # #[derive(Default, Clone)] + /// # struct Scheduler(Option); + /// # impl Scheduler { fn name(&self) -> String { format!("core-{}", self.0.unwrap_or(0)) } } + /// # impl ThreadAware for Scheduler { + /// # fn relocated(self, _: MemoryAffinity, dest: PinnedAffinity) -> Self { + /// # Self(Some(dest.processor_index())) + /// # } + /// # } /// /// # let rt = tokio::runtime::Runtime::new().unwrap(); - /// # rt.block_on(async { /// let scheduler = Scheduler::default(); /// /// // Each core gets its own Spawner whose Scheduler carries the @@ -260,7 +260,6 @@ impl Spawner { /// /// let result = spawner.spawn(async { 1 + 1 }).await; /// assert_eq!(result, 2); - /// # }); /// # } /// # #[cfg(not(feature = "tokio"))] /// # fn main() {} From b7f0df237e7222250de88156168fa70f3c14a133 Mon Sep 17 00:00:00 2001 From: "ADOMAS BEKERAS (from Dev Box)" Date: Fri, 27 Mar 2026 12:16:05 +0100 Subject: [PATCH 11/11] Rollback doctest --- crates/anyspawn/src/spawner.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/anyspawn/src/spawner.rs b/crates/anyspawn/src/spawner.rs index 78c6b08f..4178cfd2 100644 --- a/crates/anyspawn/src/spawner.rs +++ b/crates/anyspawn/src/spawner.rs @@ -243,7 +243,6 @@ impl Spawner { /// # } /// # } /// - /// # let rt = tokio::runtime::Runtime::new().unwrap(); /// let scheduler = Scheduler::default(); /// /// // Each core gets its own Spawner whose Scheduler carries the