use std::{
sync::{
atomic::{self, AtomicBool},
Arc,
},
task::Poll,
};
use futures::{
future::{self},
task::AtomicWaker,
};
pub fn channel() -> (Sender, Receiver) {
let state = Arc::new(State {
waker: AtomicWaker::new(),
signaled: AtomicBool::new(false),
});
let sender_state = Arc::clone(&state);
(Sender(sender_state), Receiver(state))
}
#[derive(Debug, Clone)]
pub struct Sender(Arc<State>);
impl Sender {
pub fn signal(&self) {
self.0.signaled.store(true, atomic::Ordering::SeqCst);
self.0.waker.wake()
}
}
#[derive(Debug)]
pub struct Receiver(Arc<State>);
impl Receiver {
pub async fn wait(&mut self) {
future::poll_fn(|cx| {
self.0.waker.register(cx.waker());
if self.0.signaled.swap(false, atomic::Ordering::SeqCst) {
Poll::Ready(())
} else {
Poll::Pending
}
})
.await
}
}
#[derive(Debug)]
struct State {
waker: AtomicWaker,
signaled: AtomicBool,
}