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
119
120
121
122
123
124
//! # Runtime Status
//! Whether the runtime is up, and whether the two threads that
//! keep it adapting are still there
use std::fmt;
/// What the runtime looked like at the moment it was asked
///
/// #### Note
/// A snapshot, not a lock. Every value was true when it was read
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct RuntimeStatus {
initialised: bool,
shut_down: bool,
reactor_alive: bool,
manager_alive: bool,
pool_alive: bool,
}
impl RuntimeStatus {
pub(crate) fn new(
initialised: bool,
shut_down: bool,
reactor_alive: bool,
manager_alive: bool,
pool_alive: bool,
) -> Self {
Self {
initialised,
shut_down,
reactor_alive,
manager_alive,
pool_alive,
}
}
/// Whether `Runtime::init` has finished
///
/// Says initialisation is over, not that it worked
pub fn initialised(&self) -> bool {
self.initialised
}
/// Whether the runtime has been shut down
///
/// Stays true until `Runtime::init` starts it again
pub fn shut_down(&self) -> bool {
self.shut_down
}
/// Whether the `Reactor` is still running
///
/// False once its supervisor stops restarting it
pub fn reactor_alive(&self) -> bool {
self.reactor_alive
}
/// Whether the manager is still running
///
/// False once its supervisor gives up on it, or once the
/// runtime has been shut down
///
/// #### Note
/// Spawned tasks still run without it. What stops is the pool
/// growing and shrinking, and every repeat driven by a timer
pub fn manager_alive(&self) -> bool {
self.manager_alive
}
/// Whether the pool has a worker running and no dead thread left
/// to recover
///
/// #### Note
/// False only briefly after a thread dies, since the pool recovers
/// on its own. It stays false once nothing can be started at all
pub fn pool_alive(&self) -> bool {
self.pool_alive
}
/// Whether everything is up and nothing has given up
///
/// #### Note
/// `false` doesn't mean spawned work has stopped running
pub fn healthy(&self) -> bool {
self.initialised
&& !self.shut_down
&& self.reactor_alive
&& self.manager_alive
&& self.pool_alive
}
}
impl fmt::Display for RuntimeStatus {
/// One line: the state, then anything that is down
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
if !self.initialised {
return write!(formatter, "not initialised");
}
if self.shut_down {
return write!(formatter, "shut down");
}
if self.healthy() {
return write!(formatter, "healthy");
}
write!(
formatter,
"degraded: reactor {}, manager {}, pool {}",
alive(self.reactor_alive),
alive(self.manager_alive),
alive(self.pool_alive),
)
}
}
#[inline(always)]
fn alive(alive: bool) -> &'static str {
match alive {
true => "up",
false => "gone",
}
}