Skip to main content

orb/
lib.rs

1#![cfg_attr(docsrs, feature(doc_cfg))]
2#![cfg_attr(docsrs, allow(unused_attributes))]
3#![doc = include_str!("../README.md")]
4
5//! ## Runtime Varieties Note
6//!
7//! ### Task Detach
8//!
9//! The drop behavior of task handle is unified to "detach", task will not be cancel unless
10//! [abort](AsyncJoiner::abort) is called.
11//!
12//! ### Panic
13//!
14//! - tokio will issolate panic between tasks, a task handle may return Err() on join.
15//! - smol will not issolate panic. Although a panic hook will work, the program might panic if one
16//! of the task panic. You may use feature `unwind` to enable panic capturing.
17//!
18//! ### thread local context
19//!
20//! When the first time enter block_on in `current()` runtime, or threaded worker spawn,
21//! we have maintain thread local ref for the runtime, so that you can use [AsyncRuntime::spawn()] static method directly.
22//! (Note that calling `AsyncRuntime::spawn()` from non-async context will panic (just like `tokio::spawn` behavior)
23//!
24//! ## Cloning the runtime
25//!
26//! [AsyncExec] is a cloneable runtime handle, can be initiated by [AsyncRuntime::current()], [AsyncRuntime::one()], [AsyncRuntime::multi()]
27
28pub mod io;
29pub mod net;
30pub mod runtime;
31pub mod time;
32pub mod utils;
33#[cfg(feature = "worker")]
34pub mod worker_pool;
35
36/// Re-export all the traits you need
37///
38/// This module contains all the essential traits needed to work with Orb.
39/// Importing this prelude is the recommended way to use Orb in your code.
40pub mod prelude {
41    pub use crate::AsyncRuntime;
42    pub use crate::io::{AsyncBufRead, AsyncBufWrite, AsyncFd, AsyncIO, AsyncRead, AsyncWrite};
43    pub use crate::net::AsyncListener;
44    pub use crate::runtime::{AsyncExec, AsyncJoiner, ThreadJoiner};
45    pub use crate::time::{AsyncTime, TimeInterval};
46    // Re-export the Stream trait so users can import it
47    pub use futures_lite::stream::Stream;
48    pub use futures_lite::stream::StreamExt;
49}
50
51use prelude::*;
52
53/// A marker trait that combines all the core async runtime capabilities,
54/// including [`AsyncIO`], and [`AsyncTime`]. It serves as a convenient
55/// way to specify that a type provides all the core async runtime functionality.
56///
57/// You can write your own trait by inheriting AsyncRuntime or any other trait, to provide extra
58/// functions along with the runtime object.
59/// There's an blanket trait to auto impl AsyncRuntime on anything that is `Deref<Target>` to an AsyncRuntime.
60pub trait AsyncRuntime: AsyncIO + AsyncTime + 'static + Send + Sync {
61    type Exec: AsyncExec;
62
63    /// Initiate executor using current thread.
64    ///
65    /// # Safety
66    ///
67    /// You should run [AsyncExec::block_on()] with this executor.
68    ///
69    /// If spawn without a `block_on()` running, it's possible
70    /// the runtime just init future without scheduling.
71    fn current() -> Self::Exec;
72
73    /// Initiate executor with one background thread.
74    ///
75    /// # NOTE
76    ///
77    /// [AsyncExec::block_on()] is optional, you can directly call [AsyncExec::spawn] with it.
78    fn one() -> Self::Exec;
79
80    /// Initiate executor with multiple background threads.
81    ///
82    /// # NOTE
83    ///
84    /// When `num` == 0, start threads that match cpu number.
85    ///
86    /// [AsyncExec::block_on()] is optional, you can directly call [AsyncExec::spawn] with it.
87    fn multi(num: usize) -> Self::Exec;
88
89    /// Spawn a task with Self::Exec in the thread context, returning a handle to await its result.
90    ///
91    /// This method creates a new task that runs concurrently with the current
92    /// task. The returned handle can be used to wait for the task's completion
93    /// and retrieve its result.
94    ///
95    /// # NOTE:
96    ///
97    /// The return AsyncJoiner adopts the behavior of tokio.
98    ///
99    /// The behavior of panic varies for runtimes:
100    /// - tokio will capture handle to task result,
101    /// - async-executor (smol) will not capture panic, the program will exit
102    ///
103    /// # Type Parameters
104    ///
105    /// * `F` - The future type to spawn
106    /// * `R` - The return type of the future
107    ///
108    /// # Parameters
109    ///
110    /// * `f` - The future to spawn
111    ///
112    /// # Returns
113    ///
114    /// A handle that implements [`AsyncJoiner`] and can be used to await
115    /// the task's result.
116    ///
117    /// # Panic
118    ///
119    /// Panic when not called in the runtime worker context.
120    fn spawn<F, R>(f: F) -> <Self::Exec as AsyncExec>::AsyncJoiner<R>
121    where
122        F: Future<Output = R> + Send + 'static,
123        R: Send + 'static;
124
125    /// Spawn a task with Self::Exec in the thread context, and detach it (no handle returned).
126    ///
127    /// This method creates a new task that runs in the background without
128    /// providing a way to wait for its completion. The task will continue
129    /// running until it completes or the program exits.
130    ///
131    /// # NOTE:
132    ///
133    /// The behavior of panic varies for runtimes:
134    /// - tokio will ignore other tasks panic after detached,
135    /// - async-executor (smol) will not capture panic by default, the program will exit. There's a
136    ///   feature switch in [orb-smol](https://docs.rs/orb-smol) to change this behavior.
137    ///
138    /// # Type Parameters
139    ///
140    /// * `F` - The future type to spawn
141    /// * `R` - The return type of the future
142    ///
143    /// # Parameters
144    ///
145    /// * `f` - The future to spawn
146    ///
147    /// # Panic
148    ///
149    /// Panic when not called in the runtime worker context.
150    fn spawn_detach<F, R>(f: F)
151    where
152        F: Future<Output = R> + Send + 'static,
153        R: Send + 'static;
154
155    /// Run blocking code with the thread context in blocking thread pool,
156    /// and return an async join handle
157    ///
158    /// # NOTE:
159    ///
160    /// This method spawn with threal pool provide by runtime in current context, globally.
161    /// In order for ResolveAddr job which does not have a AsyncExec handle, so this method is static.
162    ///
163    /// # Type Parameters
164    ///
165    /// * `F` - The future type to spawn
166    /// * `R` - The return type of the future
167    ///
168    /// # Parameters
169    ///
170    /// * `f` - The future to spawn
171    ///
172    /// # Returns
173    ///
174    /// A handle that implements [`ThreadJoiner`] and can be used to await
175    /// the call result.
176    ///
177    /// # Panic
178    ///
179    /// Panic when not called in the runtime worker context.
180    fn spawn_blocking<F, R>(f: F) -> <Self::Exec as AsyncExec>::ThreadJoiner<R>
181    where
182        F: FnOnce() -> R + Send + 'static,
183        R: Send + 'static;
184}