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