Skip to main content

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}