Skip to main content

common_traits/
atomic.rs

1use crate::{False, True};
2use crate::{IsAtomic, SameAs};
3use core::sync::atomic::Ordering;
4
5/// A trait for types that have an equivalent atomic type.
6pub trait IntoAtomic: IsAtomic<Atomic = False> + Sized + Send + Sync {
7    /// The atomic variant of the type.
8    type AtomicType: Atomic<NonAtomicType = Self>;
9    /// Convert `self` into the atomic variant of `Self`
10    fn to_atomic(self) -> Self::AtomicType;
11
12    /// Convert an array of non-atomic values into an array of atomic values.
13    fn into_atomic_array<const N: usize>(data: [Self; N]) -> [Self::AtomicType; N];
14    /// Convert an array of atomic values into an array of non-atomic values.
15    fn from_atomic_array<const N: usize>(data: [Self::AtomicType; N]) -> [Self; N];
16
17    /// Convert a slice of non-atomic values into a slice of atomic values.
18    fn get_mut_slice(this: &mut [Self::AtomicType]) -> &mut [Self];
19    /// Convert a slice of atomic values into a slice of non-atomic values.
20    fn from_mut_slice(this: &mut [Self]) -> &mut [Self::AtomicType];
21
22    /// Convert a reference to an array of non-atomic values into a reference to an array of atomic values.
23    fn get_mut_array<const N: usize>(this: &mut [Self::AtomicType; N]) -> &mut [Self; N];
24    /// Convert a reference to an array of atomic values into a reference to an array of non-atomic values.
25    fn from_mut_array<const N: usize>(this: &mut [Self; N]) -> &mut [Self::AtomicType; N];
26}
27
28/// Values that can be atomically read and written.
29pub trait Atomic: IsAtomic<Atomic = True> + Sized + Send + Sync {
30    /// The non atomic variant of this type
31    type NonAtomicType: IntoAtomic<AtomicType = Self> + SameAs<Self>;
32
33    /// Creates a new atomic integer.
34    fn new(value: Self::NonAtomicType) -> Self;
35    /// Loads a value from the atomic integer.
36    ///
37    /// load takes an [`Ordering`](`core::sync::atomic::Ordering`) argument which describes
38    /// the memory ordering of this operation.
39    /// Possible values are [`SeqCst`](`core::sync::atomic::Ordering::SeqCst`),
40    ///[`Acquire`](`core::sync::atomic::Ordering::Acquire`) and [`Relaxed`](`core::sync::atomic::Ordering::Relaxed`).
41    ///
42    /// # Panics
43    /// Panics if order is [`Release`](`core::sync::atomic::Ordering::Release`) or [`AcqRel`](`core::sync::atomic::Ordering::AcqRel`).
44    fn load(&self, order: Ordering) -> Self::NonAtomicType;
45    /// Stores a value into the atomic integer.
46    /// load takes an [`Ordering`](`core::sync::atomic::Ordering`) argument which describes
47    /// the memory ordering of this operation.
48    /// Possible values are [`SeqCst`](`core::sync::atomic::Ordering::SeqCst`),
49    /// [`Release`](`core::sync::atomic::Ordering::Release`) and [`Relaxed`](`core::sync::atomic::Ordering::Relaxed`).
50    ///
51    /// # Panics
52    /// Panics if order is [`Acquire`](`core::sync::atomic::Ordering::Acquire`) or
53    /// [`AcqRel`](`core::sync::atomic::Ordering::AcqRel`).
54    fn store(&self, value: Self::NonAtomicType, order: Ordering);
55    /// Returns a mutable reference to the underlying integer.
56    ///
57    /// This is safe because the mutable reference guarantees that no other
58    /// threads are concurrently accessing the atomic data.
59    fn get_mut(&mut self) -> &mut Self::NonAtomicType;
60    /// Consumes the atomic and returns the contained value.
61    ///
62    /// This is safe because passing `self` by value guarantees that no other
63    /// threads are concurrently accessing the atomic data.
64    fn into_inner(self) -> Self::NonAtomicType;
65
66    fn into_non_atomic_array<const N: usize>(data: [Self; N]) -> [Self::NonAtomicType; N];
67    fn from_non_atomic_array<const N: usize>(data: [Self::NonAtomicType; N]) -> [Self; N];
68
69    fn get_mut_slice(this: &mut [Self]) -> &mut [Self::NonAtomicType];
70    fn from_mut_slice(this: &mut [Self::NonAtomicType]) -> &mut [Self];
71
72    fn get_mut_array<const N: usize>(this: &mut [Self; N]) -> &mut [Self::NonAtomicType; N];
73    fn from_mut_array<const N: usize>(this: &mut [Self::NonAtomicType; N]) -> &mut [Self; N];
74
75    /// Stores a value into the atomic integer if the current value is the same
76    /// as the current value.
77    ///
78    /// The return value is a result indicating whether the new value was
79    /// written and containing the previous value. On success this value is
80    /// guaranteed to be equal to current.
81    ///
82    /// [`compare_exchange`](`Atomic::compare_exchange`) takes two
83    /// [`Ordering`](`core::sync::atomic::Ordering`)
84    /// arguments to describe the memory ordering of this operation. success
85    /// describes the required ordering for the read-modify-write operation that
86    /// takes place if the comparison with current succeeds. failure describes
87    /// the required ordering for the load operation that takes place when the
88    /// comparison fails. Using [`Acquire`](`core::sync::atomic::Ordering::Acquire`)
89    /// as success ordering makes the store part of this operation
90    /// [`Relaxed`](`core::sync::atomic::Ordering::Relaxed`), and
91    /// using [`Release`](`core::sync::atomic::Ordering::Release`) makes the
92    /// successful load [`Relaxed`](`core::sync::atomic::Ordering::Relaxed`).
93    /// The failure ordering can only be [`SeqCst`](`core::sync::atomic::Ordering::SeqCst`),
94    /// [`Acquire`](`core::sync::atomic::Ordering::Acquire`) or
95    /// [`Relaxed`](`core::sync::atomic::Ordering::Relaxed`).
96    ///
97    /// Note: This method is only available on platforms that support atomic
98    /// operations on the given type.
99    fn compare_exchange(
100        &self,
101        current: Self::NonAtomicType,
102        new: Self::NonAtomicType,
103        success: Ordering,
104        failure: Ordering,
105    ) -> Result<Self::NonAtomicType, Self::NonAtomicType>;
106
107    /// Stores a value into the atomic integer if the current value is the same
108    /// as the current value.
109    ///
110    /// Unlike [`Atomic::compare_exchange`], this function is allowed to
111    /// spuriously fail even when the comparison succeeds, which can result in
112    /// more efficient code on some platforms. The return value is a result
113    /// indicating whether the new value was written and containing the previous
114    /// value.
115    ///
116    /// [`Atomic::compare_exchange_weak`] takes two
117    /// [`Ordering`](`core::sync::atomic::Ordering`) arguments to describe the
118    /// memory ordering of this operation. success describes the required
119    /// ordering for the read-modify-write operation that takes place if the
120    /// comparison with current succeeds. failure describes the required
121    /// ordering for the load operation that takes place when the comparison
122    /// fails. Using [`Acquire`](`core::sync::atomic::Ordering::Acquire`) as
123    /// success ordering makes the store part of this operation
124    /// [`Relaxed`](`core::sync::atomic::Ordering::Relaxed`), and using
125    /// [`Release`](`core::sync::atomic::Ordering::Release`) makes the
126    /// successful load [`Relaxed`](`core::sync::atomic::Ordering::Relaxed`).
127    /// The failure ordering can only be [`SeqCst`](`core::sync::atomic::Ordering::SeqCst`),
128    /// [`Acquire`](`core::sync::atomic::Ordering::Acquire`) or
129    /// [`Relaxed`](`core::sync::atomic::Ordering::Relaxed`).
130    ///
131    /// Note: This method is only available on platforms that support atomic
132    /// operations on the given type.
133    fn compare_exchange_weak(
134        &self,
135        current: Self::NonAtomicType,
136        new: Self::NonAtomicType,
137        success: Ordering,
138        failure: Ordering,
139    ) -> Result<Self::NonAtomicType, Self::NonAtomicType>;
140
141    /// Stores a value into the atomic integer, returning the previous value.
142    ///
143    /// [`Atomic::swap`] takes an [`Ordering`](`core::sync::atomic::Ordering`) argument
144    /// which describes the memory ordering of this operation. All ordering
145    /// modes are possible.
146    /// Note that using [`Acquire`](`core::sync::atomic::Ordering::Acquire`)
147    /// makes the store part of this operation
148    /// [`Relaxed`](`core::sync::atomic::Ordering::Relaxed`), and using
149    /// [`Release`](`core::sync::atomic::Ordering::Release`) makes the load part
150    /// [`Relaxed`](`core::sync::atomic::Ordering::Relaxed`).
151    ///
152    /// Note: This method is only available on platforms that support atomic
153    /// operations on the given type.
154    fn swap(&self, new: Self::NonAtomicType, order: Ordering) -> Self::NonAtomicType;
155
156    /// Fetches the value, and applies a function to it that returns an optional
157    /// new value. Returns a [`Result`](`core::result::Result`) of
158    /// `Ok(previous_value)` if the function returned `Some(_)`, else
159    /// `Err(previous_value)`.
160    ///
161    /// Note: This may call the function multiple times if the value has been
162    /// changed from other threads in the meantime, as long as the function
163    /// returns `Some(_)`, but the function will have been applied only once to
164    /// the stored value.
165    ///
166    /// [`Atomic::fetch_update`] takes two [`Ordering`](`core::sync::atomic::Ordering`)
167    ///  arguments to describe the memory ordering of this operation. The first
168    /// describes the required ordering for when the operation finally succeeds
169    /// while the second describes the required ordering for loads. These
170    /// correspond to the success and failure orderings of
171    /// [`Atomic::compare_exchange`] respectively.
172    ///
173    /// Using [`Acquire`](`core::sync::atomic::Ordering::Acquire`) as success
174    /// ordering makes the store part of this operation
175    /// [`Relaxed`](`core::sync::atomic::Ordering::Relaxed`), and using
176    /// [`Release`](`core::sync::atomic::Ordering::Release`) makes the final
177    /// successful load
178    /// [`Relaxed`](`core::sync::atomic::Ordering::Relaxed`).
179    /// The failure ordering can only be
180    /// [`SeqCst`](`core::sync::atomic::Ordering::SeqCst`),
181    /// [`Acquire`](`core::sync::atomic::Ordering::Acquire`) or
182    /// [`Relaxed`](`core::sync::atomic::Ordering::Relaxed`).
183    ///
184    /// Note: This method is only available on platforms that support atomic
185    /// operations on usize.
186    ///
187    /// # Considerations
188    /// This method is not magic; it is not provided by the hardware. It is
189    /// implemented in terms of [`Atomic::compare_exchange_weak`], and suffers
190    /// from the same drawbacks. In particular, this method will not circumvent
191    /// the ABA Problem.
192    fn fetch_update<F>(
193        &self,
194        set_order: Ordering,
195        fetch_order: Ordering,
196        f: F,
197    ) -> Result<Self::NonAtomicType, Self::NonAtomicType>
198    where
199        F: FnMut(Self::NonAtomicType) -> Option<Self::NonAtomicType>;
200}