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 {}