1use crate::{
2 atomic_float_wrapper::AtomicFloatWrapper, atomic_integer::AtomicInteger, AtomicFloat,
3 AtomicNumber, IntoAtomicFloat, IntoAtomicInteger,
4};
5use atomic_traits::{
6 fetch::{self, And, Nand, Or, Update, Xor},
7 AsPtr, Atomic, Bitwise, FromPtr,
8};
9use core::sync::atomic::{
10 AtomicI16, AtomicI32, AtomicI64, AtomicI8, AtomicIsize, AtomicU16, AtomicU32, AtomicU64,
11 AtomicU8, AtomicUsize,
12 Ordering::{self},
13};
14use num_primitive::{PrimitiveFloat, PrimitiveInteger, PrimitiveNumber};
15use num_traits::FromPrimitive;
16
17pub trait AtomicNumberTraitBounds<N>:
18 Atomic<Type = N> + Bitwise + AsPtr + FromPtr + fetch::Update<Type = <Self as Atomic>::Type>
19{
20}
21impl<AN, N> AtomicNumberTraitBounds<N> for AN where
22 AN: Atomic<Type = N> + Bitwise + AsPtr + FromPtr + fetch::Update<Type = <Self as Atomic>::Type>
23{
24}
25
26pub(crate) trait PrimitiveAtomicNumber: PrimitiveNumber + IntoAtomicNumber {}
27impl<T> PrimitiveAtomicNumber for T where T: PrimitiveNumber + IntoAtomicNumber {}
28
29pub trait IntoAtomicNumber: Sized + FromPrimitive {
32 type AN: AtomicNumberTraitBounds<Self> + Send;
33 fn into_atomic_number(self) -> impl AtomicNumberTraitBounds<Self> {
34 Self::AN::new(self)
35 }
36}
37
38macro_rules! impl_into_atomic_number {
39 ($type:ty, $atomic:ty) => {
40 impl IntoAtomicNumber for $type {
41 type AN = $atomic;
42 }
43 };
44}
45
46impl_into_atomic_number!(i8, AtomicI8);
47impl_into_atomic_number!(i16, AtomicI16);
48impl_into_atomic_number!(i32, AtomicI32);
49impl_into_atomic_number!(i64, AtomicI64);
50impl_into_atomic_number!(isize, AtomicIsize);
51impl_into_atomic_number!(u8, AtomicU8);
53impl_into_atomic_number!(u16, AtomicU16);
54impl_into_atomic_number!(u32, AtomicU32);
55impl_into_atomic_number!(u64, AtomicU64);
56impl_into_atomic_number!(usize, AtomicUsize);
57impl_into_atomic_number!(f64, AtomicFloatWrapper<f64>);
59impl_into_atomic_number!(f32, AtomicFloatWrapper<f32>);
60
61#[expect(unsafe_code)]
64unsafe impl<F: PrimitiveAtomicNumber> Send for AtomicNumber<F> {}
65#[expect(unsafe_code)]
66unsafe impl<F: PrimitiveAtomicNumber> Sync for AtomicNumber<F> {}
67
68impl<T> Atomic for AtomicNumber<T>
69where
70 T: PrimitiveAtomicNumber + FromPrimitive,
71{
72 type Type = T;
73
74 #[inline(always)]
75 fn new(number: T) -> Self {
76 Self {
77 atomic: T::AN::new(number),
78 }
79 }
80
81 #[inline(always)]
82 fn get_mut(&mut self) -> &mut T {
83 self.atomic.get_mut()
84 }
85
86 #[inline(always)]
87 fn into_inner(self) -> T {
88 self.atomic.into_inner()
89 }
90
91 #[inline(always)]
92 fn load(&self, ordering: Ordering) -> T {
93 self.atomic.load(ordering)
94 }
95
96 #[inline(always)]
97 fn store(&self, value: T, ordering: Ordering) {
98 self.atomic.store(value, ordering);
99 }
100
101 #[inline(always)]
102 fn swap(&self, new_value: T, ordering: Ordering) -> T {
103 self.atomic.swap(new_value, ordering)
104 }
105
106 #[inline(always)]
107 #[expect(deprecated)]
108 fn compare_and_swap(&self, current: T, new: T, order: Ordering) -> T {
109 self.atomic.compare_and_swap(current, new, order)
110 }
111
112 #[inline(always)]
113 fn compare_exchange(
114 &self,
115 current: T,
116 new: T,
117 success: Ordering,
118 failure: Ordering,
119 ) -> Result<T, T> {
120 let current1 = current;
121 let bits = new;
122 self.atomic
123 .compare_exchange(current1, bits, success, failure)
124 }
125
126 #[inline(always)]
127 fn compare_exchange_weak(
128 &self,
129 current: T,
130 new: T,
131 success: Ordering,
132 failure: Ordering,
133 ) -> Result<T, T> {
134 self.atomic
135 .compare_exchange_weak(current, new, success, failure)
136 }
137}
138
139impl<T> Update for AtomicNumber<T>
140where
141 T: PrimitiveAtomicNumber + FromPrimitive,
142{
143 type Type = T;
144
145 #[inline(always)]
146 fn fetch_update<F>(&self, set_order: Ordering, fetch_order: Ordering, update: F) -> Result<T, T>
147 where
148 F: FnMut(T) -> Option<T>,
149 {
150 self.atomic.fetch_update(set_order, fetch_order, update)
151 }
152}
153
154impl<T> Bitwise for AtomicNumber<T> where T: PrimitiveAtomicNumber + FromPrimitive {}
155
156impl<T> And for AtomicNumber<T>
157where
158 T: PrimitiveAtomicNumber + FromPrimitive,
159{
160 type Type = T;
161
162 #[inline(always)]
163 fn fetch_and(&self, val: T, order: Ordering) -> T {
164 self.atomic.fetch_and(val, order)
165 }
166}
167
168impl<T> Nand for AtomicNumber<T>
169where
170 T: PrimitiveAtomicNumber + FromPrimitive,
171{
172 type Type = T;
173
174 #[inline(always)]
175 fn fetch_nand(&self, val: T, order: Ordering) -> T {
176 self.atomic.fetch_nand(val, order)
177 }
178}
179
180impl<T> Or for AtomicNumber<T>
181where
182 T: PrimitiveAtomicNumber + FromPrimitive,
183{
184 type Type = T;
185
186 #[inline(always)]
187 fn fetch_or(&self, val: T, order: Ordering) -> T {
188 self.atomic.fetch_or(val, order)
189 }
190}
191
192impl<T> Xor for AtomicNumber<T>
193where
194 T: PrimitiveAtomicNumber + FromPrimitive,
195{
196 type Type = T;
197
198 #[inline(always)]
199 fn fetch_xor(&self, val: T, order: Ordering) -> T {
200 self.atomic.fetch_xor(val, order)
201 }
202}
203
204impl<T> FromPtr for AtomicNumber<T>
205where
206 T: PrimitiveAtomicNumber + FromPrimitive,
207{
208 #[inline(always)]
209 #[expect(unsafe_code)]
210 unsafe fn from_ptr<'a>(ptr: *mut T) -> &'a Self {
211 unsafe {
212 let u: &<T as IntoAtomicNumber>::AN = T::AN::from_ptr(ptr);
213 let ptr = core::ptr::from_ref(u);
214 let atomic_ptr = ptr.cast::<Self>();
215 &*(atomic_ptr)
216 }
217 }
218}
219
220impl<T> AsPtr for AtomicNumber<T>
221where
222 T: PrimitiveAtomicNumber + FromPrimitive,
223{
224 #[inline(always)]
225 fn as_ptr(&self) -> *mut T {
226 self.atomic.as_ptr()
227 }
228}
229
230impl<T> Default for AtomicNumber<T>
231where
232 T: PrimitiveAtomicNumber + FromPrimitive,
233{
234 #[inline(always)]
235 fn default() -> Self {
236 Self {
237 atomic: T::AN::new(T::default()),
238 }
239 }
240}
241
242impl<T> core::fmt::Debug for AtomicNumber<T>
243where
244 T: PrimitiveAtomicNumber + FromPrimitive,
245{
246 #[inline(always)]
247 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
248 core::fmt::Debug::fmt(&self.load(Ordering::SeqCst), f)
249 }
250}
251
252impl<A> AtomicNumber<A>
253where
254 A: IntoAtomicFloat + PrimitiveFloat,
255{
256 pub fn into_atomic_float(self) -> impl AtomicFloat<<Self as Atomic>::Type> {
257 self
258 }
259}
260
261impl<A> AtomicNumber<A>
262where
263 A: IntoAtomicInteger + PrimitiveInteger,
264{
265 pub fn into_atomic_integer(self) -> impl AtomicInteger<<Self as Atomic>::Type> {
266 self
267 }
268}