statewatcher/
state_reader.rs

1use std::sync::{
2    Arc, RwLock, RwLockReadGuard,
3    atomic::{AtomicBool, Ordering},
4};
5
6#[derive(Clone)]
7pub struct StateReader<T> {
8    pub(crate) inner: Arc<(RwLock<T>, AtomicBool)>,
9}
10
11impl<T> StateReader<T>
12where
13    T: Clone,
14{
15    #[inline]
16    fn lock<'a>(&'a self) -> RwLockReadGuard<'a, T> {
17        match self.inner.0.read() {
18            Ok(g) => g,
19            Err(p) => p.into_inner(),
20        }
21    }
22
23    pub fn latest(&self) -> Option<T> {
24        if self.inner.1.load(Ordering::Acquire) {
25            let guard = self.lock();
26            Some(guard.clone())
27        } else {
28            None
29        }
30    }
31
32    pub fn latest_and_clear(&self) -> Option<T> {
33        if self.inner.1.swap(false, Ordering::AcqRel) {
34            let guard = self.lock();
35            Some(guard.clone())
36        } else {
37            None
38        }
39    }
40
41    pub fn with_state<F, R>(&self, f: F) -> R
42    where
43        F: FnOnce(&T) -> R,
44    {
45        let guard = self.lock();
46        f(&*guard)
47    }
48}