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}