use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
#[derive(Clone, Debug, Default)]
pub struct ScanCancel(Arc<AtomicBool>);
impl ScanCancel {
pub fn new() -> Self {
Self::default()
}
pub fn cancel(&self) {
self.0.store(true, Ordering::Relaxed);
}
pub fn is_cancelled(&self) -> bool {
self.0.load(Ordering::Relaxed)
}
pub fn check(&self) -> crate::Result<()> {
if self.is_cancelled() {
Err(crate::Error::Cancelled)
} else {
Ok(())
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn starts_uncancelled_and_cancels() {
let c = ScanCancel::new();
assert!(!c.is_cancelled());
assert!(c.check().is_ok());
c.cancel();
assert!(c.is_cancelled());
assert!(matches!(c.check(), Err(crate::Error::Cancelled)));
}
#[test]
fn clones_share_state() {
let a = ScanCancel::new();
let b = a.clone();
a.cancel();
assert!(b.is_cancelled(), "cancel on one clone is seen by another");
}
#[test]
fn default_is_never_cancelled() {
let c = ScanCancel::default();
assert!(!c.is_cancelled());
assert!(c.check().is_ok());
}
}