wsio_core/atomic/
status.rs1use std::{
2 marker::PhantomData,
3 sync::atomic::{
4 AtomicU8,
5 Ordering,
6 },
7};
8
9use anyhow::{
10 Result,
11 anyhow,
12 bail,
13};
14
15pub 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 #[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}