use core::task::Waker;
use fixedbitset::FixedBitSet;
#[derive(Debug)]
pub(crate) struct ReadinessVec {
ready_count: usize,
max_count: usize,
readiness_list: FixedBitSet,
parent_waker: Option<Waker>,
}
impl ReadinessVec {
pub(crate) fn new(len: usize) -> Self {
Self {
ready_count: len,
max_count: len,
readiness_list: FixedBitSet::with_capacity_and_blocks(len, std::iter::repeat(!0)),
parent_waker: None,
}
}
pub(crate) fn set_ready(&mut self, index: usize) -> bool {
if !self.readiness_list[index] {
self.ready_count += 1;
self.readiness_list.set(index, true);
false
} else {
true
}
}
pub(crate) fn set_all_ready(&mut self) {
self.readiness_list.set_range(.., true);
self.ready_count = self.max_count;
}
pub(crate) fn clear_ready(&mut self, index: usize) -> bool {
if self.readiness_list[index] {
self.ready_count -= 1;
self.readiness_list.set(index, false);
true
} else {
false
}
}
#[allow(unused)]
pub(crate) fn clear_all_ready(&mut self) {
self.readiness_list.set_range(.., false);
self.ready_count = 0;
}
pub(crate) fn any_ready(&self) -> bool {
self.ready_count > 0
}
#[inline]
pub(crate) fn parent_waker(&self) -> Option<&Waker> {
self.parent_waker.as_ref()
}
pub(crate) fn set_waker(&mut self, parent_waker: &Waker) {
match &mut self.parent_waker {
Some(prev) => prev.clone_from(parent_waker),
None => self.parent_waker = Some(parent_waker.clone()),
}
}
pub(crate) fn resize(&mut self, len: usize) {
self.max_count = len;
let old_len = self.readiness_list.len();
match len.cmp(&old_len) {
std::cmp::Ordering::Less => {
self.ready_count -= self.readiness_list.count_ones(len..);
self.readiness_list = FixedBitSet::with_capacity_and_blocks(
len,
self.readiness_list.as_slice().iter().cloned(),
);
}
std::cmp::Ordering::Equal => {
}
std::cmp::Ordering::Greater => {
self.readiness_list.grow(len);
self.readiness_list.set_range(old_len..len, true);
self.ready_count += len - old_len;
}
}
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn resize() {
let mut readiness = ReadinessVec::new(10);
assert!(readiness.any_ready());
readiness.clear_all_ready();
assert!(!readiness.any_ready());
readiness.set_ready(9);
assert!(readiness.any_ready());
readiness.resize(9);
assert!(!readiness.any_ready());
readiness.resize(10);
assert!(readiness.any_ready());
}
}