1use core::mem::MaybeUninit;
2use core::ptr;
3use std::task::Waker;
45const NUM_WAKERS: usize = 32;
67/// 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}
1617impl WakeList {
18pub(crate) fn new() -> Self {
19const UNINIT_WAKER: MaybeUninit<Waker> = MaybeUninit::uninit();
2021Self {
22 inner: [UNINIT_WAKER; NUM_WAKERS],
23 curr: 0,
24 }
25 }
2627#[inline]
28pub(crate) fn can_push(&self) -> bool {
29self.curr < NUM_WAKERS
30 }
3132pub(crate) fn push(&mut self, val: Waker) {
33debug_assert!(self.can_push());
3435self.inner[self.curr] = MaybeUninit::new(val);
36self.curr += 1;
37 }
3839pub(crate) fn wake_all(&mut self) {
40struct DropGuard {
41 start: *mut Waker,
42 end: *mut Waker,
43 }
4445impl Drop for DropGuard {
46fn drop(&mut self) {
47// SAFETY: Both pointers are part of the same object, with `start <= end`.
48let len = unsafe { self.end.offset_from(self.start) } as usize;
49let slice = ptr::slice_from_raw_parts_mut(self.start, len);
50// SAFETY: All elements in `start..len` are initialized, so we can drop them.
51unsafe { ptr::drop_in_place(slice) };
52 }
53 }
5455debug_assert!(self.curr <= NUM_WAKERS);
5657let mut guard = {
58let start = self.inner.as_mut_ptr().cast::<Waker>();
59// SAFETY: The resulting pointer is in bounds or one after the length of the same object.
60let end = unsafe { start.add(self.curr) };
61// Transfer ownership of the wakers in `inner` to `DropGuard`.
62self.curr = 0;
63 DropGuard { start, end }
64 };
65while !ptr::eq(guard.start, guard.end) {
66// SAFETY: `start` is always initialized if `start != end`.
67let waker = unsafe { ptr::read(guard.start) };
68// SAFETY: The resulting pointer is in bounds or one after the length of the same object.
69guard.start = unsafe { guard.start.add(1) };
70// If this panics, then `guard` will clean up the remaining wakers.
71waker.wake();
72 }
73 }
74}
7576impl Drop for WakeList {
77fn drop(&mut self) {
78let slice =
79 ptr::slice_from_raw_parts_mut(self.inner.as_mut_ptr().cast::<Waker>(), self.curr);
80// SAFETY: The first `curr` elements are initialized, so we can drop them.
81unsafe { ptr::drop_in_place(slice) };
82 }
83}