use crate::utils::numcell::NumCell;
use std::cell::Cell;
use std::fmt::Debug;
use std::fmt::Formatter;
use std::pin::Pin;
use std::task::Context;
use std::task::Poll;
use std::task::Waker;
#[derive(Default)]
pub struct AsyncEvent {
triggers: NumCell<u64>,
waker: Cell<Option<Waker>>,
}
impl Debug for AsyncEvent {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("AsyncEvent")
.field("triggers", &self.triggers.get())
.finish_non_exhaustive()
}
}
impl AsyncEvent {
pub fn clear(&self) {
self.triggers.set(0);
self.waker.take();
}
pub fn reset_triggers(&self) {
self.triggers.set(0);
}
pub fn trigger(&self) {
if self.triggers.fetch_add(1) == 0
&& let Some(waker) = self.waker.take()
{
waker.wake();
}
}
pub fn triggered(&self) -> AsyncEventTriggered<'_> {
AsyncEventTriggered { ae: self }
}
}
pub struct AsyncEventTriggered<'a> {
ae: &'a AsyncEvent,
}
impl Future for AsyncEventTriggered<'_> {
type Output = u64;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let triggers = self.ae.triggers.replace(0);
if triggers == 0 {
self.ae.waker.set(Some(cx.waker().clone()));
Poll::Pending
} else {
Poll::Ready(triggers)
}
}
}