1use std::fmt;
2use std::fmt::Debug;
3use std::fmt::Formatter;
4use std::marker::PhantomData;
5use std::sync::atomic::AtomicUsize;
6use std::sync::atomic::Ordering;
7
8use crate::Ordinal;
9
10pub struct AtomicOrdinal<T> {
36 atomic: AtomicUsize,
37 _marker: PhantomData<T>,
38}
39
40impl<T: Ordinal + Debug> Debug for AtomicOrdinal<T> {
41 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
42 let v = self.load(Ordering::Relaxed);
43 Debug::fmt(&v, f)
44 }
45}
46
47impl<T: Ordinal + Default> Default for AtomicOrdinal<T> {
49 #[inline]
50 fn default() -> Self {
51 AtomicOrdinal::new(T::default())
52 }
53}
54
55impl<T: Ordinal> AtomicOrdinal<T> {
56 #[inline]
58 pub fn new(value: T) -> Self {
59 Self {
60 atomic: AtomicUsize::new(value.ordinal()),
61 _marker: PhantomData,
62 }
63 }
64
65 pub fn load(&self, ordering: Ordering) -> T {
67 T::from_ordinal(self.atomic.load(ordering)).unwrap()
68 }
69
70 pub fn store(&self, value: T, ordering: Ordering) {
72 self.atomic.store(value.ordinal(), ordering);
73 }
74
75 pub fn compare_exchange(
77 &self,
78 old: T,
79 new: T,
80 success: Ordering,
81 failure: Ordering,
82 ) -> Result<T, T> {
83 let old_ord = old.ordinal();
84 let new_ord = new.ordinal();
85 let res = self
86 .atomic
87 .compare_exchange(old_ord, new_ord, success, failure);
88 match res {
89 Ok(v) => Ok(T::from_ordinal(v).unwrap()),
90 Err(v) => Err(T::from_ordinal(v).unwrap()),
91 }
92 }
93}