Skip to main content

atomic_primitive/
atomic.rs

1use core::sync::atomic::Ordering;
2
3use crate::Sealed;
4
5/// Trait for all primitive [atomic types], including [`AtomicBool`] and all
6/// atomic integer types.
7///
8/// This encapsulates trait implementations and inherent methods that are common
9/// among all of the primitive atomic types: [`AtomicBool`], [`AtomicU8`],
10/// [`AtomicU16`], [`AtomicU32`], [`AtomicU64`], [`AtomicUsize`], [`AtomicI8`],
11/// [`AtomicI16`], [`AtomicI32`], [`AtomicI64`], and [`AtomicIsize`].
12///
13/// See the corresponding items on the individual types for more documentation
14/// and examples.
15///
16/// This trait is sealed to prevent downstream implementations.
17///
18/// [`AtomicBool`]: core::sync::atomic::AtomicBool
19/// [`AtomicU8`]: core::sync::atomic::AtomicU8
20/// [`AtomicU16`]: core::sync::atomic::AtomicU16
21/// [`AtomicU32`]: core::sync::atomic::AtomicU32
22/// [`AtomicU64`]: core::sync::atomic::AtomicU64
23/// [`AtomicUsize`]: core::sync::atomic::AtomicUsize
24/// [`AtomicI8`]: core::sync::atomic::AtomicI8
25/// [`AtomicI16`]: core::sync::atomic::AtomicI16
26/// [`AtomicI32`]: core::sync::atomic::AtomicI32
27/// [`AtomicI64`]: core::sync::atomic::AtomicI64
28/// [`AtomicIsize`]: core::sync::atomic::AtomicIsize
29/// [atomic types]: core::sync::atomic
30#[expect(private_bounds)]
31pub trait PrimitiveAtomic: Sealed + Sized + Send + Sync {
32    /// The non-atomic type corresponding to this atomic type.
33    ///
34    /// The [`AtomicPrimitive`](crate::AtomicPrimitive) bound is the only
35    /// addition beyond standard library functionality, enabling bidirectional
36    /// navigation between atomic and non-atomic types.
37    type Value: Copy + Send + Sync + crate::AtomicPrimitive<Atomic = Self>;
38
39    /// Creates a new atomic value.
40    fn new(value: Self::Value) -> Self;
41
42    /// Returns a mutable reference to the underlying value.
43    fn get_mut(&mut self) -> &mut Self::Value;
44
45    /// Consumes the atomic and returns the contained value.
46    fn into_inner(self) -> Self::Value;
47
48    /// Loads a value from the atomic.
49    fn load(&self, order: Ordering) -> Self::Value;
50
51    /// Stores a value into the atomic.
52    fn store(&self, value: Self::Value, order: Ordering);
53
54    /// Stores a value into the atomic, returning the previous value.
55    fn swap(&self, value: Self::Value, order: Ordering) -> Self::Value;
56
57    /// Stores a value into the atomic if the current value is the same as
58    /// `current`.
59    fn compare_exchange(
60        &self,
61        current: Self::Value,
62        new: Self::Value,
63        success: Ordering,
64        failure: Ordering,
65    ) -> Result<Self::Value, Self::Value>;
66
67    /// Stores a value into the atomic if the current value is the same as
68    /// `current`. Unlike [`compare_exchange`](PrimitiveAtomic::compare_exchange),
69    /// this function is allowed to spuriously fail.
70    fn compare_exchange_weak(
71        &self,
72        current: Self::Value,
73        new: Self::Value,
74        success: Ordering,
75        failure: Ordering,
76    ) -> Result<Self::Value, Self::Value>;
77
78    /// Fetches the value, and applies a function to it that returns an optional
79    /// new value. Returns a `Result` of `Ok(previous_value)` if the function
80    /// returned `Some(_)`, else `Err(previous_value)`.
81    fn fetch_update<F>(
82        &self,
83        set_order: Ordering,
84        fetch_order: Ordering,
85        f: F,
86    ) -> Result<Self::Value, Self::Value>
87    where
88        F: FnMut(Self::Value) -> Option<Self::Value>;
89
90    /// Bitwise "and" with the current value. Returns the previous value.
91    fn fetch_and(&self, val: Self::Value, order: Ordering) -> Self::Value;
92
93    /// Bitwise "nand" with the current value. Returns the previous value.
94    fn fetch_nand(&self, val: Self::Value, order: Ordering) -> Self::Value;
95
96    /// Bitwise "or" with the current value. Returns the previous value.
97    fn fetch_or(&self, val: Self::Value, order: Ordering) -> Self::Value;
98
99    /// Bitwise "xor" with the current value. Returns the previous value.
100    fn fetch_xor(&self, val: Self::Value, order: Ordering) -> Self::Value;
101
102    /// Returns a raw pointer to the underlying value.
103    fn as_ptr(&self) -> *mut Self::Value;
104}
105
106macro_rules! impl_primitive_atomic {
107    ($Atomic:ty, $Value:ty) => {
108        impl Sealed for $Atomic {}
109
110        impl PrimitiveAtomic for $Atomic {
111            type Value = $Value;
112
113            forward! {
114                fn new(value: $Value) -> Self;
115                fn get_mut(&mut self) -> &mut $Value;
116                fn into_inner(self) -> $Value;
117                fn load(&self, order: Ordering) -> $Value;
118            }
119
120            // store: cannot use forward! (no return type)
121            #[inline]
122            fn store(&self, value: $Value, order: Ordering) {
123                <$Atomic>::store(self, value, order)
124            }
125
126            forward! {
127                fn swap(&self, value: $Value, order: Ordering) -> $Value;
128                fn compare_exchange(&self, current: $Value, new: $Value, success: Ordering, failure: Ordering) -> Result<$Value, $Value>;
129                fn compare_exchange_weak(&self, current: $Value, new: $Value, success: Ordering, failure: Ordering) -> Result<$Value, $Value>;
130            }
131
132            // fetch_update: cannot use forward! (generic parameter)
133            #[inline]
134            fn fetch_update<F>(
135                &self,
136                set_order: Ordering,
137                fetch_order: Ordering,
138                f: F,
139            ) -> Result<$Value, $Value>
140            where
141                F: FnMut($Value) -> Option<$Value>,
142            {
143                <$Atomic>::fetch_update(self, set_order, fetch_order, f)
144            }
145
146            forward! {
147                fn fetch_and(&self, val: $Value, order: Ordering) -> $Value;
148                fn fetch_nand(&self, val: $Value, order: Ordering) -> $Value;
149                fn fetch_or(&self, val: $Value, order: Ordering) -> $Value;
150                fn fetch_xor(&self, val: $Value, order: Ordering) -> $Value;
151                fn as_ptr(&self) -> *mut $Value;
152            }
153        }
154    };
155}
156
157use core::sync::atomic::{
158    AtomicBool, AtomicI8, AtomicI16, AtomicI32, AtomicI64, AtomicIsize, AtomicU8, AtomicU16,
159    AtomicU32, AtomicU64, AtomicUsize,
160};
161
162impl_primitive_atomic!(AtomicBool, bool);
163impl_primitive_atomic!(AtomicU8, u8);
164impl_primitive_atomic!(AtomicU16, u16);
165impl_primitive_atomic!(AtomicU32, u32);
166impl_primitive_atomic!(AtomicU64, u64);
167impl_primitive_atomic!(AtomicUsize, usize);
168impl_primitive_atomic!(AtomicI8, i8);
169impl_primitive_atomic!(AtomicI16, i16);
170impl_primitive_atomic!(AtomicI32, i32);
171impl_primitive_atomic!(AtomicI64, i64);
172impl_primitive_atomic!(AtomicIsize, isize);