use std::{
future::Future,
pin::Pin,
sync::Arc,
task::{
Context,
Poll,
},
};
type NotifiedBox<'a> = Pin<Box<dyn Future<Output = ()> + Send + 'a>>;
pub struct Notify {
notify: Arc<tokio::sync::Notify>,
}
impl Notify {
pub fn new() -> Self {
Self {
notify: Arc::new(tokio::sync::Notify::new()),
}
}
pub fn notified(&self) -> Notified {
Notified {
notify: self.notify.clone(),
notified: None,
}
}
pub fn notify_waiters(&self) {
self.notify.notify_waiters();
}
}
pub struct Notified {
notify: Arc<tokio::sync::Notify>,
notified: Option<NotifiedBox<'static>>,
}
impl Drop for Notified {
fn drop(&mut self) {
drop(self.notified.take());
}
}
impl Clone for Notified {
fn clone(&self) -> Self {
Self {
notify: self.notify.clone(),
notified: None,
}
}
}
impl Future for Notified {
type Output = ();
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let this: &mut Self = &mut self;
if this.notified.is_none() {
let notified: NotifiedBox<'_> = Box::pin(this.notify.notified());
let notified =
unsafe { std::mem::transmute::<NotifiedBox<'_>, NotifiedBox<'static>>(notified) };
this.notified = Some(notified);
}
this.notified.as_mut().unwrap().as_mut().poll(cx)
}
}