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
//! # Waiter
//! A parked thread waiting for the `Reactor`, used when a
//! thread couldn't get a kqueue of its own
use std::{
sync::atomic::{AtomicBool, Ordering},
thread::{self, Thread},
};
/// A thread waiting for the `Reactor` to wake it
///
/// Lives on the waiting thread's stack. The `Reactor` only
/// holds a pointer to it while the thread is waiting
pub(crate) struct Waiter {
/// The thread to unpark
thread: Thread,
/// Whether the event has arrived
///
/// Separates a real wake from `park` returning spuriously
fired: AtomicBool,
}
impl Waiter {
/// A waiter for the calling thread
pub(crate) fn new() -> Self {
Self {
thread: thread::current(),
fired: AtomicBool::new(false),
}
}
/// Blocks until the event arrives
pub(crate) fn wait(&self) {
while !self.fired.load(Ordering::Acquire) {
thread::park();
}
}
/// Says the event arrived, and wakes the waiter
///
/// The flag is set before the unpark, so a waiter always
/// finds it
pub(crate) fn wake(&self) {
self.fired.store(true, Ordering::Release);
self.thread.unpark();
}
}