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}