orb/
runtime.rs

1//! Runtime execution traits for async task management.
2//!
3//! This module defines the interface for spawning, executing, and managing
4//! asynchronous tasks across different runtime implementations.
5//!
6//! The adaptors are provided as separate crates:
7//!
8//! - [orb-tokio](https://docs.rs/orb-tokio) - For the Tokio runtime
9//! - [orb-smol](https://docs.rs/orb-smol) - For the Smol runtime
10
11use std::future::Future;
12
13/// Trait for async runtime execution capabilities.
14///
15/// This trait defines the core execution operations that any async runtime
16/// should provide, including spawning tasks, running futures to completion,
17/// and detaching tasks.
18///
19/// # Example
20///
21/// ```rust
22/// use orb::prelude::*;
23/// use std::future::Future;
24///
25/// fn example<R: AsyncExec>(runtime: &R) -> impl Future<Output = ()> {
26///     async move {
27///         // Spawn a task
28///         let handle = runtime.spawn(async {
29///             // Do some async work
30///             42
31///         });
32///         
33///         // Wait for the result
34///         let result = handle.join().await.unwrap();
35///         assert_eq!(result, 42);
36///     }
37/// }
38/// ```
39pub trait AsyncExec: Send + Sync + 'static {
40    /// Spawn a task in the background, returning a handle to await its result.
41    ///
42    /// This method creates a new task that runs concurrently with the current
43    /// task. The returned handle can be used to wait for the task's completion
44    /// and retrieve its result.
45    ///
46    /// # Type Parameters
47    ///
48    /// * `F` - The future type to spawn
49    /// * `R` - The return type of the future
50    ///
51    /// # Parameters
52    ///
53    /// * `f` - The future to spawn
54    ///
55    /// # Returns
56    ///
57    /// A handle that implements [`AsyncJoinHandle`] and can be used to await
58    /// the task's result.
59    fn spawn<F, R>(&self, f: F) -> impl AsyncJoinHandle<R>
60    where
61        F: Future<Output = R> + Send + 'static,
62        R: Send + 'static;
63
64    /// Spawn a task and detach it (no handle returned).
65    ///
66    /// This method creates a new task that runs in the background without
67    /// providing a way to wait for its completion. The task will continue
68    /// running until it completes or the program exits.
69    ///
70    /// # Type Parameters
71    ///
72    /// * `F` - The future type to spawn
73    /// * `R` - The return type of the future
74    ///
75    /// # Parameters
76    ///
77    /// * `f` - The future to spawn
78    fn spawn_detach<F, R>(&self, f: F)
79    where
80        F: Future<Output = R> + Send + 'static,
81        R: Send + 'static;
82
83    /// Run a future to completion on the runtime.
84    ///
85    /// This method blocks the current thread until the provided future
86    /// completes, returning its result.
87    ///
88    /// # Type Parameters
89    ///
90    /// * `F` - The future type to run
91    /// * `R` - The return type of the future
92    ///
93    /// # Parameters
94    ///
95    /// * `f` - The future to run to completion
96    ///
97    /// # Returns
98    ///
99    /// The output of the future when it completes.
100    fn block_on<F, R>(&self, f: F) -> R
101    where
102        F: Future<Output = R> + Send,
103        R: Send + 'static;
104}
105
106impl<FT: std::ops::Deref<Target = T> + Send + Sync + 'static, T: AsyncExec> AsyncExec for FT {
107    #[inline(always)]
108    fn spawn<F, R>(&self, f: F) -> impl AsyncJoinHandle<R>
109    where
110        F: Future<Output = R> + Send + 'static,
111        R: Send + 'static,
112    {
113        T::spawn(self.deref(), f)
114    }
115
116    #[inline(always)]
117    fn spawn_detach<F, R>(&self, f: F)
118    where
119        F: Future<Output = R> + Send + 'static,
120        R: Send + 'static,
121    {
122        T::spawn_detach(self.deref(), f)
123    }
124
125    #[inline(always)]
126    fn block_on<F, R>(&self, f: F) -> R
127    where
128        F: Future<Output = R> + Send,
129        R: Send + 'static,
130    {
131        T::block_on(self, f)
132    }
133}
134
135/// A handle for managing spawned async tasks.
136///
137/// This trait provides methods for waiting for a task's completion or
138/// detaching it to run in the background.
139///
140/// # Type Parameters
141///
142/// * `T` - The return type of the task
143pub trait AsyncJoinHandle<T: Send + 'static>: Send + 'static {
144    /// Wait for the task to complete and return its result.
145    ///
146    /// This method returns a future that resolves to either the task's
147    /// successful result or an error if the task panicked.
148    ///
149    /// # Returns
150    ///
151    /// A future that resolves to `Ok(T)` if the task completed successfully,
152    /// or `Err(())` if the task failed.
153    fn join(self) -> impl Future<Output = Result<T, ()>> + Send;
154
155    /// Detach the task to run in the background without waiting for its result.
156    ///
157    /// After calling this method, the task will continue running until it
158    /// completes or the program exits, but there will be no way to retrieve
159    /// its result.
160    ///
161    /// # Warning
162    ///
163    /// Some runtimes (like smol) will cancel the future if you drop the task handle
164    /// without calling this method. If you want the task to continue running in
165    /// the background, you must explicitly call `detach()` rather than just
166    /// dropping the handle.
167    fn detach(self);
168}