use async_ach_waker::pool::{WakerPool, WakerToken};
use async_ach_waker::WakerEntity;
use atomic_polyfill::{AtomicU64, Ordering::SeqCst};
use core::ops::Deref;
use core::task::Waker;
pub struct Waiter<const N: usize> {
pool: WakerPool<u64, N>,
next: AtomicU64,
}
impl<const N: usize> Waiter<N> {
pub const fn new() -> Self {
Self {
pool: WakerPool::new(),
next: AtomicU64::new(u64::MAX),
}
}
pub fn register(&'_ self) -> Result<Token<'_, N>, ()> {
let token = self.pool.register()?;
Ok(Token {
next: &self.next,
token,
})
}
pub fn take_next(&self) -> Option<u64> {
let next = self.next.swap(u64::MAX, SeqCst);
if next == u64::MAX {
None
} else {
Some(next)
}
}
pub fn set_next(&self, next: u64) {
self.next.fetch_min(next, SeqCst);
}
}
impl<const N: usize> Deref for Waiter<N> {
type Target = WakerPool<u64, N>;
fn deref(&self) -> &Self::Target {
&self.pool
}
}
pub struct Token<'a, const N: usize> {
next: &'a AtomicU64,
token: WakerToken<'a, u64, N>,
}
impl<'a, const N: usize> Token<'a, N> {
pub fn swap(&self, waker: Waker, deadline: u64) {
self.next.fetch_min(deadline, SeqCst);
self.token.swap(WakerEntity::new(waker, deadline));
}
}