/rust/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.52.2/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 | | //! [tasks]: crate::task |
240 | | //! [`Runtime`]: Runtime |
241 | | //! [`tokio::spawn`]: crate::spawn |
242 | | //! [`tokio::main`]: ../attr.main.html |
243 | | //! [runtime builder]: crate::runtime::Builder |
244 | | //! [`Runtime::new`]: crate::runtime::Runtime::new |
245 | | //! [`Builder::enable_io`]: crate::runtime::Builder::enable_io |
246 | | //! [`Builder::enable_time`]: crate::runtime::Builder::enable_time |
247 | | //! [`Builder::enable_all`]: crate::runtime::Builder::enable_all |
248 | | //! |
249 | | //! # Detailed runtime behavior |
250 | | //! |
251 | | //! This section gives more details into how the Tokio runtime will schedule |
252 | | //! tasks for execution. |
253 | | //! |
254 | | //! At its most basic level, a runtime has a collection of tasks that need to be |
255 | | //! scheduled. It will repeatedly remove a task from that collection and |
256 | | //! schedule it (by calling [`poll`]). When the collection is empty, the thread |
257 | | //! will go to sleep until a task is added to the collection. |
258 | | //! |
259 | | //! However, the above is not sufficient to guarantee a well-behaved runtime. |
260 | | //! For example, the runtime might have a single task that is always ready to be |
261 | | //! scheduled, and schedule that task every time. This is a problem because it |
262 | | //! starves other tasks by not scheduling them. To solve this, Tokio provides |
263 | | //! the following fairness guarantee: |
264 | | //! |
265 | | //! > If the total number of tasks does not grow without bound, and no task is |
266 | | //! > [blocking the thread], then it is guaranteed that tasks are scheduled |
267 | | //! > fairly. |
268 | | //! |
269 | | //! Or, more formally: |
270 | | //! |
271 | | //! > Under the following two assumptions: |
272 | | //! > |
273 | | //! > * There is some number `MAX_TASKS` such that the total number of tasks on |
274 | | //! > the runtime at any specific point in time never exceeds `MAX_TASKS`. |
275 | | //! > * There is some number `MAX_SCHEDULE` such that calling [`poll`] on any |
276 | | //! > task spawned on the runtime returns within `MAX_SCHEDULE` time units. |
277 | | //! > |
278 | | //! > Then, there is some number `MAX_DELAY` such that when a task is woken, it |
279 | | //! > will be scheduled by the runtime within `MAX_DELAY` time units. |
280 | | //! |
281 | | //! (Here, `MAX_TASKS` and `MAX_SCHEDULE` can be any number and the user of |
282 | | //! the runtime may choose them. The `MAX_DELAY` number is controlled by the |
283 | | //! runtime, and depends on the value of `MAX_TASKS` and `MAX_SCHEDULE`.) |
284 | | //! |
285 | | //! Other than the above fairness guarantee, there is no guarantee about the |
286 | | //! order in which tasks are scheduled. There is also no guarantee that the |
287 | | //! runtime is equally fair to all tasks. For example, if the runtime has two |
288 | | //! tasks A and B that are both ready, then the runtime may schedule A five |
289 | | //! times before it schedules B. This is the case even if A yields using |
290 | | //! [`yield_now`]. All that is guaranteed is that it will schedule B eventually. |
291 | | //! |
292 | | //! Normally, tasks are scheduled only if they have been woken by calling |
293 | | //! [`wake`] on their waker. However, this is not guaranteed, and Tokio may |
294 | | //! schedule tasks that have not been woken under some circumstances. This is |
295 | | //! called a spurious wakeup. |
296 | | //! |
297 | | //! ## IO and timers |
298 | | //! |
299 | | //! Beyond just scheduling tasks, the runtime must also manage IO resources and |
300 | | //! timers. It does this by periodically checking whether there are any IO |
301 | | //! resources or timers that are ready, and waking the relevant task so that |
302 | | //! it will be scheduled. |
303 | | //! |
304 | | //! These checks are performed periodically between scheduling tasks. Under the |
305 | | //! same assumptions as the previous fairness guarantee, Tokio guarantees that |
306 | | //! it will wake tasks with an IO or timer event within some maximum number of |
307 | | //! time units. |
308 | | //! |
309 | | //! ## Current thread runtime (behavior at the time of writing) |
310 | | //! |
311 | | //! This section describes how the [current thread runtime] behaves today. This |
312 | | //! behavior may change in future versions of Tokio. |
313 | | //! |
314 | | //! The current thread runtime maintains two FIFO queues of tasks that are ready |
315 | | //! to be scheduled: the global queue and the local queue. The runtime will prefer |
316 | | //! to choose the next task to schedule from the local queue, and will only pick a |
317 | | //! task from the global queue if the local queue is empty, or if it has picked |
318 | | //! a task from the local queue 31 times in a row. The number 31 can be |
319 | | //! changed using the [`global_queue_interval`] setting. |
320 | | //! |
321 | | //! The runtime will check for new IO or timer events whenever there are no |
322 | | //! tasks ready to be scheduled, or when it has scheduled 61 tasks in a row. The |
323 | | //! number 61 may be changed using the [`event_interval`] setting. |
324 | | //! |
325 | | //! When a task is woken from within a task running on the runtime, then the |
326 | | //! woken task is added directly to the local queue. Otherwise, the task is |
327 | | //! added to the global queue. The current thread runtime does not use [the lifo |
328 | | //! slot optimization]. |
329 | | //! |
330 | | //! ## Multi threaded runtime (behavior at the time of writing) |
331 | | //! |
332 | | //! This section describes how the [multi thread runtime] behaves today. This |
333 | | //! behavior may change in future versions of Tokio. |
334 | | //! |
335 | | //! A multi thread runtime has a fixed number of worker threads, which are all |
336 | | //! created on startup. The multi thread runtime maintains one global queue, and |
337 | | //! a local queue for each worker thread. The local queue of a worker thread can |
338 | | //! fit at most 256 tasks. If more than 256 tasks are added to the local queue, |
339 | | //! then half of them are moved to the global queue to make space. |
340 | | //! |
341 | | //! The runtime will prefer to choose the next task to schedule from the local |
342 | | //! queue, and will only pick a task from the global queue if the local queue is |
343 | | //! empty, or if it has picked a task from the local queue |
344 | | //! [`global_queue_interval`] times in a row. If the value of |
345 | | //! [`global_queue_interval`] is not explicitly set using the runtime builder, |
346 | | //! then the runtime will dynamically compute it using a heuristic that targets |
347 | | //! 10ms intervals between each check of the global queue (based on the |
348 | | //! [`worker_mean_poll_time`] metric). |
349 | | //! |
350 | | //! If both the local queue and global queue is empty, then the worker thread |
351 | | //! will attempt to steal tasks from the local queue of another worker thread. |
352 | | //! Stealing is done by moving half of the tasks in one local queue to another |
353 | | //! local queue. |
354 | | //! |
355 | | //! The runtime will check for new IO or timer events whenever there are no |
356 | | //! tasks ready to be scheduled, or when it has scheduled 61 tasks in a row. The |
357 | | //! number 61 may be changed using the [`event_interval`] setting. |
358 | | //! |
359 | | //! The multi thread runtime uses [the lifo slot optimization]: Whenever a task |
360 | | //! wakes up another task, the other task is added to the worker thread's lifo |
361 | | //! slot instead of being added to a queue. If there was already a task in the |
362 | | //! lifo slot when this happened, then the lifo slot is replaced, and the task |
363 | | //! that used to be in the lifo slot is placed in the thread's local queue. |
364 | | //! When the runtime finishes scheduling a task, it will schedule the task in |
365 | | //! the lifo slot immediately, if any. When the lifo slot is used, the [coop |
366 | | //! budget] is not reset. Furthermore, if a worker thread uses the lifo slot |
367 | | //! three times in a row, it is temporarily disabled until the worker thread has |
368 | | //! scheduled a task that didn't come from the lifo slot. The lifo slot can be |
369 | | //! disabled using the [`disable_lifo_slot`] setting. The lifo slot is separate |
370 | | //! from the local queue, so other worker threads cannot steal the task in the |
371 | | //! lifo slot. |
372 | | //! |
373 | | //! When a task is woken from a thread that is not a worker thread, then the |
374 | | //! task is placed in the global queue. |
375 | | //! |
376 | | //! # Performance tuning |
377 | | //! |
378 | | //! ## File descriptor table pre-warming |
379 | | //! |
380 | | //! On Linux, file descriptor table growth can stall worker threads. See the |
381 | | //! [`prewarm-fd-table`] example. |
382 | | //! |
383 | | //! [`poll`]: std::future::Future::poll |
384 | | //! [`wake`]: std::task::Waker::wake |
385 | | //! [`yield_now`]: crate::task::yield_now |
386 | | //! [blocking the thread]: https://ryhl.io/blog/async-what-is-blocking/ |
387 | | //! [current thread runtime]: crate::runtime::Builder::new_current_thread |
388 | | //! [multi thread runtime]: crate::runtime::Builder::new_multi_thread |
389 | | //! [`global_queue_interval`]: crate::runtime::Builder::global_queue_interval |
390 | | //! [`event_interval`]: crate::runtime::Builder::event_interval |
391 | | //! [`disable_lifo_slot`]: crate::runtime::Builder::disable_lifo_slot |
392 | | //! [the lifo slot optimization]: crate::runtime::Builder::disable_lifo_slot |
393 | | //! [coop budget]: crate::task::coop#cooperative-scheduling |
394 | | //! [`worker_mean_poll_time`]: crate::runtime::RuntimeMetrics::worker_mean_poll_time |
395 | | //! [`prewarm-fd-table`]: https://github.com/tokio-rs/tokio/blob/master/examples/prewarm-fd-table.rs |
396 | | |
397 | | // At the top due to macros |
398 | | #[cfg(test)] |
399 | | #[cfg(not(target_family = "wasm"))] |
400 | | #[macro_use] |
401 | | mod tests; |
402 | | |
403 | | pub(crate) mod context; |
404 | | |
405 | | pub(crate) mod park; |
406 | | |
407 | | pub(crate) mod driver; |
408 | | |
409 | | pub(crate) mod scheduler; |
410 | | |
411 | | cfg_io_driver_impl! { |
412 | | pub(crate) mod io; |
413 | | } |
414 | | |
415 | | cfg_process_driver! { |
416 | | mod process; |
417 | | } |
418 | | |
419 | | #[cfg_attr(not(feature = "time"), allow(dead_code))] |
420 | | #[derive(Debug, Copy, Clone, PartialEq)] |
421 | | pub(crate) enum TimerFlavor { |
422 | | Traditional, |
423 | | #[cfg(all(tokio_unstable, feature = "rt-multi-thread"))] |
424 | | Alternative, |
425 | | } |
426 | | |
427 | | cfg_time! { |
428 | | pub(crate) mod time; |
429 | | |
430 | | #[cfg(all(tokio_unstable, feature = "rt-multi-thread"))] |
431 | | pub(crate) mod time_alt; |
432 | | |
433 | | use std::task::{Context, Poll}; |
434 | | use std::pin::Pin; |
435 | | |
436 | | #[derive(Debug)] |
437 | | pub(crate) enum Timer { |
438 | | Traditional(time::TimerEntry), |
439 | | |
440 | | #[cfg(all(tokio_unstable, feature = "rt-multi-thread"))] |
441 | | Alternative(time_alt::Timer), |
442 | | } |
443 | | |
444 | | impl Timer { |
445 | | #[track_caller] |
446 | 0 | pub(crate) fn new( |
447 | 0 | handle: crate::runtime::scheduler::Handle, |
448 | 0 | deadline: crate::time::Instant, |
449 | 0 | ) -> Self { |
450 | 0 | match handle.timer_flavor() { |
451 | | crate::runtime::TimerFlavor::Traditional => { |
452 | 0 | Timer::Traditional(time::TimerEntry::new(handle, deadline)) |
453 | | } |
454 | | #[cfg(all(tokio_unstable, feature = "rt-multi-thread"))] |
455 | | crate::runtime::TimerFlavor::Alternative => { |
456 | | Timer::Alternative(time_alt::Timer::new(handle, deadline)) |
457 | | } |
458 | | } |
459 | 0 | } |
460 | | |
461 | 0 | pub(crate) fn deadline(&self) -> crate::time::Instant { |
462 | 0 | match self { |
463 | 0 | Timer::Traditional(entry) => entry.deadline(), |
464 | | #[cfg(all(tokio_unstable, feature = "rt-multi-thread"))] |
465 | | Timer::Alternative(entry) => entry.deadline(), |
466 | | } |
467 | 0 | } |
468 | | |
469 | 0 | pub(crate) fn is_elapsed(&self) -> bool { |
470 | 0 | match self { |
471 | 0 | Timer::Traditional(entry) => entry.is_elapsed(), |
472 | | #[cfg(all(tokio_unstable, feature = "rt-multi-thread"))] |
473 | | Timer::Alternative(entry) => entry.is_elapsed(), |
474 | | } |
475 | 0 | } |
476 | | |
477 | 0 | pub(crate) fn flavor(self: Pin<&Self>) -> TimerFlavor { |
478 | 0 | match self.get_ref() { |
479 | 0 | Timer::Traditional(_) => TimerFlavor::Traditional, |
480 | | #[cfg(all(tokio_unstable, feature = "rt-multi-thread"))] |
481 | | Timer::Alternative(_) => TimerFlavor::Alternative, |
482 | | } |
483 | 0 | } |
484 | | |
485 | 0 | pub(crate) fn reset( |
486 | 0 | self: Pin<&mut Self>, |
487 | 0 | new_time: crate::time::Instant, |
488 | 0 | reregister: bool |
489 | 0 | ) { |
490 | | // Safety: we never move the inner entries. |
491 | 0 | let this = unsafe { self.get_unchecked_mut() }; |
492 | 0 | match this { |
493 | 0 | Timer::Traditional(entry) => { |
494 | | // Safety: we never move the inner entries. |
495 | 0 | unsafe { Pin::new_unchecked(entry).reset(new_time, reregister); } |
496 | | } |
497 | | #[cfg(all(tokio_unstable, feature = "rt-multi-thread"))] |
498 | | Timer::Alternative(_) => panic!("not implemented yet"), |
499 | | } |
500 | 0 | } |
501 | | |
502 | 0 | pub(crate) fn poll_elapsed( |
503 | 0 | self: Pin<&mut Self>, |
504 | 0 | cx: &mut Context<'_>, |
505 | 0 | ) -> Poll<Result<(), crate::time::error::Error>> { |
506 | | // Safety: we never move the inner entries. |
507 | 0 | let this = unsafe { self.get_unchecked_mut() }; |
508 | 0 | match this { |
509 | 0 | Timer::Traditional(entry) => { |
510 | | // Safety: we never move the inner entries. |
511 | 0 | unsafe { Pin::new_unchecked(entry).poll_elapsed(cx) } |
512 | | } |
513 | | #[cfg(all(tokio_unstable, feature = "rt-multi-thread"))] |
514 | | Timer::Alternative(entry) => { |
515 | | // Safety: we never move the inner entries. |
516 | | unsafe { Pin::new_unchecked(entry).poll_elapsed(cx).map(Ok) } |
517 | | } |
518 | | } |
519 | 0 | } |
520 | | |
521 | | #[cfg(all(tokio_unstable, feature = "rt-multi-thread"))] |
522 | | pub(crate) fn scheduler_handle(&self) -> &crate::runtime::scheduler::Handle { |
523 | | match self { |
524 | | Timer::Traditional(_) => unreachable!("we should not call this on Traditional Timer"), |
525 | | #[cfg(all(tokio_unstable, feature = "rt-multi-thread"))] |
526 | | Timer::Alternative(entry) => entry.scheduler_handle(), |
527 | | } |
528 | | } |
529 | | |
530 | | #[cfg(all(tokio_unstable, feature = "tracing"))] |
531 | | pub(crate) fn driver(self: Pin<&Self>) -> &crate::runtime::time::Handle { |
532 | | match self.get_ref() { |
533 | | Timer::Traditional(entry) => entry.driver(), |
534 | | #[cfg(all(tokio_unstable, feature = "rt-multi-thread"))] |
535 | | Timer::Alternative(entry) => entry.driver(), |
536 | | } |
537 | | } |
538 | | |
539 | | #[cfg(all(tokio_unstable, feature = "tracing"))] |
540 | | pub(crate) fn clock(self: Pin<&Self>) -> &crate::time::Clock { |
541 | | match self.get_ref() { |
542 | | Timer::Traditional(entry) => entry.clock(), |
543 | | #[cfg(all(tokio_unstable, feature = "rt-multi-thread"))] |
544 | | Timer::Alternative(entry) => entry.clock(), |
545 | | } |
546 | | } |
547 | | } |
548 | | } |
549 | | |
550 | | cfg_signal_internal_and_unix! { |
551 | | pub(crate) mod signal; |
552 | | } |
553 | | |
554 | | cfg_rt! { |
555 | | pub(crate) mod task; |
556 | | |
557 | | mod config; |
558 | | use config::Config; |
559 | | |
560 | | mod blocking; |
561 | | #[cfg_attr(target_os = "wasi", allow(unused_imports))] |
562 | | pub(crate) use blocking::spawn_blocking; |
563 | | |
564 | | cfg_trace! { |
565 | | pub(crate) use blocking::Mandatory; |
566 | | } |
567 | | |
568 | | cfg_fs! { |
569 | | pub(crate) use blocking::spawn_mandatory_blocking; |
570 | | } |
571 | | |
572 | | mod builder; |
573 | | pub use self::builder::Builder; |
574 | | cfg_unstable! { |
575 | | pub use self::builder::UnhandledPanic; |
576 | | pub use crate::util::rand::RngSeed; |
577 | | |
578 | | /// Returns the index of the current worker thread, if called from a |
579 | | /// runtime worker thread. |
580 | | /// |
581 | | /// The returned value is a 0-based index matching the worker indices |
582 | | /// used by [`RuntimeMetrics`] methods such as |
583 | | /// [`worker_total_busy_duration`](RuntimeMetrics::worker_total_busy_duration). |
584 | | /// |
585 | | /// Returns `None` when called from outside a runtime worker thread |
586 | | /// (for example, from a blocking thread or a non-Tokio thread). On the |
587 | | /// multi-thread runtime, the thread that calls [`Runtime::block_on`] is |
588 | | /// not a worker thread, so this also returns `None` there. |
589 | | /// |
590 | | /// For the current-thread runtime and [`LocalRuntime`], this always |
591 | | /// returns `Some(0)` (including inside `block_on`, since the calling |
592 | | /// thread *is* the worker thread). |
593 | | /// |
594 | | /// Note that the result may change across `.await` points, as the |
595 | | /// task may be moved to a different worker thread by the scheduler. |
596 | | /// |
597 | | /// # Examples |
598 | | /// |
599 | | /// ``` |
600 | | /// # #[cfg(not(target_family = "wasm"))] |
601 | | /// # { |
602 | | /// #[tokio::main(flavor = "multi_thread", worker_threads = 4)] |
603 | | /// async fn main() { |
604 | | /// let index = tokio::spawn(async { |
605 | | /// tokio::runtime::worker_index() |
606 | | /// }).await.unwrap(); |
607 | | /// println!("Task ran on worker {:?}", index); |
608 | | /// } |
609 | | /// # } |
610 | | /// ``` |
611 | | pub fn worker_index() -> Option<usize> { |
612 | | context::worker_index() |
613 | | } |
614 | | } |
615 | | |
616 | | cfg_taskdump! { |
617 | | pub mod dump; |
618 | | pub use dump::Dump; |
619 | | } |
620 | | |
621 | | mod task_hooks; |
622 | | pub(crate) use task_hooks::{TaskHooks, TaskCallback}; |
623 | | cfg_unstable! { |
624 | | pub use task_hooks::TaskMeta; |
625 | | } |
626 | | #[cfg(not(tokio_unstable))] |
627 | | pub(crate) use task_hooks::TaskMeta; |
628 | | |
629 | | mod handle; |
630 | | pub use handle::{EnterGuard, Handle, TryCurrentError}; |
631 | | |
632 | | mod runtime; |
633 | | pub use runtime::{Runtime, RuntimeFlavor, is_rt_shutdown_err}; |
634 | | |
635 | | mod local_runtime; |
636 | | pub use local_runtime::{LocalRuntime, LocalOptions}; |
637 | | |
638 | | mod id; |
639 | | pub use id::Id; |
640 | | |
641 | | |
642 | | /// Boundary value to prevent stack overflow caused by a large-sized |
643 | | /// Future being placed in the stack. |
644 | | pub(crate) const BOX_FUTURE_THRESHOLD: usize = if cfg!(debug_assertions) { |
645 | | 2048 |
646 | | } else { |
647 | | 16384 |
648 | | }; |
649 | | |
650 | | mod thread_id; |
651 | | pub(crate) use thread_id::ThreadId; |
652 | | |
653 | | pub(crate) mod metrics; |
654 | | pub use metrics::RuntimeMetrics; |
655 | | |
656 | | cfg_unstable_metrics! { |
657 | | pub use metrics::{HistogramScale, HistogramConfiguration, LogHistogram, LogHistogramBuilder, InvalidHistogramConfiguration} ; |
658 | | |
659 | | cfg_net! { |
660 | | pub(crate) use metrics::IoDriverMetrics; |
661 | | } |
662 | | } |
663 | | |
664 | | pub(crate) use metrics::{MetricsBatch, SchedulerMetrics, WorkerMetrics, HistogramBuilder}; |
665 | | |
666 | | /// After thread starts / before thread stops |
667 | | type Callback = std::sync::Arc<dyn Fn() + Send + Sync>; |
668 | | } |