use crate::ObserverError;
use atomic_waker::AtomicWaker;
use std::sync::Arc;
use std::sync::atomic::AtomicBool;
#[derive(Debug, Clone)]
pub struct ActiveObservation {
shared: Arc<Shared>,
}
impl Drop for ActiveObservation {
fn drop(&mut self) {
self.shared
.ready
.store(true, std::sync::atomic::Ordering::Relaxed);
self.shared.waker.wake();
}
}
#[derive(Debug)]
struct Shared {
waker: AtomicWaker,
ready: AtomicBool,
}
pub(crate) struct ActiveObservationFuture {
shared: Arc<Shared>,
}
impl Future for ActiveObservationFuture {
type Output = Result<(), ObserverError>;
fn poll(
self: std::pin::Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
) -> std::task::Poll<Self::Output> {
self.shared.waker.register(cx.waker());
if self.shared.ready.load(std::sync::atomic::Ordering::Relaxed) {
return std::task::Poll::Ready(Ok(()));
}
std::task::Poll::Pending
}
}
pub fn observation() -> (ActiveObservation, ActiveObservationFuture) {
let shared = Arc::new(Shared {
waker: AtomicWaker::new(),
ready: AtomicBool::new(false),
});
(
ActiveObservation {
shared: shared.clone(),
},
ActiveObservationFuture { shared },
)
}