1 | use core::mem::MaybeUninit; |
2 | use core::ptr; |
3 | use std::task::Waker; |
4 | |
5 | const NUM_WAKERS: usize = 32; |
6 | |
7 | /// A list of wakers to be woken. |
8 | /// |
9 | /// # Invariants |
10 | /// |
11 | /// The first `curr` elements of `inner` are initialized. |
12 | pub(crate) struct WakeList { |
13 | inner: [MaybeUninit<Waker>; NUM_WAKERS], |
14 | curr: usize, |
15 | } |
16 | |
17 | impl WakeList { |
18 | pub(crate) fn new() -> Self { |
19 | const UNINIT_WAKER: MaybeUninit<Waker> = MaybeUninit::uninit(); |
20 | |
21 | Self { |
22 | inner: [UNINIT_WAKER; NUM_WAKERS], |
23 | curr: 0, |
24 | } |
25 | } |
26 | |
27 | #[inline ] |
28 | pub(crate) fn can_push(&self) -> bool { |
29 | self.curr < NUM_WAKERS |
30 | } |
31 | |
32 | pub(crate) fn push(&mut self, val: Waker) { |
33 | debug_assert!(self.can_push()); |
34 | |
35 | self.inner[self.curr] = MaybeUninit::new(val); |
36 | self.curr += 1; |
37 | } |
38 | |
39 | pub(crate) fn wake_all(&mut self) { |
40 | assert!(self.curr <= NUM_WAKERS); |
41 | while self.curr > 0 { |
42 | self.curr -= 1; |
43 | // SAFETY: The first `curr` elements of `WakeList` are initialized, so by decrementing |
44 | // `curr`, we can take ownership of the last item. |
45 | let waker = unsafe { ptr::read(self.inner[self.curr].as_mut_ptr()) }; |
46 | waker.wake(); |
47 | } |
48 | } |
49 | } |
50 | |
51 | impl Drop for WakeList { |
52 | fn drop(&mut self) { |
53 | let slice: *mut [Waker] = |
54 | ptr::slice_from_raw_parts_mut(self.inner.as_mut_ptr().cast::<Waker>(), self.curr); |
55 | // SAFETY: The first `curr` elements are initialized, so we can drop them. |
56 | unsafe { ptr::drop_in_place(to_drop:slice) }; |
57 | } |
58 | } |
59 | |