use std::{
pin::Pin,
sync::{
Arc,
atomic::{AtomicBool, Ordering},
},
task::{Context, Poll},
};
use futures_util::{Future, task::AtomicWaker};
#[derive(Debug)]
struct Inner {
waker: AtomicWaker,
set: AtomicBool,
}
#[derive(Debug, Clone)]
struct Flag(Arc<Inner>);
impl Flag {
pub fn new() -> Self {
Self(Arc::new(Inner {
waker: AtomicWaker::new(),
set: AtomicBool::new(false),
}))
}
pub fn notify(&self) {
self.0.set.store(true, Ordering::Relaxed);
self.0.waker.wake();
}
pub fn notified(&self) -> bool {
self.0.set.load(Ordering::Relaxed)
}
}
impl Future for Flag {
type Output = ();
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
if self.0.set.load(Ordering::Relaxed) {
return Poll::Ready(());
}
self.0.waker.register(cx.waker());
if self.0.set.load(Ordering::Relaxed) {
Poll::Ready(())
} else {
Poll::Pending
}
}
}
#[derive(Debug)]
pub struct Event {
flag: Flag,
}
impl Default for Event {
fn default() -> Self {
Self::new()
}
}
impl Event {
pub fn new() -> Self {
Self { flag: Flag::new() }
}
pub fn handle(&self) -> EventHandle {
EventHandle::new(self.flag.clone())
}
pub fn notified(&self) -> bool {
self.flag.notified()
}
pub async fn wait(self) {
self.flag.await
}
}
pub struct EventHandle {
flag: Flag,
}
impl EventHandle {
fn new(flag: Flag) -> Self {
Self { flag }
}
pub fn notify(self) {
self.flag.notify()
}
}