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