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