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);