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}