broker_tokio/runtime/handle.rs
1use crate::runtime::{blocking, context, io, time, Spawner};
2use std::{error, fmt};
3
4cfg_rt_core! {
5 use crate::task::JoinHandle;
6
7 use std::future::Future;
8}
9
10/// Handle to the runtime
11#[derive(Debug, Clone)]
12pub struct Handle {
13 pub(super) spawner: Spawner,
14
15 /// Handles to the I/O drivers
16 pub(super) io_handle: io::Handle,
17
18 /// Handles to the time drivers
19 pub(super) time_handle: time::Handle,
20
21 /// Source of `Instant::now()`
22 pub(super) clock: time::Clock,
23
24 /// Blocking pool spawner
25 pub(super) blocking_spawner: blocking::Spawner,
26}
27
28impl Handle {
29 /// Enter the runtime context
30 pub fn enter<F, R>(&self, f: F) -> R
31 where
32 F: FnOnce() -> R,
33 {
34 context::enter(self.clone(), f)
35 }
36
37 /// Returns a Handle view over the currently running Runtime
38 ///
39 /// # Panic
40 ///
41 /// A Runtime must have been started or this will panic
42 ///
43 /// # Examples
44 ///
45 /// This allows for the current handle to be gotten when running in a `#`
46 ///
47 /// ```
48 /// # use tokio::runtime::Runtime;
49 ///
50 /// # fn dox() {
51 /// # let rt = Runtime::new().unwrap();
52 /// # rt.spawn(async {
53 /// use tokio::runtime::Handle;
54 ///
55 /// let handle = Handle::current();
56 /// handle.spawn(async {
57 /// println!("now running in the existing Runtime");
58 /// })
59 /// # });
60 /// # }
61 /// ```
62 pub fn current() -> Self {
63 context::current().expect("not currently running on the Tokio runtime.")
64 }
65
66 /// Returns a Handle view over the currently running Runtime
67 ///
68 /// Returns an error if no Runtime has been started
69 ///
70 /// Contrary to `current`, this never panics
71 pub fn try_current() -> Result<Self, TryCurrentError> {
72 context::current().ok_or(TryCurrentError(()))
73 }
74}
75
76cfg_rt_core! {
77 impl Handle {
78 /// Spawn a future onto the Tokio runtime.
79 ///
80 /// This spawns the given future onto the runtime's executor, usually a
81 /// thread pool. The thread pool is then responsible for polling the future
82 /// until it completes.
83 ///
84 /// See [module level][mod] documentation for more details.
85 ///
86 /// [mod]: index.html
87 ///
88 /// # Examples
89 ///
90 /// ```
91 /// use tokio::runtime::Runtime;
92 ///
93 /// # fn dox() {
94 /// // Create the runtime
95 /// let rt = Runtime::new().unwrap();
96 /// let handle = rt.handle();
97 ///
98 /// // Spawn a future onto the runtime
99 /// handle.spawn(async {
100 /// println!("now running on a worker thread");
101 /// });
102 /// # }
103 /// ```
104 ///
105 /// # Panics
106 ///
107 /// This function panics if the spawn fails. Failure occurs if the executor
108 /// is currently at capacity and is unable to spawn a new future.
109 pub fn spawn<F>(&self, future: F) -> JoinHandle<F::Output>
110 where
111 F: Future + Send + 'static,
112 F::Output: Send + 'static,
113 {
114 self.spawner.spawn(future)
115 }
116 }
117}
118
119/// Error returned by `try_current` when no Runtime has been started
120pub struct TryCurrentError(());
121
122impl fmt::Debug for TryCurrentError {
123 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
124 f.debug_struct("TryCurrentError").finish()
125 }
126}
127
128impl fmt::Display for TryCurrentError {
129 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
130 f.write_str("no tokio Runtime has been initialized")
131 }
132}
133
134impl error::Error for TryCurrentError {}