use std::{
fmt::Debug,
future::Future,
sync::{
Arc,
atomic::{AtomicBool, Ordering},
},
};
use tokio::sync::Notify;
#[derive(Clone)]
pub struct Shutdown {
inner: Arc<(AtomicBool, Notify)>,
}
#[allow(unused)]
impl Shutdown {
pub fn new() -> Self {
Self {
inner: Arc::new((AtomicBool::new(false), Notify::new())),
}
}
pub fn shutdown(&self) {
self.inner.0.swap(true, Ordering::Relaxed);
self.inner.1.notify_waiters();
}
pub fn reset(&self) {
self.inner.0.store(false, Ordering::Relaxed);
}
pub fn is_terminated(&self) -> bool {
self.inner.0.load(Ordering::Relaxed)
}
pub fn wait(&'_ self) -> impl Future<Output = ()> + Send + 'static {
let inner = self.inner.clone();
async move {
if !inner.0.load(Ordering::Relaxed) {
let notify = inner.1.notified();
if !inner.0.load(Ordering::Relaxed) {
notify.await;
}
}
}
}
}
impl Default for Shutdown {
fn default() -> Self {
Self::new()
}
}
impl Debug for Shutdown {
fn fmt(
&self,
f: &mut std::fmt::Formatter<'_>,
) -> std::fmt::Result {
f.debug_struct("Shutdown").field("is_terminated", &self.inner.0.load(Ordering::Relaxed)).finish()
}
}