use std::task::Waker;
#[derive(Debug, Default)]
pub struct WakerList {
wakers: Vec<Option<Waker>>,
empty_slots: Vec<usize>,
epoch: usize,
}
pub struct WakerToken {
epoch: usize,
index: usize,
}
impl WakerList {
pub fn new() -> Self {
Self::default()
}
pub fn register(&mut self, waker: Waker) -> WakerToken {
if let Some(index) = self.empty_slots.pop() {
debug_assert!(self.wakers[index].is_none());
self.wakers[index] = Some(waker);
self.token(index)
} else {
self.wakers.push(Some(waker));
self.token(self.wakers.len() - 1)
}
}
pub fn deregister(&mut self, token: WakerToken) -> Option<Waker> {
if self.epoch != token.epoch {
None
} else if let Some(waker) = self.wakers[token.index].take() {
self.empty_slots.push(token.index);
Some(waker)
} else {
None
}
}
#[allow(clippy::manual_flatten)] pub fn wake_all(&mut self) {
for waker in &mut self.wakers {
if let Some(waker) = waker.take() {
waker.wake()
}
}
self.wakers.clear();
self.empty_slots.clear();
self.epoch += 1;
}
fn token(&self, index: usize) -> WakerToken {
WakerToken {
epoch: self.epoch,
index,
}
}
#[cfg(test)]
pub fn total_slots(&self) -> usize {
self.wakers.len()
}
#[cfg(test)]
pub fn empty_slots(&self) -> usize {
self.empty_slots.len()
}
}