use std::sync::Arc;
use tokio::sync::watch;
#[derive(Clone, Debug)]
pub struct Stop {
stopping: Arc<watch::Sender<bool>>,
}
impl Default for Stop {
fn default() -> Self {
Self::new()
}
}
impl Stop {
pub fn new() -> Self {
Self {
stopping: Arc::new(watch::channel(false).0),
}
}
pub fn stop(&self) {
self.stopping.send_replace(true);
}
pub fn is_stopping(&self) -> bool {
*self.stopping.borrow()
}
pub async fn stopping(&self) {
let mut receiver = self.stopping.subscribe();
let _ = receiver.wait_for(|stopping| *stopping).await;
}
}
#[cfg(test)]
mod tests {
use std::time::Duration;
use super::Stop;
#[tokio::test]
async fn every_clone_sees_the_stop_and_waiting_on_it_returns() {
let stop = Stop::new();
let clone = stop.clone();
assert!(!clone.is_stopping());
let waiting = tokio::spawn(async move { clone.stopping().await });
tokio::time::sleep(Duration::from_millis(10)).await;
assert!(!waiting.is_finished());
stop.stop();
stop.stop();
tokio::time::timeout(Duration::from_secs(5), waiting)
.await
.expect("the wait returns")
.unwrap();
assert!(stop.is_stopping());
stop.stopping().await;
}
}