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}