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}