1use core::mem::MaybeUninit;
2use core::ptr;
3use std::task::Waker;
4
5const 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.
12pub(crate) struct WakeList {
13 inner: [MaybeUninit<Waker>; NUM_WAKERS],
14 curr: usize,
15}
16
17impl 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
51impl Drop for WakeList {
52 fn drop(&mut self) {
53 let slice =
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(slice) };
57 }
58}
59