1use crate::signal::unix::{OsExtraData, OsStorage};
2use crate::sync::watch;
3
4use std::ops;
5use std::sync::atomic::{AtomicBool, Ordering};
6use std::sync::OnceLock;
7
8pub(crate) type EventId = usize;
9
10#[derive(Debug)]
13pub(crate) struct EventInfo {
14 pending: AtomicBool,
15 tx: watch::Sender<()>,
16}
17
18impl Default for EventInfo {
19 fn default() -> Self {
20 let (tx, _rx) = watch::channel(());
21
22 Self {
23 pending: AtomicBool::new(false),
24 tx,
25 }
26 }
27}
28
29pub(crate) trait Storage {
31 fn event_info(&self, id: EventId) -> Option<&EventInfo>;
33
34 fn iter(&self) -> impl Iterator<Item = &EventInfo>;
36}
37
38impl Storage for Vec<EventInfo> {
39 fn event_info(&self, id: EventId) -> Option<&EventInfo> {
40 self.get(id)
41 }
42
43 fn iter(&self) -> impl Iterator<Item = &EventInfo> {
44 self.as_slice().iter()
45 }
46}
47
48#[derive(Debug)]
53pub(crate) struct Registry<S> {
54 storage: S,
55}
56
57impl<S> Registry<S> {
58 fn new(storage: S) -> Self {
59 Self { storage }
60 }
61}
62
63impl<S: Storage> Registry<S> {
64 fn register_listener(&self, event_id: EventId) -> watch::Receiver<()> {
66 self.storage
67 .event_info(event_id)
68 .unwrap_or_else(|| panic!("invalid event_id: {event_id}"))
69 .tx
70 .subscribe()
71 }
72
73 fn record_event(&self, event_id: EventId) {
76 if let Some(event_info) = self.storage.event_info(event_id) {
77 event_info.pending.store(true, Ordering::SeqCst);
78 }
79 }
80
81 fn broadcast(&self) -> bool {
85 self.storage
86 .iter()
87 .filter(|event_info| event_info.pending.swap(false, Ordering::SeqCst))
89 .map(|event_info| event_info.tx.send(()).is_ok())
91 .fold(false, |acc, x| acc | x)
92 }
93}
94
95pub(crate) struct Globals {
96 extra: OsExtraData,
97 registry: Registry<OsStorage>,
98}
99
100impl ops::Deref for Globals {
101 type Target = OsExtraData;
102
103 fn deref(&self) -> &Self::Target {
104 &self.extra
105 }
106}
107
108impl Globals {
109 pub(crate) fn register_listener(&self, event_id: EventId) -> watch::Receiver<()> {
111 self.registry.register_listener(event_id)
112 }
113
114 pub(crate) fn record_event(&self, event_id: EventId) {
117 self.registry.record_event(event_id);
118 }
119
120 pub(crate) fn broadcast(&self) -> bool {
124 self.registry.broadcast()
125 }
126
127 #[cfg(unix)]
128 pub(crate) fn storage(&self) -> &OsStorage {
129 &self.registry.storage
130 }
131}
132
133fn globals_init() -> Globals
134where
135 OsExtraData: 'static + Send + Sync + Default,
136 OsStorage: 'static + Send + Sync + Default,
137{
138 Globals {
139 extra: OsExtraData::default(),
140 registry: Registry::new(OsStorage::default()),
141 }
142}
143
144pub(crate) fn globals() -> &'static Globals
145where
146 OsExtraData: 'static + Send + Sync + Default,
147 OsStorage: 'static + Send + Sync + Default,
148{
149 static GLOBALS: OnceLock<Globals> = OnceLock::new();
150
151 GLOBALS.get_or_init(globals_init)
152}
153
154#[cfg(all(test, not(loom)))]
155mod tests {
156 use super::*;
157 use crate::runtime::{self, Runtime};
158 use crate::sync::{oneshot, watch};
159
160 use futures::future;
161
162 #[test]
163 fn smoke() {
164 let rt = rt();
165 rt.block_on(async move {
166 let registry = Registry::new(vec![
167 EventInfo::default(),
168 EventInfo::default(),
169 EventInfo::default(),
170 ]);
171
172 let first = registry.register_listener(0);
173 let second = registry.register_listener(1);
174 let third = registry.register_listener(2);
175
176 let (fire, wait) = oneshot::channel();
177
178 crate::spawn(async {
179 wait.await.expect("wait failed");
180
181 registry.record_event(0);
183 registry.record_event(0);
184 registry.record_event(1);
185 registry.record_event(1);
186 registry.broadcast();
187
188 for _ in 0..100 {
193 crate::task::yield_now().await;
194 }
195
196 registry.record_event(0);
198 registry.broadcast();
199
200 drop(registry);
201 });
202
203 let _ = fire.send(());
204 let all = future::join3(collect(first), collect(second), collect(third));
205
206 let (first_results, second_results, third_results) = all.await;
207 assert_eq!(2, first_results.len());
208 assert_eq!(1, second_results.len());
209 assert_eq!(0, third_results.len());
210 });
211 }
212
213 #[test]
214 #[should_panic = "invalid event_id: 1"]
215 fn register_panics_on_invalid_input() {
216 let registry = Registry::new(vec![EventInfo::default()]);
217
218 registry.register_listener(1);
219 }
220
221 #[test]
222 fn record_invalid_event_does_nothing() {
223 let registry = Registry::new(vec![EventInfo::default()]);
224 registry.record_event(1302);
225 }
226
227 #[test]
228 fn broadcast_returns_if_at_least_one_event_fired() {
229 let registry = Registry::new(vec![EventInfo::default(), EventInfo::default()]);
230
231 registry.record_event(0);
232 assert!(!registry.broadcast());
233
234 let first = registry.register_listener(0);
235 let second = registry.register_listener(1);
236
237 registry.record_event(0);
238 assert!(registry.broadcast());
239
240 drop(first);
241 registry.record_event(0);
242 assert!(!registry.broadcast());
243
244 drop(second);
245 }
246
247 fn rt() -> Runtime {
248 runtime::Builder::new_current_thread()
249 .enable_time()
250 .build()
251 .unwrap()
252 }
253
254 async fn collect(mut rx: watch::Receiver<()>) -> Vec<()> {
255 let mut ret = vec![];
256
257 while let Ok(v) = rx.changed().await {
258 ret.push(v);
259 }
260
261 ret
262 }
263}