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> AtomicOrdinal<T> {
48 #[inline]
50 pub fn new(value: T) -> Self {
51 Self {
52 atomic: AtomicUsize::new(value.ordinal()),
53 _marker: PhantomData,
54 }
55 }
56
57 pub fn load(&self, ordering: Ordering) -> T {
59 T::from_ordinal(self.atomic.load(ordering)).unwrap()
60 }
61
62 pub fn store(&self, value: T, ordering: Ordering) {
64 self.atomic.store(value.ordinal(), ordering);
65 }
66
67 pub fn compare_exchange(
69 &self,
70 old: T,
71 new: T,
72 success: Ordering,
73 failure: Ordering,
74 ) -> Result<T, T> {
75 let old_ord = old.ordinal();
76 let new_ord = new.ordinal();
77 let res = self
78 .atomic
79 .compare_exchange(old_ord, new_ord, success, failure);
80 match res {
81 Ok(v) => Ok(T::from_ordinal(v).unwrap()),
82 Err(v) => Err(T::from_ordinal(v).unwrap()),
83 }
84 }
85}