atomic_maybe_uninit/raw.rs
1// SPDX-License-Identifier: Apache-2.0 OR MIT
2
3//! Low level API.
4
5#[cfg(doc)]
6use core::{
7 cell::UnsafeCell,
8 sync::atomic::Ordering::{AcqRel, Acquire, Relaxed, Release, SeqCst},
9};
10use core::{mem::MaybeUninit, sync::atomic::Ordering};
11
12// TODO(semver): merge AtomicLoad and AtomicStore and rename to AtomicLoadStore?
13
14/// Primitive types that may support atomic operations.
15///
16/// This trait is sealed and cannot be implemented for types outside of `atomic-maybe-uninit`.
17///
18/// Currently this is implemented only for integer types.
19pub trait Primitive: crate::private::PrimitivePriv {}
20
21/// Atomic load.
22///
23/// This trait is sealed and cannot be implemented for types outside of `atomic-maybe-uninit`.
24#[cfg_attr(
25 not(atomic_maybe_uninit_no_diagnostic_namespace),
26 diagnostic::on_unimplemented(
27 message = "atomic load of `{Self}` is not available on this target",
28 label = "this associated function is not available on this target",
29 note = "see <https://docs.rs/atomic-maybe-uninit/latest/atomic_maybe_uninit/#platform-support> for more."
30 )
31)]
32pub trait AtomicLoad: Primitive {
33 /// Loads a value from `src`.
34 ///
35 /// `atomic_load` takes an [`Ordering`] argument which describes the memory ordering of this operation.
36 /// Possible values are [`SeqCst`], [`Acquire`] and [`Relaxed`].
37 ///
38 /// # Safety
39 ///
40 /// Behavior is undefined if any of the following conditions are violated:
41 ///
42 /// - `src` must be valid for reads.
43 /// - `src` must be properly aligned **to the size of `Self`**.
44 /// (For example, if `Self` is `u128`, `src` must be aligned to 16-byte even if the alignment of `u128` is 8-byte.)
45 /// - `order` must be [`SeqCst`], [`Acquire`], or [`Relaxed`].
46 ///
47 /// The rules for the validity of the pointer follow [the rules applied to
48 /// functions exposed by the standard library's `ptr` module][validity],
49 /// except that concurrent atomic operations on `src` are allowed if the
50 /// pointer go through [`UnsafeCell::get`].
51 ///
52 /// Compatibility with read-only memory applies only to relaxed operations with a register or smaller width.
53 /// See the ["Atomic accesses to read-only memory" section in the `core::sync::atomic` docs][read-only-memory]
54 /// for more.
55 ///
56 /// [read-only-memory]: core::sync::atomic#atomic-accesses-to-read-only-memory
57 /// [validity]: core::ptr#safety
58 unsafe fn atomic_load(src: *const MaybeUninit<Self>, order: Ordering) -> MaybeUninit<Self>;
59}
60
61/// Atomic store.
62///
63/// This trait is sealed and cannot be implemented for types outside of `atomic-maybe-uninit`.
64#[cfg_attr(
65 not(atomic_maybe_uninit_no_diagnostic_namespace),
66 diagnostic::on_unimplemented(
67 message = "atomic store of `{Self}` is not available on this target",
68 label = "this associated function is not available on this target",
69 note = "see <https://docs.rs/atomic-maybe-uninit/latest/atomic_maybe_uninit/#platform-support> for more."
70 )
71)]
72pub trait AtomicStore: Primitive {
73 /// Stores a value into `dst`.
74 ///
75 /// `atomic_store` takes an [`Ordering`] argument which describes the memory ordering of this operation.
76 /// Possible values are [`SeqCst`], [`Release`] and [`Relaxed`].
77 ///
78 /// # Safety
79 ///
80 /// Behavior is undefined if any of the following conditions are violated:
81 ///
82 /// - `dst` must be valid for writes
83 /// - `dst` must be properly aligned **to the size of `Self`**.
84 /// (For example, if `Self` is `u128`, `dst` must be aligned to 16-byte even if the alignment of `u128` is 8-byte.)
85 /// - `order` must be [`SeqCst`], [`Release`], or [`Relaxed`].
86 ///
87 /// The rules for the validity of the pointer follow [the rules applied to
88 /// functions exposed by the standard library's `ptr` module][validity],
89 /// except that concurrent atomic operations on `dst` are allowed if the
90 /// pointer go through [`UnsafeCell::get`].
91 ///
92 /// Compatibility with write-only memory applies only to relaxed operations with a register or smaller width.
93 /// See the ["Atomic accesses to read-only memory" section in the `core::sync::atomic` docs][read-only-memory]
94 /// for more.
95 ///
96 /// [read-only-memory]: core::sync::atomic#atomic-accesses-to-read-only-memory
97 /// [validity]: core::ptr#safety
98 unsafe fn atomic_store(dst: *mut MaybeUninit<Self>, val: MaybeUninit<Self>, order: Ordering);
99}
100
101/// Atomic swap.
102///
103/// This trait is sealed and cannot be implemented for types outside of `atomic-maybe-uninit`.
104#[cfg_attr(
105 not(atomic_maybe_uninit_no_diagnostic_namespace),
106 diagnostic::on_unimplemented(
107 message = "atomic swap of `{Self}` is not available on this target",
108 label = "this associated function is not available on this target",
109 note = "see <https://docs.rs/atomic-maybe-uninit/latest/atomic_maybe_uninit/#platform-support> for more."
110 )
111)]
112pub trait AtomicSwap: AtomicLoad + AtomicStore {
113 /// Stores a value into `dst`, returning the previous value.
114 ///
115 /// `atomic_swap` takes an [`Ordering`] argument which describes the memory ordering
116 /// of this operation. All ordering modes are possible. Note that using
117 /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
118 /// using [`Release`] makes the load part [`Relaxed`].
119 ///
120 /// # Safety
121 ///
122 /// Behavior is undefined if any of the following conditions are violated:
123 ///
124 /// - `dst` must be valid for both reads and writes.
125 /// - `dst` must be properly aligned **to the size of `Self`**.
126 /// (For example, if `Self` is `u128`, `dst` must be aligned to 16-byte even if the alignment of `u128` is 8-byte.)
127 /// - `order` must be [`SeqCst`], [`AcqRel`], [`Acquire`], [`Release`], or [`Relaxed`].
128 ///
129 /// The rules for the validity of the pointer follow [the rules applied to
130 /// functions exposed by the standard library's `ptr` module][validity],
131 /// except that concurrent atomic operations on `dst` are allowed if the
132 /// pointer go through [`UnsafeCell::get`].
133 ///
134 /// [validity]: core::ptr#safety
135 unsafe fn atomic_swap(
136 dst: *mut MaybeUninit<Self>,
137 val: MaybeUninit<Self>,
138 order: Ordering,
139 ) -> MaybeUninit<Self>;
140}
141
142/// Atomic compare and exchange.
143///
144/// This trait is sealed and cannot be implemented for types outside of `atomic-maybe-uninit`.
145#[cfg_attr(
146 not(atomic_maybe_uninit_no_diagnostic_namespace),
147 diagnostic::on_unimplemented(
148 message = "atomic compare and exchange of `{Self}` is not available on this target",
149 label = "this associated function is not available on this target",
150 note = "see <https://docs.rs/atomic-maybe-uninit/latest/atomic_maybe_uninit/#platform-support> for more."
151 )
152)]
153pub trait AtomicCompareExchange: AtomicLoad + AtomicStore {
154 /// Stores a value into `dst` if the current value is the same as
155 /// the `current` value. Here, "the same" is determined using byte-wise
156 /// equality, not `PartialEq`.
157 ///
158 /// The return value is a tuple of the previous value and the result indicating whether the new
159 /// value was written and containing the previous value. On success, the returned value is
160 /// guaranteed to be equal to the value at `current`.
161 ///
162 /// `atomic_compare_exchange` takes two [`Ordering`] arguments to describe the memory
163 /// ordering of this operation. `success` describes the required ordering for the
164 /// read-modify-write operation that takes place if the comparison with `current` succeeds.
165 /// `failure` describes the required ordering for the load operation that takes place when
166 /// the comparison fails. Using [`Acquire`] as success ordering makes the store part
167 /// of this operation [`Relaxed`], and using [`Release`] makes the successful load
168 /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
169 ///
170 /// # Safety
171 ///
172 /// Behavior is undefined if any of the following conditions are violated:
173 ///
174 /// - `dst` must be valid for both reads and writes.
175 /// - `dst` must be properly aligned **to the size of `Self`**.
176 /// (For example, if `Self` is `u128`, `dst` must be aligned to 16-byte even if the alignment of `u128` is 8-byte.)
177 /// - `success` must be [`SeqCst`], [`AcqRel`], [`Acquire`], [`Release`], or [`Relaxed`].
178 /// - `failure` must be [`SeqCst`], [`Acquire`], or [`Relaxed`].
179 ///
180 /// The rules for the validity of the pointer follow [the rules applied to
181 /// functions exposed by the standard library's `ptr` module][validity],
182 /// except that concurrent atomic operations on `dst` are allowed if the
183 /// pointer go through [`UnsafeCell::get`].
184 ///
185 /// [validity]: core::ptr#safety
186 ///
187 /// # Notes
188 ///
189 /// Comparison of two values containing uninitialized bytes may fail even if
190 /// they are equivalent as Rust's type, because values can be byte-wise
191 /// inequal even when they are equal as Rust values.
192 ///
193 /// See [`AtomicMaybeUninit::compare_exchange`](crate::AtomicMaybeUninit::compare_exchange) for details.
194 unsafe fn atomic_compare_exchange(
195 dst: *mut MaybeUninit<Self>,
196 current: MaybeUninit<Self>,
197 new: MaybeUninit<Self>,
198 success: Ordering,
199 failure: Ordering,
200 ) -> (MaybeUninit<Self>, bool);
201
202 /// Stores a value into `dst` if the current value is the same as
203 /// the `current` value. Here, "the same" is determined using byte-wise
204 /// equality, not `PartialEq`.
205 ///
206 /// This function is allowed to spuriously fail even when the comparison succeeds, which can
207 /// result in more efficient code on some platforms. The return value is a tuple of the previous
208 /// value and the result indicating whether the new value was written and containing the
209 /// previous value.
210 ///
211 /// `atomic_compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory
212 /// ordering of this operation. `success` describes the required ordering for the
213 /// read-modify-write operation that takes place if the comparison with `current` succeeds.
214 /// `failure` describes the required ordering for the load operation that takes place when
215 /// the comparison fails. Using [`Acquire`] as success ordering makes the store part
216 /// of this operation [`Relaxed`], and using [`Release`] makes the successful load
217 /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
218 ///
219 /// # Safety
220 ///
221 /// Behavior is undefined if any of the following conditions are violated:
222 ///
223 /// - `dst` must be valid for both reads and writes.
224 /// - `dst` must be properly aligned **to the size of `Self`**.
225 /// (For example, if `Self` is `u128`, `dst` must be aligned to 16-byte even if the alignment of `u128` is 8-byte.)
226 /// - `success` must be [`SeqCst`], [`AcqRel`], [`Acquire`], [`Release`], or [`Relaxed`].
227 /// - `failure` must be [`SeqCst`], [`Acquire`], or [`Relaxed`].
228 ///
229 /// The rules for the validity of the pointer follow [the rules applied to
230 /// functions exposed by the standard library's `ptr` module][validity],
231 /// except that concurrent atomic operations on `dst` are allowed if the
232 /// pointer go through [`UnsafeCell::get`].
233 ///
234 /// [validity]: core::ptr#safety
235 ///
236 /// # Notes
237 ///
238 /// Comparison of two values containing uninitialized bytes may fail even if
239 /// they are equivalent as Rust's type, because values can be byte-wise
240 /// inequal even when they are equal as Rust values.
241 ///
242 /// See [`AtomicMaybeUninit::compare_exchange`](crate::AtomicMaybeUninit::compare_exchange) for details.
243 #[inline]
244 unsafe fn atomic_compare_exchange_weak(
245 dst: *mut MaybeUninit<Self>,
246 current: MaybeUninit<Self>,
247 new: MaybeUninit<Self>,
248 success: Ordering,
249 failure: Ordering,
250 ) -> (MaybeUninit<Self>, bool) {
251 // SAFETY: the caller must uphold the safety contract.
252 unsafe { Self::atomic_compare_exchange(dst, current, new, success, failure) }
253 }
254}