1 //! Multi-threaded runtime
2 
3 mod counters;
4 use counters::Counters;
5 
6 mod handle;
7 pub(crate) use handle::Handle;
8 
9 mod overflow;
10 pub(crate) use overflow::Overflow;
11 
12 mod idle;
13 use self::idle::Idle;
14 
15 mod stats;
16 pub(crate) use stats::Stats;
17 
18 mod park;
19 pub(crate) use park::{Parker, Unparker};
20 
21 pub(crate) mod queue;
22 
23 mod worker;
24 pub(crate) use worker::{Context, Launch, Shared};
25 
26 cfg_taskdump! {
27     mod trace;
28     use trace::TraceStatus;
29 
30     pub(crate) use worker::Synced;
31 }
32 
33 cfg_not_taskdump! {
34     mod trace_mock;
35     use trace_mock::TraceStatus;
36 }
37 
38 pub(crate) use worker::block_in_place;
39 
40 use crate::loom::sync::Arc;
41 use crate::runtime::{
42     blocking,
43     driver::{self, Driver},
44     scheduler, Config,
45 };
46 use crate::util::RngSeedGenerator;
47 
48 use std::fmt;
49 use std::future::Future;
50 
51 /// Work-stealing based thread pool for executing futures.
52 pub(crate) struct MultiThread;
53 
54 // ===== impl MultiThread =====
55 
56 impl MultiThread {
new( size: usize, driver: Driver, driver_handle: driver::Handle, blocking_spawner: blocking::Spawner, seed_generator: RngSeedGenerator, config: Config, ) -> (MultiThread, Arc<Handle>, Launch)57     pub(crate) fn new(
58         size: usize,
59         driver: Driver,
60         driver_handle: driver::Handle,
61         blocking_spawner: blocking::Spawner,
62         seed_generator: RngSeedGenerator,
63         config: Config,
64     ) -> (MultiThread, Arc<Handle>, Launch) {
65         let parker = Parker::new(driver);
66         let (handle, launch) = worker::create(
67             size,
68             parker,
69             driver_handle,
70             blocking_spawner,
71             seed_generator,
72             config,
73         );
74 
75         (MultiThread, handle, launch)
76     }
77 
78     /// Blocks the current thread waiting for the future to complete.
79     ///
80     /// The future will execute on the current thread, but all spawned tasks
81     /// will be executed on the thread pool.
block_on<F>(&self, handle: &scheduler::Handle, future: F) -> F::Output where F: Future,82     pub(crate) fn block_on<F>(&self, handle: &scheduler::Handle, future: F) -> F::Output
83     where
84         F: Future,
85     {
86         crate::runtime::context::enter_runtime(handle, true, |blocking| {
87             blocking.block_on(future).expect("failed to park thread")
88         })
89     }
90 
shutdown(&mut self, handle: &scheduler::Handle)91     pub(crate) fn shutdown(&mut self, handle: &scheduler::Handle) {
92         match handle {
93             scheduler::Handle::MultiThread(handle) => handle.shutdown(),
94             _ => panic!("expected MultiThread scheduler"),
95         }
96     }
97 }
98 
99 impl fmt::Debug for MultiThread {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result100     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
101         fmt.debug_struct("MultiThread").finish()
102     }
103 }
104