Skip to main content

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}