product_os_async_executor/lib.rs
1//! # Product OS : Async Executor
2//!
3//! Product OS : Async Executor provides a set of tools to handle async execution generically
4//! so that the desired async library (e.g. tokio, smol, async-std) can be chosen at compile time.
5//!
6//! ## Features
7//!
8//! - **Generic Executor Traits**: Define common interfaces for working with different async runtimes
9//! - **Runtime Support**: Out-of-the-box support for Tokio, Smol, and Async-std
10//! - **Timer Support**: One-time and interval timers that work across runtimes
11//! - **Async I/O Traits**: `AsyncRead` and `AsyncWrite` traits for cross-runtime I/O
12//! - **No-std Support**: Works in `no_std` environments with alloc
13//!
14//! ## Examples
15//!
16//! ### Using with Tokio
17//!
18//! ```rust,no_run
19//! # #[cfg(feature = "exec_tokio")]
20//! # {
21//! use product_os_async_executor::{Executor, ExecutorPerform, TokioExecutor};
22//!
23//! #[tokio::main]
24//! async fn main() {
25//! // Create an executor context
26//! let executor = TokioExecutor::context().await.unwrap();
27//!
28//! // Spawn a task
29//! let result = TokioExecutor::spawn_in_context(async {
30//! 42
31//! }).await;
32//!
33//! assert!(result.is_ok());
34//! }
35//! # }
36//! ```
37//!
38//! ### Using Timers
39//!
40//! ```rust,no_run
41//! # #[cfg(feature = "exec_tokio")]
42//! # {
43//! use product_os_async_executor::{Timer, TokioExecutor};
44//!
45//! #[tokio::main]
46//! async fn main() {
47//! let mut timer = TokioExecutor::interval(100).await;
48//! let _ = timer.tick().await; // Waits ~100ms
49//! }
50//! # }
51//! ```
52//!
53//! ## Feature Flags
54//!
55//! - `exec_tokio`: Enable Tokio executor support
56//! - `exec_smol`: Enable Smol executor support
57//! - `exec_async_std`: Enable Async-std executor support
58//! - `moment`: Enable time abstraction utilities
59//! - `hyper_executor`: Enable Hyper executor integration
60//!
61#![no_std]
62#![warn(missing_docs)]
63#![warn(clippy::all)]
64#![warn(clippy::pedantic)]
65#![warn(clippy::nursery)]
66#![allow(clippy::module_name_repetitions)]
67#![allow(clippy::must_use_candidate)]
68
69extern crate no_std_compat as std;
70extern crate alloc;
71
72use std::prelude::v1::*;
73
74
75#[cfg(feature = "exec_tokio")]
76mod tokio;
77#[cfg(feature = "exec_tokio")]
78pub use tokio::TokioExecutor;
79
80#[cfg(feature = "exec_smol")]
81mod smol;
82
83#[cfg(feature = "exec_smol")]
84pub use smol::SmolExecutor;
85
86
87#[cfg(feature = "exec_async_std")]
88mod async_std;
89
90/// Async read/write traits for cross-runtime I/O operations.
91///
92/// This module provides `AsyncRead` and `AsyncWrite` traits that work across
93/// different async runtimes, along with utilities for buffered I/O.
94pub mod read_write;
95
96/// Sleep trait for cross-runtime sleeping.
97pub mod sleep;
98
99/// Time abstraction utilities for testable time operations.
100///
101/// The `Moment` struct allows you to abstract time operations, making it easier
102/// to test code that depends on the current time.
103pub mod moment;
104
105#[cfg(feature = "exec_async_std")]
106pub use async_std::AsyncStdExecutor;
107
108use async_trait::async_trait;
109use std::sync::Arc;
110use std::future::Future;
111
112pub use chrono::*;
113pub use ioslice::IoSlice;
114
115/// Type alias for boxed error types that are Send + Sync.
116///
117/// This is used throughout the crate for error handling in async contexts.
118pub type BoxError = Box<dyn core_error::Error + Send + Sync>;
119
120
121/// Trait for managing executor contexts across different async runtimes.
122///
123/// This trait provides a unified interface for creating, configuring, and accessing
124/// executor contexts regardless of the underlying async runtime (Tokio, Smol, etc.).
125///
126/// # Type Parameters
127///
128/// * `X` - The executor handle type specific to the runtime (e.g., `tokio::runtime::Handle`)
129///
130/// # Examples
131///
132/// ```rust,no_run
133/// # #[cfg(feature = "exec_tokio")]
134/// # {
135/// use product_os_async_executor::{Executor, TokioExecutor};
136///
137/// #[tokio::main]
138/// async fn main() {
139/// let executor = TokioExecutor::context().await.unwrap();
140/// executor.enter_context().await;
141/// }
142/// # }
143/// ```
144#[async_trait]
145pub trait Executor<X>: Send + Sync
146{
147 /// Creates a new executor context asynchronously.
148 ///
149 /// # Errors
150 ///
151 /// Returns an error if the executor context cannot be created.
152 async fn context() -> Result<Self, futures_task::SpawnError>
153 where
154 Self: Sized;
155
156 /// Sets the executor context to the provided executor.
157 async fn set_context(&mut self, executor: X);
158
159 /// Enters the executor context.
160 async fn enter_context(&self);
161
162 /// Gets a reference to the underlying executor.
163 async fn get_executor(&self) -> &X;
164
165 /// Creates a new executor context synchronously.
166 ///
167 /// # Errors
168 ///
169 /// Returns an error if the executor context cannot be created.
170 fn context_sync() -> Result<Self, futures_task::SpawnError>
171 where
172 Self: Sized;
173
174 /// Sets the executor context synchronously.
175 fn set_context_sync(&mut self, executor: X);
176
177 /// Enters the executor context synchronously.
178 fn enter_context_sync(&self);
179
180 /// Gets a reference to the underlying executor synchronously.
181 fn get_executor_sync(&self) -> &X;
182}
183
184
185/// Trait for spawning and managing async tasks.
186///
187/// This trait provides methods for spawning tasks on an executor and blocking
188/// on futures. It complements the `Executor` trait by focusing on task execution.
189///
190/// # Type Parameters
191///
192/// * `X` - The executor handle type
193///
194/// # Examples
195///
196/// ```rust,no_run
197/// # #[cfg(feature = "exec_tokio")]
198/// # {
199/// use product_os_async_executor::{ExecutorPerform, TokioExecutor};
200///
201/// #[tokio::main]
202/// async fn main() {
203/// let task = TokioExecutor::spawn_in_context(async {
204/// println!("Hello from spawned task!");
205/// 42
206/// }).await;
207///
208/// assert!(task.is_ok());
209/// }
210/// # }
211/// ```
212#[async_trait]
213pub trait ExecutorPerform<X>: Send + Sync
214{
215 /// Spawns a task in the current context asynchronously.
216 ///
217 /// # Errors
218 ///
219 /// Returns an error if the task cannot be spawned.
220 async fn spawn_in_context<F>(future: F) -> Result<Arc<dyn Task<F::Output, Output = F::Output>>, futures_task::SpawnError>
221 where
222 F: Future + Send + 'static,
223 F::Output: Send + 'static;
224
225 /// Spawns a task from an executor asynchronously.
226 ///
227 /// # Errors
228 ///
229 /// Returns an error if the task cannot be spawned.
230 async fn spawn_from_executor<E, F>(executor: &E, future: F) -> Result<Arc<dyn Task<F::Output, Output = F::Output>>, futures_task::SpawnError>
231 where
232 E: Executor<X>,
233 F: Future + Send + 'static,
234 F::Output: Send + 'static;
235
236 /// Blocks on a future using the executor.
237 ///
238 /// This method blocks the current thread until the future completes.
239 async fn block_from_executor<E, F>(executor: &E, future: F) -> F::Output
240 where
241 E: Executor<X>,
242 F: Future + Send + 'static,
243 F::Output: Send + 'static;
244
245 /// Spawns a task in the current context synchronously.
246 ///
247 /// # Errors
248 ///
249 /// Returns an error if the task cannot be spawned.
250 fn spawn_in_context_sync<F>(future: F) -> Result<Arc<dyn Task<F::Output, Output = F::Output>>, futures_task::SpawnError>
251 where
252 F: Future + Send + 'static,
253 F::Output: Send + 'static;
254
255 /// Spawns a task from an executor synchronously.
256 ///
257 /// # Errors
258 ///
259 /// Returns an error if the task cannot be spawned.
260 fn spawn_from_executor_sync<E, F>(executor: &E, future: F) -> Result<Arc<dyn Task<F::Output, Output = F::Output>>, futures_task::SpawnError>
261 where
262 E: Executor<X>,
263 F: Future + Send + 'static,
264 F::Output: Send + 'static;
265
266 /// Blocks on a future using the executor synchronously.
267 ///
268 /// This method blocks the current thread until the future completes.
269 fn block_from_executor_sync<E, F>(executor: &E, future: F) -> F::Output
270 where
271 E: Executor<X>,
272 F: Future + Send + 'static,
273 F::Output: Send + 'static;
274}
275
276
277
278/// Trait for timer functionality across async runtimes.
279///
280/// Provides a unified interface for one-shot and interval timers that work
281/// with any supported async runtime.
282///
283/// # Examples
284///
285/// ```rust,no_run
286/// # #[cfg(feature = "exec_tokio")]
287/// # {
288/// use product_os_async_executor::{Timer, TokioExecutor};
289///
290/// #[tokio::main]
291/// async fn main() {
292/// // Create an interval timer that fires every 100ms
293/// let mut timer = TokioExecutor::interval(100).await;
294///
295/// // Wait for the first tick
296/// let elapsed = timer.tick().await;
297/// println!("Elapsed: {}ms", elapsed);
298/// }
299/// # }
300/// ```
301#[async_trait]
302pub trait Timer: Send + Sync {
303 /// Creates a one-shot timer that fires after the specified duration.
304 async fn once(duration_millis: u32) -> Self;
305
306 /// Creates an interval timer that fires repeatedly at the specified interval.
307 async fn interval(duration_millis: u32) -> Self;
308
309 /// Cancels the timer.
310 async fn cancel(&mut self);
311
312 /// Creates a one-shot timer synchronously.
313 fn once_sync(duration_millis: u32) -> Self;
314
315 /// Creates an interval timer synchronously.
316 fn interval_sync(duration_millis: u32) -> Self;
317
318 /// Cancels the timer synchronously.
319 fn cancel_sync(&mut self);
320
321 /// Waits for the next tick of the timer and returns elapsed milliseconds.
322 async fn tick(&mut self) -> u32;
323}
324
325
326/// Trait representing an async task that can be awaited.
327///
328/// This trait combines the `Future` trait with methods for managing task lifecycle.
329///
330/// # Type Parameters
331///
332/// * `Out` - The output type of the task
333#[async_trait]
334pub trait Task<Out>: Future
335where
336 Out: Send + 'static
337{
338 /// Consumes the task and returns its output.
339 async fn output(self) -> Out;
340
341 /// Detaches the task, allowing it to run independently.
342 fn detach(self);
343
344 /// Drops the task, cancelling it if not detached.
345 fn drop(self);
346}