use std::sync::{Arc, atomic::{AtomicU8, Ordering}}; use tokio::sync::Notify; #[derive(Clone, Debug)] pub struct CompletionToken { inner: Arc<(AtomicU8, Notify)>, } impl CompletionToken { pub fn new() -> Self { Self { inner: Arc::new((AtomicU8::new(0), Notify::new())) } } pub fn complete(&self, success: bool) { let new = if success { 1 } else { 2 }; self.inner.0.compare_exchange(0, new, Ordering::Relaxed, Ordering::Relaxed).ok(); self.inner.1.notify_waiters(); } pub fn completed(&self) -> Option { let state = self.inner.0.load(Ordering::Relaxed); if state == 0 { None } else { Some(state == 1) } } pub async fn future(&self) -> bool { loop { if let Some(state) = self.completed() { return state; } let notified = self.inner.1.notified(); if let Some(state) = self.completed() { return state; } notified.await; } } }