1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
mod atomic_cell;
use atomic_cell::AtomicCell;
mod idle;
use self::idle::Idle;
mod worker;
pub(crate) use worker::Launch;
pub(crate) use worker::block_in_place;
use crate::loom::sync::Arc;
use crate::runtime::stats::RuntimeStats;
use crate::runtime::task::JoinHandle;
use crate::runtime::{Callback, Parker};
use std::fmt;
use std::future::Future;
pub(crate) struct ThreadPool {
spawner: Spawner,
}
#[derive(Clone)]
pub(crate) struct Spawner {
shared: Arc<worker::Shared>,
}
impl ThreadPool {
pub(crate) fn new(
size: usize,
parker: Parker,
before_park: Option<Callback>,
after_unpark: Option<Callback>,
) -> (ThreadPool, Launch) {
let (shared, launch) = worker::create(size, parker, before_park, after_unpark);
let spawner = Spawner { shared };
let thread_pool = ThreadPool { spawner };
(thread_pool, launch)
}
pub(crate) fn spawner(&self) -> &Spawner {
&self.spawner
}
pub(crate) fn block_on<F>(&self, future: F) -> F::Output
where
F: Future,
{
let mut enter = crate::runtime::enter(true);
enter.block_on(future).expect("failed to park thread")
}
}
impl fmt::Debug for ThreadPool {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct("ThreadPool").finish()
}
}
impl Drop for ThreadPool {
fn drop(&mut self) {
self.spawner.shutdown();
}
}
impl Spawner {
pub(crate) fn spawn<F>(&self, future: F) -> JoinHandle<F::Output>
where
F: crate::future::Future + Send + 'static,
F::Output: Send + 'static,
{
worker::Shared::bind_new_task(&self.shared, future)
}
pub(crate) fn shutdown(&mut self) {
self.shared.close();
}
pub(crate) fn stats(&self) -> &RuntimeStats {
self.shared.stats()
}
}
impl fmt::Debug for Spawner {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct("Spawner").finish()
}
}