roam_session/runtime/
tokio_runtime.rs

1//! Native (tokio) runtime implementation.
2
3use std::future::Future;
4use std::time::Duration;
5
6// Re-export tokio sync types directly
7pub use tokio::sync::Mutex;
8pub use tokio::sync::mpsc::{
9    Receiver, Sender, UnboundedReceiver, UnboundedSender, channel, error::SendError,
10    unbounded_channel,
11};
12pub use tokio::sync::oneshot::{Receiver as OneshotReceiver, Sender as OneshotSender};
13
14/// Create a bounded mpsc channel.
15pub fn bounded<T>(buffer: usize) -> (Sender<T>, Receiver<T>) {
16    channel(buffer)
17}
18
19/// Create an unbounded mpsc channel.
20pub fn unbounded<T>() -> (UnboundedSender<T>, UnboundedReceiver<T>) {
21    unbounded_channel()
22}
23
24/// Create a oneshot channel.
25pub fn oneshot<T>() -> (OneshotSender<T>, OneshotReceiver<T>) {
26    tokio::sync::oneshot::channel()
27}
28
29/// Handle that can be used to abort a spawned task.
30///
31/// On native, this wraps tokio's AbortHandle. On WASM, abort is a no-op
32/// since there's no way to cancel fire-and-forget tasks.
33#[derive(Debug)]
34pub struct AbortHandle(tokio::task::AbortHandle);
35
36impl AbortHandle {
37    /// Abort the associated task.
38    ///
39    /// Returns `true` if the task was successfully aborted, `false` if it had
40    /// already completed.
41    pub fn abort(&self) -> bool {
42        // tokio's abort() doesn't return anything, but we can check if finished
43        self.0.abort();
44        // Return true since we sent the abort signal
45        true
46    }
47}
48
49/// Spawn a task that runs concurrently.
50///
51/// On native, this returns a JoinHandle. On WASM, spawning is fire-and-forget.
52pub fn spawn<F>(future: F) -> tokio::task::JoinHandle<F::Output>
53where
54    F: Future + Send + 'static,
55    F::Output: Send + 'static,
56{
57    tokio::spawn(future)
58}
59
60/// Spawn a task and return an abort handle that can be used to cancel it.
61///
62/// On native, this uses tokio's abort mechanism. On WASM, the abort handle
63/// is a no-op since tasks can't be cancelled.
64pub fn spawn_with_abort<F>(future: F) -> AbortHandle
65where
66    F: Future<Output = ()> + Send + 'static,
67{
68    let handle = tokio::spawn(future);
69    AbortHandle(handle.abort_handle())
70}
71
72/// Sleep for the given duration.
73pub async fn sleep(duration: Duration) {
74    tokio::time::sleep(duration).await;
75}
76
77/// Run a future with a timeout.
78///
79/// Returns `Some(result)` if the future completes within the timeout,
80/// or `None` if the timeout expires.
81pub async fn timeout<F, T>(duration: Duration, future: F) -> Option<T>
82where
83    F: Future<Output = T>,
84{
85    (tokio::time::timeout(duration, future).await).ok()
86}