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
//! # Wake Target
//! How the `Reactor` reaches the thread waiting on an event,
//! packed into a `kevent`'s one word of user data
use crate::modules::waiter::Waiter;
use libc::c_void;
/// What to do when an event comes back
pub(crate) enum WakeTarget {
/// Nobody is waiting on this event
None,
/// Raise a trigger on this kqueue
Queue(i32),
/// Set this waiter's flag and unpark its thread
Parked(*mut Waiter),
}
impl WakeTarget {
/// Packs a target into a `kevent`'s user data
///
/// A queue is stored one higher, so descriptor 0 doesn't read
/// back as `None`
pub(crate) fn encode(self) -> *mut c_void {
match self {
Self::None => std::ptr::null_mut::<c_void>(),
Self::Queue(queue) => (((queue as usize) + 1) << 1) as *mut c_void,
Self::Parked(waiter) => ((waiter as usize) | 1) as *mut c_void,
}
}
/// Reads a target back out of a `kevent`'s user data
///
/// The low bit marks a `Waiter`, which is always at least word
/// aligned
pub(crate) fn decode(udata: *mut c_void) -> Self {
let raw = udata as usize;
if raw == 0 {
return Self::None;
}
if raw & 1 == 1 {
return Self::Parked((raw & !1) as *mut Waiter);
}
Self::Queue(((raw >> 1) - 1) as i32)
}
}