pistonite_cu/
atomic.rs

1/// An atomic wrapper with an underlying atomic storage and conversion to
2/// a type T.
3///
4/// `Acquire` ordering is used for load and `Release` ordering is used for store.
5///
6/// A proc macro might be provided in the future to simplify declaring a compatible enum type.
7///
8/// ```rust
9/// # use pistonite_cu as cu;
10/// #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
11/// #[repr(u8)]
12/// pub enum MyEnum {
13///    A,
14///    B,
15///    C,
16///    Invalid, //
17/// }
18/// impl From<u8> for MyEnum {
19///     fn from(value: u8) -> Self {
20///         match value {
21///             0 => Self::A,
22///             1 => Self::B,
23///             2 => Self::C,
24///             _ => Self::Invalid,
25///         }
26///     }
27/// }
28/// impl From<MyEnum> for u8 {
29///     fn from(value: MyEnum) -> Self {
30///         value as Self
31///     }
32/// }
33///
34/// # fn main() {
35/// let value: cu::Atomic<u8, MyEnum> = cu::Atomic::new_u8(MyEnum::A as u8);
36/// assert_eq!(MyEnum::A, value.get());
37/// value.set(MyEnum::C);
38/// assert_eq!(MyEnum::C, value.get());
39/// # }
40/// ```
41#[derive(Debug, Default)]
42pub struct Atomic<S, T>(S::Type, std::marker::PhantomData<T>)
43where
44    S: AtomicType,
45    T: From<S> + Into<S>;
46/// Marker type to associate primitive with their atomic versions
47pub trait AtomicType {
48    type Type;
49}
50macro_rules! impl_atomic_type {
51    ($($t:ident => $Atomic:ident, $newfn:ident),* $(,)?) => { $(
52    impl AtomicType for $t {
53        type Type = std::sync::atomic::$Atomic;
54    }
55    impl<T: From<$t> + Into<$t>> Atomic<$t, T> {
56        pub const fn $newfn(value: $t) -> Self {
57            Self(std::sync::atomic::$Atomic::new(value), std::marker::PhantomData)
58        }
59        pub fn get(&self) -> T {
60            self.0.load(std::sync::atomic::Ordering::Acquire).into()
61        }
62        pub fn set(&self, value: T) {
63            self.0.store(value.into(), std::sync::atomic::Ordering::Release)
64        }
65    }
66    )* }
67}
68impl_atomic_type! {
69    i8 => AtomicI8, new_i8,
70    i16 => AtomicI16, new_i16,
71    i32 => AtomicI32, new_i32,
72    i64 => AtomicI64, new_i64,
73    u8 => AtomicU8, new_u8,
74    u16 => AtomicU16, new_u16,
75    u32 => AtomicU32, new_u32,
76    u64 => AtomicU64, new_u64,
77    bool => AtomicBool, new_bool,
78    isize => AtomicIsize, new_isize,
79    usize => AtomicUsize, new_usize,
80}