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