async_ui_web_core/combinators/utils/wakers/array/
readiness.rs

1use async_ui_internal_utils::dummy_waker::dummy_waker;
2
3use core::task::Waker;
4
5pub(crate) struct ReadinessArray<const N: usize> {
6    /// Whether each subfuture has woken.
7    awake_set: [bool; N],
8    /// Indices of subfutures that have woken.
9    awake_list: [usize; N],
10    /// Number of subfutures that have woken.
11    /// `awake_list` and `awake_list_len` together makes up something like ArrayVec<usize>.
12    // TODO: Maybe just use the ArrayVec crate?
13    awake_list_len: usize,
14    parent_waker: Waker,
15}
16
17impl<const N: usize> ReadinessArray<N> {
18    pub(crate) fn new() -> Self {
19        Self {
20            awake_set: [true; N],
21            awake_list: core::array::from_fn(core::convert::identity),
22            awake_list_len: N,
23            parent_waker: dummy_waker(), // parent waker is dummy at first
24        }
25    }
26    pub(crate) fn set_parent_waker(&mut self, waker: &Waker) {
27        // If self.parent_waker and the given waker are the same then don't do the replacement.
28        if !self.parent_waker.will_wake(waker) {
29            self.parent_waker = waker.to_owned();
30        }
31    }
32    fn set_woken(&mut self, index: usize) -> bool {
33        let was_awake = std::mem::replace(&mut self.awake_set[index], true);
34        if !was_awake {
35            self.awake_list[self.awake_list_len] = index;
36            self.awake_list_len += 1;
37        }
38        was_awake
39    }
40    pub(crate) fn wake(&mut self, index: usize) {
41        if !self.set_woken(index) && self.awake_list_len == 1 {
42            self.parent_waker.wake_by_ref();
43        }
44    }
45    pub(crate) fn awake_list(&self) -> &[usize] {
46        &self.awake_list[..self.awake_list_len]
47    }
48    const TRESHOLD: usize = N / 64;
49    pub(crate) fn clear(&mut self) {
50        // Depending on how many items was in the list,
51        // either use `fill` (memset) or iterate and set each.
52        // TODO: I came up with the 64 factor at random. Maybe test different factors?
53        if self.awake_list_len < Self::TRESHOLD {
54            self.awake_set.fill(false);
55        } else {
56            let awake_set = &mut self.awake_set;
57            self.awake_list.iter().for_each(|&idx| {
58                awake_set[idx] = false;
59            });
60        }
61        self.awake_list_len = 0;
62    }
63}