Skip to main content

pagers_core/
cancel.rs

1use std::sync::atomic::{AtomicBool, Ordering};
2use std::sync::{Arc, Condvar, Mutex};
3
4#[derive(Clone, Debug)]
5pub struct Cancellation(Arc<State>);
6
7#[derive(Debug)]
8struct State {
9    cancelled: AtomicBool,
10    event: Condvar,
11    lock: Mutex<()>,
12}
13
14impl Cancellation {
15    pub fn new() -> Self {
16        Self(Arc::new(State {
17            cancelled: AtomicBool::new(false),
18            event: Condvar::new(),
19            lock: Mutex::new(()),
20        }))
21    }
22
23    pub fn cancel(&self) {
24        let _guard = self.0.lock.lock().unwrap();
25        if !self.0.cancelled.swap(true, Ordering::Release) {
26            self.0.event.notify_all();
27        }
28    }
29
30    pub fn is_cancelled(&self) -> bool {
31        self.0.cancelled.load(Ordering::Acquire)
32    }
33
34    pub fn wait(&self) {
35        let guard = self.0.lock.lock().unwrap();
36        drop(
37            self.0
38                .event
39                .wait_while(guard, |_| !self.is_cancelled())
40                .unwrap(),
41        );
42    }
43
44    pub fn check(&self) -> crate::Result<()> {
45        if self.is_cancelled() {
46            Err(crate::Error::Cancelled)
47        } else {
48            Ok(())
49        }
50    }
51}
52
53impl Default for Cancellation {
54    fn default() -> Self {
55        Self::new()
56    }
57}