wsio_core/atomic/
status.rs

1use std::{
2    marker::PhantomData,
3    sync::atomic::{
4        AtomicU8,
5        Ordering,
6    },
7};
8
9use anyhow::{
10    Result,
11    anyhow,
12    bail,
13};
14
15// Structs
16pub struct AtomicStatus<T: Eq + Into<u8> + PartialEq + TryFrom<u8>> {
17    _marker: PhantomData<T>,
18    inner: AtomicU8,
19}
20
21impl<T: Eq + Into<u8> + PartialEq + TryFrom<u8>> AtomicStatus<T> {
22    #[inline]
23    pub fn new(status: T) -> Self {
24        Self {
25            _marker: PhantomData,
26            inner: AtomicU8::new(status.into()),
27        }
28    }
29
30    // Public methods
31    #[inline]
32    pub fn ensure<F: FnOnce(T) -> String>(&self, expected: T, message: F) -> Result<()> {
33        let status = self.get();
34        if status != expected {
35            bail!("{}", message(status));
36        }
37
38        Ok(())
39    }
40
41    #[inline]
42    pub fn get(&self) -> T {
43        T::try_from(self.inner.load(Ordering::SeqCst)).ok().unwrap()
44    }
45
46    #[inline]
47    pub fn is(&self, status: T) -> bool {
48        self.inner.load(Ordering::SeqCst) == status.into()
49    }
50
51    #[inline]
52    pub fn store(&self, status: T) {
53        self.inner.store(status.into(), Ordering::SeqCst);
54    }
55
56    #[inline]
57    pub fn try_transition(&self, from: T, to: T) -> Result<()> {
58        self.inner
59            .compare_exchange(from.into(), to.into(), Ordering::SeqCst, Ordering::SeqCst)
60            .map(|_| ())
61            .map_err(|_| anyhow!("Failed to transition status"))
62    }
63}