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