1use crate::runtime::blocking::BlockingPool;
2use crate::runtime::scheduler::CurrentThread;
3use crate::runtime::{context, EnterGuard, Handle};
4use crate::task::JoinHandle;
5
6use std::future::Future;
7use std::time::Duration;
8
9cfg_rt_multi_thread! {
10 use crate::runtime::Builder;
11 use crate::runtime::scheduler::MultiThread;
12}
13
14/// The Tokio runtime.
15///
16/// The runtime provides an I/O driver, task scheduler, [timer], and
17/// blocking pool, necessary for running asynchronous tasks.
18///
19/// Instances of `Runtime` can be created using [`new`], or [`Builder`].
20/// However, most users will use the `#[tokio::main]` annotation on their
21/// entry point instead.
22///
23/// See [module level][mod] documentation for more details.
24///
25/// # Shutdown
26///
27/// Shutting down the runtime is done by dropping the value, or calling
28/// [`Runtime::shutdown_background`] or [`Runtime::shutdown_timeout`].
29///
30/// Tasks spawned through [`Runtime::spawn`] keep running until they yield.
31/// Then they are dropped. They are not *guaranteed* to run to completion, but
32/// *might* do so if they do not yield until completion.
33///
34/// Blocking functions spawned through [`Runtime::spawn_blocking`] keep running
35/// until they return.
36///
37/// The thread initiating the shutdown blocks until all spawned work has been
38/// stopped. This can take an indefinite amount of time. The `Drop`
39/// implementation waits forever for this.
40///
41/// `shutdown_background` and `shutdown_timeout` can be used if waiting forever
42/// is undesired. When the timeout is reached, spawned work that did not stop
43/// in time and threads running it are leaked. The work continues to run until
44/// one of the stopping conditions is fulfilled, but the thread initiating the
45/// shutdown is unblocked.
46///
47/// Once the runtime has been dropped, any outstanding I/O resources bound to
48/// it will no longer function. Calling any method on them will result in an
49/// error.
50///
51/// # Sharing
52///
53/// The Tokio runtime implements `Sync` and `Send` to allow you to wrap it
54/// in a `Arc`. Most fn take `&self` to allow you to call them concurrently
55/// across multiple threads.
56///
57/// Calls to `shutdown` and `shutdown_timeout` require exclusive ownership of
58/// the runtime type and this can be achieved via `Arc::try_unwrap` when only
59/// one strong count reference is left over.
60///
61/// [timer]: crate::time
62/// [mod]: index.html
63/// [`new`]: method@Self::new
64/// [`Builder`]: struct@Builder
65#[derive(Debug)]
66pub struct Runtime {
67 /// Task scheduler
68 scheduler: Scheduler,
69
70 /// Handle to runtime, also contains driver handles
71 handle: Handle,
72
73 /// Blocking pool handle, used to signal shutdown
74 blocking_pool: BlockingPool,
75}
76
77/// The flavor of a `Runtime`.
78///
79/// This is the return type for [`Handle::runtime_flavor`](crate::runtime::Handle::runtime_flavor()).
80#[derive(Debug, PartialEq, Eq)]
81#[non_exhaustive]
82pub enum RuntimeFlavor {
83 /// The flavor that executes all tasks on the current thread.
84 CurrentThread,
85 /// The flavor that executes tasks across multiple threads.
86 MultiThread,
87}
88
89/// The runtime scheduler is either a multi-thread or a current-thread executor.
90#[derive(Debug)]
91pub(super) enum Scheduler {
92 /// Execute all tasks on the current-thread.
93 CurrentThread(CurrentThread),
94
95 /// Execute tasks across multiple threads.
96 #[cfg(all(feature = "rt-multi-thread", not(tokio_wasi)))]
97 MultiThread(MultiThread),
98}
99
100impl Runtime {
101 pub(super) fn from_parts(
102 scheduler: Scheduler,
103 handle: Handle,
104 blocking_pool: BlockingPool,
105 ) -> Runtime {
106 Runtime {
107 scheduler,
108 handle,
109 blocking_pool,
110 }
111 }
112
113 cfg_not_wasi! {
114 /// Creates a new runtime instance with default configuration values.
115 ///
116 /// This results in the multi threaded scheduler, I/O driver, and time driver being
117 /// initialized.
118 ///
119 /// Most applications will not need to call this function directly. Instead,
120 /// they will use the [`#[tokio::main]` attribute][main]. When a more complex
121 /// configuration is necessary, the [runtime builder] may be used.
122 ///
123 /// See [module level][mod] documentation for more details.
124 ///
125 /// # Examples
126 ///
127 /// Creating a new `Runtime` with default configuration values.
128 ///
129 /// ```
130 /// use tokio::runtime::Runtime;
131 ///
132 /// let rt = Runtime::new()
133 /// .unwrap();
134 ///
135 /// // Use the runtime...
136 /// ```
137 ///
138 /// [mod]: index.html
139 /// [main]: ../attr.main.html
140 /// [threaded scheduler]: index.html#threaded-scheduler
141 /// [runtime builder]: crate::runtime::Builder
142 #[cfg(feature = "rt-multi-thread")]
143 #[cfg_attr(docsrs, doc(cfg(feature = "rt-multi-thread")))]
144 pub fn new() -> std::io::Result<Runtime> {
145 Builder::new_multi_thread().enable_all().build()
146 }
147 }
148
149 /// Returns a handle to the runtime's spawner.
150 ///
151 /// The returned handle can be used to spawn tasks that run on this runtime, and can
152 /// be cloned to allow moving the `Handle` to other threads.
153 ///
154 /// Calling [`Handle::block_on`] on a handle to a `current_thread` runtime is error-prone.
155 /// Refer to the documentation of [`Handle::block_on`] for more.
156 ///
157 /// # Examples
158 ///
159 /// ```
160 /// use tokio::runtime::Runtime;
161 ///
162 /// let rt = Runtime::new()
163 /// .unwrap();
164 ///
165 /// let handle = rt.handle();
166 ///
167 /// // Use the handle...
168 /// ```
169 pub fn handle(&self) -> &Handle {
170 &self.handle
171 }
172
173 /// Spawns a future onto the Tokio runtime.
174 ///
175 /// This spawns the given future onto the runtime's executor, usually a
176 /// thread pool. The thread pool is then responsible for polling the future
177 /// until it completes.
178 ///
179 /// The provided future will start running in the background immediately
180 /// when `spawn` is called, even if you don't await the returned
181 /// `JoinHandle`.
182 ///
183 /// See [module level][mod] documentation for more details.
184 ///
185 /// [mod]: index.html
186 ///
187 /// # Examples
188 ///
189 /// ```
190 /// use tokio::runtime::Runtime;
191 ///
192 /// # fn dox() {
193 /// // Create the runtime
194 /// let rt = Runtime::new().unwrap();
195 ///
196 /// // Spawn a future onto the runtime
197 /// rt.spawn(async {
198 /// println!("now running on a worker thread");
199 /// });
200 /// # }
201 /// ```
202 #[track_caller]
203 pub fn spawn<F>(&self, future: F) -> JoinHandle<F::Output>
204 where
205 F: Future + Send + 'static,
206 F::Output: Send + 'static,
207 {
208 self.handle.spawn(future)
209 }
210
211 /// Runs the provided function on an executor dedicated to blocking operations.
212 ///
213 /// # Examples
214 ///
215 /// ```
216 /// use tokio::runtime::Runtime;
217 ///
218 /// # fn dox() {
219 /// // Create the runtime
220 /// let rt = Runtime::new().unwrap();
221 ///
222 /// // Spawn a blocking function onto the runtime
223 /// rt.spawn_blocking(|| {
224 /// println!("now running on a worker thread");
225 /// });
226 /// # }
227 #[track_caller]
228 pub fn spawn_blocking<F, R>(&self, func: F) -> JoinHandle<R>
229 where
230 F: FnOnce() -> R + Send + 'static,
231 R: Send + 'static,
232 {
233 self.handle.spawn_blocking(func)
234 }
235
236 /// Runs a future to completion on the Tokio runtime. This is the
237 /// runtime's entry point.
238 ///
239 /// This runs the given future on the current thread, blocking until it is
240 /// complete, and yielding its resolved result. Any tasks or timers
241 /// which the future spawns internally will be executed on the runtime.
242 ///
243 /// # Non-worker future
244 ///
245 /// Note that the future required by this function does not run as a
246 /// worker. The expectation is that other tasks are spawned by the future here.
247 /// Awaiting on other futures from the future provided here will not
248 /// perform as fast as those spawned as workers.
249 ///
250 /// # Multi thread scheduler
251 ///
252 /// When the multi thread scheduler is used this will allow futures
253 /// to run within the io driver and timer context of the overall runtime.
254 ///
255 /// Any spawned tasks will continue running after `block_on` returns.
256 ///
257 /// # Current thread scheduler
258 ///
259 /// When the current thread scheduler is enabled `block_on`
260 /// can be called concurrently from multiple threads. The first call
261 /// will take ownership of the io and timer drivers. This means
262 /// other threads which do not own the drivers will hook into that one.
263 /// When the first `block_on` completes, other threads will be able to
264 /// "steal" the driver to allow continued execution of their futures.
265 ///
266 /// Any spawned tasks will be suspended after `block_on` returns. Calling
267 /// `block_on` again will resume previously spawned tasks.
268 ///
269 /// # Panics
270 ///
271 /// This function panics if the provided future panics, or if called within an
272 /// asynchronous execution context.
273 ///
274 /// # Examples
275 ///
276 /// ```no_run
277 /// use tokio::runtime::Runtime;
278 ///
279 /// // Create the runtime
280 /// let rt = Runtime::new().unwrap();
281 ///
282 /// // Execute the future, blocking the current thread until completion
283 /// rt.block_on(async {
284 /// println!("hello");
285 /// });
286 /// ```
287 ///
288 /// [handle]: fn@Handle::block_on
289 #[track_caller]
290 pub fn block_on<F: Future>(&self, future: F) -> F::Output {
291 #[cfg(all(
292 tokio_unstable,
293 tokio_taskdump,
294 feature = "rt",
295 target_os = "linux",
296 any(target_arch = "aarch64", target_arch = "x86", target_arch = "x86_64")
297 ))]
298 let future = super::task::trace::Trace::root(future);
299
300 #[cfg(all(tokio_unstable, feature = "tracing"))]
301 let future = crate::util::trace::task(
302 future,
303 "block_on",
304 None,
305 crate::runtime::task::Id::next().as_u64(),
306 );
307
308 let _enter = self.enter();
309
310 match &self.scheduler {
311 Scheduler::CurrentThread(exec) => exec.block_on(&self.handle.inner, future),
312 #[cfg(all(feature = "rt-multi-thread", not(tokio_wasi)))]
313 Scheduler::MultiThread(exec) => exec.block_on(&self.handle.inner, future),
314 }
315 }
316
317 /// Enters the runtime context.
318 ///
319 /// This allows you to construct types that must have an executor
320 /// available on creation such as [`Sleep`] or [`TcpStream`]. It will
321 /// also allow you to call methods such as [`tokio::spawn`].
322 ///
323 /// [`Sleep`]: struct@crate::time::Sleep
324 /// [`TcpStream`]: struct@crate::net::TcpStream
325 /// [`tokio::spawn`]: fn@crate::spawn
326 ///
327 /// # Example
328 ///
329 /// ```
330 /// use tokio::runtime::Runtime;
331 ///
332 /// fn function_that_spawns(msg: String) {
333 /// // Had we not used `rt.enter` below, this would panic.
334 /// tokio::spawn(async move {
335 /// println!("{}", msg);
336 /// });
337 /// }
338 ///
339 /// fn main() {
340 /// let rt = Runtime::new().unwrap();
341 ///
342 /// let s = "Hello World!".to_string();
343 ///
344 /// // By entering the context, we tie `tokio::spawn` to this executor.
345 /// let _guard = rt.enter();
346 /// function_that_spawns(s);
347 /// }
348 /// ```
349 pub fn enter(&self) -> EnterGuard<'_> {
350 self.handle.enter()
351 }
352
353 /// Shuts down the runtime, waiting for at most `duration` for all spawned
354 /// work to stop.
355 ///
356 /// See the [struct level documentation](Runtime#shutdown) for more details.
357 ///
358 /// # Examples
359 ///
360 /// ```
361 /// use tokio::runtime::Runtime;
362 /// use tokio::task;
363 ///
364 /// use std::thread;
365 /// use std::time::Duration;
366 ///
367 /// fn main() {
368 /// let runtime = Runtime::new().unwrap();
369 ///
370 /// runtime.block_on(async move {
371 /// task::spawn_blocking(move || {
372 /// thread::sleep(Duration::from_secs(10_000));
373 /// });
374 /// });
375 ///
376 /// runtime.shutdown_timeout(Duration::from_millis(100));
377 /// }
378 /// ```
379 pub fn shutdown_timeout(mut self, duration: Duration) {
380 // Wakeup and shutdown all the worker threads
381 self.handle.inner.shutdown();
382 self.blocking_pool.shutdown(Some(duration));
383 }
384
385 /// Shuts down the runtime, without waiting for any spawned work to stop.
386 ///
387 /// This can be useful if you want to drop a runtime from within another runtime.
388 /// Normally, dropping a runtime will block indefinitely for spawned blocking tasks
389 /// to complete, which would normally not be permitted within an asynchronous context.
390 /// By calling `shutdown_background()`, you can drop the runtime from such a context.
391 ///
392 /// Note however, that because we do not wait for any blocking tasks to complete, this
393 /// may result in a resource leak (in that any blocking tasks are still running until they
394 /// return.
395 ///
396 /// See the [struct level documentation](Runtime#shutdown) for more details.
397 ///
398 /// This function is equivalent to calling `shutdown_timeout(Duration::from_nanos(0))`.
399 ///
400 /// ```
401 /// use tokio::runtime::Runtime;
402 ///
403 /// fn main() {
404 /// let runtime = Runtime::new().unwrap();
405 ///
406 /// runtime.block_on(async move {
407 /// let inner_runtime = Runtime::new().unwrap();
408 /// // ...
409 /// inner_runtime.shutdown_background();
410 /// });
411 /// }
412 /// ```
413 pub fn shutdown_background(self) {
414 self.shutdown_timeout(Duration::from_nanos(0))
415 }
416}
417
418#[allow(clippy::single_match)] // there are comments in the error branch, so we don't want if-let
419impl Drop for Runtime {
420 fn drop(&mut self) {
421 match &mut self.scheduler {
422 Scheduler::CurrentThread(current_thread: &mut CurrentThread) => {
423 // This ensures that tasks spawned on the current-thread
424 // runtime are dropped inside the runtime's context.
425 let _guard: Option = context::try_set_current(&self.handle.inner);
426 current_thread.shutdown(&self.handle.inner);
427 }
428 #[cfg(all(feature = "rt-multi-thread", not(tokio_wasi)))]
429 Scheduler::MultiThread(multi_thread: &mut MultiThread) => {
430 // The threaded scheduler drops its tasks on its worker threads, which is
431 // already in the runtime's context.
432 multi_thread.shutdown(&self.handle.inner);
433 }
434 }
435 }
436}
437
438cfg_metrics! {
439 impl Runtime {
440 /// TODO
441 pub fn metrics(&self) -> crate::runtime::RuntimeMetrics {
442 self.handle.metrics()
443 }
444 }
445}
446