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}