/rust/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.53.1/src/runtime/mod.rs
Line | Count | Source |
1 | | //! The Tokio runtime. |
2 | | //! |
3 | | //! Unlike other Rust programs, asynchronous applications require runtime |
4 | | //! support. In particular, the following runtime services are necessary: |
5 | | //! |
6 | | //! * An **I/O event loop**, called the driver, which drives I/O resources and |
7 | | //! dispatches I/O events to tasks that depend on them. |
8 | | //! * A **scheduler** to execute [tasks] that use these I/O resources. |
9 | | //! * A **timer** for scheduling work to run after a set period of time. |
10 | | //! |
11 | | //! Tokio's [`Runtime`] bundles all of these services as a single type, allowing |
12 | | //! them to be started, shut down, and configured together. However, often it is |
13 | | //! not required to configure a [`Runtime`] manually, and a user may just use the |
14 | | //! [`tokio::main`] attribute macro, which creates a [`Runtime`] under the hood. |
15 | | //! |
16 | | //! # Choose your runtime |
17 | | //! |
18 | | //! Here is the rules of thumb to choose the right runtime for your application. |
19 | | //! |
20 | | //! ```plaintext |
21 | | //! +------------------------------------------------------+ |
22 | | //! | Do you want work-stealing or multi-thread scheduler? | |
23 | | //! +------------------------------------------------------+ |
24 | | //! | Yes | No |
25 | | //! | | |
26 | | //! | | |
27 | | //! v | |
28 | | //! +------------------------+ | |
29 | | //! | Multi-threaded Runtime | | |
30 | | //! +------------------------+ | |
31 | | //! | |
32 | | //! V |
33 | | //! +--------------------------------+ |
34 | | //! | Do you execute `!Send` Future? | |
35 | | //! +--------------------------------+ |
36 | | //! | Yes | No |
37 | | //! | | |
38 | | //! V | |
39 | | //! +---------------+ | |
40 | | //! | Local Runtime | | |
41 | | //! +---------------+ | |
42 | | //! | |
43 | | //! v |
44 | | //! +------------------------+ |
45 | | //! | Current-thread Runtime | |
46 | | //! +------------------------+ |
47 | | //! ``` |
48 | | //! |
49 | | //! The above decision tree is not exhaustive. there are other factors that |
50 | | //! may influence your decision. |
51 | | //! |
52 | | //! ## Bridging with sync code |
53 | | //! |
54 | | //! See <https://tokio.rs/tokio/topics/bridging> for details. |
55 | | //! |
56 | | //! ## NUMA awareness |
57 | | //! |
58 | | //! The tokio runtime is not NUMA (Non-Uniform Memory Access) aware. |
59 | | //! You may want to start multiple runtimes instead of a single runtime |
60 | | //! for better performance on NUMA systems. |
61 | | //! |
62 | | //! # Usage |
63 | | //! |
64 | | //! When no fine tuning is required, the [`tokio::main`] attribute macro can be |
65 | | //! used. |
66 | | //! |
67 | | //! ```no_run |
68 | | //! # #[cfg(not(target_family = "wasm"))] |
69 | | //! # { |
70 | | //! use tokio::net::TcpListener; |
71 | | //! use tokio::io::{AsyncReadExt, AsyncWriteExt}; |
72 | | //! |
73 | | //! #[tokio::main] |
74 | | //! async fn main() -> Result<(), Box<dyn std::error::Error>> { |
75 | | //! let listener = TcpListener::bind("127.0.0.1:8080").await?; |
76 | | //! |
77 | | //! loop { |
78 | | //! let (mut socket, _) = listener.accept().await?; |
79 | | //! |
80 | | //! tokio::spawn(async move { |
81 | | //! let mut buf = [0; 1024]; |
82 | | //! |
83 | | //! // In a loop, read data from the socket and write the data back. |
84 | | //! loop { |
85 | | //! let n = match socket.read(&mut buf).await { |
86 | | //! // socket closed |
87 | | //! Ok(0) => return, |
88 | | //! Ok(n) => n, |
89 | | //! Err(e) => { |
90 | | //! println!("failed to read from socket; err = {:?}", e); |
91 | | //! return; |
92 | | //! } |
93 | | //! }; |
94 | | //! |
95 | | //! // Write the data back |
96 | | //! if let Err(e) = socket.write_all(&buf[0..n]).await { |
97 | | //! println!("failed to write to socket; err = {:?}", e); |
98 | | //! return; |
99 | | //! } |
100 | | //! } |
101 | | //! }); |
102 | | //! } |
103 | | //! } |
104 | | //! # } |
105 | | //! ``` |
106 | | //! |
107 | | //! From within the context of the runtime, additional tasks are spawned using |
108 | | //! the [`tokio::spawn`] function. Futures spawned using this function will be |
109 | | //! executed on the same thread pool used by the [`Runtime`]. |
110 | | //! |
111 | | //! A [`Runtime`] instance can also be used directly. |
112 | | //! |
113 | | //! ```no_run |
114 | | //! # #[cfg(not(target_family = "wasm"))] |
115 | | //! # { |
116 | | //! use tokio::net::TcpListener; |
117 | | //! use tokio::io::{AsyncReadExt, AsyncWriteExt}; |
118 | | //! use tokio::runtime::Runtime; |
119 | | //! |
120 | | //! fn main() -> Result<(), Box<dyn std::error::Error>> { |
121 | | //! // Create the runtime |
122 | | //! let rt = Runtime::new()?; |
123 | | //! |
124 | | //! // Spawn the root task |
125 | | //! rt.block_on(async { |
126 | | //! let listener = TcpListener::bind("127.0.0.1:8080").await?; |
127 | | //! |
128 | | //! loop { |
129 | | //! let (mut socket, _) = listener.accept().await?; |
130 | | //! |
131 | | //! tokio::spawn(async move { |
132 | | //! let mut buf = [0; 1024]; |
133 | | //! |
134 | | //! // In a loop, read data from the socket and write the data back. |
135 | | //! loop { |
136 | | //! let n = match socket.read(&mut buf).await { |
137 | | //! // socket closed |
138 | | //! Ok(0) => return, |
139 | | //! Ok(n) => n, |
140 | | //! Err(e) => { |
141 | | //! println!("failed to read from socket; err = {:?}", e); |
142 | | //! return; |
143 | | //! } |
144 | | //! }; |
145 | | //! |
146 | | //! // Write the data back |
147 | | //! if let Err(e) = socket.write_all(&buf[0..n]).await { |
148 | | //! println!("failed to write to socket; err = {:?}", e); |
149 | | //! return; |
150 | | //! } |
151 | | //! } |
152 | | //! }); |
153 | | //! } |
154 | | //! }) |
155 | | //! } |
156 | | //! # } |
157 | | //! ``` |
158 | | //! |
159 | | //! ## Runtime Configurations |
160 | | //! |
161 | | //! Tokio provides multiple task scheduling strategies, suitable for different |
162 | | //! applications. The [runtime builder] or `#[tokio::main]` attribute may be |
163 | | //! used to select which scheduler to use. |
164 | | //! |
165 | | //! #### Multi-Thread Scheduler |
166 | | //! |
167 | | //! The multi-thread scheduler executes futures on a _thread pool_, using a |
168 | | //! work-stealing strategy. By default, it will start a worker thread for each |
169 | | //! CPU core available on the system. This tends to be the ideal configuration |
170 | | //! for most applications. The multi-thread scheduler requires the `rt-multi-thread` |
171 | | //! feature flag, and is selected by default: |
172 | | //! ``` |
173 | | //! # #[cfg(not(target_family = "wasm"))] |
174 | | //! # { |
175 | | //! use tokio::runtime; |
176 | | //! |
177 | | //! # fn main() -> Result<(), Box<dyn std::error::Error>> { |
178 | | //! let threaded_rt = runtime::Runtime::new()?; |
179 | | //! # Ok(()) } |
180 | | //! # } |
181 | | //! ``` |
182 | | //! |
183 | | //! Most applications should use the multi-thread scheduler, except in some |
184 | | //! niche use-cases, such as when running only a single thread is required. |
185 | | //! |
186 | | //! #### Current-Thread Scheduler |
187 | | //! |
188 | | //! The current-thread scheduler provides a _single-threaded_ future executor. |
189 | | //! All tasks will be created and executed on the current thread. This requires |
190 | | //! the `rt` feature flag. |
191 | | //! ``` |
192 | | //! use tokio::runtime; |
193 | | //! |
194 | | //! # fn main() -> Result<(), Box<dyn std::error::Error>> { |
195 | | //! let rt = runtime::Builder::new_current_thread() |
196 | | //! .build()?; |
197 | | //! # Ok(()) } |
198 | | //! ``` |
199 | | //! |
200 | | //! #### Resource drivers |
201 | | //! |
202 | | //! When configuring a runtime by hand, no resource drivers are enabled by |
203 | | //! default. In this case, attempting to use networking types or time types will |
204 | | //! fail. In order to enable these types, the resource drivers must be enabled. |
205 | | //! This is done with [`Builder::enable_io`] and [`Builder::enable_time`]. As a |
206 | | //! shorthand, [`Builder::enable_all`] enables both resource drivers. |
207 | | //! |
208 | | //! ## Driving the runtime |
209 | | //! |
210 | | //! A Tokio runtime can only execute tasks if the runtime is running. Normally |
211 | | //! this is not an issue as the default configuration of a runtime is always running, |
212 | | //! but alternate configurations such as the current-thread runtime require that |
213 | | //! [`Runtime::block_on`] is called. |
214 | | //! |
215 | | //! - A multi-threaded runtime is always running because it spawns its own worker |
216 | | //! threads. |
217 | | //! - A current-thread runtime does not spawn any worker threads, so it can only |
218 | | //! execute tasks when you provide a thread by calling [`Runtime::block_on`]. |
219 | | //! - A [`LocalSet`](crate::task::LocalSet) only executes local tasks spawned on |
220 | | //! it when the `LocalSet` is `.awaited` or otherwise driven using one of its |
221 | | //! methods for this purpose. |
222 | | //! |
223 | | //! Please be aware that [`Handle::block_on`] does not drive the runtime. |
224 | | //! There must be at least one call to [`Runtime::block_on`] when using the current |
225 | | //! thread runtime. [`Handle::block_on`] is not enough. |
226 | | //! |
227 | | //! ## Lifetime of spawned threads |
228 | | //! |
229 | | //! The runtime may spawn threads depending on its configuration and usage. The |
230 | | //! multi-thread scheduler spawns threads to schedule tasks and for `spawn_blocking` |
231 | | //! calls. |
232 | | //! |
233 | | //! While the `Runtime` is active, threads may shut down after periods of being |
234 | | //! idle. Once `Runtime` is dropped, all runtime threads have usually been |
235 | | //! terminated, but in the presence of unstoppable spawned work are not |
236 | | //! guaranteed to have been terminated. See the |
237 | | //! [struct level documentation](Runtime#shutdown) for more details. |
238 | | //! |
239 | | //! ## Unix `fork` |
240 | | //! |
241 | | //! User code that calls `fork(2)` without immediately calling `exec` must not |
242 | | //! reuse Tokio in the child process. Tokio supports this kind of fork only in |
243 | | //! two cases: |
244 | | //! |
245 | | //! - The fork happens before the parent process has used Tokio in any way. |
246 | | //! - The child process does not use Tokio after the fork. |
247 | | //! |
248 | | //! Creating or using a Tokio runtime in a child process after the parent has |
249 | | //! used Tokio is not supported, even if the runtime in the child is newly |
250 | | //! created. Some Tokio modules, including process and signal handling, use |
251 | | //! process-global state that cannot currently be reset after `fork`. |
252 | | //! |
253 | | //! [tasks]: crate::task |
254 | | //! [`Runtime`]: Runtime |
255 | | //! [`tokio::spawn`]: crate::spawn |
256 | | //! [`tokio::main`]: ../attr.main.html |
257 | | //! [runtime builder]: crate::runtime::Builder |
258 | | //! [`Runtime::new`]: crate::runtime::Runtime::new |
259 | | //! [`Builder::enable_io`]: crate::runtime::Builder::enable_io |
260 | | //! [`Builder::enable_time`]: crate::runtime::Builder::enable_time |
261 | | //! [`Builder::enable_all`]: crate::runtime::Builder::enable_all |
262 | | //! |
263 | | //! # Detailed runtime behavior |
264 | | //! |
265 | | //! This section gives more details into how the Tokio runtime will schedule |
266 | | //! tasks for execution. |
267 | | //! |
268 | | //! At its most basic level, a runtime has a collection of tasks that need to be |
269 | | //! scheduled. It will repeatedly remove a task from that collection and |
270 | | //! schedule it (by calling [`poll`]). When the collection is empty, the thread |
271 | | //! will go to sleep until a task is added to the collection. |
272 | | //! |
273 | | //! However, the above is not sufficient to guarantee a well-behaved runtime. |
274 | | //! For example, the runtime might have a single task that is always ready to be |
275 | | //! scheduled, and schedule that task every time. This is a problem because it |
276 | | //! starves other tasks by not scheduling them. To solve this, Tokio provides |
277 | | //! the following fairness guarantee: |
278 | | //! |
279 | | //! > If the total number of tasks does not grow without bound, and no task is |
280 | | //! > [blocking the thread], then it is guaranteed that tasks are scheduled |
281 | | //! > fairly. |
282 | | //! |
283 | | //! Or, more formally: |
284 | | //! |
285 | | //! > Under the following two assumptions: |
286 | | //! > |
287 | | //! > * There is some number `MAX_TASKS` such that the total number of tasks on |
288 | | //! > the runtime at any specific point in time never exceeds `MAX_TASKS`. |
289 | | //! > * There is some number `MAX_SCHEDULE` such that calling [`poll`] on any |
290 | | //! > task spawned on the runtime returns within `MAX_SCHEDULE` time units. |
291 | | //! > |
292 | | //! > Then, there is some number `MAX_DELAY` such that when a task is woken, it |
293 | | //! > will be scheduled by the runtime within `MAX_DELAY` time units. |
294 | | //! |
295 | | //! (Here, `MAX_TASKS` and `MAX_SCHEDULE` can be any number and the user of |
296 | | //! the runtime may choose them. The `MAX_DELAY` number is controlled by the |
297 | | //! runtime, and depends on the value of `MAX_TASKS` and `MAX_SCHEDULE`.) |
298 | | //! |
299 | | //! Other than the above fairness guarantee, there is no guarantee about the |
300 | | //! order in which tasks are scheduled. There is also no guarantee that the |
301 | | //! runtime is equally fair to all tasks. For example, if the runtime has two |
302 | | //! tasks A and B that are both ready, then the runtime may schedule A five |
303 | | //! times before it schedules B. This is the case even if A yields using |
304 | | //! [`yield_now`]. All that is guaranteed is that it will schedule B eventually. |
305 | | //! |
306 | | //! Normally, tasks are scheduled only if they have been woken by calling |
307 | | //! [`wake`] on their waker. However, this is not guaranteed, and Tokio may |
308 | | //! schedule tasks that have not been woken under some circumstances. This is |
309 | | //! called a spurious wakeup. |
310 | | //! |
311 | | //! ## IO and timers |
312 | | //! |
313 | | //! Beyond just scheduling tasks, the runtime must also manage IO resources and |
314 | | //! timers. It does this by periodically checking whether there are any IO |
315 | | //! resources or timers that are ready, and waking the relevant task so that |
316 | | //! it will be scheduled. |
317 | | //! |
318 | | //! These checks are performed periodically between scheduling tasks. Under the |
319 | | //! same assumptions as the previous fairness guarantee, Tokio guarantees that |
320 | | //! it will wake tasks with an IO or timer event within some maximum number of |
321 | | //! time units. |
322 | | //! |
323 | | //! ## Current thread runtime (behavior at the time of writing) |
324 | | //! |
325 | | //! This section describes how the [current thread runtime] behaves today. This |
326 | | //! behavior may change in future versions of Tokio. |
327 | | //! |
328 | | //! The current thread runtime maintains two FIFO queues of tasks that are ready |
329 | | //! to be scheduled: the global queue and the local queue. The runtime will prefer |
330 | | //! to choose the next task to schedule from the local queue, and will only pick a |
331 | | //! task from the global queue if the local queue is empty, or if it has picked |
332 | | //! a task from the local queue 31 times in a row. The number 31 can be |
333 | | //! changed using the [`global_queue_interval`] setting. |
334 | | //! |
335 | | //! The runtime will check for new IO or timer events whenever there are no |
336 | | //! tasks ready to be scheduled, or when it has scheduled 61 tasks in a row. The |
337 | | //! number 61 may be changed using the [`event_interval`] setting. |
338 | | //! |
339 | | //! When a task is woken from within a task running on the runtime, then the |
340 | | //! woken task is added directly to the local queue. Otherwise, the task is |
341 | | //! added to the global queue. The current thread runtime does not use [the lifo |
342 | | //! slot optimization]. |
343 | | //! |
344 | | //! ## Multi threaded runtime (behavior at the time of writing) |
345 | | //! |
346 | | //! This section describes how the [multi thread runtime] behaves today. This |
347 | | //! behavior may change in future versions of Tokio. |
348 | | //! |
349 | | //! A multi thread runtime has a fixed number of worker threads, which are all |
350 | | //! created on startup. The multi thread runtime maintains one global queue, and |
351 | | //! a local queue for each worker thread. The local queue of a worker thread can |
352 | | //! fit at most 256 tasks. If more than 256 tasks are added to the local queue, |
353 | | //! then half of them are moved to the global queue to make space. |
354 | | //! |
355 | | //! The runtime will prefer to choose the next task to schedule from the local |
356 | | //! queue, and will only pick a task from the global queue if the local queue is |
357 | | //! empty, or if it has picked a task from the local queue |
358 | | //! [`global_queue_interval`] times in a row. If the value of |
359 | | //! [`global_queue_interval`] is not explicitly set using the runtime builder, |
360 | | //! then the runtime will dynamically compute it using a heuristic that targets |
361 | | //! 10ms intervals between each check of the global queue (based on the |
362 | | //! [`worker_mean_poll_time`] metric). |
363 | | //! |
364 | | //! If both the local queue and global queue is empty, then the worker thread |
365 | | //! will attempt to steal tasks from the local queue of another worker thread. |
366 | | //! Stealing is done by moving half of the tasks in one local queue to another |
367 | | //! local queue. |
368 | | //! |
369 | | //! The runtime will check for new IO or timer events whenever there are no |
370 | | //! tasks ready to be scheduled, or when it has scheduled 61 tasks in a row. The |
371 | | //! number 61 may be changed using the [`event_interval`] setting. |
372 | | //! |
373 | | //! The multi thread runtime uses [the lifo slot optimization]: Whenever a task |
374 | | //! wakes up another task, the other task is added to the worker thread's lifo |
375 | | //! slot instead of being added to a queue. If there was already a task in the |
376 | | //! lifo slot when this happened, then the lifo slot is replaced, and the task |
377 | | //! that used to be in the lifo slot is placed in the thread's local queue. |
378 | | //! When the runtime finishes scheduling a task, it will schedule the task in |
379 | | //! the lifo slot immediately, if any. When the lifo slot is used, the [coop |
380 | | //! budget] is not reset. Furthermore, if a worker thread uses the lifo slot |
381 | | //! three times in a row, it is temporarily disabled until the worker thread has |
382 | | //! scheduled a task that didn't come from the lifo slot. The lifo slot can be |
383 | | //! disabled using the [`disable_lifo_slot`] setting. The lifo slot is separate |
384 | | //! from the local queue, so other worker threads cannot steal the task in the |
385 | | //! lifo slot. |
386 | | //! |
387 | | //! When a task is woken from a thread that is not a worker thread, then the |
388 | | //! task is placed in the global queue. |
389 | | //! |
390 | | //! # Performance tuning |
391 | | //! |
392 | | //! ## File descriptor table pre-warming |
393 | | //! |
394 | | //! On Linux, file descriptor table growth can stall worker threads. See the |
395 | | //! [`prewarm-fd-table`] example. |
396 | | //! |
397 | | //! [`poll`]: std::future::Future::poll |
398 | | //! [`wake`]: std::task::Waker::wake |
399 | | //! [`yield_now`]: crate::task::yield_now |
400 | | //! [blocking the thread]: https://ryhl.io/blog/async-what-is-blocking/ |
401 | | //! [current thread runtime]: crate::runtime::Builder::new_current_thread |
402 | | //! [multi thread runtime]: crate::runtime::Builder::new_multi_thread |
403 | | //! [`global_queue_interval`]: crate::runtime::Builder::global_queue_interval |
404 | | //! [`event_interval`]: crate::runtime::Builder::event_interval |
405 | | //! [`disable_lifo_slot`]: crate::runtime::Builder::disable_lifo_slot |
406 | | //! [the lifo slot optimization]: crate::runtime::Builder::disable_lifo_slot |
407 | | //! [coop budget]: crate::task::coop#cooperative-scheduling |
408 | | //! [`worker_mean_poll_time`]: crate::runtime::RuntimeMetrics::worker_mean_poll_time |
409 | | //! [`prewarm-fd-table`]: https://github.com/tokio-rs/tokio/blob/master/examples/prewarm-fd-table.rs |
410 | | |
411 | | // At the top due to macros |
412 | | #[cfg(test)] |
413 | | #[cfg(not(target_family = "wasm"))] |
414 | | #[macro_use] |
415 | | mod tests; |
416 | | |
417 | | pub(crate) mod context; |
418 | | |
419 | | pub(crate) mod park; |
420 | | |
421 | | pub(crate) mod driver; |
422 | | |
423 | | pub(crate) mod scheduler; |
424 | | |
425 | | cfg_io_driver_impl! { |
426 | | pub(crate) mod io; |
427 | | } |
428 | | |
429 | | cfg_process_driver! { |
430 | | mod process; |
431 | | } |
432 | | |
433 | | #[allow(dead_code)] |
434 | | #[derive(Debug, Copy, Clone, PartialEq)] |
435 | | pub(crate) enum TimerFlavor { |
436 | | Traditional, |
437 | | #[cfg(all(tokio_unstable, feature = "rt-multi-thread"))] |
438 | | Alternative, |
439 | | } |
440 | | |
441 | | cfg_time! { |
442 | | pub(crate) mod time; |
443 | | |
444 | | #[cfg(all(tokio_unstable, feature = "rt-multi-thread"))] |
445 | | pub(crate) mod time_alt; |
446 | | |
447 | | use crate::time::Instant; |
448 | | |
449 | | use std::task::{Context, Poll}; |
450 | | use std::pin::Pin; |
451 | | |
452 | | #[derive(Debug)] |
453 | | pub(crate) enum Timer { |
454 | | Traditional(time::TimerEntry), |
455 | | |
456 | | #[cfg(all(tokio_unstable, feature = "rt-multi-thread"))] |
457 | | Alternative(time_alt::Timer), |
458 | | } |
459 | | |
460 | | impl Timer { |
461 | | #[cfg_attr(not(all(tokio_unstable, feature = "rt-multi-thread")), allow(unused_variables))] |
462 | | #[track_caller] |
463 | 0 | pub(crate) fn new(handle: scheduler::Handle, deadline: Instant) -> Self { |
464 | 0 | match handle.timer_flavor() { |
465 | | TimerFlavor::Traditional => { |
466 | 0 | Timer::Traditional(time::TimerEntry::new(handle)) |
467 | | } |
468 | | #[cfg(all(tokio_unstable, feature = "rt-multi-thread"))] |
469 | | TimerFlavor::Alternative => { |
470 | | Timer::Alternative(time_alt::Timer::new(handle, deadline)) |
471 | | } |
472 | | } |
473 | 0 | } |
474 | | |
475 | 0 | pub(crate) fn init(self: Pin<&mut Self>, deadline: Instant) { |
476 | | // Safety: we never move the inner entries. |
477 | 0 | let this = unsafe { self.get_unchecked_mut() }; |
478 | 0 | match this { |
479 | | // Safety: we never move the inner entries. |
480 | 0 | Timer::Traditional(entry) => unsafe { |
481 | 0 | Pin::new_unchecked(entry).init(deadline) |
482 | | } |
483 | | #[cfg(all(tokio_unstable, feature = "rt-multi-thread"))] |
484 | | Timer::Alternative(_) => {}, |
485 | | } |
486 | 0 | } |
487 | | |
488 | 0 | pub(crate) fn is_elapsed(&self) -> bool { |
489 | 0 | match self { |
490 | 0 | Timer::Traditional(entry) => entry.is_elapsed(), |
491 | | #[cfg(all(tokio_unstable, feature = "rt-multi-thread"))] |
492 | | Timer::Alternative(entry) => entry.is_elapsed(), |
493 | | } |
494 | 0 | } |
495 | | |
496 | | #[cfg_attr(not(all(tokio_unstable, feature = "rt-multi-thread")), allow(unused_variables))] |
497 | 0 | pub(crate) fn reset(self: Pin<&mut Self>, handle: scheduler::Handle, deadline: Instant) { |
498 | | // Safety: we never move the inner entries. |
499 | 0 | let this = unsafe { self.get_unchecked_mut() }; |
500 | 0 | match this { |
501 | | // Safety: we never move the inner entries. |
502 | 0 | Timer::Traditional(entry) => unsafe { |
503 | 0 | Pin::new_unchecked(entry).reset(deadline) |
504 | | } |
505 | | // Safety: we never move the inner entries. |
506 | | #[cfg(all(tokio_unstable, feature = "rt-multi-thread"))] |
507 | | Timer::Alternative(entry) => unsafe { |
508 | | Pin::new_unchecked(entry).set(time_alt::Timer::new(handle, deadline)) |
509 | | }, |
510 | | } |
511 | 0 | } |
512 | | |
513 | 0 | pub(crate) fn poll_elapsed( |
514 | 0 | self: Pin<&mut Self>, |
515 | 0 | cx: &mut Context<'_>, |
516 | 0 | ) -> Poll<Result<(), crate::time::error::Error>> { |
517 | | // Safety: we never move the inner entries. |
518 | 0 | let this = unsafe { self.get_unchecked_mut() }; |
519 | 0 | match this { |
520 | | // Safety: we never move the inner entries. |
521 | 0 | Timer::Traditional(entry) => unsafe { |
522 | 0 | Pin::new_unchecked(entry).poll_elapsed(cx) |
523 | | } |
524 | | // Safety: we never move the inner entries. |
525 | | #[cfg(all(tokio_unstable, feature = "rt-multi-thread"))] |
526 | | Timer::Alternative(entry) => unsafe { |
527 | | Pin::new_unchecked(entry).poll_elapsed(cx).map(Ok) |
528 | | } |
529 | | } |
530 | 0 | } |
531 | | } |
532 | | } |
533 | | |
534 | | cfg_signal_internal_and_unix! { |
535 | | pub(crate) mod signal; |
536 | | } |
537 | | |
538 | | cfg_rt! { |
539 | | pub(crate) mod task; |
540 | | |
541 | | mod config; |
542 | | use config::Config; |
543 | | |
544 | | mod blocking; |
545 | | #[cfg_attr(target_os = "wasi", allow(unused_imports))] |
546 | | pub(crate) use blocking::spawn_blocking; |
547 | | |
548 | | cfg_trace! { |
549 | | pub(crate) use blocking::Mandatory; |
550 | | } |
551 | | |
552 | | cfg_fs! { |
553 | | pub(crate) use blocking::spawn_mandatory_blocking; |
554 | | } |
555 | | |
556 | | mod builder; |
557 | | pub use self::builder::Builder; |
558 | | cfg_unstable! { |
559 | | pub use self::builder::UnhandledPanic; |
560 | | pub use crate::util::rand::RngSeed; |
561 | | |
562 | | /// Returns the index of the current worker thread, if called from a |
563 | | /// runtime worker thread. |
564 | | /// |
565 | | /// The returned value is a 0-based index matching the worker indices |
566 | | /// used by [`RuntimeMetrics`] methods such as |
567 | | /// [`worker_total_busy_duration`](RuntimeMetrics::worker_total_busy_duration). |
568 | | /// |
569 | | /// Returns `None` when called from outside a runtime worker thread |
570 | | /// (for example, from a blocking thread or a non-Tokio thread). On the |
571 | | /// multi-thread runtime, the thread that calls [`Runtime::block_on`] is |
572 | | /// not a worker thread, so this also returns `None` there. |
573 | | /// |
574 | | /// For the current-thread runtime and [`LocalRuntime`], this always |
575 | | /// returns `Some(0)` (including inside `block_on`, since the calling |
576 | | /// thread *is* the worker thread). |
577 | | /// |
578 | | /// Note that the result may change across `.await` points, as the |
579 | | /// task may be moved to a different worker thread by the scheduler. |
580 | | /// |
581 | | /// # Examples |
582 | | /// |
583 | | /// ``` |
584 | | /// # #[cfg(not(target_family = "wasm"))] |
585 | | /// # { |
586 | | /// #[tokio::main(flavor = "multi_thread", worker_threads = 4)] |
587 | | /// async fn main() { |
588 | | /// let index = tokio::spawn(async { |
589 | | /// tokio::runtime::worker_index() |
590 | | /// }).await.unwrap(); |
591 | | /// println!("Task ran on worker {:?}", index); |
592 | | /// } |
593 | | /// # } |
594 | | /// ``` |
595 | | pub fn worker_index() -> Option<usize> { |
596 | | context::worker_index() |
597 | | } |
598 | | } |
599 | | |
600 | | cfg_taskdump! { |
601 | | pub mod dump; |
602 | | pub use dump::Dump; |
603 | | } |
604 | | |
605 | | mod task_hooks; |
606 | | pub(crate) use task_hooks::{TaskHooks, TaskCallback}; |
607 | | cfg_unstable! { |
608 | | pub use task_hooks::TaskMeta; |
609 | | } |
610 | | #[cfg(not(tokio_unstable))] |
611 | | pub(crate) use task_hooks::TaskMeta; |
612 | | |
613 | | mod handle; |
614 | | pub use handle::{EnterGuard, Handle, TryCurrentError}; |
615 | | |
616 | | mod runtime; |
617 | | pub use runtime::{Runtime, RuntimeFlavor, is_rt_shutdown_err}; |
618 | | |
619 | | mod local_runtime; |
620 | | pub use local_runtime::{LocalRuntime, LocalOptions}; |
621 | | |
622 | | mod id; |
623 | | pub use id::Id; |
624 | | |
625 | | |
626 | | /// Boundary value to prevent stack overflow caused by a large-sized |
627 | | /// Future being placed in the stack. |
628 | | pub(crate) const BOX_FUTURE_THRESHOLD: usize = if cfg!(debug_assertions) { |
629 | | 2048 |
630 | | } else { |
631 | | 16384 |
632 | | }; |
633 | | |
634 | | mod thread_id; |
635 | | pub(crate) use thread_id::ThreadId; |
636 | | |
637 | | pub(crate) mod metrics; |
638 | | pub use metrics::RuntimeMetrics; |
639 | | |
640 | | cfg_unstable_metrics! { |
641 | | pub use metrics::{HistogramScale, HistogramConfiguration, LogHistogram, LogHistogramBuilder, InvalidHistogramConfiguration} ; |
642 | | |
643 | | cfg_net! { |
644 | | pub(crate) use metrics::IoDriverMetrics; |
645 | | } |
646 | | } |
647 | | |
648 | | pub(crate) use metrics::{MetricsBatch, SchedulerMetrics, WorkerMetrics, HistogramBuilder}; |
649 | | |
650 | | /// After thread starts / before thread stops |
651 | | type Callback = std::sync::Arc<dyn Fn() + Send + Sync>; |
652 | | } |