luminal/runtime/
handle.rs

1//! Runtime handle implementation
2//!
3//! This module provides the implementation of Handle, which is a lightweight
4//! reference to a Runtime that can be used to spawn tasks and block on futures.
5
6#[cfg(feature = "std")]
7use std::{future::Future, sync::Arc};
8
9#[cfg(not(feature = "std"))]
10use core::future::Future;
11
12#[cfg(not(feature = "std"))]
13use alloc::sync::Arc;
14
15#[cfg(feature = "std")]
16use super::executor::Executor;
17#[cfg(not(feature = "std"))]
18use super::simple_executor::SimpleExecutor as Executor;
19use super::join_handle::JoinHandle;
20
21/// A lightweight handle to a Runtime
22///
23/// Handle provides a way to interact with the runtime
24/// without having to clone the entire Runtime structure.
25/// It allows spawning tasks and blocking on futures.
26pub struct Handle {
27    /// The executor that this handle refers to
28    pub(crate) executor: Arc<Executor>,
29}
30
31impl Handle {
32    /// Creates a new handle to the provided executor
33    ///
34    /// # Parameters
35    ///
36    /// * `executor` - The executor this handle will use
37    ///
38    /// # Returns
39    ///
40    /// A new Handle instance
41    pub(crate) fn new(executor: Arc<Executor>) -> Self {
42        Handle { executor }
43    }
44
45    /// Spawns a future onto the runtime
46    ///
47    /// This method takes a future and begins executing it on the runtime,
48    /// returning a JoinHandle that can be used to await its completion and
49    /// retrieve its result.
50    ///
51    /// # Type Parameters
52    ///
53    /// * `F` - The future type
54    ///
55    /// # Parameters
56    ///
57    /// * `future` - The future to execute
58    ///
59    /// # Returns
60    ///
61    /// A JoinHandle that can be used to await the future's completion
62    ///
63    /// # Examples
64    ///
65    /// ```
66    /// use luminal::Runtime;
67    ///
68    /// let rt = Runtime::new().unwrap();
69    /// let handle = rt.handle();
70    /// 
71    /// let task = handle.spawn(async {
72    ///     println!("Running from a handle");
73    ///     42
74    /// });
75    /// 
76    /// let result = handle.block_on(task);
77    /// assert_eq!(result, 42);
78    /// ```
79    pub fn spawn<F>(&self, future: F) -> JoinHandle<F::Output>
80    where
81        F: Future + Send + 'static,
82        F::Output: Send + 'static,
83    {
84        self.executor.spawn(future)
85    }
86
87    /// Blocks the current thread until the provided future completes
88    ///
89    /// This method takes a future and blocks the current thread until it completes,
90    /// helping process other tasks while waiting to avoid deadlocks.
91    ///
92    /// # Type Parameters
93    ///
94    /// * `F` - The future type
95    ///
96    /// # Parameters
97    ///
98    /// * `future` - The future to execute and wait for
99    ///
100    /// # Returns
101    ///
102    /// The output of the future
103    ///
104    /// # Examples
105    ///
106    /// ```
107    /// use luminal::Runtime;
108    ///
109    /// let rt = Runtime::new().unwrap();
110    /// let handle = rt.handle();
111    /// 
112    /// let result = handle.block_on(async {
113    ///     println!("Blocking using a handle");
114    ///     42
115    /// });
116    /// 
117    /// assert_eq!(result, 42);
118    /// ```
119    pub fn block_on<F>(&self, future: F) -> F::Output
120    where
121        F: Future + Send + 'static,
122        F::Output: Send + 'static,
123    {
124        self.executor.block_on(future)
125    }
126}
127
128impl Clone for Handle {
129    /// Creates a new handle referring to the same executor
130    ///
131    /// This creates a lightweight clone that shares the same
132    /// underlying executor as the original handle.
133    ///
134    /// # Returns
135    ///
136    /// A new Handle instance referring to the same executor
137    fn clone(&self) -> Self {
138        Handle {
139            executor: self.executor.clone(),
140        }
141    }
142}