1use std::sync::atomic::{
4 AtomicBool, AtomicI8, AtomicI16, AtomicI32, AtomicI64, AtomicIsize, AtomicPtr, AtomicU8,
5 AtomicU16, AtomicU32, AtomicU64, AtomicUsize, Ordering,
6};
7
8pub trait AtomicPrimitive: Sync + Send + Sized {
15 type InnerPrimitive: Default;
17
18 fn new(value: Self::InnerPrimitive) -> Self;
20 fn load(&self) -> Self::InnerPrimitive;
22 fn store(&self, value: Self::InnerPrimitive);
24
25 fn new_default() -> Self {
28 Self::new(Default::default())
29 }
30}
31
32macro_rules! impl_atomic_primitive {
33 ($atomic:ty, $inner:ty) => {
34 impl AtomicPrimitive for $atomic {
35 type InnerPrimitive = $inner;
36
37 fn new(value: $inner) -> Self {
38 <$atomic>::new(value)
39 }
40
41 fn load(&self) -> $inner {
42 self.load(Ordering::Relaxed)
43 }
44
45 fn store(&self, value: $inner) {
46 self.store(value, Ordering::Relaxed)
47 }
48 }
49 };
50}
51
52impl_atomic_primitive!(AtomicBool, bool);
53impl_atomic_primitive!(AtomicU8, u8);
54impl_atomic_primitive!(AtomicI8, i8);
55impl_atomic_primitive!(AtomicU16, u16);
56impl_atomic_primitive!(AtomicI16, i16);
57impl_atomic_primitive!(AtomicU32, u32);
58impl_atomic_primitive!(AtomicI32, i32);
59impl_atomic_primitive!(AtomicU64, u64);
60impl_atomic_primitive!(AtomicI64, i64);
61impl_atomic_primitive!(AtomicUsize, usize);
62impl_atomic_primitive!(AtomicIsize, isize);
63
64impl<T> AtomicPrimitive for AtomicPtr<T> {
65 type InnerPrimitive = *mut T;
66
67 fn new(value: *mut T) -> Self {
68 AtomicPtr::new(value)
69 }
70
71 fn load(&self) -> *mut T {
72 self.load(Ordering::Relaxed)
73 }
74
75 fn store(&self, value: *mut T) {
76 self.store(value, Ordering::Relaxed)
77 }
78}
79
80#[derive(Debug, Default)]
82pub struct AtomicConstPtr<T> {
83 p: AtomicPtr<T>,
84}
85
86impl<T> AtomicPrimitive for AtomicConstPtr<T> {
87 type InnerPrimitive = *const T;
88
89 fn new(value: *const T) -> Self {
90 Self {
93 p: AtomicPtr::new(value as *mut T),
94 }
95 }
96
97 fn load(&self) -> *const T {
98 self.p.load(Ordering::Relaxed) as *const T
99 }
100
101 fn store(&self, value: *const T) {
102 self.p.store(value as *mut T, Ordering::Relaxed)
105 }
106}
107
108#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
110pub struct AtomicUnit;
111
112impl AtomicPrimitive for AtomicUnit {
113 type InnerPrimitive = ();
114
115 fn new(_: ()) -> Self {
116 Self
117 }
118
119 fn load(&self) -> Self::InnerPrimitive {}
120
121 fn store(&self, _: Self::InnerPrimitive) {}
122}
123
124pub trait Payload:
132 From<<Self::UnderlyingAtomic as AtomicPrimitive>::InnerPrimitive>
133 + Into<<Self::UnderlyingAtomic as AtomicPrimitive>::InnerPrimitive>
134 + Copy
135{
136 type UnderlyingAtomic: AtomicPrimitive;
137}
138
139macro_rules! impl_payload {
140 ($inner:ty, $atomic:ty) => {
141 impl Payload for $inner {
142 type UnderlyingAtomic = $atomic;
143 }
144 };
145}
146
147impl_payload!((), AtomicUnit);
148impl_payload!(bool, AtomicBool);
149impl_payload!(u8, AtomicU8);
150impl_payload!(i8, AtomicI8);
151impl_payload!(u16, AtomicU16);
152impl_payload!(i16, AtomicI16);
153impl_payload!(u32, AtomicU32);
154impl_payload!(i32, AtomicI32);
155impl_payload!(u64, AtomicU64);
156impl_payload!(i64, AtomicI64);
157impl_payload!(usize, AtomicUsize);
158impl_payload!(isize, AtomicIsize);
159
160impl<T> Payload for *mut T {
161 type UnderlyingAtomic = AtomicPtr<T>;
162}
163
164impl<T> Payload for *const T {
165 type UnderlyingAtomic = AtomicConstPtr<T>;
166}