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