core/sync/atomic.rs
1//! Atomic types
2//!
3//! Atomic types provide primitive shared-memory communication between
4//! threads, and are the building blocks of other concurrent
5//! types.
6//!
7//! This module defines atomic versions of a select number of primitive
8//! types, including [`AtomicBool`], [`AtomicIsize`], [`AtomicUsize`],
9//! [`AtomicI8`], [`AtomicU16`], etc.
10//! Atomic types present operations that, when used correctly, synchronize
11//! updates between threads.
12//!
13//! Atomic variables are safe to share between threads (they implement [`Sync`])
14//! but they do not themselves provide the mechanism for sharing and follow the
15//! [threading model](../../../std/thread/index.html#the-threading-model) of Rust.
16//! The most common way to share an atomic variable is to put it into an [`Arc`][arc] (an
17//! atomically-reference-counted shared pointer).
18//!
19//! [arc]: ../../../std/sync/struct.Arc.html
20//!
21//! Atomic types may be stored in static variables, initialized using
22//! the constant initializers like [`AtomicBool::new`]. Atomic statics
23//! are often used for lazy global initialization.
24//!
25//! ## Memory model for atomic accesses
26//!
27//! Rust atomics currently follow the same rules as [C++20 atomics][cpp], specifically the rules
28//! from the [`intro.races`][cpp-intro.races] section, without the "consume" memory ordering. Since
29//! C++ uses an object-based memory model whereas Rust is access-based, a bit of translation work
30//! has to be done to apply the C++ rules to Rust: whenever C++ talks about "the value of an
31//! object", we understand that to mean the resulting bytes obtained when doing a read. When the C++
32//! standard talks about "the value of an atomic object", this refers to the result of doing an
33//! atomic load (via the operations provided in this module). A "modification of an atomic object"
34//! refers to an atomic store.
35//!
36//! The end result is *almost* equivalent to saying that creating a *shared reference* to one of the
37//! Rust atomic types corresponds to creating an `atomic_ref` in C++, with the `atomic_ref` being
38//! destroyed when the lifetime of the shared reference ends. The main difference is that Rust
39//! permits concurrent atomic and non-atomic reads to the same memory as those cause no issue in the
40//! C++ memory model, they are just forbidden in C++ because memory is partitioned into "atomic
41//! objects" and "non-atomic objects" (with `atomic_ref` temporarily converting a non-atomic object
42//! into an atomic object).
43//!
44//! The most important aspect of this model is that *data races* are undefined behavior. A data race
45//! is defined as conflicting non-synchronized accesses where at least one of the accesses is
46//! non-atomic. Here, accesses are *conflicting* if they affect overlapping regions of memory and at
47//! least one of them is a write. (A `compare_exchange` or `compare_exchange_weak` that does not
48//! succeed is not considered a write.) They are *non-synchronized* if neither of them
49//! *happens-before* the other, according to the happens-before order of the memory model.
50//!
51//! The other possible cause of undefined behavior in the memory model are mixed-size accesses: Rust
52//! inherits the C++ limitation that non-synchronized conflicting atomic accesses may not partially
53//! overlap. In other words, every pair of non-synchronized atomic accesses must be either disjoint,
54//! access the exact same memory (including using the same access size), or both be reads.
55//!
56//! Each atomic access takes an [`Ordering`] which defines how the operation interacts with the
57//! happens-before order. These orderings behave the same as the corresponding [C++20 atomic
58//! orderings][cpp_memory_order]. For more information, see the [nomicon].
59//!
60//! [cpp]: https://en.cppreference.com/w/cpp/atomic
61//! [cpp-intro.races]: https://timsong-cpp.github.io/cppwp/n4868/intro.multithread#intro.races
62//! [cpp_memory_order]: https://en.cppreference.com/w/cpp/atomic/memory_order
63//! [nomicon]: ../../../nomicon/atomics.html
64//!
65//! ```rust,no_run undefined_behavior
66//! use std::sync::atomic::{AtomicU16, AtomicU8, Ordering};
67//! use std::mem::transmute;
68//! use std::thread;
69//!
70//! let atomic = AtomicU16::new(0);
71//!
72//! thread::scope(|s| {
73//! // This is UB: conflicting non-synchronized accesses, at least one of which is non-atomic.
74//! s.spawn(|| atomic.store(1, Ordering::Relaxed)); // atomic store
75//! s.spawn(|| unsafe { atomic.as_ptr().write(2) }); // non-atomic write
76//! });
77//!
78//! thread::scope(|s| {
79//! // This is fine: the accesses do not conflict (as none of them performs any modification).
80//! // In C++ this would be disallowed since creating an `atomic_ref` precludes
81//! // further non-atomic accesses, but Rust does not have that limitation.
82//! s.spawn(|| atomic.load(Ordering::Relaxed)); // atomic load
83//! s.spawn(|| unsafe { atomic.as_ptr().read() }); // non-atomic read
84//! });
85//!
86//! thread::scope(|s| {
87//! // This is fine: `join` synchronizes the code in a way such that the atomic
88//! // store happens-before the non-atomic write.
89//! let handle = s.spawn(|| atomic.store(1, Ordering::Relaxed)); // atomic store
90//! handle.join().expect("thread won't panic"); // synchronize
91//! s.spawn(|| unsafe { atomic.as_ptr().write(2) }); // non-atomic write
92//! });
93//!
94//! thread::scope(|s| {
95//! // This is UB: non-synchronized conflicting differently-sized atomic accesses.
96//! s.spawn(|| atomic.store(1, Ordering::Relaxed));
97//! s.spawn(|| unsafe {
98//! let differently_sized = transmute::<&AtomicU16, &AtomicU8>(&atomic);
99//! differently_sized.store(2, Ordering::Relaxed);
100//! });
101//! });
102//!
103//! thread::scope(|s| {
104//! // This is fine: `join` synchronizes the code in a way such that
105//! // the 1-byte store happens-before the 2-byte store.
106//! let handle = s.spawn(|| atomic.store(1, Ordering::Relaxed));
107//! handle.join().expect("thread won't panic");
108//! s.spawn(|| unsafe {
109//! let differently_sized = transmute::<&AtomicU16, &AtomicU8>(&atomic);
110//! differently_sized.store(2, Ordering::Relaxed);
111//! });
112//! });
113//! ```
114//!
115//! # Portability
116//!
117//! All atomic types in this module are guaranteed to be [lock-free] if they're
118//! available. This means they don't internally acquire a global mutex. Atomic
119//! types and operations are not guaranteed to be wait-free. This means that
120//! operations like `fetch_or` may be implemented with a compare-and-swap loop.
121//!
122//! Atomic operations may be implemented at the instruction layer with
123//! larger-size atomics. For example some platforms use 4-byte atomic
124//! instructions to implement `AtomicI8`. Note that this emulation should not
125//! have an impact on correctness of code, it's just something to be aware of.
126//!
127//! The atomic types in this module might not be available on all platforms. The
128//! atomic types here are all widely available, however, and can generally be
129//! relied upon existing. Some notable exceptions are:
130//!
131//! * PowerPC and MIPS platforms with 32-bit pointers do not have `AtomicU64` or
132//! `AtomicI64` types.
133//! * Legacy ARM platforms like ARMv4T and ARMv5TE have very limited hardware
134//! support for atomics. The bare-metal targets disable this module
135//! entirely, but the Linux targets [use the kernel] to assist (which comes
136//! with a performance penalty). It's not until ARMv6K onwards that ARM CPUs
137//! have support for load/store and Compare and Swap (CAS) atomics in hardware.
138//! * ARMv6-M and ARMv8-M baseline targets (`thumbv6m-*` and
139//! `thumbv8m.base-*`) only provide `load` and `store` operations, and do
140//! not support Compare and Swap (CAS) operations, such as `swap`,
141//! `fetch_add`, etc. Full CAS support is available on ARMv7-M and ARMv8-M
142//! Mainline (`thumbv7m-*`, `thumbv7em*` and `thumbv8m.main-*`).
143//!
144//! [use the kernel]: https://www.kernel.org/doc/Documentation/arm/kernel_user_helpers.txt
145//!
146//! Note that future platforms may be added that also do not have support for
147//! some atomic operations. Maximally portable code will want to be careful
148//! about which atomic types are used. `AtomicUsize` and `AtomicIsize` are
149//! generally the most portable, but even then they're not available everywhere.
150//! For reference, the `std` library requires `AtomicBool`s and pointer-sized atomics, although
151//! `core` does not.
152//!
153//! The `#[cfg(target_has_atomic)]` attribute can be used to conditionally
154//! compile based on the target's supported bit widths. It is a key-value
155//! option set for each supported size, with values "8", "16", "32", "64",
156//! "128", and "ptr" for pointer-sized atomics.
157//!
158//! [lock-free]: https://en.wikipedia.org/wiki/Non-blocking_algorithm
159//!
160//! # Atomic accesses to read-only memory
161//!
162//! In general, *all* atomic accesses on read-only memory are undefined behavior. For instance, attempting
163//! to do a `compare_exchange` that will definitely fail (making it conceptually a read-only
164//! operation) can still cause a segmentation fault if the underlying memory page is mapped read-only. Since
165//! atomic `load`s might be implemented using compare-exchange operations, even a `load` can fault
166//! on read-only memory.
167//!
168//! For the purpose of this section, "read-only memory" is defined as memory that is read-only in
169//! the underlying target, i.e., the pages are mapped with a read-only flag and any attempt to write
170//! will cause a page fault. In particular, an `&u128` reference that points to memory that is
171//! read-write mapped is *not* considered to point to "read-only memory". In Rust, almost all memory
172//! is read-write; the only exceptions are memory created by `const` items or `static` items without
173//! interior mutability, and memory that was specifically marked as read-only by the operating
174//! system via platform-specific APIs.
175//!
176//! As an exception from the general rule stated above, "sufficiently small" atomic loads with
177//! `Ordering::Relaxed` are implemented in a way that works on read-only memory, and are hence not
178//! undefined behavior. The exact size limit for what makes a load "sufficiently small" varies
179//! depending on the target:
180//!
181//! | `target_arch` | Size limit |
182//! |---------------|---------|
183//! | `x86`, `arm`, `loongarch32`, `mips`, `mips32r6`, `powerpc`, `riscv32`, `sparc`, `hexagon` | 4 bytes |
184//! | `x86_64`, `aarch64`, `loongarch64`, `mips64`, `mips64r6`, `powerpc64`, `riscv64`, `sparc64`, `s390x` | 8 bytes |
185//!
186//! Atomics loads that are larger than this limit as well as atomic loads with ordering other
187//! than `Relaxed`, as well as *all* atomic loads on targets not listed in the table, might still be
188//! read-only under certain conditions, but that is not a stable guarantee and should not be relied
189//! upon.
190//!
191//! If you need to do an acquire load on read-only memory, you can do a relaxed load followed by an
192//! acquire fence instead.
193//!
194//! # Examples
195//!
196//! A simple spinlock:
197//!
198//! ```ignore-wasm
199//! use std::sync::Arc;
200//! use std::sync::atomic::{AtomicUsize, Ordering};
201//! use std::{hint, thread};
202//!
203//! fn main() {
204//! let spinlock = Arc::new(AtomicUsize::new(1));
205//!
206//! let spinlock_clone = Arc::clone(&spinlock);
207//!
208//! let thread = thread::spawn(move || {
209//! spinlock_clone.store(0, Ordering::Release);
210//! });
211//!
212//! // Wait for the other thread to release the lock
213//! while spinlock.load(Ordering::Acquire) != 0 {
214//! hint::spin_loop();
215//! }
216//!
217//! if let Err(panic) = thread.join() {
218//! println!("Thread had an error: {panic:?}");
219//! }
220//! }
221//! ```
222//!
223//! Keep a global count of live threads:
224//!
225//! ```
226//! use std::sync::atomic::{AtomicUsize, Ordering};
227//!
228//! static GLOBAL_THREAD_COUNT: AtomicUsize = AtomicUsize::new(0);
229//!
230//! // Note that Relaxed ordering doesn't synchronize anything
231//! // except the global thread counter itself.
232//! let old_thread_count = GLOBAL_THREAD_COUNT.fetch_add(1, Ordering::Relaxed);
233//! // Note that this number may not be true at the moment of printing
234//! // because some other thread may have changed static value already.
235//! println!("live threads: {}", old_thread_count + 1);
236//! ```
237
238#![stable(feature = "rust1", since = "1.0.0")]
239#![cfg_attr(not(target_has_atomic_load_store = "8"), allow(dead_code))]
240#![cfg_attr(not(target_has_atomic_load_store = "8"), allow(unused_imports))]
241// Clippy complains about the pattern of "safe function calling unsafe function taking pointers".
242// This happens with AtomicPtr intrinsics but is fine, as the pointers clippy is concerned about
243// are just normal values that get loaded/stored, but not dereferenced.
244#![allow(clippy::not_unsafe_ptr_arg_deref)]
245
246use self::Ordering::*;
247use crate::cell::UnsafeCell;
248use crate::hint::spin_loop;
249use crate::intrinsics::AtomicOrdering as AO;
250use crate::mem::transmute;
251use crate::{fmt, intrinsics};
252
253#[unstable(
254 feature = "atomic_internals",
255 reason = "implementation detail which may disappear or be replaced at any time",
256 issue = "none"
257)]
258#[expect(missing_debug_implementations)]
259mod private {
260 #[cfg(target_has_atomic_load_store = "8")]
261 #[repr(C, align(1))]
262 #[ferrocene::prevalidated]
263 pub struct Align1<T>(T);
264 #[cfg(target_has_atomic_load_store = "16")]
265 #[repr(C, align(2))]
266 #[ferrocene::prevalidated]
267 pub struct Align2<T>(T);
268 #[cfg(target_has_atomic_load_store = "32")]
269 #[repr(C, align(4))]
270 #[ferrocene::prevalidated]
271 pub struct Align4<T>(T);
272 #[cfg(target_has_atomic_load_store = "64")]
273 #[repr(C, align(8))]
274 #[ferrocene::prevalidated]
275 pub struct Align8<T>(T);
276 #[cfg(any(target_has_atomic_load_store = "128", doc))]
277 #[repr(C, align(16))]
278 #[ferrocene::prevalidated]
279 pub struct Align16<T>(T);
280}
281
282/// A marker trait for primitive types which can be modified atomically.
283///
284/// This is an implementation detail for <code>[Atomic]\<T></code> which may disappear or be replaced at any time.
285//
286// # Safety
287//
288// Types implementing this trait must be primitives that can be modified atomically.
289//
290// The associated `Self::Storage` type must have the same size, but may have fewer validity
291// invariants or a higher alignment requirement than `Self`.
292#[unstable(
293 feature = "atomic_internals",
294 reason = "implementation detail which may disappear or be replaced at any time",
295 issue = "none"
296)]
297pub impl(self) unsafe trait AtomicPrimitive: Sized + Copy {
298 /// Temporary implementation detail.
299 type Storage: Sized;
300}
301
302macro impl_atomic_primitive {
303 (
304 @impl [$($T:ident)?] $Primitive:ty as $Storage:ident<$Operand:ty>,
305 $cfg:meta
306 ) => {
307 #[unstable(
308 feature = "atomic_internals",
309 reason = "implementation detail which may disappear or be replaced at any time",
310 issue = "none"
311 )]
312 #[cfg($cfg)]
313 unsafe impl $(<$T>)? AtomicPrimitive for $Primitive {
314 type Storage = private::$Storage<$Operand>;
315 }
316 },
317
318 (
319 [$($T:ident)?] $Primitive:ty as $Storage:ident<$Operand:ty>,
320 size($size:literal)
321 ) => {
322 impl_atomic_primitive!(
323 @impl [$($T)?] $Primitive as $Storage<$Operand>,
324 target_has_atomic_load_store = $size
325 );
326 },
327
328 (
329 [$($T:ident)?] $Primitive:ty as $Storage:ident<$Operand:ty>,
330 size($size:literal),
331 doc
332 ) => {
333 impl_atomic_primitive!(
334 @impl [$($T)?] $Primitive as $Storage<$Operand>,
335 any(target_has_atomic_load_store = $size, doc)
336 );
337 },
338}
339
340impl_atomic_primitive!([] bool as Align1<u8>, size("8"));
341impl_atomic_primitive!([] i8 as Align1<i8>, size("8"));
342impl_atomic_primitive!([] u8 as Align1<u8>, size("8"));
343impl_atomic_primitive!([] i16 as Align2<i16>, size("16"));
344impl_atomic_primitive!([] u16 as Align2<u16>, size("16"));
345impl_atomic_primitive!([] i32 as Align4<i32>, size("32"));
346impl_atomic_primitive!([] u32 as Align4<u32>, size("32"));
347impl_atomic_primitive!([] i64 as Align8<i64>, size("64"));
348impl_atomic_primitive!([] u64 as Align8<u64>, size("64"));
349impl_atomic_primitive!([] i128 as Align16<i128>, size("128"), doc);
350impl_atomic_primitive!([] u128 as Align16<u128>, size("128"), doc);
351
352#[cfg(target_pointer_width = "16")]
353impl_atomic_primitive!([] isize as Align2<isize>, size("ptr"));
354#[cfg(target_pointer_width = "32")]
355impl_atomic_primitive!([] isize as Align4<isize>, size("ptr"));
356#[cfg(target_pointer_width = "64")]
357impl_atomic_primitive!([] isize as Align8<isize>, size("ptr"));
358
359#[cfg(target_pointer_width = "16")]
360impl_atomic_primitive!([] usize as Align2<usize>, size("ptr"));
361#[cfg(target_pointer_width = "32")]
362impl_atomic_primitive!([] usize as Align4<usize>, size("ptr"));
363#[cfg(target_pointer_width = "64")]
364impl_atomic_primitive!([] usize as Align8<usize>, size("ptr"));
365
366#[cfg(target_pointer_width = "16")]
367impl_atomic_primitive!([T] *mut T as Align2<*mut T>, size("ptr"));
368#[cfg(target_pointer_width = "32")]
369impl_atomic_primitive!([T] *mut T as Align4<*mut T>, size("ptr"));
370#[cfg(target_pointer_width = "64")]
371impl_atomic_primitive!([T] *mut T as Align8<*mut T>, size("ptr"));
372
373/// A memory location which can be safely modified from multiple threads.
374///
375/// This has the same size and bit validity as the underlying type `T`. However,
376/// the alignment of this type is always equal to its size, even on targets where
377/// `T` has alignment less than its size.
378///
379/// For more about the differences between atomic types and non-atomic types as
380/// well as information about the portability of this type, please see the
381/// [module-level documentation].
382///
383/// **Note:** This type is only available on platforms that support atomic loads
384/// and stores of `T`.
385///
386/// [module-level documentation]: crate::sync::atomic
387#[unstable(feature = "generic_atomic", issue = "130539")]
388#[repr(C)]
389#[rustc_diagnostic_item = "Atomic"]
390#[ferrocene::prevalidated]
391pub struct Atomic<T: AtomicPrimitive> {
392 v: UnsafeCell<T::Storage>,
393}
394
395#[stable(feature = "rust1", since = "1.0.0")]
396unsafe impl<T: AtomicPrimitive> Send for Atomic<T> {}
397#[stable(feature = "rust1", since = "1.0.0")]
398unsafe impl<T: AtomicPrimitive> Sync for Atomic<T> {}
399
400// Some architectures don't have byte-sized atomics, which results in LLVM
401// emulating them using a LL/SC loop. However for AtomicBool we can take
402// advantage of the fact that it only ever contains 0 or 1 and use atomic OR/AND
403// instead, which LLVM can emulate using a larger atomic OR/AND operation.
404//
405// This list should only contain architectures which have word-sized atomic-or/
406// atomic-and instructions but don't natively support byte-sized atomics.
407#[cfg(target_has_atomic = "8")]
408const EMULATE_ATOMIC_BOOL: bool = cfg!(any(
409 target_arch = "riscv32",
410 target_arch = "riscv64",
411 target_arch = "loongarch32",
412 target_arch = "loongarch64"
413));
414
415/// A boolean type which can be safely shared between threads.
416///
417/// This type has the same size, alignment, and bit validity as a [`bool`].
418///
419/// **Note**: This type is only available on platforms that support atomic
420/// loads and stores of `u8`.
421#[cfg(target_has_atomic_load_store = "8")]
422#[stable(feature = "rust1", since = "1.0.0")]
423pub type AtomicBool = Atomic<bool>;
424
425#[cfg(target_has_atomic_load_store = "8")]
426#[stable(feature = "rust1", since = "1.0.0")]
427impl Default for AtomicBool {
428 /// Creates an `AtomicBool` initialized to `false`.
429 #[inline]
430 fn default() -> Self {
431 Self::new(false)
432 }
433}
434
435/// A raw pointer type which can be safely shared between threads.
436///
437/// This type has the same size and bit validity as a `*mut T`.
438///
439/// **Note**: This type is only available on platforms that support atomic
440/// loads and stores of pointers. Its size depends on the target pointer's size.
441#[cfg(target_has_atomic_load_store = "ptr")]
442#[stable(feature = "rust1", since = "1.0.0")]
443pub type AtomicPtr<T> = Atomic<*mut T>;
444
445#[cfg(target_has_atomic_load_store = "ptr")]
446#[stable(feature = "rust1", since = "1.0.0")]
447impl<T> Default for AtomicPtr<T> {
448 /// Creates a null `AtomicPtr<T>`.
449 fn default() -> AtomicPtr<T> {
450 AtomicPtr::new(crate::ptr::null_mut())
451 }
452}
453
454/// Atomic memory orderings
455///
456/// Memory orderings specify the way atomic operations synchronize memory.
457/// In its weakest [`Ordering::Relaxed`], only the memory directly touched by the
458/// operation is synchronized. On the other hand, a store-load pair of [`Ordering::SeqCst`]
459/// operations synchronize other memory while additionally preserving a total order of such
460/// operations across all threads.
461///
462/// Rust's memory orderings are [the same as those of
463/// C++20](https://en.cppreference.com/w/cpp/atomic/memory_order).
464///
465/// For more information see the [nomicon].
466///
467/// [nomicon]: ../../../nomicon/atomics.html
468#[stable(feature = "rust1", since = "1.0.0")]
469#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
470#[non_exhaustive]
471#[rustc_diagnostic_item = "Ordering"]
472#[ferrocene::prevalidated]
473pub enum Ordering {
474 /// No ordering constraints, only atomic operations.
475 ///
476 /// Corresponds to [`memory_order_relaxed`] in C++20.
477 ///
478 /// [`memory_order_relaxed`]: https://en.cppreference.com/w/cpp/atomic/memory_order#Relaxed_ordering
479 #[stable(feature = "rust1", since = "1.0.0")]
480 Relaxed,
481 /// When coupled with a store, all previous operations become ordered
482 /// before any load of this value with [`Acquire`] (or stronger) ordering.
483 /// In particular, all previous writes become visible to all threads
484 /// that perform an [`Acquire`] (or stronger) load of this value.
485 ///
486 /// Notice that using this ordering for an operation that combines loads
487 /// and stores leads to a [`Relaxed`] load operation!
488 ///
489 /// This ordering is only applicable for operations that can perform a store.
490 ///
491 /// Corresponds to [`memory_order_release`] in C++20.
492 ///
493 /// [`memory_order_release`]: https://en.cppreference.com/w/cpp/atomic/memory_order#Release-Acquire_ordering
494 #[stable(feature = "rust1", since = "1.0.0")]
495 Release,
496 /// When coupled with a load, if the loaded value was written by a store operation with
497 /// [`Release`] (or stronger) ordering, then all subsequent operations
498 /// become ordered after that store. In particular, all subsequent loads will see data
499 /// written before the store.
500 ///
501 /// Notice that using this ordering for an operation that combines loads
502 /// and stores leads to a [`Relaxed`] store operation!
503 ///
504 /// This ordering is only applicable for operations that can perform a load.
505 ///
506 /// Corresponds to [`memory_order_acquire`] in C++20.
507 ///
508 /// [`memory_order_acquire`]: https://en.cppreference.com/w/cpp/atomic/memory_order#Release-Acquire_ordering
509 #[stable(feature = "rust1", since = "1.0.0")]
510 Acquire,
511 /// Has the effects of both [`Acquire`] and [`Release`] together:
512 /// For loads it uses [`Acquire`] ordering. For stores it uses the [`Release`] ordering.
513 ///
514 /// Notice that in the case of `compare_and_swap`, it is possible that the operation ends up
515 /// not performing any store and hence it has just [`Acquire`] ordering. However,
516 /// `AcqRel` will never perform [`Relaxed`] accesses.
517 ///
518 /// This ordering is only applicable for operations that combine both loads and stores.
519 ///
520 /// Corresponds to [`memory_order_acq_rel`] in C++20.
521 ///
522 /// [`memory_order_acq_rel`]: https://en.cppreference.com/w/cpp/atomic/memory_order#Release-Acquire_ordering
523 #[stable(feature = "rust1", since = "1.0.0")]
524 AcqRel,
525 /// Like [`Acquire`]/[`Release`]/[`AcqRel`] (for load, store, and load-with-store
526 /// operations, respectively) with the additional guarantee that all threads see all
527 /// sequentially consistent operations in the same order.
528 ///
529 /// Corresponds to [`memory_order_seq_cst`] in C++20.
530 ///
531 /// [`memory_order_seq_cst`]: https://en.cppreference.com/w/cpp/atomic/memory_order#Sequentially-consistent_ordering
532 #[stable(feature = "rust1", since = "1.0.0")]
533 SeqCst,
534}
535
536/// An [`AtomicBool`] initialized to `false`.
537#[cfg(target_has_atomic_load_store = "8")]
538#[stable(feature = "rust1", since = "1.0.0")]
539#[deprecated(
540 since = "1.34.0",
541 note = "the `new` function is now preferred",
542 suggestion = "AtomicBool::new(false)"
543)]
544pub const ATOMIC_BOOL_INIT: AtomicBool = AtomicBool::new(false);
545
546#[cfg(target_has_atomic_load_store = "8")]
547impl AtomicBool {
548 /// Creates a new `AtomicBool`.
549 ///
550 /// # Examples
551 ///
552 /// ```
553 /// use std::sync::atomic::AtomicBool;
554 ///
555 /// let atomic_true = AtomicBool::new(true);
556 /// let atomic_false = AtomicBool::new(false);
557 /// ```
558 #[inline]
559 #[stable(feature = "rust1", since = "1.0.0")]
560 #[rustc_const_stable(feature = "const_atomic_new", since = "1.24.0")]
561 #[must_use]
562 #[ferrocene::prevalidated]
563 pub const fn new(v: bool) -> AtomicBool {
564 // SAFETY:
565 // `Atomic<T>` is essentially a transparent wrapper around `T`.
566 unsafe { transmute(v) }
567 }
568
569 /// Creates a new `AtomicBool` from a pointer.
570 ///
571 /// # Examples
572 ///
573 /// ```
574 /// use std::sync::atomic::{self, AtomicBool};
575 ///
576 /// // Get a pointer to an allocated value
577 /// let ptr: *mut bool = Box::into_raw(Box::new(false));
578 ///
579 /// assert!(ptr.cast::<AtomicBool>().is_aligned());
580 ///
581 /// {
582 /// // Create an atomic view of the allocated value
583 /// let atomic = unsafe { AtomicBool::from_ptr(ptr) };
584 ///
585 /// // Use `atomic` for atomic operations, possibly share it with other threads
586 /// atomic.store(true, atomic::Ordering::Relaxed);
587 /// }
588 ///
589 /// // It's ok to non-atomically access the value behind `ptr`,
590 /// // since the reference to the atomic ended its lifetime in the block above
591 /// assert_eq!(unsafe { *ptr }, true);
592 ///
593 /// // Deallocate the value
594 /// unsafe { drop(Box::from_raw(ptr)) }
595 /// ```
596 ///
597 /// # Safety
598 ///
599 /// * `ptr` must be aligned to `align_of::<AtomicBool>()` (note that this is always true, since
600 /// `align_of::<AtomicBool>() == 1`).
601 /// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`.
602 /// * You must adhere to the [Memory model for atomic accesses]. In particular, it is not
603 /// allowed to mix conflicting atomic and non-atomic accesses, or atomic accesses of different
604 /// sizes, without synchronization.
605 ///
606 /// [valid]: crate::ptr#safety
607 /// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses
608 #[inline]
609 #[stable(feature = "atomic_from_ptr", since = "1.75.0")]
610 #[rustc_const_stable(feature = "const_atomic_from_ptr", since = "1.84.0")]
611 pub const unsafe fn from_ptr<'a>(ptr: *mut bool) -> &'a AtomicBool {
612 // SAFETY: guaranteed by the caller
613 unsafe { &*ptr.cast() }
614 }
615
616 /// Returns a mutable reference to the underlying [`bool`].
617 ///
618 /// This is safe because the mutable reference guarantees that no other threads are
619 /// concurrently accessing the atomic data.
620 ///
621 /// # Examples
622 ///
623 /// ```
624 /// use std::sync::atomic::{AtomicBool, Ordering};
625 ///
626 /// let mut some_bool = AtomicBool::new(true);
627 /// assert_eq!(*some_bool.get_mut(), true);
628 /// *some_bool.get_mut() = false;
629 /// assert_eq!(some_bool.load(Ordering::SeqCst), false);
630 /// ```
631 #[inline]
632 #[stable(feature = "atomic_access", since = "1.15.0")]
633 pub fn get_mut(&mut self) -> &mut bool {
634 // SAFETY: the mutable reference guarantees unique ownership.
635 unsafe { &mut *self.as_ptr() }
636 }
637
638 /// Gets atomic access to a `&mut bool`.
639 ///
640 /// # Examples
641 ///
642 /// ```
643 /// use std::sync::atomic::{AtomicBool, Ordering};
644 ///
645 /// let mut some_bool = true;
646 /// let a = AtomicBool::from_mut(&mut some_bool);
647 /// a.store(false, Ordering::Relaxed);
648 /// assert_eq!(some_bool, false);
649 /// ```
650 #[inline]
651 #[cfg(target_has_atomic_primitive_alignment = "8")]
652 #[stable(feature = "atomic_from_mut", since = "1.98.0")]
653 pub fn from_mut(v: &mut bool) -> &mut Self {
654 // SAFETY: the mutable reference guarantees unique ownership, and
655 // alignment of both `bool` and `Self` is 1.
656 unsafe { &mut *(v as *mut bool as *mut Self) }
657 }
658
659 /// Gets non-atomic access to a `&mut [AtomicBool]` slice.
660 ///
661 /// This is safe because the mutable reference guarantees that no other threads are
662 /// concurrently accessing the atomic data.
663 ///
664 /// # Examples
665 ///
666 /// ```ignore-wasm
667 /// use std::sync::atomic::{AtomicBool, Ordering};
668 ///
669 /// let mut some_bools = [const { AtomicBool::new(false) }; 10];
670 ///
671 /// let view: &mut [bool] = AtomicBool::get_mut_slice(&mut some_bools);
672 /// assert_eq!(view, [false; 10]);
673 /// view[..5].copy_from_slice(&[true; 5]);
674 ///
675 /// std::thread::scope(|s| {
676 /// for t in &some_bools[..5] {
677 /// s.spawn(move || assert_eq!(t.load(Ordering::Relaxed), true));
678 /// }
679 ///
680 /// for f in &some_bools[5..] {
681 /// s.spawn(move || assert_eq!(f.load(Ordering::Relaxed), false));
682 /// }
683 /// });
684 /// ```
685 #[inline]
686 #[stable(feature = "atomic_from_mut", since = "1.98.0")]
687 pub fn get_mut_slice(this: &mut [Self]) -> &mut [bool] {
688 // SAFETY: the mutable reference guarantees unique ownership.
689 unsafe { &mut *(this as *mut [Self] as *mut [bool]) }
690 }
691
692 /// Gets atomic access to a `&mut [bool]` slice.
693 ///
694 /// # Examples
695 ///
696 /// ```rust,ignore-wasm
697 /// use std::sync::atomic::{AtomicBool, Ordering};
698 ///
699 /// let mut some_bools = [false; 10];
700 /// let a = &*AtomicBool::from_mut_slice(&mut some_bools);
701 /// std::thread::scope(|s| {
702 /// for i in 0..a.len() {
703 /// s.spawn(move || a[i].store(true, Ordering::Relaxed));
704 /// }
705 /// });
706 /// assert_eq!(some_bools, [true; 10]);
707 /// ```
708 #[inline]
709 #[cfg(target_has_atomic_primitive_alignment = "8")]
710 #[stable(feature = "atomic_from_mut", since = "1.98.0")]
711 pub fn from_mut_slice(v: &mut [bool]) -> &mut [Self] {
712 // SAFETY: the mutable reference guarantees unique ownership, and
713 // alignment of both `bool` and `Self` is 1.
714 unsafe { &mut *(v as *mut [bool] as *mut [Self]) }
715 }
716
717 /// Consumes the atomic and returns the contained value.
718 ///
719 /// This is safe because passing `self` by value guarantees that no other threads are
720 /// concurrently accessing the atomic data.
721 ///
722 /// # Examples
723 ///
724 /// ```
725 /// use std::sync::atomic::AtomicBool;
726 ///
727 /// let some_bool = AtomicBool::new(true);
728 /// assert_eq!(some_bool.into_inner(), true);
729 /// ```
730 #[inline]
731 #[stable(feature = "atomic_access", since = "1.15.0")]
732 #[rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0")]
733 pub const fn into_inner(self) -> bool {
734 // SAFETY:
735 // * `Atomic<T>` is essentially a transparent wrapper around `T`.
736 // * all operations on `Atomic<bool>` ensure that `T::Storage` remains
737 // a valid `bool`.
738 unsafe { transmute(self) }
739 }
740
741 /// Loads a value from the bool.
742 ///
743 /// `load` takes an [`Ordering`] argument which describes the memory ordering
744 /// of this operation. Possible values are [`SeqCst`], [`Acquire`] and [`Relaxed`].
745 ///
746 /// # Panics
747 ///
748 /// Panics if `order` is [`Release`] or [`AcqRel`].
749 ///
750 /// # Examples
751 ///
752 /// ```
753 /// use std::sync::atomic::{AtomicBool, Ordering};
754 ///
755 /// let some_bool = AtomicBool::new(true);
756 ///
757 /// assert_eq!(some_bool.load(Ordering::Relaxed), true);
758 /// ```
759 #[inline]
760 #[stable(feature = "rust1", since = "1.0.0")]
761 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
762 #[ferrocene::prevalidated]
763 pub fn load(&self, order: Ordering) -> bool {
764 // SAFETY: any data races are prevented by atomic intrinsics and the raw
765 // pointer passed in is valid because we got it from a reference.
766 unsafe { atomic_load(self.v.get().cast::<u8>(), order) != 0 }
767 }
768
769 /// Stores a value into the bool.
770 ///
771 /// `store` takes an [`Ordering`] argument which describes the memory ordering
772 /// of this operation. Possible values are [`SeqCst`], [`Release`] and [`Relaxed`].
773 ///
774 /// # Panics
775 ///
776 /// Panics if `order` is [`Acquire`] or [`AcqRel`].
777 ///
778 /// # Examples
779 ///
780 /// ```
781 /// use std::sync::atomic::{AtomicBool, Ordering};
782 ///
783 /// let some_bool = AtomicBool::new(true);
784 ///
785 /// some_bool.store(false, Ordering::Relaxed);
786 /// assert_eq!(some_bool.load(Ordering::Relaxed), false);
787 /// ```
788 #[inline]
789 #[stable(feature = "rust1", since = "1.0.0")]
790 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
791 #[rustc_should_not_be_called_on_const_items]
792 #[ferrocene::prevalidated]
793 pub fn store(&self, val: bool, order: Ordering) {
794 // SAFETY: any data races are prevented by atomic intrinsics and the raw
795 // pointer passed in is valid because we got it from a reference.
796 unsafe {
797 atomic_store(self.v.get().cast::<u8>(), val as u8, order);
798 }
799 }
800
801 /// Stores a value into the bool, returning the previous value.
802 ///
803 /// `swap` takes an [`Ordering`] argument which describes the memory ordering
804 /// of this operation. All ordering modes are possible. Note that using
805 /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
806 /// using [`Release`] makes the load part [`Relaxed`].
807 ///
808 /// **Note:** This method is only available on platforms that support atomic
809 /// operations on `u8`.
810 ///
811 /// # Examples
812 ///
813 /// ```
814 /// use std::sync::atomic::{AtomicBool, Ordering};
815 ///
816 /// let some_bool = AtomicBool::new(true);
817 ///
818 /// assert_eq!(some_bool.swap(false, Ordering::Relaxed), true);
819 /// assert_eq!(some_bool.load(Ordering::Relaxed), false);
820 /// ```
821 #[inline]
822 #[stable(feature = "rust1", since = "1.0.0")]
823 #[cfg(target_has_atomic = "8")]
824 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
825 #[rustc_should_not_be_called_on_const_items]
826 #[ferrocene::prevalidated]
827 pub fn swap(&self, val: bool, order: Ordering) -> bool {
828 if EMULATE_ATOMIC_BOOL {
829 #[ferrocene::annotation(
830 "Cannot be covered as this code does not run in any of the platforms for which we track coverage"
831 )]
832 if val { self.fetch_or(true, order) } else { self.fetch_and(false, order) }
833 } else {
834 // SAFETY: data races are prevented by atomic intrinsics.
835 unsafe { atomic_swap(self.v.get().cast::<u8>(), val as u8, order) != 0 }
836 }
837 }
838
839 /// Stores a value into the [`bool`] if the current value is the same as the `current` value.
840 ///
841 /// The return value is always the previous value. If it is equal to `current`, then the value
842 /// was updated.
843 ///
844 /// `compare_and_swap` also takes an [`Ordering`] argument which describes the memory
845 /// ordering of this operation. Notice that even when using [`AcqRel`], the operation
846 /// might fail and hence just perform an `Acquire` load, but not have `Release` semantics.
847 /// Using [`Acquire`] makes the store part of this operation [`Relaxed`] if it
848 /// happens, and using [`Release`] makes the load part [`Relaxed`].
849 ///
850 /// **Note:** This method is only available on platforms that support atomic
851 /// operations on `u8`.
852 ///
853 /// # Migrating to `compare_exchange` and `compare_exchange_weak`
854 ///
855 /// `compare_and_swap` is equivalent to `compare_exchange` with the following mapping for
856 /// memory orderings:
857 ///
858 /// Original | Success | Failure
859 /// -------- | ------- | -------
860 /// Relaxed | Relaxed | Relaxed
861 /// Acquire | Acquire | Acquire
862 /// Release | Release | Relaxed
863 /// AcqRel | AcqRel | Acquire
864 /// SeqCst | SeqCst | SeqCst
865 ///
866 /// `compare_and_swap` and `compare_exchange` also differ in their return type. You can use
867 /// `compare_exchange(...).unwrap_or_else(|x| x)` to recover the behavior of `compare_and_swap`,
868 /// but in most cases it is more idiomatic to check whether the return value is `Ok` or `Err`
869 /// rather than to infer success vs failure based on the value that was read.
870 ///
871 /// During migration, consider whether it makes sense to use `compare_exchange_weak` instead.
872 /// `compare_exchange_weak` is allowed to fail spuriously even when the comparison succeeds,
873 /// which allows the compiler to generate better assembly code when the compare and swap
874 /// is used in a loop.
875 ///
876 /// # Examples
877 ///
878 /// ```
879 /// use std::sync::atomic::{AtomicBool, Ordering};
880 ///
881 /// let some_bool = AtomicBool::new(true);
882 ///
883 /// assert_eq!(some_bool.compare_and_swap(true, false, Ordering::Relaxed), true);
884 /// assert_eq!(some_bool.load(Ordering::Relaxed), false);
885 ///
886 /// assert_eq!(some_bool.compare_and_swap(true, true, Ordering::Relaxed), false);
887 /// assert_eq!(some_bool.load(Ordering::Relaxed), false);
888 /// ```
889 #[inline]
890 #[stable(feature = "rust1", since = "1.0.0")]
891 #[deprecated(
892 since = "1.50.0",
893 note = "Use `compare_exchange` or `compare_exchange_weak` instead"
894 )]
895 #[cfg(target_has_atomic = "8")]
896 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
897 #[rustc_should_not_be_called_on_const_items]
898 pub fn compare_and_swap(&self, current: bool, new: bool, order: Ordering) -> bool {
899 match self.compare_exchange(current, new, order, strongest_failure_ordering(order)) {
900 Ok(x) => x,
901 Err(x) => x,
902 }
903 }
904
905 /// Stores a value into the [`bool`] if the current value is the same as the `current` value.
906 ///
907 /// The return value is a result indicating whether the new value was written and containing
908 /// the previous value. On success this value is guaranteed to be equal to `current`.
909 ///
910 /// `compare_exchange` takes two [`Ordering`] arguments to describe the memory
911 /// ordering of this operation. `success` describes the required ordering for the
912 /// read-modify-write operation that takes place if the comparison with `current` succeeds.
913 /// `failure` describes the required ordering for the load operation that takes place when
914 /// the comparison fails. Using [`Acquire`] as success ordering makes the store part
915 /// of this operation [`Relaxed`], and using [`Release`] makes the successful load
916 /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
917 ///
918 /// **Note:** This method is only available on platforms that support atomic
919 /// operations on `u8`.
920 ///
921 /// # Examples
922 ///
923 /// ```
924 /// use std::sync::atomic::{AtomicBool, Ordering};
925 ///
926 /// let some_bool = AtomicBool::new(true);
927 ///
928 /// assert_eq!(some_bool.compare_exchange(true,
929 /// false,
930 /// Ordering::Acquire,
931 /// Ordering::Relaxed),
932 /// Ok(true));
933 /// assert_eq!(some_bool.load(Ordering::Relaxed), false);
934 ///
935 /// assert_eq!(some_bool.compare_exchange(true, true,
936 /// Ordering::SeqCst,
937 /// Ordering::Acquire),
938 /// Err(false));
939 /// assert_eq!(some_bool.load(Ordering::Relaxed), false);
940 /// ```
941 ///
942 /// # Considerations
943 ///
944 /// `compare_exchange` is a [compare-and-swap operation] and thus exhibits the usual downsides
945 /// of CAS operations. In particular, a load of the value followed by a successful
946 /// `compare_exchange` with the previous load *does not ensure* that other threads have not
947 /// changed the value in the interim. This is usually important when the *equality* check in
948 /// the `compare_exchange` is being used to check the *identity* of a value, but equality
949 /// does not necessarily imply identity. In this case, `compare_exchange` can lead to the
950 /// [ABA problem].
951 ///
952 /// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
953 /// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
954 #[inline]
955 #[stable(feature = "extended_compare_and_swap", since = "1.10.0")]
956 #[doc(alias = "compare_and_swap")]
957 #[cfg(target_has_atomic = "8")]
958 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
959 #[rustc_should_not_be_called_on_const_items]
960 #[ferrocene::prevalidated]
961 pub fn compare_exchange(
962 &self,
963 current: bool,
964 new: bool,
965 success: Ordering,
966 failure: Ordering,
967 ) -> Result<bool, bool> {
968 if EMULATE_ATOMIC_BOOL {
969 #[ferrocene::annotation(
970 "Cannot be covered as this code does not run in any of the platforms for which we track coverage"
971 )]
972 {
973 // Pick the strongest ordering from success and failure.
974 let order = match (success, failure) {
975 (SeqCst, _) => SeqCst,
976 (_, SeqCst) => SeqCst,
977 (AcqRel, _) => AcqRel,
978 (_, AcqRel) => {
979 panic!("there is no such thing as an acquire-release failure ordering")
980 }
981 (Release, Acquire) => AcqRel,
982 (Acquire, _) => Acquire,
983 (_, Acquire) => Acquire,
984 (Release, Relaxed) => Release,
985 (_, Release) => panic!("there is no such thing as a release failure ordering"),
986 (Relaxed, Relaxed) => Relaxed,
987 };
988 let old = if current == new {
989 // This is a no-op, but we still need to perform the operation
990 // for memory ordering reasons.
991 self.fetch_or(false, order)
992 } else {
993 // This sets the value to the new one and returns the old one.
994 self.swap(new, order)
995 };
996 if old == current { Ok(old) } else { Err(old) }
997 }
998 } else {
999 // SAFETY: data races are prevented by atomic intrinsics.
1000 match unsafe {
1001 atomic_compare_exchange(
1002 self.v.get().cast::<u8>(),
1003 current as u8,
1004 new as u8,
1005 success,
1006 failure,
1007 )
1008 } {
1009 Ok(x) => Ok(x != 0),
1010 Err(x) => Err(x != 0),
1011 }
1012 }
1013 }
1014
1015 /// Stores a value into the [`bool`] if the current value is the same as the `current` value.
1016 ///
1017 /// Unlike [`AtomicBool::compare_exchange`], this function is allowed to spuriously fail even when the
1018 /// comparison succeeds, which can result in more efficient code on some platforms. The
1019 /// return value is a result indicating whether the new value was written and containing the
1020 /// previous value.
1021 ///
1022 /// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory
1023 /// ordering of this operation. `success` describes the required ordering for the
1024 /// read-modify-write operation that takes place if the comparison with `current` succeeds.
1025 /// `failure` describes the required ordering for the load operation that takes place when
1026 /// the comparison fails. Using [`Acquire`] as success ordering makes the store part
1027 /// of this operation [`Relaxed`], and using [`Release`] makes the successful load
1028 /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
1029 ///
1030 /// **Note:** This method is only available on platforms that support atomic
1031 /// operations on `u8`.
1032 ///
1033 /// # Examples
1034 ///
1035 /// ```
1036 /// use std::sync::atomic::{AtomicBool, Ordering};
1037 ///
1038 /// let val = AtomicBool::new(false);
1039 ///
1040 /// let new = true;
1041 /// let mut old = val.load(Ordering::Relaxed);
1042 /// loop {
1043 /// match val.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) {
1044 /// Ok(_) => break,
1045 /// Err(x) => old = x,
1046 /// }
1047 /// }
1048 /// ```
1049 ///
1050 /// # Considerations
1051 ///
1052 /// `compare_exchange` is a [compare-and-swap operation] and thus exhibits the usual downsides
1053 /// of CAS operations. In particular, a load of the value followed by a successful
1054 /// `compare_exchange` with the previous load *does not ensure* that other threads have not
1055 /// changed the value in the interim. This is usually important when the *equality* check in
1056 /// the `compare_exchange` is being used to check the *identity* of a value, but equality
1057 /// does not necessarily imply identity. In this case, `compare_exchange` can lead to the
1058 /// [ABA problem].
1059 ///
1060 /// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
1061 /// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
1062 #[inline]
1063 #[stable(feature = "extended_compare_and_swap", since = "1.10.0")]
1064 #[doc(alias = "compare_and_swap")]
1065 #[cfg(target_has_atomic = "8")]
1066 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
1067 #[rustc_should_not_be_called_on_const_items]
1068 pub fn compare_exchange_weak(
1069 &self,
1070 current: bool,
1071 new: bool,
1072 success: Ordering,
1073 failure: Ordering,
1074 ) -> Result<bool, bool> {
1075 if EMULATE_ATOMIC_BOOL {
1076 return self.compare_exchange(current, new, success, failure);
1077 }
1078
1079 // SAFETY: data races are prevented by atomic intrinsics.
1080 match unsafe {
1081 atomic_compare_exchange_weak(
1082 self.v.get().cast::<u8>(),
1083 current as u8,
1084 new as u8,
1085 success,
1086 failure,
1087 )
1088 } {
1089 Ok(x) => Ok(x != 0),
1090 Err(x) => Err(x != 0),
1091 }
1092 }
1093
1094 /// Logical "and" with a boolean value.
1095 ///
1096 /// Performs a logical "and" operation on the current value and the argument `val`, and sets
1097 /// the new value to the result.
1098 ///
1099 /// Returns the previous value.
1100 ///
1101 /// `fetch_and` takes an [`Ordering`] argument which describes the memory ordering
1102 /// of this operation. All ordering modes are possible. Note that using
1103 /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
1104 /// using [`Release`] makes the load part [`Relaxed`].
1105 ///
1106 /// **Note:** This method is only available on platforms that support atomic
1107 /// operations on `u8`.
1108 ///
1109 /// # Examples
1110 ///
1111 /// ```
1112 /// use std::sync::atomic::{AtomicBool, Ordering};
1113 ///
1114 /// let foo = AtomicBool::new(true);
1115 /// assert_eq!(foo.fetch_and(false, Ordering::SeqCst), true);
1116 /// assert_eq!(foo.load(Ordering::SeqCst), false);
1117 ///
1118 /// let foo = AtomicBool::new(true);
1119 /// assert_eq!(foo.fetch_and(true, Ordering::SeqCst), true);
1120 /// assert_eq!(foo.load(Ordering::SeqCst), true);
1121 ///
1122 /// let foo = AtomicBool::new(false);
1123 /// assert_eq!(foo.fetch_and(false, Ordering::SeqCst), false);
1124 /// assert_eq!(foo.load(Ordering::SeqCst), false);
1125 /// ```
1126 #[inline]
1127 #[stable(feature = "rust1", since = "1.0.0")]
1128 #[cfg(target_has_atomic = "8")]
1129 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
1130 #[rustc_should_not_be_called_on_const_items]
1131 #[ferrocene::prevalidated]
1132 pub fn fetch_and(&self, val: bool, order: Ordering) -> bool {
1133 // SAFETY: data races are prevented by atomic intrinsics.
1134 unsafe { atomic_and(self.v.get().cast::<u8>(), val as u8, order) != 0 }
1135 }
1136
1137 /// Logical "nand" with a boolean value.
1138 ///
1139 /// Performs a logical "nand" operation on the current value and the argument `val`, and sets
1140 /// the new value to the result.
1141 ///
1142 /// Returns the previous value.
1143 ///
1144 /// `fetch_nand` takes an [`Ordering`] argument which describes the memory ordering
1145 /// of this operation. All ordering modes are possible. Note that using
1146 /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
1147 /// using [`Release`] makes the load part [`Relaxed`].
1148 ///
1149 /// **Note:** This method is only available on platforms that support atomic
1150 /// operations on `u8`.
1151 ///
1152 /// # Examples
1153 ///
1154 /// ```
1155 /// use std::sync::atomic::{AtomicBool, Ordering};
1156 ///
1157 /// let foo = AtomicBool::new(true);
1158 /// assert_eq!(foo.fetch_nand(false, Ordering::SeqCst), true);
1159 /// assert_eq!(foo.load(Ordering::SeqCst), true);
1160 ///
1161 /// let foo = AtomicBool::new(true);
1162 /// assert_eq!(foo.fetch_nand(true, Ordering::SeqCst), true);
1163 /// assert_eq!(foo.load(Ordering::SeqCst) as usize, 0);
1164 /// assert_eq!(foo.load(Ordering::SeqCst), false);
1165 ///
1166 /// let foo = AtomicBool::new(false);
1167 /// assert_eq!(foo.fetch_nand(false, Ordering::SeqCst), false);
1168 /// assert_eq!(foo.load(Ordering::SeqCst), true);
1169 /// ```
1170 #[inline]
1171 #[stable(feature = "rust1", since = "1.0.0")]
1172 #[cfg(target_has_atomic = "8")]
1173 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
1174 #[rustc_should_not_be_called_on_const_items]
1175 pub fn fetch_nand(&self, val: bool, order: Ordering) -> bool {
1176 // We can't use atomic_nand here because it can result in a bool with
1177 // an invalid value. This happens because the atomic operation is done
1178 // with an 8-bit integer internally, which would set the upper 7 bits.
1179 // So we just use fetch_xor or swap instead.
1180 if val {
1181 // !(x & true) == !x
1182 // We must invert the bool.
1183 self.fetch_xor(true, order)
1184 } else {
1185 // !(x & false) == true
1186 // We must set the bool to true.
1187 self.swap(true, order)
1188 }
1189 }
1190
1191 /// Logical "or" with a boolean value.
1192 ///
1193 /// Performs a logical "or" operation on the current value and the argument `val`, and sets the
1194 /// new value to the result.
1195 ///
1196 /// Returns the previous value.
1197 ///
1198 /// `fetch_or` takes an [`Ordering`] argument which describes the memory ordering
1199 /// of this operation. All ordering modes are possible. Note that using
1200 /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
1201 /// using [`Release`] makes the load part [`Relaxed`].
1202 ///
1203 /// **Note:** This method is only available on platforms that support atomic
1204 /// operations on `u8`.
1205 ///
1206 /// # Examples
1207 ///
1208 /// ```
1209 /// use std::sync::atomic::{AtomicBool, Ordering};
1210 ///
1211 /// let foo = AtomicBool::new(true);
1212 /// assert_eq!(foo.fetch_or(false, Ordering::SeqCst), true);
1213 /// assert_eq!(foo.load(Ordering::SeqCst), true);
1214 ///
1215 /// let foo = AtomicBool::new(false);
1216 /// assert_eq!(foo.fetch_or(true, Ordering::SeqCst), false);
1217 /// assert_eq!(foo.load(Ordering::SeqCst), true);
1218 ///
1219 /// let foo = AtomicBool::new(false);
1220 /// assert_eq!(foo.fetch_or(false, Ordering::SeqCst), false);
1221 /// assert_eq!(foo.load(Ordering::SeqCst), false);
1222 /// ```
1223 #[inline]
1224 #[stable(feature = "rust1", since = "1.0.0")]
1225 #[cfg(target_has_atomic = "8")]
1226 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
1227 #[rustc_should_not_be_called_on_const_items]
1228 #[ferrocene::prevalidated]
1229 pub fn fetch_or(&self, val: bool, order: Ordering) -> bool {
1230 // SAFETY: data races are prevented by atomic intrinsics.
1231 unsafe { atomic_or(self.v.get().cast::<u8>(), val as u8, order) != 0 }
1232 }
1233
1234 /// Logical "xor" with a boolean value.
1235 ///
1236 /// Performs a logical "xor" operation on the current value and the argument `val`, and sets
1237 /// the new value to the result.
1238 ///
1239 /// Returns the previous value.
1240 ///
1241 /// `fetch_xor` takes an [`Ordering`] argument which describes the memory ordering
1242 /// of this operation. All ordering modes are possible. Note that using
1243 /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
1244 /// using [`Release`] makes the load part [`Relaxed`].
1245 ///
1246 /// **Note:** This method is only available on platforms that support atomic
1247 /// operations on `u8`.
1248 ///
1249 /// # Examples
1250 ///
1251 /// ```
1252 /// use std::sync::atomic::{AtomicBool, Ordering};
1253 ///
1254 /// let foo = AtomicBool::new(true);
1255 /// assert_eq!(foo.fetch_xor(false, Ordering::SeqCst), true);
1256 /// assert_eq!(foo.load(Ordering::SeqCst), true);
1257 ///
1258 /// let foo = AtomicBool::new(true);
1259 /// assert_eq!(foo.fetch_xor(true, Ordering::SeqCst), true);
1260 /// assert_eq!(foo.load(Ordering::SeqCst), false);
1261 ///
1262 /// let foo = AtomicBool::new(false);
1263 /// assert_eq!(foo.fetch_xor(false, Ordering::SeqCst), false);
1264 /// assert_eq!(foo.load(Ordering::SeqCst), false);
1265 /// ```
1266 #[inline]
1267 #[stable(feature = "rust1", since = "1.0.0")]
1268 #[cfg(target_has_atomic = "8")]
1269 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
1270 #[rustc_should_not_be_called_on_const_items]
1271 pub fn fetch_xor(&self, val: bool, order: Ordering) -> bool {
1272 // SAFETY: data races are prevented by atomic intrinsics.
1273 unsafe { atomic_xor(self.v.get().cast::<u8>(), val as u8, order) != 0 }
1274 }
1275
1276 /// Logical "not" with a boolean value.
1277 ///
1278 /// Performs a logical "not" operation on the current value, and sets
1279 /// the new value to the result.
1280 ///
1281 /// Returns the previous value.
1282 ///
1283 /// `fetch_not` takes an [`Ordering`] argument which describes the memory ordering
1284 /// of this operation. All ordering modes are possible. Note that using
1285 /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
1286 /// using [`Release`] makes the load part [`Relaxed`].
1287 ///
1288 /// **Note:** This method is only available on platforms that support atomic
1289 /// operations on `u8`.
1290 ///
1291 /// # Examples
1292 ///
1293 /// ```
1294 /// use std::sync::atomic::{AtomicBool, Ordering};
1295 ///
1296 /// let foo = AtomicBool::new(true);
1297 /// assert_eq!(foo.fetch_not(Ordering::SeqCst), true);
1298 /// assert_eq!(foo.load(Ordering::SeqCst), false);
1299 ///
1300 /// let foo = AtomicBool::new(false);
1301 /// assert_eq!(foo.fetch_not(Ordering::SeqCst), false);
1302 /// assert_eq!(foo.load(Ordering::SeqCst), true);
1303 /// ```
1304 #[inline]
1305 #[stable(feature = "atomic_bool_fetch_not", since = "1.81.0")]
1306 #[cfg(target_has_atomic = "8")]
1307 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
1308 #[rustc_should_not_be_called_on_const_items]
1309 pub fn fetch_not(&self, order: Ordering) -> bool {
1310 self.fetch_xor(true, order)
1311 }
1312
1313 /// Returns a mutable pointer to the underlying [`bool`].
1314 ///
1315 /// Doing non-atomic reads and writes on the resulting boolean can be a data race.
1316 /// This method is mostly useful for FFI, where the function signature may use
1317 /// `*mut bool` instead of `&AtomicBool`.
1318 ///
1319 /// Returning an `*mut` pointer from a shared reference to this atomic is safe because the
1320 /// atomic types work with interior mutability. All modifications of an atomic change the value
1321 /// through a shared reference, and can do so safely as long as they use atomic operations. Any
1322 /// use of the returned raw pointer requires an `unsafe` block and still has to uphold the
1323 /// requirements of the [memory model].
1324 ///
1325 /// # Examples
1326 ///
1327 /// ```ignore (extern-declaration)
1328 /// # fn main() {
1329 /// use std::sync::atomic::AtomicBool;
1330 ///
1331 /// extern "C" {
1332 /// fn my_atomic_op(arg: *mut bool);
1333 /// }
1334 ///
1335 /// let mut atomic = AtomicBool::new(true);
1336 /// unsafe {
1337 /// my_atomic_op(atomic.as_ptr());
1338 /// }
1339 /// # }
1340 /// ```
1341 ///
1342 /// [memory model]: self#memory-model-for-atomic-accesses
1343 #[inline]
1344 #[stable(feature = "atomic_as_ptr", since = "1.70.0")]
1345 #[rustc_const_stable(feature = "atomic_as_ptr", since = "1.70.0")]
1346 #[rustc_never_returns_null_ptr]
1347 #[rustc_should_not_be_called_on_const_items]
1348 pub const fn as_ptr(&self) -> *mut bool {
1349 self.v.get().cast()
1350 }
1351
1352 /// An alias for [`AtomicBool::try_update`].
1353 #[inline]
1354 #[stable(feature = "atomic_fetch_update", since = "1.53.0")]
1355 #[cfg(target_has_atomic = "8")]
1356 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
1357 #[rustc_should_not_be_called_on_const_items]
1358 #[deprecated(
1359 since = "1.99.0",
1360 note = "renamed to `try_update` for consistency",
1361 suggestion = "try_update"
1362 )]
1363 pub fn fetch_update<F>(
1364 &self,
1365 set_order: Ordering,
1366 fetch_order: Ordering,
1367 f: F,
1368 ) -> Result<bool, bool>
1369 where
1370 F: FnMut(bool) -> Option<bool>,
1371 {
1372 self.try_update(set_order, fetch_order, f)
1373 }
1374
1375 /// Fetches the value, and applies a function to it that returns an optional
1376 /// new value. Returns a `Result` of `Ok(previous_value)` if the function
1377 /// returned `Some(_)`, else `Err(previous_value)`.
1378 ///
1379 /// See also: [`update`](`AtomicBool::update`).
1380 ///
1381 /// Note: This may call the function multiple times if the value has been
1382 /// changed from other threads in the meantime, as long as the function
1383 /// returns `Some(_)`, but the function will have been applied only once to
1384 /// the stored value.
1385 ///
1386 /// `try_update` takes two [`Ordering`] arguments to describe the memory
1387 /// ordering of this operation. The first describes the required ordering for
1388 /// when the operation finally succeeds while the second describes the
1389 /// required ordering for loads. These correspond to the success and failure
1390 /// orderings of [`AtomicBool::compare_exchange`] respectively.
1391 ///
1392 /// Using [`Acquire`] as success ordering makes the store part of this
1393 /// operation [`Relaxed`], and using [`Release`] makes the final successful
1394 /// load [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`],
1395 /// [`Acquire`] or [`Relaxed`].
1396 ///
1397 /// **Note:** This method is only available on platforms that support atomic
1398 /// operations on `u8`.
1399 ///
1400 /// # Considerations
1401 ///
1402 /// This method is not magic; it is not provided by the hardware, and does not act like a
1403 /// critical section or mutex.
1404 ///
1405 /// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
1406 /// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem].
1407 ///
1408 /// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
1409 /// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
1410 ///
1411 /// # Examples
1412 ///
1413 /// ```rust
1414 /// use std::sync::atomic::{AtomicBool, Ordering};
1415 ///
1416 /// let x = AtomicBool::new(false);
1417 /// assert_eq!(x.try_update(Ordering::SeqCst, Ordering::SeqCst, |_| None), Err(false));
1418 /// assert_eq!(x.try_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(!x)), Ok(false));
1419 /// assert_eq!(x.try_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(!x)), Ok(true));
1420 /// assert_eq!(x.load(Ordering::SeqCst), false);
1421 /// ```
1422 #[inline]
1423 #[stable(feature = "atomic_try_update", since = "1.95.0")]
1424 #[cfg(target_has_atomic = "8")]
1425 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
1426 #[rustc_should_not_be_called_on_const_items]
1427 pub fn try_update(
1428 &self,
1429 set_order: Ordering,
1430 fetch_order: Ordering,
1431 mut f: impl FnMut(bool) -> Option<bool>,
1432 ) -> Result<bool, bool> {
1433 let mut prev = self.load(fetch_order);
1434 while let Some(next) = f(prev) {
1435 match self.compare_exchange_weak(prev, next, set_order, fetch_order) {
1436 x @ Ok(_) => return x,
1437 Err(next_prev) => prev = next_prev,
1438 }
1439 }
1440 Err(prev)
1441 }
1442
1443 /// Fetches the value, applies a function to it that it return a new value.
1444 /// The new value is stored and the old value is returned.
1445 ///
1446 /// See also: [`try_update`](`AtomicBool::try_update`).
1447 ///
1448 /// Note: This may call the function multiple times if the value has been changed from other threads in
1449 /// the meantime, but the function will have been applied only once to the stored value.
1450 ///
1451 /// `update` takes two [`Ordering`] arguments to describe the memory
1452 /// ordering of this operation. The first describes the required ordering for
1453 /// when the operation finally succeeds while the second describes the
1454 /// required ordering for loads. These correspond to the success and failure
1455 /// orderings of [`AtomicBool::compare_exchange`] respectively.
1456 ///
1457 /// Using [`Acquire`] as success ordering makes the store part
1458 /// of this operation [`Relaxed`], and using [`Release`] makes the final successful load
1459 /// [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
1460 ///
1461 /// **Note:** This method is only available on platforms that support atomic operations on `u8`.
1462 ///
1463 /// # Considerations
1464 ///
1465 /// This method is not magic; it is not provided by the hardware, and does not act like a
1466 /// critical section or mutex.
1467 ///
1468 /// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
1469 /// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem].
1470 ///
1471 /// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
1472 /// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
1473 ///
1474 /// # Examples
1475 ///
1476 /// ```rust
1477 ///
1478 /// use std::sync::atomic::{AtomicBool, Ordering};
1479 ///
1480 /// let x = AtomicBool::new(false);
1481 /// assert_eq!(x.update(Ordering::SeqCst, Ordering::SeqCst, |x| !x), false);
1482 /// assert_eq!(x.update(Ordering::SeqCst, Ordering::SeqCst, |x| !x), true);
1483 /// assert_eq!(x.load(Ordering::SeqCst), false);
1484 /// ```
1485 #[inline]
1486 #[stable(feature = "atomic_try_update", since = "1.95.0")]
1487 #[cfg(target_has_atomic = "8")]
1488 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
1489 #[rustc_should_not_be_called_on_const_items]
1490 pub fn update(
1491 &self,
1492 set_order: Ordering,
1493 fetch_order: Ordering,
1494 mut f: impl FnMut(bool) -> bool,
1495 ) -> bool {
1496 let mut prev = self.load(fetch_order);
1497 loop {
1498 match self.compare_exchange_weak(prev, f(prev), set_order, fetch_order) {
1499 Ok(x) => break x,
1500 Err(next_prev) => prev = next_prev,
1501 }
1502 }
1503 }
1504}
1505
1506#[cfg(target_has_atomic_load_store = "ptr")]
1507impl<T> AtomicPtr<T> {
1508 /// Creates a new `AtomicPtr`.
1509 ///
1510 /// # Examples
1511 ///
1512 /// ```
1513 /// use std::sync::atomic::AtomicPtr;
1514 ///
1515 /// let ptr = &mut 5;
1516 /// let atomic_ptr = AtomicPtr::new(ptr);
1517 /// ```
1518 #[inline]
1519 #[stable(feature = "rust1", since = "1.0.0")]
1520 #[rustc_const_stable(feature = "const_atomic_new", since = "1.24.0")]
1521 pub const fn new(p: *mut T) -> AtomicPtr<T> {
1522 // SAFETY:
1523 // `Atomic<T>` is essentially a transparent wrapper around `T`.
1524 unsafe { transmute(p) }
1525 }
1526
1527 /// Creates a new `AtomicPtr` from a pointer.
1528 ///
1529 /// # Examples
1530 ///
1531 /// ```
1532 /// use std::sync::atomic::{self, AtomicPtr};
1533 ///
1534 /// // Get a pointer to an allocated value
1535 /// let ptr: *mut *mut u8 = Box::into_raw(Box::new(std::ptr::null_mut()));
1536 ///
1537 /// assert!(ptr.cast::<AtomicPtr<u8>>().is_aligned());
1538 ///
1539 /// {
1540 /// // Create an atomic view of the allocated value
1541 /// let atomic = unsafe { AtomicPtr::from_ptr(ptr) };
1542 ///
1543 /// // Use `atomic` for atomic operations, possibly share it with other threads
1544 /// atomic.store(std::ptr::NonNull::dangling().as_ptr(), atomic::Ordering::Relaxed);
1545 /// }
1546 ///
1547 /// // It's ok to non-atomically access the value behind `ptr`,
1548 /// // since the reference to the atomic ended its lifetime in the block above
1549 /// assert!(!unsafe { *ptr }.is_null());
1550 ///
1551 /// // Deallocate the value
1552 /// unsafe { drop(Box::from_raw(ptr)) }
1553 /// ```
1554 ///
1555 /// # Safety
1556 ///
1557 /// * `ptr` must be aligned to `align_of::<AtomicPtr<T>>()` (note that on some platforms this
1558 /// can be bigger than `align_of::<*mut T>()`).
1559 /// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`.
1560 /// * You must adhere to the [Memory model for atomic accesses]. In particular, it is not
1561 /// allowed to mix conflicting atomic and non-atomic accesses, or atomic accesses of different
1562 /// sizes, without synchronization.
1563 ///
1564 /// [valid]: crate::ptr#safety
1565 /// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses
1566 #[inline]
1567 #[stable(feature = "atomic_from_ptr", since = "1.75.0")]
1568 #[rustc_const_stable(feature = "const_atomic_from_ptr", since = "1.84.0")]
1569 pub const unsafe fn from_ptr<'a>(ptr: *mut *mut T) -> &'a AtomicPtr<T> {
1570 // SAFETY: guaranteed by the caller
1571 unsafe { &*ptr.cast() }
1572 }
1573
1574 /// Creates a new `AtomicPtr` initialized with a null pointer.
1575 ///
1576 /// # Examples
1577 ///
1578 /// ```
1579 /// #![feature(atomic_ptr_null)]
1580 /// use std::sync::atomic::{AtomicPtr, Ordering};
1581 ///
1582 /// let atomic_ptr = AtomicPtr::<()>::null();
1583 /// assert!(atomic_ptr.load(Ordering::Relaxed).is_null());
1584 /// ```
1585 #[inline]
1586 #[must_use]
1587 #[unstable(feature = "atomic_ptr_null", issue = "150733")]
1588 pub const fn null() -> AtomicPtr<T> {
1589 AtomicPtr::new(crate::ptr::null_mut())
1590 }
1591
1592 /// Returns a mutable reference to the underlying pointer.
1593 ///
1594 /// This is safe because the mutable reference guarantees that no other threads are
1595 /// concurrently accessing the atomic data.
1596 ///
1597 /// # Examples
1598 ///
1599 /// ```
1600 /// use std::sync::atomic::{AtomicPtr, Ordering};
1601 ///
1602 /// let mut data = 10;
1603 /// let mut atomic_ptr = AtomicPtr::new(&mut data);
1604 /// let mut other_data = 5;
1605 /// *atomic_ptr.get_mut() = &mut other_data;
1606 /// assert_eq!(unsafe { *atomic_ptr.load(Ordering::SeqCst) }, 5);
1607 /// ```
1608 #[inline]
1609 #[stable(feature = "atomic_access", since = "1.15.0")]
1610 pub fn get_mut(&mut self) -> &mut *mut T {
1611 // SAFETY:
1612 // `Atomic<T>` is essentially a transparent wrapper around `T`.
1613 unsafe { &mut *self.as_ptr() }
1614 }
1615
1616 /// Gets atomic access to a pointer.
1617 ///
1618 /// **Note:** This function is only available on targets where `AtomicPtr<T>` has the same alignment as `*const T`
1619 ///
1620 /// # Examples
1621 ///
1622 /// ```
1623 /// use std::sync::atomic::{AtomicPtr, Ordering};
1624 ///
1625 /// let mut data = 123;
1626 /// let mut some_ptr = &mut data as *mut i32;
1627 /// let a = AtomicPtr::from_mut(&mut some_ptr);
1628 /// let mut other_data = 456;
1629 /// a.store(&mut other_data, Ordering::Relaxed);
1630 /// assert_eq!(unsafe { *some_ptr }, 456);
1631 /// ```
1632 #[inline]
1633 #[cfg(target_has_atomic_primitive_alignment = "ptr")]
1634 #[stable(feature = "atomic_from_mut", since = "1.98.0")]
1635 pub fn from_mut(v: &mut *mut T) -> &mut Self {
1636 let [] = [(); align_of::<AtomicPtr<()>>() - align_of::<*mut ()>()];
1637 // SAFETY:
1638 // - the mutable reference guarantees unique ownership.
1639 // - the alignment of `*mut T` and `Self` is the same on all platforms
1640 // supported by rust, as verified above.
1641 unsafe { &mut *(v as *mut *mut T as *mut Self) }
1642 }
1643
1644 /// Gets non-atomic access to a `&mut [AtomicPtr]` slice.
1645 ///
1646 /// This is safe because the mutable reference guarantees that no other threads are
1647 /// concurrently accessing the atomic data.
1648 ///
1649 /// # Examples
1650 ///
1651 /// ```ignore-wasm
1652 /// use std::ptr::null_mut;
1653 /// use std::sync::atomic::{AtomicPtr, Ordering};
1654 ///
1655 /// let mut some_ptrs = [const { AtomicPtr::new(null_mut::<String>()) }; 10];
1656 ///
1657 /// let view: &mut [*mut String] = AtomicPtr::get_mut_slice(&mut some_ptrs);
1658 /// assert_eq!(view, [null_mut::<String>(); 10]);
1659 /// view
1660 /// .iter_mut()
1661 /// .enumerate()
1662 /// .for_each(|(i, ptr)| *ptr = Box::into_raw(Box::new(format!("iteration#{i}"))));
1663 ///
1664 /// std::thread::scope(|s| {
1665 /// for ptr in &some_ptrs {
1666 /// s.spawn(move || {
1667 /// let ptr = ptr.load(Ordering::Relaxed);
1668 /// assert!(!ptr.is_null());
1669 ///
1670 /// let name = unsafe { Box::from_raw(ptr) };
1671 /// println!("Hello, {name}!");
1672 /// });
1673 /// }
1674 /// });
1675 /// ```
1676 #[inline]
1677 #[stable(feature = "atomic_from_mut", since = "1.98.0")]
1678 pub fn get_mut_slice(this: &mut [Self]) -> &mut [*mut T] {
1679 // SAFETY: the mutable reference guarantees unique ownership.
1680 unsafe { &mut *(this as *mut [Self] as *mut [*mut T]) }
1681 }
1682
1683 /// Gets atomic access to a slice of pointers.
1684 ///
1685 /// **Note:** This function is only available on targets where `AtomicPtr<T>` has the same alignment as `*const T`
1686 ///
1687 /// # Examples
1688 ///
1689 /// ```ignore-wasm
1690 /// use std::ptr::null_mut;
1691 /// use std::sync::atomic::{AtomicPtr, Ordering};
1692 ///
1693 /// let mut some_ptrs = [null_mut::<String>(); 10];
1694 /// let a = &*AtomicPtr::from_mut_slice(&mut some_ptrs);
1695 /// std::thread::scope(|s| {
1696 /// for i in 0..a.len() {
1697 /// s.spawn(move || {
1698 /// let name = Box::new(format!("thread{i}"));
1699 /// a[i].store(Box::into_raw(name), Ordering::Relaxed);
1700 /// });
1701 /// }
1702 /// });
1703 /// for p in some_ptrs {
1704 /// assert!(!p.is_null());
1705 /// let name = unsafe { Box::from_raw(p) };
1706 /// println!("Hello, {name}!");
1707 /// }
1708 /// ```
1709 #[inline]
1710 #[cfg(target_has_atomic_primitive_alignment = "ptr")]
1711 #[stable(feature = "atomic_from_mut", since = "1.98.0")]
1712 pub fn from_mut_slice(v: &mut [*mut T]) -> &mut [Self] {
1713 // SAFETY:
1714 // - the mutable reference guarantees unique ownership.
1715 // - the alignment of `*mut T` and `Self` is the same on all platforms
1716 // supported by rust, as verified above.
1717 unsafe { &mut *(v as *mut [*mut T] as *mut [Self]) }
1718 }
1719
1720 /// Consumes the atomic and returns the contained value.
1721 ///
1722 /// This is safe because passing `self` by value guarantees that no other threads are
1723 /// concurrently accessing the atomic data.
1724 ///
1725 /// # Examples
1726 ///
1727 /// ```
1728 /// use std::sync::atomic::AtomicPtr;
1729 ///
1730 /// let mut data = 5;
1731 /// let atomic_ptr = AtomicPtr::new(&mut data);
1732 /// assert_eq!(unsafe { *atomic_ptr.into_inner() }, 5);
1733 /// ```
1734 #[inline]
1735 #[stable(feature = "atomic_access", since = "1.15.0")]
1736 #[rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0")]
1737 pub const fn into_inner(self) -> *mut T {
1738 // SAFETY:
1739 // `Atomic<T>` is essentially a transparent wrapper around `T`.
1740 unsafe { transmute(self) }
1741 }
1742
1743 /// Loads a value from the pointer.
1744 ///
1745 /// `load` takes an [`Ordering`] argument which describes the memory ordering
1746 /// of this operation. Possible values are [`SeqCst`], [`Acquire`] and [`Relaxed`].
1747 ///
1748 /// # Panics
1749 ///
1750 /// Panics if `order` is [`Release`] or [`AcqRel`].
1751 ///
1752 /// # Examples
1753 ///
1754 /// ```
1755 /// use std::sync::atomic::{AtomicPtr, Ordering};
1756 ///
1757 /// let ptr = &mut 5;
1758 /// let some_ptr = AtomicPtr::new(ptr);
1759 ///
1760 /// let value = some_ptr.load(Ordering::Relaxed);
1761 /// ```
1762 #[inline]
1763 #[stable(feature = "rust1", since = "1.0.0")]
1764 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
1765 pub fn load(&self, order: Ordering) -> *mut T {
1766 // SAFETY: data races are prevented by atomic intrinsics.
1767 unsafe { atomic_load(self.as_ptr(), order) }
1768 }
1769
1770 /// Stores a value into the pointer.
1771 ///
1772 /// `store` takes an [`Ordering`] argument which describes the memory ordering
1773 /// of this operation. Possible values are [`SeqCst`], [`Release`] and [`Relaxed`].
1774 ///
1775 /// # Panics
1776 ///
1777 /// Panics if `order` is [`Acquire`] or [`AcqRel`].
1778 ///
1779 /// # Examples
1780 ///
1781 /// ```
1782 /// use std::sync::atomic::{AtomicPtr, Ordering};
1783 ///
1784 /// let ptr = &mut 5;
1785 /// let some_ptr = AtomicPtr::new(ptr);
1786 ///
1787 /// let other_ptr = &mut 10;
1788 ///
1789 /// some_ptr.store(other_ptr, Ordering::Relaxed);
1790 /// ```
1791 #[inline]
1792 #[stable(feature = "rust1", since = "1.0.0")]
1793 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
1794 #[rustc_should_not_be_called_on_const_items]
1795 pub fn store(&self, ptr: *mut T, order: Ordering) {
1796 // SAFETY: data races are prevented by atomic intrinsics.
1797 unsafe {
1798 atomic_store(self.as_ptr(), ptr, order);
1799 }
1800 }
1801
1802 /// Stores a value into the pointer, returning the previous value.
1803 ///
1804 /// `swap` takes an [`Ordering`] argument which describes the memory ordering
1805 /// of this operation. All ordering modes are possible. Note that using
1806 /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
1807 /// using [`Release`] makes the load part [`Relaxed`].
1808 ///
1809 /// **Note:** This method is only available on platforms that support atomic
1810 /// operations on pointers.
1811 ///
1812 /// # Examples
1813 ///
1814 /// ```
1815 /// use std::sync::atomic::{AtomicPtr, Ordering};
1816 ///
1817 /// let ptr = &mut 5;
1818 /// let some_ptr = AtomicPtr::new(ptr);
1819 ///
1820 /// let other_ptr = &mut 10;
1821 ///
1822 /// let value = some_ptr.swap(other_ptr, Ordering::Relaxed);
1823 /// ```
1824 #[inline]
1825 #[stable(feature = "rust1", since = "1.0.0")]
1826 #[cfg(target_has_atomic = "ptr")]
1827 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
1828 #[rustc_should_not_be_called_on_const_items]
1829 pub fn swap(&self, ptr: *mut T, order: Ordering) -> *mut T {
1830 // SAFETY: data races are prevented by atomic intrinsics.
1831 unsafe { atomic_swap(self.as_ptr(), ptr, order) }
1832 }
1833
1834 /// Stores a value into the pointer if the current value is the same as the `current` value.
1835 ///
1836 /// The return value is always the previous value. If it is equal to `current`, then the value
1837 /// was updated.
1838 ///
1839 /// `compare_and_swap` also takes an [`Ordering`] argument which describes the memory
1840 /// ordering of this operation. Notice that even when using [`AcqRel`], the operation
1841 /// might fail and hence just perform an `Acquire` load, but not have `Release` semantics.
1842 /// Using [`Acquire`] makes the store part of this operation [`Relaxed`] if it
1843 /// happens, and using [`Release`] makes the load part [`Relaxed`].
1844 ///
1845 /// **Note:** This method is only available on platforms that support atomic
1846 /// operations on pointers.
1847 ///
1848 /// # Migrating to `compare_exchange` and `compare_exchange_weak`
1849 ///
1850 /// `compare_and_swap` is equivalent to `compare_exchange` with the following mapping for
1851 /// memory orderings:
1852 ///
1853 /// Original | Success | Failure
1854 /// -------- | ------- | -------
1855 /// Relaxed | Relaxed | Relaxed
1856 /// Acquire | Acquire | Acquire
1857 /// Release | Release | Relaxed
1858 /// AcqRel | AcqRel | Acquire
1859 /// SeqCst | SeqCst | SeqCst
1860 ///
1861 /// `compare_and_swap` and `compare_exchange` also differ in their return type. You can use
1862 /// `compare_exchange(...).unwrap_or_else(|x| x)` to recover the behavior of `compare_and_swap`,
1863 /// but in most cases it is more idiomatic to check whether the return value is `Ok` or `Err`
1864 /// rather than to infer success vs failure based on the value that was read.
1865 ///
1866 /// During migration, consider whether it makes sense to use `compare_exchange_weak` instead.
1867 /// `compare_exchange_weak` is allowed to fail spuriously even when the comparison succeeds,
1868 /// which allows the compiler to generate better assembly code when the compare and swap
1869 /// is used in a loop.
1870 ///
1871 /// # Examples
1872 ///
1873 /// ```
1874 /// use std::sync::atomic::{AtomicPtr, Ordering};
1875 ///
1876 /// let ptr = &mut 5;
1877 /// let some_ptr = AtomicPtr::new(ptr);
1878 ///
1879 /// let other_ptr = &mut 10;
1880 ///
1881 /// let value = some_ptr.compare_and_swap(ptr, other_ptr, Ordering::Relaxed);
1882 /// ```
1883 #[inline]
1884 #[stable(feature = "rust1", since = "1.0.0")]
1885 #[deprecated(
1886 since = "1.50.0",
1887 note = "Use `compare_exchange` or `compare_exchange_weak` instead"
1888 )]
1889 #[cfg(target_has_atomic = "ptr")]
1890 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
1891 #[rustc_should_not_be_called_on_const_items]
1892 pub fn compare_and_swap(&self, current: *mut T, new: *mut T, order: Ordering) -> *mut T {
1893 match self.compare_exchange(current, new, order, strongest_failure_ordering(order)) {
1894 Ok(x) => x,
1895 Err(x) => x,
1896 }
1897 }
1898
1899 /// Stores a value into the pointer if the current value is the same as the `current` value.
1900 ///
1901 /// The return value is a result indicating whether the new value was written and containing
1902 /// the previous value. On success this value is guaranteed to be equal to `current`.
1903 ///
1904 /// `compare_exchange` takes two [`Ordering`] arguments to describe the memory
1905 /// ordering of this operation. `success` describes the required ordering for the
1906 /// read-modify-write operation that takes place if the comparison with `current` succeeds.
1907 /// `failure` describes the required ordering for the load operation that takes place when
1908 /// the comparison fails. Using [`Acquire`] as success ordering makes the store part
1909 /// of this operation [`Relaxed`], and using [`Release`] makes the successful load
1910 /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
1911 ///
1912 /// **Note:** This method is only available on platforms that support atomic
1913 /// operations on pointers.
1914 ///
1915 /// # Examples
1916 ///
1917 /// ```
1918 /// use std::sync::atomic::{AtomicPtr, Ordering};
1919 ///
1920 /// let ptr = &mut 5;
1921 /// let some_ptr = AtomicPtr::new(ptr);
1922 ///
1923 /// let other_ptr = &mut 10;
1924 ///
1925 /// let value = some_ptr.compare_exchange(ptr, other_ptr,
1926 /// Ordering::SeqCst, Ordering::Relaxed);
1927 /// ```
1928 ///
1929 /// # Considerations
1930 ///
1931 /// `compare_exchange` is a [compare-and-swap operation] and thus exhibits the usual downsides
1932 /// of CAS operations. In particular, a load of the value followed by a successful
1933 /// `compare_exchange` with the previous load *does not ensure* that other threads have not
1934 /// changed the value in the interim. This is usually important when the *equality* check in
1935 /// the `compare_exchange` is being used to check the *identity* of a value, but equality
1936 /// does not necessarily imply identity. This is a particularly common case for pointers, as
1937 /// a pointer holding the same address does not imply that the same object exists at that
1938 /// address! In this case, `compare_exchange` can lead to the [ABA problem].
1939 ///
1940 /// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
1941 /// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
1942 #[inline]
1943 #[stable(feature = "extended_compare_and_swap", since = "1.10.0")]
1944 #[cfg(target_has_atomic = "ptr")]
1945 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
1946 #[rustc_should_not_be_called_on_const_items]
1947 pub fn compare_exchange(
1948 &self,
1949 current: *mut T,
1950 new: *mut T,
1951 success: Ordering,
1952 failure: Ordering,
1953 ) -> Result<*mut T, *mut T> {
1954 // SAFETY: data races are prevented by atomic intrinsics.
1955 unsafe { atomic_compare_exchange(self.as_ptr(), current, new, success, failure) }
1956 }
1957
1958 /// Stores a value into the pointer if the current value is the same as the `current` value.
1959 ///
1960 /// Unlike [`AtomicPtr::compare_exchange`], this function is allowed to spuriously fail even when the
1961 /// comparison succeeds, which can result in more efficient code on some platforms. The
1962 /// return value is a result indicating whether the new value was written and containing the
1963 /// previous value.
1964 ///
1965 /// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory
1966 /// ordering of this operation. `success` describes the required ordering for the
1967 /// read-modify-write operation that takes place if the comparison with `current` succeeds.
1968 /// `failure` describes the required ordering for the load operation that takes place when
1969 /// the comparison fails. Using [`Acquire`] as success ordering makes the store part
1970 /// of this operation [`Relaxed`], and using [`Release`] makes the successful load
1971 /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
1972 ///
1973 /// **Note:** This method is only available on platforms that support atomic
1974 /// operations on pointers.
1975 ///
1976 /// # Examples
1977 ///
1978 /// ```
1979 /// use std::sync::atomic::{AtomicPtr, Ordering};
1980 ///
1981 /// let some_ptr = AtomicPtr::new(&mut 5);
1982 ///
1983 /// let new = &mut 10;
1984 /// let mut old = some_ptr.load(Ordering::Relaxed);
1985 /// loop {
1986 /// match some_ptr.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) {
1987 /// Ok(_) => break,
1988 /// Err(x) => old = x,
1989 /// }
1990 /// }
1991 /// ```
1992 ///
1993 /// # Considerations
1994 ///
1995 /// `compare_exchange` is a [compare-and-swap operation] and thus exhibits the usual downsides
1996 /// of CAS operations. In particular, a load of the value followed by a successful
1997 /// `compare_exchange` with the previous load *does not ensure* that other threads have not
1998 /// changed the value in the interim. This is usually important when the *equality* check in
1999 /// the `compare_exchange` is being used to check the *identity* of a value, but equality
2000 /// does not necessarily imply identity. This is a particularly common case for pointers, as
2001 /// a pointer holding the same address does not imply that the same object exists at that
2002 /// address! In this case, `compare_exchange` can lead to the [ABA problem].
2003 ///
2004 /// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
2005 /// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
2006 #[inline]
2007 #[stable(feature = "extended_compare_and_swap", since = "1.10.0")]
2008 #[cfg(target_has_atomic = "ptr")]
2009 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
2010 #[rustc_should_not_be_called_on_const_items]
2011 pub fn compare_exchange_weak(
2012 &self,
2013 current: *mut T,
2014 new: *mut T,
2015 success: Ordering,
2016 failure: Ordering,
2017 ) -> Result<*mut T, *mut T> {
2018 // SAFETY: This intrinsic is unsafe because it operates on a raw pointer
2019 // but we know for sure that the pointer is valid (we just got it from
2020 // an `UnsafeCell` that we have by reference) and the atomic operation
2021 // itself allows us to safely mutate the `UnsafeCell` contents.
2022 unsafe { atomic_compare_exchange_weak(self.as_ptr(), current, new, success, failure) }
2023 }
2024
2025 /// An alias for [`AtomicPtr::try_update`].
2026 #[inline]
2027 #[stable(feature = "atomic_fetch_update", since = "1.53.0")]
2028 #[cfg(target_has_atomic = "ptr")]
2029 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
2030 #[rustc_should_not_be_called_on_const_items]
2031 #[deprecated(
2032 since = "1.99.0",
2033 note = "renamed to `try_update` for consistency",
2034 suggestion = "try_update"
2035 )]
2036 pub fn fetch_update<F>(
2037 &self,
2038 set_order: Ordering,
2039 fetch_order: Ordering,
2040 f: F,
2041 ) -> Result<*mut T, *mut T>
2042 where
2043 F: FnMut(*mut T) -> Option<*mut T>,
2044 {
2045 self.try_update(set_order, fetch_order, f)
2046 }
2047 /// Fetches the value, and applies a function to it that returns an optional
2048 /// new value. Returns a `Result` of `Ok(previous_value)` if the function
2049 /// returned `Some(_)`, else `Err(previous_value)`.
2050 ///
2051 /// See also: [`update`](`AtomicPtr::update`).
2052 ///
2053 /// Note: This may call the function multiple times if the value has been
2054 /// changed from other threads in the meantime, as long as the function
2055 /// returns `Some(_)`, but the function will have been applied only once to
2056 /// the stored value.
2057 ///
2058 /// `try_update` takes two [`Ordering`] arguments to describe the memory
2059 /// ordering of this operation. The first describes the required ordering for
2060 /// when the operation finally succeeds while the second describes the
2061 /// required ordering for loads. These correspond to the success and failure
2062 /// orderings of [`AtomicPtr::compare_exchange`] respectively.
2063 ///
2064 /// Using [`Acquire`] as success ordering makes the store part of this
2065 /// operation [`Relaxed`], and using [`Release`] makes the final successful
2066 /// load [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`],
2067 /// [`Acquire`] or [`Relaxed`].
2068 ///
2069 /// **Note:** This method is only available on platforms that support atomic
2070 /// operations on pointers.
2071 ///
2072 /// # Considerations
2073 ///
2074 /// This method is not magic; it is not provided by the hardware, and does not act like a
2075 /// critical section or mutex.
2076 ///
2077 /// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
2078 /// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem],
2079 /// which is a particularly common pitfall for pointers!
2080 ///
2081 /// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
2082 /// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
2083 ///
2084 /// # Examples
2085 ///
2086 /// ```rust
2087 /// use std::sync::atomic::{AtomicPtr, Ordering};
2088 ///
2089 /// let ptr: *mut _ = &mut 5;
2090 /// let some_ptr = AtomicPtr::new(ptr);
2091 ///
2092 /// let new: *mut _ = &mut 10;
2093 /// assert_eq!(some_ptr.try_update(Ordering::SeqCst, Ordering::SeqCst, |_| None), Err(ptr));
2094 /// let result = some_ptr.try_update(Ordering::SeqCst, Ordering::SeqCst, |x| {
2095 /// if x == ptr {
2096 /// Some(new)
2097 /// } else {
2098 /// None
2099 /// }
2100 /// });
2101 /// assert_eq!(result, Ok(ptr));
2102 /// assert_eq!(some_ptr.load(Ordering::SeqCst), new);
2103 /// ```
2104 #[inline]
2105 #[stable(feature = "atomic_try_update", since = "1.95.0")]
2106 #[cfg(target_has_atomic = "ptr")]
2107 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
2108 #[rustc_should_not_be_called_on_const_items]
2109 pub fn try_update(
2110 &self,
2111 set_order: Ordering,
2112 fetch_order: Ordering,
2113 mut f: impl FnMut(*mut T) -> Option<*mut T>,
2114 ) -> Result<*mut T, *mut T> {
2115 let mut prev = self.load(fetch_order);
2116 while let Some(next) = f(prev) {
2117 match self.compare_exchange_weak(prev, next, set_order, fetch_order) {
2118 x @ Ok(_) => return x,
2119 Err(next_prev) => prev = next_prev,
2120 }
2121 }
2122 Err(prev)
2123 }
2124
2125 /// Fetches the value, applies a function to it that it return a new value.
2126 /// The new value is stored and the old value is returned.
2127 ///
2128 /// See also: [`try_update`](`AtomicPtr::try_update`).
2129 ///
2130 /// Note: This may call the function multiple times if the value has been changed from other threads in
2131 /// the meantime, but the function will have been applied only once to the stored value.
2132 ///
2133 /// `update` takes two [`Ordering`] arguments to describe the memory
2134 /// ordering of this operation. The first describes the required ordering for
2135 /// when the operation finally succeeds while the second describes the
2136 /// required ordering for loads. These correspond to the success and failure
2137 /// orderings of [`AtomicPtr::compare_exchange`] respectively.
2138 ///
2139 /// Using [`Acquire`] as success ordering makes the store part
2140 /// of this operation [`Relaxed`], and using [`Release`] makes the final successful load
2141 /// [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
2142 ///
2143 /// **Note:** This method is only available on platforms that support atomic
2144 /// operations on pointers.
2145 ///
2146 /// # Considerations
2147 ///
2148 /// This method is not magic; it is not provided by the hardware, and does not act like a
2149 /// critical section or mutex.
2150 ///
2151 /// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
2152 /// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem],
2153 /// which is a particularly common pitfall for pointers!
2154 ///
2155 /// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
2156 /// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
2157 ///
2158 /// # Examples
2159 ///
2160 /// ```rust
2161 ///
2162 /// use std::sync::atomic::{AtomicPtr, Ordering};
2163 ///
2164 /// let ptr: *mut _ = &mut 5;
2165 /// let some_ptr = AtomicPtr::new(ptr);
2166 ///
2167 /// let new: *mut _ = &mut 10;
2168 /// let result = some_ptr.update(Ordering::SeqCst, Ordering::SeqCst, |_| new);
2169 /// assert_eq!(result, ptr);
2170 /// assert_eq!(some_ptr.load(Ordering::SeqCst), new);
2171 /// ```
2172 #[inline]
2173 #[stable(feature = "atomic_try_update", since = "1.95.0")]
2174 #[cfg(target_has_atomic = "ptr")]
2175 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
2176 #[rustc_should_not_be_called_on_const_items]
2177 pub fn update(
2178 &self,
2179 set_order: Ordering,
2180 fetch_order: Ordering,
2181 mut f: impl FnMut(*mut T) -> *mut T,
2182 ) -> *mut T {
2183 let mut prev = self.load(fetch_order);
2184 loop {
2185 match self.compare_exchange_weak(prev, f(prev), set_order, fetch_order) {
2186 Ok(x) => break x,
2187 Err(next_prev) => prev = next_prev,
2188 }
2189 }
2190 }
2191
2192 /// Offsets the pointer's address by adding `val` (in units of `T`),
2193 /// returning the previous pointer.
2194 ///
2195 /// This is equivalent to using [`wrapping_add`] to atomically perform the
2196 /// equivalent of `ptr = ptr.wrapping_add(val);`.
2197 ///
2198 /// This method operates in units of `T`, which means that it cannot be used
2199 /// to offset the pointer by an amount which is not a multiple of
2200 /// `size_of::<T>()`. This can sometimes be inconvenient, as you may want to
2201 /// work with a deliberately misaligned pointer. In such cases, you may use
2202 /// the [`fetch_byte_add`](Self::fetch_byte_add) method instead.
2203 ///
2204 /// `fetch_ptr_add` takes an [`Ordering`] argument which describes the
2205 /// memory ordering of this operation. All ordering modes are possible. Note
2206 /// that using [`Acquire`] makes the store part of this operation
2207 /// [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`].
2208 ///
2209 /// **Note**: This method is only available on platforms that support atomic
2210 /// operations on [`AtomicPtr`].
2211 ///
2212 /// [`wrapping_add`]: pointer::wrapping_add
2213 ///
2214 /// # Examples
2215 ///
2216 /// ```
2217 /// use core::sync::atomic::{AtomicPtr, Ordering};
2218 ///
2219 /// let atom = AtomicPtr::<i64>::new(core::ptr::null_mut());
2220 /// assert_eq!(atom.fetch_ptr_add(1, Ordering::Relaxed).addr(), 0);
2221 /// // Note: units of `size_of::<i64>()`.
2222 /// assert_eq!(atom.load(Ordering::Relaxed).addr(), 8);
2223 /// ```
2224 #[inline]
2225 #[cfg(target_has_atomic = "ptr")]
2226 #[stable(feature = "strict_provenance_atomic_ptr", since = "1.91.0")]
2227 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
2228 #[rustc_should_not_be_called_on_const_items]
2229 pub fn fetch_ptr_add(&self, val: usize, order: Ordering) -> *mut T {
2230 self.fetch_byte_add(val.wrapping_mul(size_of::<T>()), order)
2231 }
2232
2233 /// Offsets the pointer's address by subtracting `val` (in units of `T`),
2234 /// returning the previous pointer.
2235 ///
2236 /// This is equivalent to using [`wrapping_sub`] to atomically perform the
2237 /// equivalent of `ptr = ptr.wrapping_sub(val);`.
2238 ///
2239 /// This method operates in units of `T`, which means that it cannot be used
2240 /// to offset the pointer by an amount which is not a multiple of
2241 /// `size_of::<T>()`. This can sometimes be inconvenient, as you may want to
2242 /// work with a deliberately misaligned pointer. In such cases, you may use
2243 /// the [`fetch_byte_sub`](Self::fetch_byte_sub) method instead.
2244 ///
2245 /// `fetch_ptr_sub` takes an [`Ordering`] argument which describes the memory
2246 /// ordering of this operation. All ordering modes are possible. Note that
2247 /// using [`Acquire`] makes the store part of this operation [`Relaxed`],
2248 /// and using [`Release`] makes the load part [`Relaxed`].
2249 ///
2250 /// **Note**: This method is only available on platforms that support atomic
2251 /// operations on [`AtomicPtr`].
2252 ///
2253 /// [`wrapping_sub`]: pointer::wrapping_sub
2254 ///
2255 /// # Examples
2256 ///
2257 /// ```
2258 /// use core::sync::atomic::{AtomicPtr, Ordering};
2259 ///
2260 /// let array = [1i32, 2i32];
2261 /// let atom = AtomicPtr::new(array.as_ptr().wrapping_add(1) as *mut _);
2262 ///
2263 /// assert!(core::ptr::eq(
2264 /// atom.fetch_ptr_sub(1, Ordering::Relaxed),
2265 /// &array[1],
2266 /// ));
2267 /// assert!(core::ptr::eq(atom.load(Ordering::Relaxed), &array[0]));
2268 /// ```
2269 #[inline]
2270 #[cfg(target_has_atomic = "ptr")]
2271 #[stable(feature = "strict_provenance_atomic_ptr", since = "1.91.0")]
2272 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
2273 #[rustc_should_not_be_called_on_const_items]
2274 pub fn fetch_ptr_sub(&self, val: usize, order: Ordering) -> *mut T {
2275 self.fetch_byte_sub(val.wrapping_mul(size_of::<T>()), order)
2276 }
2277
2278 /// Offsets the pointer's address by adding `val` *bytes*, returning the
2279 /// previous pointer.
2280 ///
2281 /// This is equivalent to using [`wrapping_byte_add`] to atomically
2282 /// perform `ptr = ptr.wrapping_byte_add(val)`.
2283 ///
2284 /// `fetch_byte_add` takes an [`Ordering`] argument which describes the
2285 /// memory ordering of this operation. All ordering modes are possible. Note
2286 /// that using [`Acquire`] makes the store part of this operation
2287 /// [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`].
2288 ///
2289 /// **Note**: This method is only available on platforms that support atomic
2290 /// operations on [`AtomicPtr`].
2291 ///
2292 /// [`wrapping_byte_add`]: pointer::wrapping_byte_add
2293 ///
2294 /// # Examples
2295 ///
2296 /// ```
2297 /// use core::sync::atomic::{AtomicPtr, Ordering};
2298 ///
2299 /// let atom = AtomicPtr::<i64>::new(core::ptr::null_mut());
2300 /// assert_eq!(atom.fetch_byte_add(1, Ordering::Relaxed).addr(), 0);
2301 /// // Note: in units of bytes, not `size_of::<i64>()`.
2302 /// assert_eq!(atom.load(Ordering::Relaxed).addr(), 1);
2303 /// ```
2304 #[inline]
2305 #[cfg(target_has_atomic = "ptr")]
2306 #[stable(feature = "strict_provenance_atomic_ptr", since = "1.91.0")]
2307 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
2308 #[rustc_should_not_be_called_on_const_items]
2309 pub fn fetch_byte_add(&self, val: usize, order: Ordering) -> *mut T {
2310 // SAFETY: data races are prevented by atomic intrinsics.
2311 unsafe { atomic_add(self.as_ptr(), val, order).cast() }
2312 }
2313
2314 /// Offsets the pointer's address by subtracting `val` *bytes*, returning the
2315 /// previous pointer.
2316 ///
2317 /// This is equivalent to using [`wrapping_byte_sub`] to atomically
2318 /// perform `ptr = ptr.wrapping_byte_sub(val)`.
2319 ///
2320 /// `fetch_byte_sub` takes an [`Ordering`] argument which describes the
2321 /// memory ordering of this operation. All ordering modes are possible. Note
2322 /// that using [`Acquire`] makes the store part of this operation
2323 /// [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`].
2324 ///
2325 /// **Note**: This method is only available on platforms that support atomic
2326 /// operations on [`AtomicPtr`].
2327 ///
2328 /// [`wrapping_byte_sub`]: pointer::wrapping_byte_sub
2329 ///
2330 /// # Examples
2331 ///
2332 /// ```
2333 /// use core::sync::atomic::{AtomicPtr, Ordering};
2334 ///
2335 /// let mut arr = [0i64, 1];
2336 /// let atom = AtomicPtr::<i64>::new(&raw mut arr[1]);
2337 /// assert_eq!(atom.fetch_byte_sub(8, Ordering::Relaxed).addr(), (&raw const arr[1]).addr());
2338 /// assert_eq!(atom.load(Ordering::Relaxed).addr(), (&raw const arr[0]).addr());
2339 /// ```
2340 #[inline]
2341 #[cfg(target_has_atomic = "ptr")]
2342 #[stable(feature = "strict_provenance_atomic_ptr", since = "1.91.0")]
2343 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
2344 #[rustc_should_not_be_called_on_const_items]
2345 pub fn fetch_byte_sub(&self, val: usize, order: Ordering) -> *mut T {
2346 // SAFETY: data races are prevented by atomic intrinsics.
2347 unsafe { atomic_sub(self.as_ptr(), val, order).cast() }
2348 }
2349
2350 /// Performs a bitwise "or" operation on the address of the current pointer,
2351 /// and the argument `val`, and stores a pointer with provenance of the
2352 /// current pointer and the resulting address.
2353 ///
2354 /// This is equivalent to using [`map_addr`] to atomically perform
2355 /// `ptr = ptr.map_addr(|a| a | val)`. This can be used in tagged
2356 /// pointer schemes to atomically set tag bits.
2357 ///
2358 /// **Caveat**: This operation returns the previous value. To compute the
2359 /// stored value without losing provenance, you may use [`map_addr`]. For
2360 /// example: `a.fetch_or(val).map_addr(|a| a | val)`.
2361 ///
2362 /// `fetch_or` takes an [`Ordering`] argument which describes the memory
2363 /// ordering of this operation. All ordering modes are possible. Note that
2364 /// using [`Acquire`] makes the store part of this operation [`Relaxed`],
2365 /// and using [`Release`] makes the load part [`Relaxed`].
2366 ///
2367 /// **Note**: This method is only available on platforms that support atomic
2368 /// operations on [`AtomicPtr`].
2369 ///
2370 /// This API and its claimed semantics are part of the Strict Provenance
2371 /// experiment, see the [module documentation for `ptr`][crate::ptr] for
2372 /// details.
2373 ///
2374 /// [`map_addr`]: pointer::map_addr
2375 ///
2376 /// # Examples
2377 ///
2378 /// ```
2379 /// use core::sync::atomic::{AtomicPtr, Ordering};
2380 ///
2381 /// let pointer = &mut 3i64 as *mut i64;
2382 ///
2383 /// let atom = AtomicPtr::<i64>::new(pointer);
2384 /// // Tag the bottom bit of the pointer.
2385 /// assert_eq!(atom.fetch_or(1, Ordering::Relaxed).addr() & 1, 0);
2386 /// // Extract and untag.
2387 /// let tagged = atom.load(Ordering::Relaxed);
2388 /// assert_eq!(tagged.addr() & 1, 1);
2389 /// assert_eq!(tagged.map_addr(|p| p & !1), pointer);
2390 /// ```
2391 #[inline]
2392 #[cfg(target_has_atomic = "ptr")]
2393 #[stable(feature = "strict_provenance_atomic_ptr", since = "1.91.0")]
2394 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
2395 #[rustc_should_not_be_called_on_const_items]
2396 pub fn fetch_or(&self, val: usize, order: Ordering) -> *mut T {
2397 // SAFETY: data races are prevented by atomic intrinsics.
2398 unsafe { atomic_or(self.as_ptr(), val, order).cast() }
2399 }
2400
2401 /// Performs a bitwise "and" operation on the address of the current
2402 /// pointer, and the argument `val`, and stores a pointer with provenance of
2403 /// the current pointer and the resulting address.
2404 ///
2405 /// This is equivalent to using [`map_addr`] to atomically perform
2406 /// `ptr = ptr.map_addr(|a| a & val)`. This can be used in tagged
2407 /// pointer schemes to atomically unset tag bits.
2408 ///
2409 /// **Caveat**: This operation returns the previous value. To compute the
2410 /// stored value without losing provenance, you may use [`map_addr`]. For
2411 /// example: `a.fetch_and(val).map_addr(|a| a & val)`.
2412 ///
2413 /// `fetch_and` takes an [`Ordering`] argument which describes the memory
2414 /// ordering of this operation. All ordering modes are possible. Note that
2415 /// using [`Acquire`] makes the store part of this operation [`Relaxed`],
2416 /// and using [`Release`] makes the load part [`Relaxed`].
2417 ///
2418 /// **Note**: This method is only available on platforms that support atomic
2419 /// operations on [`AtomicPtr`].
2420 ///
2421 /// This API and its claimed semantics are part of the Strict Provenance
2422 /// experiment, see the [module documentation for `ptr`][crate::ptr] for
2423 /// details.
2424 ///
2425 /// [`map_addr`]: pointer::map_addr
2426 ///
2427 /// # Examples
2428 ///
2429 /// ```
2430 /// use core::sync::atomic::{AtomicPtr, Ordering};
2431 ///
2432 /// let pointer = &mut 3i64 as *mut i64;
2433 /// // A tagged pointer
2434 /// let atom = AtomicPtr::<i64>::new(pointer.map_addr(|a| a | 1));
2435 /// assert_eq!(atom.fetch_or(1, Ordering::Relaxed).addr() & 1, 1);
2436 /// // Untag, and extract the previously tagged pointer.
2437 /// let untagged = atom.fetch_and(!1, Ordering::Relaxed)
2438 /// .map_addr(|a| a & !1);
2439 /// assert_eq!(untagged, pointer);
2440 /// ```
2441 #[inline]
2442 #[cfg(target_has_atomic = "ptr")]
2443 #[stable(feature = "strict_provenance_atomic_ptr", since = "1.91.0")]
2444 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
2445 #[rustc_should_not_be_called_on_const_items]
2446 pub fn fetch_and(&self, val: usize, order: Ordering) -> *mut T {
2447 // SAFETY: data races are prevented by atomic intrinsics.
2448 unsafe { atomic_and(self.as_ptr(), val, order).cast() }
2449 }
2450
2451 /// Performs a bitwise "xor" operation on the address of the current
2452 /// pointer, and the argument `val`, and stores a pointer with provenance of
2453 /// the current pointer and the resulting address.
2454 ///
2455 /// This is equivalent to using [`map_addr`] to atomically perform
2456 /// `ptr = ptr.map_addr(|a| a ^ val)`. This can be used in tagged
2457 /// pointer schemes to atomically toggle tag bits.
2458 ///
2459 /// **Caveat**: This operation returns the previous value. To compute the
2460 /// stored value without losing provenance, you may use [`map_addr`]. For
2461 /// example: `a.fetch_xor(val).map_addr(|a| a ^ val)`.
2462 ///
2463 /// `fetch_xor` takes an [`Ordering`] argument which describes the memory
2464 /// ordering of this operation. All ordering modes are possible. Note that
2465 /// using [`Acquire`] makes the store part of this operation [`Relaxed`],
2466 /// and using [`Release`] makes the load part [`Relaxed`].
2467 ///
2468 /// **Note**: This method is only available on platforms that support atomic
2469 /// operations on [`AtomicPtr`].
2470 ///
2471 /// This API and its claimed semantics are part of the Strict Provenance
2472 /// experiment, see the [module documentation for `ptr`][crate::ptr] for
2473 /// details.
2474 ///
2475 /// [`map_addr`]: pointer::map_addr
2476 ///
2477 /// # Examples
2478 ///
2479 /// ```
2480 /// use core::sync::atomic::{AtomicPtr, Ordering};
2481 ///
2482 /// let pointer = &mut 3i64 as *mut i64;
2483 /// let atom = AtomicPtr::<i64>::new(pointer);
2484 ///
2485 /// // Toggle a tag bit on the pointer.
2486 /// atom.fetch_xor(1, Ordering::Relaxed);
2487 /// assert_eq!(atom.load(Ordering::Relaxed).addr() & 1, 1);
2488 /// ```
2489 #[inline]
2490 #[cfg(target_has_atomic = "ptr")]
2491 #[stable(feature = "strict_provenance_atomic_ptr", since = "1.91.0")]
2492 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
2493 #[rustc_should_not_be_called_on_const_items]
2494 pub fn fetch_xor(&self, val: usize, order: Ordering) -> *mut T {
2495 // SAFETY: data races are prevented by atomic intrinsics.
2496 unsafe { atomic_xor(self.as_ptr(), val, order).cast() }
2497 }
2498
2499 /// Returns a mutable pointer to the underlying pointer.
2500 ///
2501 /// Doing non-atomic reads and writes on the resulting pointer can be a data race.
2502 /// This method is mostly useful for FFI, where the function signature may use
2503 /// `*mut *mut T` instead of `&AtomicPtr<T>`.
2504 ///
2505 /// Returning an `*mut` pointer from a shared reference to this atomic is safe because the
2506 /// atomic types work with interior mutability. All modifications of an atomic change the value
2507 /// through a shared reference, and can do so safely as long as they use atomic operations. Any
2508 /// use of the returned raw pointer requires an `unsafe` block and still has to uphold the
2509 /// requirements of the [memory model].
2510 ///
2511 /// # Examples
2512 ///
2513 /// ```ignore (extern-declaration)
2514 /// use std::sync::atomic::AtomicPtr;
2515 ///
2516 /// extern "C" {
2517 /// fn my_atomic_op(arg: *mut *mut u32);
2518 /// }
2519 ///
2520 /// let mut value = 17;
2521 /// let atomic = AtomicPtr::new(&mut value);
2522 ///
2523 /// // SAFETY: Safe as long as `my_atomic_op` is atomic.
2524 /// unsafe {
2525 /// my_atomic_op(atomic.as_ptr());
2526 /// }
2527 /// ```
2528 ///
2529 /// [memory model]: self#memory-model-for-atomic-accesses
2530 #[inline]
2531 #[stable(feature = "atomic_as_ptr", since = "1.70.0")]
2532 #[rustc_const_stable(feature = "atomic_as_ptr", since = "1.70.0")]
2533 #[rustc_never_returns_null_ptr]
2534 pub const fn as_ptr(&self) -> *mut *mut T {
2535 self.v.get().cast()
2536 }
2537}
2538
2539#[cfg(target_has_atomic_load_store = "8")]
2540#[stable(feature = "atomic_bool_from", since = "1.24.0")]
2541#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
2542const impl From<bool> for AtomicBool {
2543 /// Converts a `bool` into an `AtomicBool`.
2544 ///
2545 /// # Examples
2546 ///
2547 /// ```
2548 /// use std::sync::atomic::AtomicBool;
2549 /// let atomic_bool = AtomicBool::from(true);
2550 /// assert_eq!(format!("{atomic_bool:?}"), "true")
2551 /// ```
2552 #[inline]
2553 fn from(b: bool) -> Self {
2554 Self::new(b)
2555 }
2556}
2557
2558#[cfg(target_has_atomic_load_store = "ptr")]
2559#[stable(feature = "atomic_from", since = "1.23.0")]
2560#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
2561const impl<T> From<*mut T> for AtomicPtr<T> {
2562 /// Converts a `*mut T` into an `AtomicPtr<T>`.
2563 #[inline]
2564 fn from(p: *mut T) -> Self {
2565 Self::new(p)
2566 }
2567}
2568
2569#[allow(unused_macros)] // This macro ends up being unused on some architectures.
2570macro_rules! if_8_bit {
2571 (u8, $( yes = [$($yes:tt)*], )? $( no = [$($no:tt)*], )? ) => { concat!("", $($($yes)*)?) };
2572 (i8, $( yes = [$($yes:tt)*], )? $( no = [$($no:tt)*], )? ) => { concat!("", $($($yes)*)?) };
2573 ($_:ident, $( yes = [$($yes:tt)*], )? $( no = [$($no:tt)*], )? ) => { concat!("", $($($no)*)?) };
2574}
2575
2576#[cfg(target_has_atomic_load_store)]
2577macro_rules! atomic_int {
2578 ($cfg_base:meta,
2579 $cfg_cas:meta,
2580 $cfg_align:meta,
2581 $stable:meta,
2582 $stable_cxchg:meta,
2583 $stable_debug:meta,
2584 $stable_access:meta,
2585 $stable_from:meta,
2586 $stable_nand:meta,
2587 $const_stable_new:meta,
2588 $const_stable_into_inner:meta,
2589 $s_int_type:literal,
2590 $extra_feature:expr,
2591 $min_fn:ident, $max_fn:ident,
2592 $align:expr,
2593 $int_type:ident $atomic_type:ident) => {
2594 /// An integer type which can be safely shared between threads.
2595 ///
2596 /// This type has the same
2597 #[doc = if_8_bit!(
2598 $int_type,
2599 yes = ["size, alignment, and bit validity"],
2600 no = ["size and bit validity"],
2601 )]
2602 /// as the underlying integer type, [`
2603 #[doc = $s_int_type]
2604 /// `].
2605 #[doc = if_8_bit! {
2606 $int_type,
2607 no = [
2608 "However, the alignment of this type is always equal to its ",
2609 "size, even on targets where [`", $s_int_type, "`] has a ",
2610 "lesser alignment."
2611 ],
2612 }]
2613 ///
2614 /// For more about the differences between atomic types and
2615 /// non-atomic types as well as information about the portability of
2616 /// this type, please see the [module-level documentation].
2617 ///
2618 /// **Note:** This type is only available on platforms that support
2619 /// atomic loads and stores of [`
2620 #[doc = $s_int_type]
2621 /// `].
2622 ///
2623 /// [module-level documentation]: crate::sync::atomic
2624 #[$stable]
2625 pub type $atomic_type = Atomic<$int_type>;
2626
2627 #[$stable]
2628 impl Default for $atomic_type {
2629 #[inline]
2630 #[ferrocene::prevalidated]
2631 fn default() -> Self {
2632 Self::new(Default::default())
2633 }
2634 }
2635
2636 #[$stable_from]
2637 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
2638 const impl From<$int_type> for $atomic_type {
2639 #[doc = concat!("Converts an `", stringify!($int_type), "` into an `", stringify!($atomic_type), "`.")]
2640 #[inline]
2641 #[ferrocene::prevalidated]
2642 fn from(v: $int_type) -> Self { Self::new(v) }
2643 }
2644
2645 #[$stable_debug]
2646 impl fmt::Debug for $atomic_type {
2647 #[ferrocene::prevalidated]
2648 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2649 fmt::Debug::fmt(&self.load(Ordering::Relaxed), f)
2650 }
2651 }
2652
2653 impl $atomic_type {
2654 /// Creates a new atomic integer.
2655 ///
2656 /// # Examples
2657 ///
2658 #[cfg_attr($cfg_base, doc = "```")]
2659 #[cfg_attr(not($cfg_base), doc = "```compile_fail")]
2660 #[doc = concat!($extra_feature, "use std::sync::atomic::", stringify!($atomic_type), ";")]
2661 ///
2662 #[doc = concat!("let atomic_forty_two = ", stringify!($atomic_type), "::new(42);")]
2663 /// ```
2664 #[inline]
2665 #[$stable]
2666 #[$const_stable_new]
2667 #[must_use]
2668 #[ferrocene::prevalidated]
2669 pub const fn new(v: $int_type) -> Self {
2670 // SAFETY:
2671 // `Atomic<T>` is essentially a transparent wrapper around `T`.
2672 unsafe { transmute(v) }
2673 }
2674
2675 /// Creates a new reference to an atomic integer from a pointer.
2676 ///
2677 /// # Examples
2678 ///
2679 #[cfg_attr($cfg_base, doc = "```rust")]
2680 #[cfg_attr(not($cfg_base), doc = "```rust,compile_fail")]
2681 #[doc = concat!($extra_feature, "use std::sync::atomic::{self, ", stringify!($atomic_type), "};")]
2682 ///
2683 /// // Get a pointer to an allocated value
2684 #[doc = concat!("let ptr: *mut ", stringify!($int_type), " = Box::into_raw(Box::new(0));")]
2685 ///
2686 #[doc = concat!("assert!(ptr.cast::<", stringify!($atomic_type), ">().is_aligned());")]
2687 ///
2688 /// {
2689 /// // Create an atomic view of the allocated value
2690 // SAFETY: this is a doc comment, tidy, it can't hurt you (also guaranteed by the construction of `ptr` and the assert above)
2691 #[doc = concat!(" let atomic = unsafe {", stringify!($atomic_type), "::from_ptr(ptr) };")]
2692 ///
2693 /// // Use `atomic` for atomic operations, possibly share it with other threads
2694 /// atomic.store(1, atomic::Ordering::Relaxed);
2695 /// }
2696 ///
2697 /// // It's ok to non-atomically access the value behind `ptr`,
2698 /// // since the reference to the atomic ended its lifetime in the block above
2699 /// assert_eq!(unsafe { *ptr }, 1);
2700 ///
2701 /// // Deallocate the value
2702 /// unsafe { drop(Box::from_raw(ptr)) }
2703 /// ```
2704 ///
2705 /// # Safety
2706 ///
2707 /// * `ptr` must be aligned to
2708 #[doc = concat!(" `align_of::<", stringify!($atomic_type), ">()`")]
2709 #[doc = if_8_bit!{
2710 $int_type,
2711 yes = [
2712 " (note that this is always true, since `align_of::<",
2713 stringify!($atomic_type), ">() == 1`)."
2714 ],
2715 no = [
2716 " (note that on some platforms this can be bigger than `align_of::<",
2717 stringify!($int_type), ">()`)."
2718 ],
2719 }]
2720 /// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`.
2721 /// * You must adhere to the [Memory model for atomic accesses]. In particular, it is not
2722 /// allowed to mix conflicting atomic and non-atomic accesses, or atomic accesses of different
2723 /// sizes, without synchronization.
2724 ///
2725 /// [valid]: crate::ptr#safety
2726 /// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses
2727 #[inline]
2728 #[stable(feature = "atomic_from_ptr", since = "1.75.0")]
2729 #[rustc_const_stable(feature = "const_atomic_from_ptr", since = "1.84.0")]
2730 #[ferrocene::prevalidated]
2731 pub const unsafe fn from_ptr<'a>(ptr: *mut $int_type) -> &'a $atomic_type {
2732 // SAFETY: guaranteed by the caller
2733 unsafe { &*ptr.cast() }
2734 }
2735
2736 /// Returns a mutable reference to the underlying integer.
2737 ///
2738 /// This is safe because the mutable reference guarantees that no other threads are
2739 /// concurrently accessing the atomic data.
2740 ///
2741 /// # Examples
2742 ///
2743 #[cfg_attr($cfg_base, doc = "```")]
2744 #[cfg_attr(not($cfg_base), doc = "```compile_fail")]
2745 #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
2746 ///
2747 #[doc = concat!("let mut some_var = ", stringify!($atomic_type), "::new(10);")]
2748 /// assert_eq!(*some_var.get_mut(), 10);
2749 /// *some_var.get_mut() = 5;
2750 /// assert_eq!(some_var.load(Ordering::SeqCst), 5);
2751 /// ```
2752 #[inline]
2753 #[$stable_access]
2754 #[ferrocene::prevalidated]
2755 pub fn get_mut(&mut self) -> &mut $int_type {
2756 // SAFETY:
2757 // `Atomic<T>` is essentially a transparent wrapper around `T`.
2758 unsafe { &mut *self.as_ptr() }
2759 }
2760
2761 #[doc = concat!("Get atomic access to a `&mut ", stringify!($int_type), "`.")]
2762 ///
2763 #[doc = if_8_bit! {
2764 $int_type,
2765 no = [
2766 "**Note:** This function is only available on targets where `",
2767 stringify!($atomic_type), "` has the same alignment as `", stringify!($int_type), "`."
2768 ],
2769 }]
2770 ///
2771 /// # Examples
2772 ///
2773 #[cfg_attr($cfg_align, doc = "```rust")]
2774 #[cfg_attr(not($cfg_align), doc = "```rust,compile_fail")]
2775 #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
2776 ///
2777 /// let mut some_int = 123;
2778 #[doc = concat!("let a = ", stringify!($atomic_type), "::from_mut(&mut some_int);")]
2779 /// a.store(100, Ordering::Relaxed);
2780 /// assert_eq!(some_int, 100);
2781 /// ```
2782 ///
2783 #[ferrocene::prevalidated]
2784 #[inline]
2785 #[cfg(any($cfg_align, doc))]
2786 #[stable(feature = "atomic_from_mut", since = "1.98.0")]
2787 pub fn from_mut(v: &mut $int_type) -> &mut Self {
2788 let [] = [(); align_of::<Self>() - align_of::<$int_type>()];
2789 // SAFETY:
2790 // - the mutable reference guarantees unique ownership.
2791 // - the alignment of `$int_type` and `Self` is the
2792 // same, as promised by $cfg_align and verified above.
2793 unsafe { &mut *(v as *mut $int_type as *mut Self) }
2794 }
2795
2796 #[doc = concat!("Get non-atomic access to a `&mut [", stringify!($atomic_type), "]` slice")]
2797 ///
2798 /// This is safe because the mutable reference guarantees that no other threads are
2799 /// concurrently accessing the atomic data.
2800 ///
2801 /// # Examples
2802 ///
2803 #[cfg_attr($cfg_base, doc = "```ignore-wasm")]
2804 #[cfg_attr(not($cfg_base), doc = "```ignore-wasm,compile_fail")]
2805 #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
2806 ///
2807 #[doc = concat!("let mut some_ints = [const { ", stringify!($atomic_type), "::new(0) }; 10];")]
2808 ///
2809 #[doc = concat!("let view: &mut [", stringify!($int_type), "] = ", stringify!($atomic_type), "::get_mut_slice(&mut some_ints);")]
2810 /// assert_eq!(view, [0; 10]);
2811 /// view
2812 /// .iter_mut()
2813 /// .enumerate()
2814 /// .for_each(|(idx, int)| *int = idx as _);
2815 ///
2816 /// std::thread::scope(|s| {
2817 /// some_ints
2818 /// .iter()
2819 /// .enumerate()
2820 /// .for_each(|(idx, int)| {
2821 /// s.spawn(move || assert_eq!(int.load(Ordering::Relaxed), idx as _));
2822 /// })
2823 /// });
2824 /// ```
2825 #[ferrocene::prevalidated]
2826 #[inline]
2827 #[stable(feature = "atomic_from_mut", since = "1.98.0")]
2828 pub fn get_mut_slice(this: &mut [Self]) -> &mut [$int_type] {
2829 // SAFETY: the mutable reference guarantees unique ownership.
2830 unsafe { &mut *(this as *mut [Self] as *mut [$int_type]) }
2831 }
2832
2833 #[doc = concat!("Get atomic access to a `&mut [", stringify!($int_type), "]` slice.")]
2834 ///
2835 #[doc = if_8_bit! {
2836 $int_type,
2837 no = [
2838 "**Note:** This function is only available on targets where `",
2839 stringify!($atomic_type), "` has the same alignment as `", stringify!($int_type), "`."
2840 ],
2841 }]
2842 ///
2843 /// # Examples
2844 ///
2845 #[cfg_attr($cfg_align, doc = "```ignore-wasm")]
2846 #[cfg_attr(not($cfg_align), doc = "```ignore-wasm,compile_fail")]
2847 #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
2848 ///
2849 /// let mut some_ints = [0; 10];
2850 #[doc = concat!("let a = &*", stringify!($atomic_type), "::from_mut_slice(&mut some_ints);")]
2851 /// std::thread::scope(|s| {
2852 /// for i in 0..a.len() {
2853 /// s.spawn(move || a[i].store(i as _, Ordering::Relaxed));
2854 /// }
2855 /// });
2856 /// for (i, n) in some_ints.into_iter().enumerate() {
2857 /// assert_eq!(i, n as usize);
2858 /// }
2859 /// ```
2860 #[ferrocene::prevalidated]
2861 #[inline]
2862 #[cfg(any($cfg_align, doc))]
2863 #[stable(feature = "atomic_from_mut", since = "1.98.0")]
2864 pub fn from_mut_slice(v: &mut [$int_type]) -> &mut [Self] {
2865 let [] = [(); align_of::<Self>() - align_of::<$int_type>()];
2866 // SAFETY:
2867 // - the mutable reference guarantees unique ownership.
2868 // - the alignment of `$int_type` and `Self` is the
2869 // same, as promised by $cfg_align and verified above.
2870 unsafe { &mut *(v as *mut [$int_type] as *mut [Self]) }
2871 }
2872
2873 /// Consumes the atomic and returns the contained value.
2874 ///
2875 /// This is safe because passing `self` by value guarantees that no other threads are
2876 /// concurrently accessing the atomic data.
2877 ///
2878 /// # Examples
2879 ///
2880 #[cfg_attr($cfg_base, doc = "```")]
2881 #[cfg_attr(not($cfg_base), doc = "```compile_fail")]
2882 #[doc = concat!($extra_feature, "use std::sync::atomic::", stringify!($atomic_type), ";")]
2883 ///
2884 #[doc = concat!("let some_var = ", stringify!($atomic_type), "::new(5);")]
2885 /// assert_eq!(some_var.into_inner(), 5);
2886 /// ```
2887 #[inline]
2888 #[$stable_access]
2889 #[$const_stable_into_inner]
2890 #[ferrocene::prevalidated]
2891 pub const fn into_inner(self) -> $int_type {
2892 // SAFETY:
2893 // `Atomic<T>` is essentially a transparent wrapper around `T`.
2894 unsafe { transmute(self) }
2895 }
2896
2897 /// Loads a value from the atomic integer.
2898 ///
2899 /// `load` takes an [`Ordering`] argument which describes the memory ordering of this operation.
2900 /// Possible values are [`SeqCst`], [`Acquire`] and [`Relaxed`].
2901 ///
2902 /// # Panics
2903 ///
2904 /// Panics if `order` is [`Release`] or [`AcqRel`].
2905 ///
2906 /// # Examples
2907 ///
2908 #[cfg_attr($cfg_base, doc = "```")]
2909 #[cfg_attr(not($cfg_base), doc = "```compile_fail")]
2910 #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
2911 ///
2912 #[doc = concat!("let some_var = ", stringify!($atomic_type), "::new(5);")]
2913 ///
2914 /// assert_eq!(some_var.load(Ordering::Relaxed), 5);
2915 /// ```
2916 #[inline]
2917 #[$stable]
2918 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
2919 #[ferrocene::prevalidated]
2920 pub fn load(&self, order: Ordering) -> $int_type {
2921 // SAFETY: data races are prevented by atomic intrinsics.
2922 unsafe { atomic_load(self.as_ptr(), order) }
2923 }
2924
2925 /// Stores a value into the atomic integer.
2926 ///
2927 /// `store` takes an [`Ordering`] argument which describes the memory ordering of this operation.
2928 /// Possible values are [`SeqCst`], [`Release`] and [`Relaxed`].
2929 ///
2930 /// # Panics
2931 ///
2932 /// Panics if `order` is [`Acquire`] or [`AcqRel`].
2933 ///
2934 /// # Examples
2935 ///
2936 #[cfg_attr($cfg_base, doc = "```")]
2937 #[cfg_attr(not($cfg_base), doc = "```compile_fail")]
2938 #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
2939 ///
2940 #[doc = concat!("let some_var = ", stringify!($atomic_type), "::new(5);")]
2941 ///
2942 /// some_var.store(10, Ordering::Relaxed);
2943 /// assert_eq!(some_var.load(Ordering::Relaxed), 10);
2944 /// ```
2945 #[inline]
2946 #[$stable]
2947 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
2948 #[rustc_should_not_be_called_on_const_items]
2949 #[ferrocene::prevalidated]
2950 pub fn store(&self, val: $int_type, order: Ordering) {
2951 // SAFETY: data races are prevented by atomic intrinsics.
2952 unsafe { atomic_store(self.as_ptr(), val, order); }
2953 }
2954
2955 /// Stores a value into the atomic integer, returning the previous value.
2956 ///
2957 /// `swap` takes an [`Ordering`] argument which describes the memory ordering
2958 /// of this operation. All ordering modes are possible. Note that using
2959 /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
2960 /// using [`Release`] makes the load part [`Relaxed`].
2961 ///
2962 /// **Note**: This method is only available on platforms that support atomic operations on
2963 #[doc = concat!("[`", $s_int_type, "`].")]
2964 ///
2965 /// # Examples
2966 ///
2967 #[cfg_attr($cfg_cas, doc = "```")]
2968 #[cfg_attr(not($cfg_cas), doc = "```compile_fail")]
2969 #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
2970 ///
2971 #[doc = concat!("let some_var = ", stringify!($atomic_type), "::new(5);")]
2972 ///
2973 /// assert_eq!(some_var.swap(10, Ordering::Relaxed), 5);
2974 /// ```
2975 #[inline]
2976 #[$stable]
2977 #[cfg(any($cfg_cas, doc))]
2978 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
2979 #[rustc_should_not_be_called_on_const_items]
2980 #[ferrocene::prevalidated]
2981 pub fn swap(&self, val: $int_type, order: Ordering) -> $int_type {
2982 // SAFETY: data races are prevented by atomic intrinsics.
2983 unsafe { atomic_swap(self.as_ptr(), val, order) }
2984 }
2985
2986 /// Stores a value into the atomic integer if the current value is the same as
2987 /// the `current` value.
2988 ///
2989 /// The return value is always the previous value. If it is equal to `current`, then the
2990 /// value was updated.
2991 ///
2992 /// `compare_and_swap` also takes an [`Ordering`] argument which describes the memory
2993 /// ordering of this operation. Notice that even when using [`AcqRel`], the operation
2994 /// might fail and hence just perform an `Acquire` load, but not have `Release` semantics.
2995 /// Using [`Acquire`] makes the store part of this operation [`Relaxed`] if it
2996 /// happens, and using [`Release`] makes the load part [`Relaxed`].
2997 ///
2998 /// **Note**: This method is only available on platforms that support atomic operations on
2999 #[doc = concat!("[`", $s_int_type, "`].")]
3000 ///
3001 /// # Migrating to `compare_exchange` and `compare_exchange_weak`
3002 ///
3003 /// `compare_and_swap` is equivalent to `compare_exchange` with the following mapping for
3004 /// memory orderings:
3005 ///
3006 /// Original | Success | Failure
3007 /// -------- | ------- | -------
3008 /// Relaxed | Relaxed | Relaxed
3009 /// Acquire | Acquire | Acquire
3010 /// Release | Release | Relaxed
3011 /// AcqRel | AcqRel | Acquire
3012 /// SeqCst | SeqCst | SeqCst
3013 ///
3014 /// `compare_and_swap` and `compare_exchange` also differ in their return type. You can use
3015 /// `compare_exchange(...).unwrap_or_else(|x| x)` to recover the behavior of `compare_and_swap`,
3016 /// but in most cases it is more idiomatic to check whether the return value is `Ok` or `Err`
3017 /// rather than to infer success vs failure based on the value that was read.
3018 ///
3019 /// During migration, consider whether it makes sense to use `compare_exchange_weak` instead.
3020 /// `compare_exchange_weak` is allowed to fail spuriously even when the comparison succeeds,
3021 /// which allows the compiler to generate better assembly code when the compare and swap
3022 /// is used in a loop.
3023 ///
3024 /// # Examples
3025 ///
3026 #[cfg_attr($cfg_cas, doc = "```")]
3027 #[cfg_attr(not($cfg_cas), doc = "```compile_fail")]
3028 #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
3029 ///
3030 #[doc = concat!("let some_var = ", stringify!($atomic_type), "::new(5);")]
3031 ///
3032 /// assert_eq!(some_var.compare_and_swap(5, 10, Ordering::Relaxed), 5);
3033 /// assert_eq!(some_var.load(Ordering::Relaxed), 10);
3034 ///
3035 /// assert_eq!(some_var.compare_and_swap(6, 12, Ordering::Relaxed), 10);
3036 /// assert_eq!(some_var.load(Ordering::Relaxed), 10);
3037 /// ```
3038 #[inline]
3039 #[$stable]
3040 #[deprecated(
3041 since = "1.50.0",
3042 note = "Use `compare_exchange` or `compare_exchange_weak` instead")
3043 ]
3044 #[cfg(any($cfg_cas, doc))]
3045 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
3046 #[rustc_should_not_be_called_on_const_items]
3047 #[ferrocene::prevalidated]
3048 pub fn compare_and_swap(&self,
3049 current: $int_type,
3050 new: $int_type,
3051 order: Ordering) -> $int_type {
3052 match self.compare_exchange(current,
3053 new,
3054 order,
3055 strongest_failure_ordering(order)) {
3056 Ok(x) => x,
3057 Err(x) => x,
3058 }
3059 }
3060
3061 /// Stores a value into the atomic integer if the current value is the same as
3062 /// the `current` value.
3063 ///
3064 /// The return value is a result indicating whether the new value was written and
3065 /// containing the previous value. On success this value is guaranteed to be equal to
3066 /// `current`.
3067 ///
3068 /// `compare_exchange` takes two [`Ordering`] arguments to describe the memory
3069 /// ordering of this operation. `success` describes the required ordering for the
3070 /// read-modify-write operation that takes place if the comparison with `current` succeeds.
3071 /// `failure` describes the required ordering for the load operation that takes place when
3072 /// the comparison fails. Using [`Acquire`] as success ordering makes the store part
3073 /// of this operation [`Relaxed`], and using [`Release`] makes the successful load
3074 /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
3075 ///
3076 /// **Note**: This method is only available on platforms that support atomic operations on
3077 #[doc = concat!("[`", $s_int_type, "`].")]
3078 ///
3079 /// # Examples
3080 ///
3081 #[cfg_attr($cfg_cas, doc = "```")]
3082 #[cfg_attr(not($cfg_cas), doc = "```compile_fail")]
3083 #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
3084 ///
3085 #[doc = concat!("let some_var = ", stringify!($atomic_type), "::new(5);")]
3086 ///
3087 /// assert_eq!(some_var.compare_exchange(5, 10,
3088 /// Ordering::Acquire,
3089 /// Ordering::Relaxed),
3090 /// Ok(5));
3091 /// assert_eq!(some_var.load(Ordering::Relaxed), 10);
3092 ///
3093 /// assert_eq!(some_var.compare_exchange(6, 12,
3094 /// Ordering::SeqCst,
3095 /// Ordering::Acquire),
3096 /// Err(10));
3097 /// assert_eq!(some_var.load(Ordering::Relaxed), 10);
3098 /// ```
3099 ///
3100 /// # Considerations
3101 ///
3102 /// `compare_exchange` is a [compare-and-swap operation] and thus exhibits the usual downsides
3103 /// of CAS operations. In particular, a load of the value followed by a successful
3104 /// `compare_exchange` with the previous load *does not ensure* that other threads have not
3105 /// changed the value in the interim! This is usually important when the *equality* check in
3106 /// the `compare_exchange` is being used to check the *identity* of a value, but equality
3107 /// does not necessarily imply identity. This is a particularly common case for pointers, as
3108 /// a pointer holding the same address does not imply that the same object exists at that
3109 /// address! In this case, `compare_exchange` can lead to the [ABA problem].
3110 ///
3111 /// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
3112 /// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
3113 #[inline]
3114 #[$stable_cxchg]
3115 #[cfg(any($cfg_cas, doc))]
3116 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
3117 #[rustc_should_not_be_called_on_const_items]
3118 #[ferrocene::prevalidated]
3119 pub fn compare_exchange(&self,
3120 current: $int_type,
3121 new: $int_type,
3122 success: Ordering,
3123 failure: Ordering) -> Result<$int_type, $int_type> {
3124 // SAFETY: data races are prevented by atomic intrinsics.
3125 unsafe { atomic_compare_exchange(self.as_ptr(), current, new, success, failure) }
3126 }
3127
3128 /// Stores a value into the atomic integer if the current value is the same as
3129 /// the `current` value.
3130 ///
3131 #[doc = concat!("Unlike [`", stringify!($atomic_type), "::compare_exchange`],")]
3132 /// this function is allowed to spuriously fail even
3133 /// when the comparison succeeds, which can result in more efficient code on some
3134 /// platforms. The return value is a result indicating whether the new value was
3135 /// written and containing the previous value.
3136 ///
3137 /// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory
3138 /// ordering of this operation. `success` describes the required ordering for the
3139 /// read-modify-write operation that takes place if the comparison with `current` succeeds.
3140 /// `failure` describes the required ordering for the load operation that takes place when
3141 /// the comparison fails. Using [`Acquire`] as success ordering makes the store part
3142 /// of this operation [`Relaxed`], and using [`Release`] makes the successful load
3143 /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
3144 ///
3145 /// **Note**: This method is only available on platforms that support atomic operations on
3146 #[doc = concat!("[`", $s_int_type, "`].")]
3147 ///
3148 /// # Examples
3149 ///
3150 #[cfg_attr($cfg_cas, doc = "```")]
3151 #[cfg_attr(not($cfg_cas), doc = "```compile_fail")]
3152 #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
3153 ///
3154 #[doc = concat!("let val = ", stringify!($atomic_type), "::new(4);")]
3155 ///
3156 /// let mut old = val.load(Ordering::Relaxed);
3157 /// loop {
3158 /// let new = old * 2;
3159 /// match val.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) {
3160 /// Ok(_) => break,
3161 /// Err(x) => old = x,
3162 /// }
3163 /// }
3164 /// ```
3165 ///
3166 /// # Considerations
3167 ///
3168 /// `compare_exchange` is a [compare-and-swap operation] and thus exhibits the usual downsides
3169 /// of CAS operations. In particular, a load of the value followed by a successful
3170 /// `compare_exchange` with the previous load *does not ensure* that other threads have not
3171 /// changed the value in the interim. This is usually important when the *equality* check in
3172 /// the `compare_exchange` is being used to check the *identity* of a value, but equality
3173 /// does not necessarily imply identity. This is a particularly common case for pointers, as
3174 /// a pointer holding the same address does not imply that the same object exists at that
3175 /// address! In this case, `compare_exchange` can lead to the [ABA problem].
3176 ///
3177 /// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
3178 /// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
3179 #[inline]
3180 #[$stable_cxchg]
3181 #[cfg(any($cfg_cas, doc))]
3182 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
3183 #[rustc_should_not_be_called_on_const_items]
3184 #[ferrocene::prevalidated]
3185 pub fn compare_exchange_weak(&self,
3186 current: $int_type,
3187 new: $int_type,
3188 success: Ordering,
3189 failure: Ordering) -> Result<$int_type, $int_type> {
3190 // SAFETY: data races are prevented by atomic intrinsics.
3191 unsafe {
3192 atomic_compare_exchange_weak(self.as_ptr(), current, new, success, failure)
3193 }
3194 }
3195
3196 /// Adds to the current value, returning the previous value.
3197 ///
3198 /// This operation wraps around on overflow.
3199 ///
3200 /// `fetch_add` takes an [`Ordering`] argument which describes the memory ordering
3201 /// of this operation. All ordering modes are possible. Note that using
3202 /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
3203 /// using [`Release`] makes the load part [`Relaxed`].
3204 ///
3205 /// **Note**: This method is only available on platforms that support atomic operations on
3206 #[doc = concat!("[`", $s_int_type, "`].")]
3207 ///
3208 /// # Examples
3209 ///
3210 #[cfg_attr($cfg_cas, doc = "```")]
3211 #[cfg_attr(not($cfg_cas), doc = "```compile_fail")]
3212 #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
3213 ///
3214 #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(0);")]
3215 /// assert_eq!(foo.fetch_add(10, Ordering::SeqCst), 0);
3216 /// assert_eq!(foo.load(Ordering::SeqCst), 10);
3217 /// ```
3218 #[inline]
3219 #[$stable]
3220 #[cfg(any($cfg_cas, doc))]
3221 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
3222 #[rustc_should_not_be_called_on_const_items]
3223 #[ferrocene::prevalidated]
3224 pub fn fetch_add(&self, val: $int_type, order: Ordering) -> $int_type {
3225 // SAFETY: data races are prevented by atomic intrinsics.
3226 unsafe { atomic_add(self.as_ptr(), val, order) }
3227 }
3228
3229 /// Subtracts from the current value, returning the previous value.
3230 ///
3231 /// This operation wraps around on overflow.
3232 ///
3233 /// `fetch_sub` takes an [`Ordering`] argument which describes the memory ordering
3234 /// of this operation. All ordering modes are possible. Note that using
3235 /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
3236 /// using [`Release`] makes the load part [`Relaxed`].
3237 ///
3238 /// **Note**: This method is only available on platforms that support atomic operations on
3239 #[doc = concat!("[`", $s_int_type, "`].")]
3240 ///
3241 /// # Examples
3242 ///
3243 #[cfg_attr($cfg_cas, doc = "```")]
3244 #[cfg_attr(not($cfg_cas), doc = "```compile_fail")]
3245 #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
3246 ///
3247 #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(20);")]
3248 /// assert_eq!(foo.fetch_sub(10, Ordering::SeqCst), 20);
3249 /// assert_eq!(foo.load(Ordering::SeqCst), 10);
3250 /// ```
3251 #[inline]
3252 #[$stable]
3253 #[cfg(any($cfg_cas, doc))]
3254 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
3255 #[rustc_should_not_be_called_on_const_items]
3256 #[ferrocene::prevalidated]
3257 pub fn fetch_sub(&self, val: $int_type, order: Ordering) -> $int_type {
3258 // SAFETY: data races are prevented by atomic intrinsics.
3259 unsafe { atomic_sub(self.as_ptr(), val, order) }
3260 }
3261
3262 /// Bitwise "and" with the current value.
3263 ///
3264 /// Performs a bitwise "and" operation on the current value and the argument `val`, and
3265 /// sets the new value to the result.
3266 ///
3267 /// Returns the previous value.
3268 ///
3269 /// `fetch_and` takes an [`Ordering`] argument which describes the memory ordering
3270 /// of this operation. All ordering modes are possible. Note that using
3271 /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
3272 /// using [`Release`] makes the load part [`Relaxed`].
3273 ///
3274 /// **Note**: This method is only available on platforms that support atomic operations on
3275 #[doc = concat!("[`", $s_int_type, "`].")]
3276 ///
3277 /// # Examples
3278 ///
3279 #[cfg_attr($cfg_cas, doc = "```")]
3280 #[cfg_attr(not($cfg_cas), doc = "```compile_fail")]
3281 #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
3282 ///
3283 #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(0b101101);")]
3284 /// assert_eq!(foo.fetch_and(0b110011, Ordering::SeqCst), 0b101101);
3285 /// assert_eq!(foo.load(Ordering::SeqCst), 0b100001);
3286 /// ```
3287 #[inline]
3288 #[$stable]
3289 #[cfg(any($cfg_cas, doc))]
3290 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
3291 #[rustc_should_not_be_called_on_const_items]
3292 #[ferrocene::prevalidated]
3293 pub fn fetch_and(&self, val: $int_type, order: Ordering) -> $int_type {
3294 // SAFETY: data races are prevented by atomic intrinsics.
3295 unsafe { atomic_and(self.as_ptr(), val, order) }
3296 }
3297
3298 /// Bitwise "nand" with the current value.
3299 ///
3300 /// Performs a bitwise "nand" operation on the current value and the argument `val`, and
3301 /// sets the new value to the result.
3302 ///
3303 /// Returns the previous value.
3304 ///
3305 /// `fetch_nand` takes an [`Ordering`] argument which describes the memory ordering
3306 /// of this operation. All ordering modes are possible. Note that using
3307 /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
3308 /// using [`Release`] makes the load part [`Relaxed`].
3309 ///
3310 /// **Note**: This method is only available on platforms that support atomic operations on
3311 #[doc = concat!("[`", $s_int_type, "`].")]
3312 ///
3313 /// # Examples
3314 ///
3315 #[cfg_attr($cfg_cas, doc = "```")]
3316 #[cfg_attr(not($cfg_cas), doc = "```compile_fail")]
3317 #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
3318 ///
3319 #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(0x13);")]
3320 /// assert_eq!(foo.fetch_nand(0x31, Ordering::SeqCst), 0x13);
3321 /// assert_eq!(foo.load(Ordering::SeqCst), !(0x13 & 0x31));
3322 /// ```
3323 #[inline]
3324 #[$stable_nand]
3325 #[cfg(any($cfg_cas, doc))]
3326 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
3327 #[rustc_should_not_be_called_on_const_items]
3328 #[ferrocene::prevalidated]
3329 pub fn fetch_nand(&self, val: $int_type, order: Ordering) -> $int_type {
3330 // SAFETY: data races are prevented by atomic intrinsics.
3331 unsafe { atomic_nand(self.as_ptr(), val, order) }
3332 }
3333
3334 /// Bitwise "or" with the current value.
3335 ///
3336 /// Performs a bitwise "or" operation on the current value and the argument `val`, and
3337 /// sets the new value to the result.
3338 ///
3339 /// Returns the previous value.
3340 ///
3341 /// `fetch_or` takes an [`Ordering`] argument which describes the memory ordering
3342 /// of this operation. All ordering modes are possible. Note that using
3343 /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
3344 /// using [`Release`] makes the load part [`Relaxed`].
3345 ///
3346 /// **Note**: This method is only available on platforms that support atomic operations on
3347 #[doc = concat!("[`", $s_int_type, "`].")]
3348 ///
3349 /// # Examples
3350 ///
3351 #[cfg_attr($cfg_cas, doc = "```")]
3352 #[cfg_attr(not($cfg_cas), doc = "```compile_fail")]
3353 #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
3354 ///
3355 #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(0b101101);")]
3356 /// assert_eq!(foo.fetch_or(0b110011, Ordering::SeqCst), 0b101101);
3357 /// assert_eq!(foo.load(Ordering::SeqCst), 0b111111);
3358 /// ```
3359 #[inline]
3360 #[$stable]
3361 #[cfg(any($cfg_cas, doc))]
3362 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
3363 #[rustc_should_not_be_called_on_const_items]
3364 #[ferrocene::prevalidated]
3365 pub fn fetch_or(&self, val: $int_type, order: Ordering) -> $int_type {
3366 // SAFETY: data races are prevented by atomic intrinsics.
3367 unsafe { atomic_or(self.as_ptr(), val, order) }
3368 }
3369
3370 /// Bitwise "xor" with the current value.
3371 ///
3372 /// Performs a bitwise "xor" operation on the current value and the argument `val`, and
3373 /// sets the new value to the result.
3374 ///
3375 /// Returns the previous value.
3376 ///
3377 /// `fetch_xor` takes an [`Ordering`] argument which describes the memory ordering
3378 /// of this operation. All ordering modes are possible. Note that using
3379 /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
3380 /// using [`Release`] makes the load part [`Relaxed`].
3381 ///
3382 /// **Note**: This method is only available on platforms that support atomic operations on
3383 #[doc = concat!("[`", $s_int_type, "`].")]
3384 ///
3385 /// # Examples
3386 ///
3387 #[cfg_attr($cfg_cas, doc = "```")]
3388 #[cfg_attr(not($cfg_cas), doc = "```compile_fail")]
3389 #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
3390 ///
3391 #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(0b101101);")]
3392 /// assert_eq!(foo.fetch_xor(0b110011, Ordering::SeqCst), 0b101101);
3393 /// assert_eq!(foo.load(Ordering::SeqCst), 0b011110);
3394 /// ```
3395 #[inline]
3396 #[$stable]
3397 #[cfg(any($cfg_cas, doc))]
3398 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
3399 #[rustc_should_not_be_called_on_const_items]
3400 #[ferrocene::prevalidated]
3401 pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
3402 // SAFETY: data races are prevented by atomic intrinsics.
3403 unsafe { atomic_xor(self.as_ptr(), val, order) }
3404 }
3405
3406 /// An alias for
3407 #[doc = concat!("[`", stringify!($atomic_type), "::try_update`]")]
3408 /// .
3409 #[inline]
3410 #[stable(feature = "no_more_cas", since = "1.45.0")]
3411 #[cfg(any($cfg_cas, doc))]
3412 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
3413 #[rustc_should_not_be_called_on_const_items]
3414 #[deprecated(
3415 since = "1.99.0",
3416 note = "renamed to `try_update` for consistency",
3417 suggestion = "try_update"
3418 )]
3419 #[ferrocene::prevalidated]
3420 pub fn fetch_update<F>(&self,
3421 set_order: Ordering,
3422 fetch_order: Ordering,
3423 f: F) -> Result<$int_type, $int_type>
3424 where F: FnMut($int_type) -> Option<$int_type> {
3425 self.try_update(set_order, fetch_order, f)
3426 }
3427
3428 /// Fetches the value, and applies a function to it that returns an optional
3429 /// new value. Returns a `Result` of `Ok(previous_value)` if the function returned `Some(_)`, else
3430 /// `Err(previous_value)`.
3431 ///
3432 #[doc = concat!("See also: [`update`](`", stringify!($atomic_type), "::update`).")]
3433 ///
3434 /// Note: This may call the function multiple times if the value has been changed from other threads in
3435 /// the meantime, as long as the function returns `Some(_)`, but the function will have been applied
3436 /// only once to the stored value.
3437 ///
3438 /// `try_update` takes two [`Ordering`] arguments to describe the memory ordering of this operation.
3439 /// The first describes the required ordering for when the operation finally succeeds while the second
3440 /// describes the required ordering for loads. These correspond to the success and failure orderings of
3441 #[doc = concat!("[`", stringify!($atomic_type), "::compare_exchange`]")]
3442 /// respectively.
3443 ///
3444 /// Using [`Acquire`] as success ordering makes the store part
3445 /// of this operation [`Relaxed`], and using [`Release`] makes the final successful load
3446 /// [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
3447 ///
3448 /// **Note**: This method is only available on platforms that support atomic operations on
3449 #[doc = concat!("[`", $s_int_type, "`].")]
3450 ///
3451 /// # Considerations
3452 ///
3453 /// This method is not magic; it is not provided by the hardware, and does not act like a
3454 /// critical section or mutex.
3455 ///
3456 /// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
3457 /// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem]
3458 /// if this atomic integer is an index or more generally if knowledge of only the *bitwise value*
3459 /// of the atomic is not in and of itself sufficient to ensure any required preconditions.
3460 ///
3461 /// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
3462 /// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
3463 ///
3464 /// # Examples
3465 ///
3466 #[cfg_attr($cfg_cas, doc = "```rust")]
3467 #[cfg_attr(not($cfg_cas), doc = "```rust,compile_fail")]
3468 #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
3469 ///
3470 #[doc = concat!("let x = ", stringify!($atomic_type), "::new(7);")]
3471 /// assert_eq!(x.try_update(Ordering::SeqCst, Ordering::SeqCst, |_| None), Err(7));
3472 /// assert_eq!(x.try_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(x + 1)), Ok(7));
3473 /// assert_eq!(x.try_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(x + 1)), Ok(8));
3474 /// assert_eq!(x.load(Ordering::SeqCst), 9);
3475 /// ```
3476 #[inline]
3477 #[stable(feature = "atomic_try_update", since = "1.95.0")]
3478 #[cfg(any($cfg_cas, doc))]
3479 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
3480 #[rustc_should_not_be_called_on_const_items]
3481 #[ferrocene::prevalidated]
3482 pub fn try_update(
3483 &self,
3484 set_order: Ordering,
3485 fetch_order: Ordering,
3486 mut f: impl FnMut($int_type) -> Option<$int_type>,
3487 ) -> Result<$int_type, $int_type> {
3488 let mut prev = self.load(fetch_order);
3489 while let Some(next) = f(prev) {
3490 match self.compare_exchange_weak(prev, next, set_order, fetch_order) {
3491 x @ Ok(_) => return x,
3492 Err(next_prev) => prev = next_prev
3493 }
3494 }
3495 Err(prev)
3496 }
3497
3498 /// Fetches the value, applies a function to it that it return a new value.
3499 /// The new value is stored and the old value is returned.
3500 ///
3501 #[doc = concat!("See also: [`try_update`](`", stringify!($atomic_type), "::try_update`).")]
3502 ///
3503 /// Note: This may call the function multiple times if the value has been changed from other threads in
3504 /// the meantime, but the function will have been applied only once to the stored value.
3505 ///
3506 /// `update` takes two [`Ordering`] arguments to describe the memory ordering of this operation.
3507 /// The first describes the required ordering for when the operation finally succeeds while the second
3508 /// describes the required ordering for loads. These correspond to the success and failure orderings of
3509 #[doc = concat!("[`", stringify!($atomic_type), "::compare_exchange`]")]
3510 /// respectively.
3511 ///
3512 /// Using [`Acquire`] as success ordering makes the store part
3513 /// of this operation [`Relaxed`], and using [`Release`] makes the final successful load
3514 /// [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
3515 ///
3516 /// **Note**: This method is only available on platforms that support atomic operations on
3517 #[doc = concat!("[`", $s_int_type, "`].")]
3518 ///
3519 /// # Considerations
3520 ///
3521 /// [CAS operation]: https://en.wikipedia.org/wiki/Compare-and-swap
3522 /// This method is not magic; it is not provided by the hardware, and does not act like a
3523 /// critical section or mutex.
3524 ///
3525 /// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
3526 /// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem]
3527 /// if this atomic integer is an index or more generally if knowledge of only the *bitwise value*
3528 /// of the atomic is not in and of itself sufficient to ensure any required preconditions.
3529 ///
3530 /// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
3531 /// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
3532 ///
3533 /// # Examples
3534 ///
3535 #[cfg_attr($cfg_cas, doc = "```rust")]
3536 #[cfg_attr(not($cfg_cas), doc = "```rust,compile_fail")]
3537 #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
3538 ///
3539 #[doc = concat!("let x = ", stringify!($atomic_type), "::new(7);")]
3540 /// assert_eq!(x.update(Ordering::SeqCst, Ordering::SeqCst, |x| x + 1), 7);
3541 /// assert_eq!(x.update(Ordering::SeqCst, Ordering::SeqCst, |x| x + 1), 8);
3542 /// assert_eq!(x.load(Ordering::SeqCst), 9);
3543 /// ```
3544 #[inline]
3545 #[stable(feature = "atomic_try_update", since = "1.95.0")]
3546 #[cfg(any($cfg_cas, doc))]
3547 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
3548 #[rustc_should_not_be_called_on_const_items]
3549 #[ferrocene::prevalidated]
3550 pub fn update(
3551 &self,
3552 set_order: Ordering,
3553 fetch_order: Ordering,
3554 mut f: impl FnMut($int_type) -> $int_type,
3555 ) -> $int_type {
3556 let mut prev = self.load(fetch_order);
3557 loop {
3558 match self.compare_exchange_weak(prev, f(prev), set_order, fetch_order) {
3559 Ok(x) => break x,
3560 Err(next_prev) => prev = next_prev,
3561 }
3562 }
3563 }
3564
3565 /// Maximum with the current value.
3566 ///
3567 /// Finds the maximum of the current value and the argument `val`, and
3568 /// sets the new value to the result.
3569 ///
3570 /// Returns the previous value.
3571 ///
3572 /// `fetch_max` takes an [`Ordering`] argument which describes the memory ordering
3573 /// of this operation. All ordering modes are possible. Note that using
3574 /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
3575 /// using [`Release`] makes the load part [`Relaxed`].
3576 ///
3577 /// **Note**: This method is only available on platforms that support atomic operations on
3578 #[doc = concat!("[`", $s_int_type, "`].")]
3579 ///
3580 /// # Examples
3581 ///
3582 #[cfg_attr($cfg_cas, doc = "```")]
3583 #[cfg_attr(not($cfg_cas), doc = "```compile_fail")]
3584 #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
3585 ///
3586 #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(23);")]
3587 /// assert_eq!(foo.fetch_max(42, Ordering::SeqCst), 23);
3588 /// assert_eq!(foo.load(Ordering::SeqCst), 42);
3589 /// ```
3590 ///
3591 /// If you want to obtain the maximum value in one step, you can use the following:
3592 ///
3593 #[cfg_attr($cfg_cas, doc = "```")]
3594 #[cfg_attr(not($cfg_cas), doc = "```compile_fail")]
3595 #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
3596 ///
3597 #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(23);")]
3598 /// let bar = 42;
3599 /// let max_foo = foo.fetch_max(bar, Ordering::SeqCst).max(bar);
3600 /// assert!(max_foo == 42);
3601 /// ```
3602 #[inline]
3603 #[stable(feature = "atomic_min_max", since = "1.45.0")]
3604 #[cfg(any($cfg_cas, doc))]
3605 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
3606 #[rustc_should_not_be_called_on_const_items]
3607 #[ferrocene::prevalidated]
3608 pub fn fetch_max(&self, val: $int_type, order: Ordering) -> $int_type {
3609 // SAFETY: data races are prevented by atomic intrinsics.
3610 unsafe { $max_fn(self.as_ptr(), val, order) }
3611 }
3612
3613 /// Minimum with the current value.
3614 ///
3615 /// Finds the minimum of the current value and the argument `val`, and
3616 /// sets the new value to the result.
3617 ///
3618 /// Returns the previous value.
3619 ///
3620 /// `fetch_min` takes an [`Ordering`] argument which describes the memory ordering
3621 /// of this operation. All ordering modes are possible. Note that using
3622 /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
3623 /// using [`Release`] makes the load part [`Relaxed`].
3624 ///
3625 /// **Note**: This method is only available on platforms that support atomic operations on
3626 #[doc = concat!("[`", $s_int_type, "`].")]
3627 ///
3628 /// # Examples
3629 ///
3630 #[cfg_attr($cfg_cas, doc = "```")]
3631 #[cfg_attr(not($cfg_cas), doc = "```compile_fail")]
3632 #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
3633 ///
3634 #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(23);")]
3635 /// assert_eq!(foo.fetch_min(42, Ordering::Relaxed), 23);
3636 /// assert_eq!(foo.load(Ordering::Relaxed), 23);
3637 /// assert_eq!(foo.fetch_min(22, Ordering::Relaxed), 23);
3638 /// assert_eq!(foo.load(Ordering::Relaxed), 22);
3639 /// ```
3640 ///
3641 /// If you want to obtain the minimum value in one step, you can use the following:
3642 ///
3643 #[cfg_attr($cfg_cas, doc = "```")]
3644 #[cfg_attr(not($cfg_cas), doc = "```compile_fail")]
3645 #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
3646 ///
3647 #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(23);")]
3648 /// let bar = 12;
3649 /// let min_foo = foo.fetch_min(bar, Ordering::SeqCst).min(bar);
3650 /// assert_eq!(min_foo, 12);
3651 /// ```
3652 #[inline]
3653 #[stable(feature = "atomic_min_max", since = "1.45.0")]
3654 #[cfg(any($cfg_cas, doc))]
3655 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
3656 #[rustc_should_not_be_called_on_const_items]
3657 #[ferrocene::prevalidated]
3658 pub fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type {
3659 // SAFETY: data races are prevented by atomic intrinsics.
3660 unsafe { $min_fn(self.as_ptr(), val, order) }
3661 }
3662
3663 /// Returns a mutable pointer to the underlying integer.
3664 ///
3665 /// Doing non-atomic reads and writes on the resulting integer can be a data race.
3666 /// This method is mostly useful for FFI, where the function signature may use
3667 #[doc = concat!("`*mut ", stringify!($int_type), "` instead of `&", stringify!($atomic_type), "`.")]
3668 ///
3669 /// Returning an `*mut` pointer from a shared reference to this atomic is safe because the
3670 /// atomic types work with interior mutability. All modifications of an atomic change the value
3671 /// through a shared reference, and can do so safely as long as they use atomic operations. Any
3672 /// use of the returned raw pointer requires an `unsafe` block and still has to uphold the
3673 /// requirements of the [memory model].
3674 ///
3675 /// # Examples
3676 ///
3677 /// ```ignore (extern-declaration)
3678 /// # fn main() {
3679 #[doc = concat!($extra_feature, "use std::sync::atomic::", stringify!($atomic_type), ";")]
3680 ///
3681 /// extern "C" {
3682 #[doc = concat!(" fn my_atomic_op(arg: *mut ", stringify!($int_type), ");")]
3683 /// }
3684 ///
3685 #[doc = concat!("let atomic = ", stringify!($atomic_type), "::new(1);")]
3686 ///
3687 /// // SAFETY: Safe as long as `my_atomic_op` is atomic.
3688 /// unsafe {
3689 /// my_atomic_op(atomic.as_ptr());
3690 /// }
3691 /// # }
3692 /// ```
3693 ///
3694 /// [memory model]: self#memory-model-for-atomic-accesses
3695 #[inline]
3696 #[stable(feature = "atomic_as_ptr", since = "1.70.0")]
3697 #[rustc_const_stable(feature = "atomic_as_ptr", since = "1.70.0")]
3698 #[rustc_never_returns_null_ptr]
3699 #[ferrocene::prevalidated]
3700 pub const fn as_ptr(&self) -> *mut $int_type {
3701 self.v.get().cast()
3702 }
3703 }
3704 }
3705}
3706
3707#[cfg(target_has_atomic_load_store = "8")]
3708atomic_int! {
3709 target_has_atomic_load_store = "8",
3710 target_has_atomic = "8",
3711 target_has_atomic_primitive_alignment = "8",
3712 stable(feature = "integer_atomics_stable", since = "1.34.0"),
3713 stable(feature = "integer_atomics_stable", since = "1.34.0"),
3714 stable(feature = "integer_atomics_stable", since = "1.34.0"),
3715 stable(feature = "integer_atomics_stable", since = "1.34.0"),
3716 stable(feature = "integer_atomics_stable", since = "1.34.0"),
3717 stable(feature = "integer_atomics_stable", since = "1.34.0"),
3718 rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
3719 rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"),
3720 "i8",
3721 "",
3722 atomic_min, atomic_max,
3723 1,
3724 i8 AtomicI8
3725}
3726#[cfg(target_has_atomic_load_store = "8")]
3727atomic_int! {
3728 target_has_atomic_load_store = "8",
3729 target_has_atomic = "8",
3730 target_has_atomic_primitive_alignment = "8",
3731 stable(feature = "integer_atomics_stable", since = "1.34.0"),
3732 stable(feature = "integer_atomics_stable", since = "1.34.0"),
3733 stable(feature = "integer_atomics_stable", since = "1.34.0"),
3734 stable(feature = "integer_atomics_stable", since = "1.34.0"),
3735 stable(feature = "integer_atomics_stable", since = "1.34.0"),
3736 stable(feature = "integer_atomics_stable", since = "1.34.0"),
3737 rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
3738 rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"),
3739 "u8",
3740 "",
3741 atomic_umin, atomic_umax,
3742 1,
3743 u8 AtomicU8
3744}
3745#[cfg(target_has_atomic_load_store = "16")]
3746atomic_int! {
3747 target_has_atomic_load_store = "16",
3748 target_has_atomic = "16",
3749 target_has_atomic_primitive_alignment = "16",
3750 stable(feature = "integer_atomics_stable", since = "1.34.0"),
3751 stable(feature = "integer_atomics_stable", since = "1.34.0"),
3752 stable(feature = "integer_atomics_stable", since = "1.34.0"),
3753 stable(feature = "integer_atomics_stable", since = "1.34.0"),
3754 stable(feature = "integer_atomics_stable", since = "1.34.0"),
3755 stable(feature = "integer_atomics_stable", since = "1.34.0"),
3756 rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
3757 rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"),
3758 "i16",
3759 "",
3760 atomic_min, atomic_max,
3761 2,
3762 i16 AtomicI16
3763}
3764#[cfg(target_has_atomic_load_store = "16")]
3765atomic_int! {
3766 target_has_atomic_load_store = "16",
3767 target_has_atomic = "16",
3768 target_has_atomic_primitive_alignment = "16",
3769 stable(feature = "integer_atomics_stable", since = "1.34.0"),
3770 stable(feature = "integer_atomics_stable", since = "1.34.0"),
3771 stable(feature = "integer_atomics_stable", since = "1.34.0"),
3772 stable(feature = "integer_atomics_stable", since = "1.34.0"),
3773 stable(feature = "integer_atomics_stable", since = "1.34.0"),
3774 stable(feature = "integer_atomics_stable", since = "1.34.0"),
3775 rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
3776 rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"),
3777 "u16",
3778 "",
3779 atomic_umin, atomic_umax,
3780 2,
3781 u16 AtomicU16
3782}
3783#[cfg(target_has_atomic_load_store = "32")]
3784atomic_int! {
3785 target_has_atomic_load_store = "32",
3786 target_has_atomic = "32",
3787 target_has_atomic_primitive_alignment = "32",
3788 stable(feature = "integer_atomics_stable", since = "1.34.0"),
3789 stable(feature = "integer_atomics_stable", since = "1.34.0"),
3790 stable(feature = "integer_atomics_stable", since = "1.34.0"),
3791 stable(feature = "integer_atomics_stable", since = "1.34.0"),
3792 stable(feature = "integer_atomics_stable", since = "1.34.0"),
3793 stable(feature = "integer_atomics_stable", since = "1.34.0"),
3794 rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
3795 rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"),
3796 "i32",
3797 "",
3798 atomic_min, atomic_max,
3799 4,
3800 i32 AtomicI32
3801}
3802#[cfg(target_has_atomic_load_store = "32")]
3803atomic_int! {
3804 target_has_atomic_load_store = "32",
3805 target_has_atomic = "32",
3806 target_has_atomic_primitive_alignment = "32",
3807 stable(feature = "integer_atomics_stable", since = "1.34.0"),
3808 stable(feature = "integer_atomics_stable", since = "1.34.0"),
3809 stable(feature = "integer_atomics_stable", since = "1.34.0"),
3810 stable(feature = "integer_atomics_stable", since = "1.34.0"),
3811 stable(feature = "integer_atomics_stable", since = "1.34.0"),
3812 stable(feature = "integer_atomics_stable", since = "1.34.0"),
3813 rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
3814 rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"),
3815 "u32",
3816 "",
3817 atomic_umin, atomic_umax,
3818 4,
3819 u32 AtomicU32
3820}
3821#[cfg(target_has_atomic_load_store = "64")]
3822atomic_int! {
3823 target_has_atomic_load_store = "64",
3824 target_has_atomic = "64",
3825 target_has_atomic_primitive_alignment = "64",
3826 stable(feature = "integer_atomics_stable", since = "1.34.0"),
3827 stable(feature = "integer_atomics_stable", since = "1.34.0"),
3828 stable(feature = "integer_atomics_stable", since = "1.34.0"),
3829 stable(feature = "integer_atomics_stable", since = "1.34.0"),
3830 stable(feature = "integer_atomics_stable", since = "1.34.0"),
3831 stable(feature = "integer_atomics_stable", since = "1.34.0"),
3832 rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
3833 rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"),
3834 "i64",
3835 "",
3836 atomic_min, atomic_max,
3837 8,
3838 i64 AtomicI64
3839}
3840#[cfg(target_has_atomic_load_store = "64")]
3841atomic_int! {
3842 target_has_atomic_load_store = "64",
3843 target_has_atomic = "64",
3844 target_has_atomic_primitive_alignment = "64",
3845 stable(feature = "integer_atomics_stable", since = "1.34.0"),
3846 stable(feature = "integer_atomics_stable", since = "1.34.0"),
3847 stable(feature = "integer_atomics_stable", since = "1.34.0"),
3848 stable(feature = "integer_atomics_stable", since = "1.34.0"),
3849 stable(feature = "integer_atomics_stable", since = "1.34.0"),
3850 stable(feature = "integer_atomics_stable", since = "1.34.0"),
3851 rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
3852 rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"),
3853 "u64",
3854 "",
3855 atomic_umin, atomic_umax,
3856 8,
3857 u64 AtomicU64
3858}
3859#[cfg(any(target_has_atomic_load_store = "128", doc))]
3860atomic_int! {
3861 target_has_atomic_load_store = "128",
3862 target_has_atomic = "128",
3863 target_has_atomic_primitive_alignment = "128",
3864 unstable(feature = "integer_atomics", issue = "99069"),
3865 unstable(feature = "integer_atomics", issue = "99069"),
3866 unstable(feature = "integer_atomics", issue = "99069"),
3867 unstable(feature = "integer_atomics", issue = "99069"),
3868 unstable(feature = "integer_atomics", issue = "99069"),
3869 unstable(feature = "integer_atomics", issue = "99069"),
3870 rustc_const_unstable(feature = "integer_atomics", issue = "99069"),
3871 rustc_const_unstable(feature = "integer_atomics", issue = "99069"),
3872 "i128",
3873 "#![feature(integer_atomics)]\n\n",
3874 atomic_min, atomic_max,
3875 16,
3876 i128 AtomicI128
3877}
3878#[cfg(any(target_has_atomic_load_store = "128", doc))]
3879atomic_int! {
3880 target_has_atomic_load_store = "128",
3881 target_has_atomic = "128",
3882 target_has_atomic_primitive_alignment = "128",
3883 unstable(feature = "integer_atomics", issue = "99069"),
3884 unstable(feature = "integer_atomics", issue = "99069"),
3885 unstable(feature = "integer_atomics", issue = "99069"),
3886 unstable(feature = "integer_atomics", issue = "99069"),
3887 unstable(feature = "integer_atomics", issue = "99069"),
3888 unstable(feature = "integer_atomics", issue = "99069"),
3889 rustc_const_unstable(feature = "integer_atomics", issue = "99069"),
3890 rustc_const_unstable(feature = "integer_atomics", issue = "99069"),
3891 "u128",
3892 "#![feature(integer_atomics)]\n\n",
3893 atomic_umin, atomic_umax,
3894 16,
3895 u128 AtomicU128
3896}
3897
3898#[cfg(target_has_atomic_load_store = "ptr")]
3899macro_rules! atomic_int_ptr_sized {
3900 ( $($target_pointer_width:literal $align:literal)* ) => { $(
3901 #[cfg(target_pointer_width = $target_pointer_width)]
3902 atomic_int! {
3903 target_has_atomic_load_store = "ptr",
3904 target_has_atomic = "ptr",
3905 target_has_atomic_primitive_alignment = "ptr",
3906 stable(feature = "rust1", since = "1.0.0"),
3907 stable(feature = "extended_compare_and_swap", since = "1.10.0"),
3908 stable(feature = "atomic_debug", since = "1.3.0"),
3909 stable(feature = "atomic_access", since = "1.15.0"),
3910 stable(feature = "atomic_from", since = "1.23.0"),
3911 stable(feature = "atomic_nand", since = "1.27.0"),
3912 rustc_const_stable(feature = "const_ptr_sized_atomics", since = "1.24.0"),
3913 rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"),
3914 "isize",
3915 "",
3916 atomic_min, atomic_max,
3917 $align,
3918 isize AtomicIsize
3919 }
3920 #[cfg(target_pointer_width = $target_pointer_width)]
3921 atomic_int! {
3922 target_has_atomic_load_store = "ptr",
3923 target_has_atomic = "ptr",
3924 target_has_atomic_primitive_alignment = "ptr",
3925 stable(feature = "rust1", since = "1.0.0"),
3926 stable(feature = "extended_compare_and_swap", since = "1.10.0"),
3927 stable(feature = "atomic_debug", since = "1.3.0"),
3928 stable(feature = "atomic_access", since = "1.15.0"),
3929 stable(feature = "atomic_from", since = "1.23.0"),
3930 stable(feature = "atomic_nand", since = "1.27.0"),
3931 rustc_const_stable(feature = "const_ptr_sized_atomics", since = "1.24.0"),
3932 rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"),
3933 "usize",
3934 "",
3935 atomic_umin, atomic_umax,
3936 $align,
3937 usize AtomicUsize
3938 }
3939
3940 /// An [`AtomicIsize`] initialized to `0`.
3941 #[cfg(target_pointer_width = $target_pointer_width)]
3942 #[stable(feature = "rust1", since = "1.0.0")]
3943 #[deprecated(
3944 since = "1.34.0",
3945 note = "the `new` function is now preferred",
3946 suggestion = "AtomicIsize::new(0)",
3947 )]
3948 pub const ATOMIC_ISIZE_INIT: AtomicIsize = AtomicIsize::new(0);
3949
3950 /// An [`AtomicUsize`] initialized to `0`.
3951 #[cfg(target_pointer_width = $target_pointer_width)]
3952 #[stable(feature = "rust1", since = "1.0.0")]
3953 #[deprecated(
3954 since = "1.34.0",
3955 note = "the `new` function is now preferred",
3956 suggestion = "AtomicUsize::new(0)",
3957 )]
3958 pub const ATOMIC_USIZE_INIT: AtomicUsize = AtomicUsize::new(0);
3959 )* };
3960}
3961
3962#[cfg(target_has_atomic_load_store = "ptr")]
3963atomic_int_ptr_sized! {
3964 "16" 2
3965 "32" 4
3966 "64" 8
3967}
3968
3969#[inline]
3970#[cfg(target_has_atomic)]
3971#[ferrocene::prevalidated]
3972fn strongest_failure_ordering(order: Ordering) -> Ordering {
3973 match order {
3974 Release => Relaxed,
3975 Relaxed => Relaxed,
3976 SeqCst => SeqCst,
3977 Acquire => Acquire,
3978 AcqRel => Acquire,
3979 }
3980}
3981
3982#[inline]
3983#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
3984#[ferrocene::prevalidated]
3985unsafe fn atomic_store<T: Copy>(dst: *mut T, val: T, order: Ordering) {
3986 // SAFETY: the caller must uphold the safety contract for `atomic_store`.
3987 unsafe {
3988 match order {
3989 Relaxed => intrinsics::atomic_store::<T, { AO::Relaxed }>(dst, val),
3990 Release => intrinsics::atomic_store::<T, { AO::Release }>(dst, val),
3991 SeqCst => intrinsics::atomic_store::<T, { AO::SeqCst }>(dst, val),
3992 Acquire => panic!("there is no such thing as an acquire store"),
3993 AcqRel => panic!("there is no such thing as an acquire-release store"),
3994 }
3995 }
3996}
3997
3998#[inline]
3999#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
4000#[ferrocene::prevalidated]
4001unsafe fn atomic_load<T: Copy>(dst: *const T, order: Ordering) -> T {
4002 // SAFETY: the caller must uphold the safety contract for `atomic_load`.
4003 unsafe {
4004 match order {
4005 Relaxed => intrinsics::atomic_load::<T, { AO::Relaxed }>(dst),
4006 Acquire => intrinsics::atomic_load::<T, { AO::Acquire }>(dst),
4007 SeqCst => intrinsics::atomic_load::<T, { AO::SeqCst }>(dst),
4008 Release => panic!("there is no such thing as a release load"),
4009 AcqRel => panic!("there is no such thing as an acquire-release load"),
4010 }
4011 }
4012}
4013
4014#[inline]
4015#[cfg(target_has_atomic)]
4016#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
4017#[ferrocene::prevalidated]
4018unsafe fn atomic_swap<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
4019 // SAFETY: the caller must uphold the safety contract for `atomic_swap`.
4020 unsafe {
4021 match order {
4022 Relaxed => intrinsics::atomic_xchg::<T, { AO::Relaxed }>(dst, val),
4023 Acquire => intrinsics::atomic_xchg::<T, { AO::Acquire }>(dst, val),
4024 Release => intrinsics::atomic_xchg::<T, { AO::Release }>(dst, val),
4025 AcqRel => intrinsics::atomic_xchg::<T, { AO::AcqRel }>(dst, val),
4026 SeqCst => intrinsics::atomic_xchg::<T, { AO::SeqCst }>(dst, val),
4027 }
4028 }
4029}
4030
4031/// Returns the previous value (like __sync_fetch_and_add).
4032#[inline]
4033#[cfg(target_has_atomic)]
4034#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
4035#[ferrocene::prevalidated]
4036unsafe fn atomic_add<T: Copy, U: Copy>(dst: *mut T, val: U, order: Ordering) -> T {
4037 // SAFETY: the caller must uphold the safety contract for `atomic_add`.
4038 unsafe {
4039 match order {
4040 Relaxed => intrinsics::atomic_xadd::<T, U, { AO::Relaxed }>(dst, val),
4041 Acquire => intrinsics::atomic_xadd::<T, U, { AO::Acquire }>(dst, val),
4042 Release => intrinsics::atomic_xadd::<T, U, { AO::Release }>(dst, val),
4043 AcqRel => intrinsics::atomic_xadd::<T, U, { AO::AcqRel }>(dst, val),
4044 SeqCst => intrinsics::atomic_xadd::<T, U, { AO::SeqCst }>(dst, val),
4045 }
4046 }
4047}
4048
4049/// Returns the previous value (like __sync_fetch_and_sub).
4050#[inline]
4051#[cfg(target_has_atomic)]
4052#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
4053#[ferrocene::prevalidated]
4054unsafe fn atomic_sub<T: Copy, U: Copy>(dst: *mut T, val: U, order: Ordering) -> T {
4055 // SAFETY: the caller must uphold the safety contract for `atomic_sub`.
4056 unsafe {
4057 match order {
4058 Relaxed => intrinsics::atomic_xsub::<T, U, { AO::Relaxed }>(dst, val),
4059 Acquire => intrinsics::atomic_xsub::<T, U, { AO::Acquire }>(dst, val),
4060 Release => intrinsics::atomic_xsub::<T, U, { AO::Release }>(dst, val),
4061 AcqRel => intrinsics::atomic_xsub::<T, U, { AO::AcqRel }>(dst, val),
4062 SeqCst => intrinsics::atomic_xsub::<T, U, { AO::SeqCst }>(dst, val),
4063 }
4064 }
4065}
4066
4067/// Publicly exposed for stdarch; nobody else should use this.
4068#[inline]
4069#[cfg(target_has_atomic)]
4070#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
4071#[unstable(feature = "core_intrinsics", issue = "none")]
4072#[doc(hidden)]
4073#[ferrocene::prevalidated]
4074pub unsafe fn atomic_compare_exchange<T: Copy>(
4075 dst: *mut T,
4076 old: T,
4077 new: T,
4078 success: Ordering,
4079 failure: Ordering,
4080) -> Result<T, T> {
4081 // SAFETY: the caller must uphold the safety contract for `atomic_compare_exchange`.
4082 let (val, ok) = unsafe {
4083 match (success, failure) {
4084 (Relaxed, Relaxed) => {
4085 intrinsics::atomic_cxchg::<T, { AO::Relaxed }, { AO::Relaxed }>(dst, old, new)
4086 }
4087 (Relaxed, Acquire) => {
4088 intrinsics::atomic_cxchg::<T, { AO::Relaxed }, { AO::Acquire }>(dst, old, new)
4089 }
4090 (Relaxed, SeqCst) => {
4091 intrinsics::atomic_cxchg::<T, { AO::Relaxed }, { AO::SeqCst }>(dst, old, new)
4092 }
4093 (Acquire, Relaxed) => {
4094 intrinsics::atomic_cxchg::<T, { AO::Acquire }, { AO::Relaxed }>(dst, old, new)
4095 }
4096 (Acquire, Acquire) => {
4097 intrinsics::atomic_cxchg::<T, { AO::Acquire }, { AO::Acquire }>(dst, old, new)
4098 }
4099 (Acquire, SeqCst) => {
4100 intrinsics::atomic_cxchg::<T, { AO::Acquire }, { AO::SeqCst }>(dst, old, new)
4101 }
4102 (Release, Relaxed) => {
4103 intrinsics::atomic_cxchg::<T, { AO::Release }, { AO::Relaxed }>(dst, old, new)
4104 }
4105 (Release, Acquire) => {
4106 intrinsics::atomic_cxchg::<T, { AO::Release }, { AO::Acquire }>(dst, old, new)
4107 }
4108 (Release, SeqCst) => {
4109 intrinsics::atomic_cxchg::<T, { AO::Release }, { AO::SeqCst }>(dst, old, new)
4110 }
4111 (AcqRel, Relaxed) => {
4112 intrinsics::atomic_cxchg::<T, { AO::AcqRel }, { AO::Relaxed }>(dst, old, new)
4113 }
4114 (AcqRel, Acquire) => {
4115 intrinsics::atomic_cxchg::<T, { AO::AcqRel }, { AO::Acquire }>(dst, old, new)
4116 }
4117 (AcqRel, SeqCst) => {
4118 intrinsics::atomic_cxchg::<T, { AO::AcqRel }, { AO::SeqCst }>(dst, old, new)
4119 }
4120 (SeqCst, Relaxed) => {
4121 intrinsics::atomic_cxchg::<T, { AO::SeqCst }, { AO::Relaxed }>(dst, old, new)
4122 }
4123 (SeqCst, Acquire) => {
4124 intrinsics::atomic_cxchg::<T, { AO::SeqCst }, { AO::Acquire }>(dst, old, new)
4125 }
4126 (SeqCst, SeqCst) => {
4127 intrinsics::atomic_cxchg::<T, { AO::SeqCst }, { AO::SeqCst }>(dst, old, new)
4128 }
4129 (_, AcqRel) => panic!("there is no such thing as an acquire-release failure ordering"),
4130 (_, Release) => panic!("there is no such thing as a release failure ordering"),
4131 }
4132 };
4133 if ok { Ok(val) } else { Err(val) }
4134}
4135
4136#[inline]
4137#[cfg(target_has_atomic)]
4138#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
4139#[ferrocene::prevalidated]
4140unsafe fn atomic_compare_exchange_weak<T: Copy>(
4141 dst: *mut T,
4142 old: T,
4143 new: T,
4144 success: Ordering,
4145 failure: Ordering,
4146) -> Result<T, T> {
4147 // SAFETY: the caller must uphold the safety contract for `atomic_compare_exchange_weak`.
4148 let (val, ok) = unsafe {
4149 match (success, failure) {
4150 (Relaxed, Relaxed) => {
4151 intrinsics::atomic_cxchgweak::<T, { AO::Relaxed }, { AO::Relaxed }>(dst, old, new)
4152 }
4153 (Relaxed, Acquire) => {
4154 intrinsics::atomic_cxchgweak::<T, { AO::Relaxed }, { AO::Acquire }>(dst, old, new)
4155 }
4156 (Relaxed, SeqCst) => {
4157 intrinsics::atomic_cxchgweak::<T, { AO::Relaxed }, { AO::SeqCst }>(dst, old, new)
4158 }
4159 (Acquire, Relaxed) => {
4160 intrinsics::atomic_cxchgweak::<T, { AO::Acquire }, { AO::Relaxed }>(dst, old, new)
4161 }
4162 (Acquire, Acquire) => {
4163 intrinsics::atomic_cxchgweak::<T, { AO::Acquire }, { AO::Acquire }>(dst, old, new)
4164 }
4165 (Acquire, SeqCst) => {
4166 intrinsics::atomic_cxchgweak::<T, { AO::Acquire }, { AO::SeqCst }>(dst, old, new)
4167 }
4168 (Release, Relaxed) => {
4169 intrinsics::atomic_cxchgweak::<T, { AO::Release }, { AO::Relaxed }>(dst, old, new)
4170 }
4171 (Release, Acquire) => {
4172 intrinsics::atomic_cxchgweak::<T, { AO::Release }, { AO::Acquire }>(dst, old, new)
4173 }
4174 (Release, SeqCst) => {
4175 intrinsics::atomic_cxchgweak::<T, { AO::Release }, { AO::SeqCst }>(dst, old, new)
4176 }
4177 (AcqRel, Relaxed) => {
4178 intrinsics::atomic_cxchgweak::<T, { AO::AcqRel }, { AO::Relaxed }>(dst, old, new)
4179 }
4180 (AcqRel, Acquire) => {
4181 intrinsics::atomic_cxchgweak::<T, { AO::AcqRel }, { AO::Acquire }>(dst, old, new)
4182 }
4183 (AcqRel, SeqCst) => {
4184 intrinsics::atomic_cxchgweak::<T, { AO::AcqRel }, { AO::SeqCst }>(dst, old, new)
4185 }
4186 (SeqCst, Relaxed) => {
4187 intrinsics::atomic_cxchgweak::<T, { AO::SeqCst }, { AO::Relaxed }>(dst, old, new)
4188 }
4189 (SeqCst, Acquire) => {
4190 intrinsics::atomic_cxchgweak::<T, { AO::SeqCst }, { AO::Acquire }>(dst, old, new)
4191 }
4192 (SeqCst, SeqCst) => {
4193 intrinsics::atomic_cxchgweak::<T, { AO::SeqCst }, { AO::SeqCst }>(dst, old, new)
4194 }
4195 (_, AcqRel) => panic!("there is no such thing as an acquire-release failure ordering"),
4196 (_, Release) => panic!("there is no such thing as a release failure ordering"),
4197 }
4198 };
4199 if ok { Ok(val) } else { Err(val) }
4200}
4201
4202#[inline]
4203#[cfg(target_has_atomic)]
4204#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
4205#[ferrocene::prevalidated]
4206unsafe fn atomic_and<T: Copy, U: Copy>(dst: *mut T, val: U, order: Ordering) -> T {
4207 // SAFETY: the caller must uphold the safety contract for `atomic_and`
4208 unsafe {
4209 match order {
4210 Relaxed => intrinsics::atomic_and::<T, U, { AO::Relaxed }>(dst, val),
4211 Acquire => intrinsics::atomic_and::<T, U, { AO::Acquire }>(dst, val),
4212 Release => intrinsics::atomic_and::<T, U, { AO::Release }>(dst, val),
4213 AcqRel => intrinsics::atomic_and::<T, U, { AO::AcqRel }>(dst, val),
4214 SeqCst => intrinsics::atomic_and::<T, U, { AO::SeqCst }>(dst, val),
4215 }
4216 }
4217}
4218
4219#[inline]
4220#[cfg(target_has_atomic)]
4221#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
4222#[ferrocene::prevalidated]
4223unsafe fn atomic_nand<T: Copy, U: Copy>(dst: *mut T, val: U, order: Ordering) -> T {
4224 // SAFETY: the caller must uphold the safety contract for `atomic_nand`
4225 unsafe {
4226 match order {
4227 Relaxed => intrinsics::atomic_nand::<T, U, { AO::Relaxed }>(dst, val),
4228 Acquire => intrinsics::atomic_nand::<T, U, { AO::Acquire }>(dst, val),
4229 Release => intrinsics::atomic_nand::<T, U, { AO::Release }>(dst, val),
4230 AcqRel => intrinsics::atomic_nand::<T, U, { AO::AcqRel }>(dst, val),
4231 SeqCst => intrinsics::atomic_nand::<T, U, { AO::SeqCst }>(dst, val),
4232 }
4233 }
4234}
4235
4236#[inline]
4237#[cfg(target_has_atomic)]
4238#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
4239#[ferrocene::prevalidated]
4240unsafe fn atomic_or<T: Copy, U: Copy>(dst: *mut T, val: U, order: Ordering) -> T {
4241 // SAFETY: the caller must uphold the safety contract for `atomic_or`
4242 unsafe {
4243 match order {
4244 SeqCst => intrinsics::atomic_or::<T, U, { AO::SeqCst }>(dst, val),
4245 Acquire => intrinsics::atomic_or::<T, U, { AO::Acquire }>(dst, val),
4246 Release => intrinsics::atomic_or::<T, U, { AO::Release }>(dst, val),
4247 AcqRel => intrinsics::atomic_or::<T, U, { AO::AcqRel }>(dst, val),
4248 Relaxed => intrinsics::atomic_or::<T, U, { AO::Relaxed }>(dst, val),
4249 }
4250 }
4251}
4252
4253#[inline]
4254#[cfg(target_has_atomic)]
4255#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
4256#[ferrocene::prevalidated]
4257unsafe fn atomic_xor<T: Copy, U: Copy>(dst: *mut T, val: U, order: Ordering) -> T {
4258 // SAFETY: the caller must uphold the safety contract for `atomic_xor`
4259 unsafe {
4260 match order {
4261 SeqCst => intrinsics::atomic_xor::<T, U, { AO::SeqCst }>(dst, val),
4262 Acquire => intrinsics::atomic_xor::<T, U, { AO::Acquire }>(dst, val),
4263 Release => intrinsics::atomic_xor::<T, U, { AO::Release }>(dst, val),
4264 AcqRel => intrinsics::atomic_xor::<T, U, { AO::AcqRel }>(dst, val),
4265 Relaxed => intrinsics::atomic_xor::<T, U, { AO::Relaxed }>(dst, val),
4266 }
4267 }
4268}
4269
4270/// Updates `*dst` to the max value of `val` and the old value (signed comparison)
4271#[inline]
4272#[cfg(target_has_atomic)]
4273#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
4274#[ferrocene::prevalidated]
4275unsafe fn atomic_max<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
4276 // SAFETY: the caller must uphold the safety contract for `atomic_max`
4277 unsafe {
4278 match order {
4279 Relaxed => intrinsics::atomic_max::<T, { AO::Relaxed }>(dst, val),
4280 Acquire => intrinsics::atomic_max::<T, { AO::Acquire }>(dst, val),
4281 Release => intrinsics::atomic_max::<T, { AO::Release }>(dst, val),
4282 AcqRel => intrinsics::atomic_max::<T, { AO::AcqRel }>(dst, val),
4283 SeqCst => intrinsics::atomic_max::<T, { AO::SeqCst }>(dst, val),
4284 }
4285 }
4286}
4287
4288/// Updates `*dst` to the min value of `val` and the old value (signed comparison)
4289#[inline]
4290#[cfg(target_has_atomic)]
4291#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
4292#[ferrocene::prevalidated]
4293unsafe fn atomic_min<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
4294 // SAFETY: the caller must uphold the safety contract for `atomic_min`
4295 unsafe {
4296 match order {
4297 Relaxed => intrinsics::atomic_min::<T, { AO::Relaxed }>(dst, val),
4298 Acquire => intrinsics::atomic_min::<T, { AO::Acquire }>(dst, val),
4299 Release => intrinsics::atomic_min::<T, { AO::Release }>(dst, val),
4300 AcqRel => intrinsics::atomic_min::<T, { AO::AcqRel }>(dst, val),
4301 SeqCst => intrinsics::atomic_min::<T, { AO::SeqCst }>(dst, val),
4302 }
4303 }
4304}
4305
4306/// Updates `*dst` to the max value of `val` and the old value (unsigned comparison)
4307#[inline]
4308#[cfg(target_has_atomic)]
4309#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
4310#[ferrocene::prevalidated]
4311unsafe fn atomic_umax<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
4312 // SAFETY: the caller must uphold the safety contract for `atomic_umax`
4313 unsafe {
4314 match order {
4315 Relaxed => intrinsics::atomic_umax::<T, { AO::Relaxed }>(dst, val),
4316 Acquire => intrinsics::atomic_umax::<T, { AO::Acquire }>(dst, val),
4317 Release => intrinsics::atomic_umax::<T, { AO::Release }>(dst, val),
4318 AcqRel => intrinsics::atomic_umax::<T, { AO::AcqRel }>(dst, val),
4319 SeqCst => intrinsics::atomic_umax::<T, { AO::SeqCst }>(dst, val),
4320 }
4321 }
4322}
4323
4324/// Updates `*dst` to the min value of `val` and the old value (unsigned comparison)
4325#[inline]
4326#[cfg(target_has_atomic)]
4327#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
4328#[ferrocene::prevalidated]
4329unsafe fn atomic_umin<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
4330 // SAFETY: the caller must uphold the safety contract for `atomic_umin`
4331 unsafe {
4332 match order {
4333 Relaxed => intrinsics::atomic_umin::<T, { AO::Relaxed }>(dst, val),
4334 Acquire => intrinsics::atomic_umin::<T, { AO::Acquire }>(dst, val),
4335 Release => intrinsics::atomic_umin::<T, { AO::Release }>(dst, val),
4336 AcqRel => intrinsics::atomic_umin::<T, { AO::AcqRel }>(dst, val),
4337 SeqCst => intrinsics::atomic_umin::<T, { AO::SeqCst }>(dst, val),
4338 }
4339 }
4340}
4341
4342/// An atomic fence.
4343///
4344/// Fences create synchronization between themselves and atomic operations or fences in other
4345/// threads. It can be helpful to think of a fence as preventing the compiler and CPU from
4346/// reordering certain types of memory operations around it, but that is a simplified model which
4347/// fails to capture some of the nuances.
4348///
4349/// There are 3 different ways to use an atomic fence:
4350///
4351/// - atomic - fence synchronization: an atomic operation with (at least) [`Release`] ordering
4352/// semantics synchronizes with a fence with (at least) [`Acquire`] ordering semantics.
4353/// - fence - atomic synchronization: a fence with (at least) [`Release`] ordering semantics
4354/// synchronizes with an atomic operation with (at least) [`Acquire`] ordering semantics.
4355/// - fence - fence synchronization: a fence with (at least) [`Release`] ordering semantics
4356/// synchronizes with a fence with (at least) [`Acquire`] ordering semantics.
4357///
4358/// These 3 ways complement the regular, fence-less, atomic - atomic synchronization.
4359///
4360/// ## Atomic - Fence
4361///
4362/// An atomic operation on one thread will synchronize with a fence on another thread when:
4363///
4364/// - on thread 1:
4365/// - an atomic operation 'X' with (at least) [`Release`] ordering semantics on some atomic
4366/// object 'm',
4367///
4368/// - is paired on thread 2 with:
4369/// - an atomic read 'Y' with any order on 'm',
4370/// - followed by a fence 'B' with (at least) [`Acquire`] ordering semantics.
4371///
4372/// This provides a happens-before dependence between X and B.
4373///
4374/// ```text
4375/// Thread 1 Thread 2
4376///
4377/// m.store(3, Release); X ---------
4378/// |
4379/// |
4380/// -------------> Y if m.load(Relaxed) == 3 {
4381/// B fence(Acquire);
4382/// ...
4383/// }
4384/// ```
4385///
4386/// ## Fence - Atomic
4387///
4388/// A fence on one thread will synchronize with an atomic operation on another thread when:
4389///
4390/// - on thread:
4391/// - a fence 'A' with (at least) [`Release`] ordering semantics,
4392/// - followed by an atomic write 'X' with any ordering on some atomic object 'm',
4393///
4394/// - is paired on thread 2 with:
4395/// - an atomic operation 'Y' with (at least) [`Acquire`] ordering semantics.
4396///
4397/// This provides a happens-before dependence between A and Y.
4398///
4399/// ```text
4400/// Thread 1 Thread 2
4401///
4402/// fence(Release); A
4403/// m.store(3, Relaxed); X ---------
4404/// |
4405/// |
4406/// -------------> Y if m.load(Acquire) == 3 {
4407/// ...
4408/// }
4409/// ```
4410///
4411/// ## Fence - Fence
4412///
4413/// A fence on one thread will synchronize with a fence on another thread when:
4414///
4415/// - on thread 1:
4416/// - a fence 'A' which has (at least) [`Release`] ordering semantics,
4417/// - followed by an atomic write 'X' with any ordering on some atomic object 'm',
4418///
4419/// - is paired on thread 2 with:
4420/// - an atomic read 'Y' with any ordering on 'm',
4421/// - followed by a fence 'B' with (at least) [`Acquire`] ordering semantics.
4422///
4423/// This provides a happens-before dependence between A and B.
4424///
4425/// ```text
4426/// Thread 1 Thread 2
4427///
4428/// fence(Release); A --------------
4429/// m.store(3, Relaxed); X --------- |
4430/// | |
4431/// | |
4432/// -------------> Y if m.load(Relaxed) == 3 {
4433/// |-------> B fence(Acquire);
4434/// ...
4435/// }
4436/// ```
4437///
4438/// ## Mandatory Atomic
4439///
4440/// Note that in the examples above, it is crucial that the access to `m` are atomic. Fences cannot
4441/// be used to establish synchronization between non-atomic accesses in different threads. However,
4442/// thanks to the happens-before relationship, any non-atomic access that happen-before the atomic
4443/// operation or fence with (at least) [`Release`] ordering semantics are now also properly
4444/// synchronized with any non-atomic accesses that happen-after the atomic operation or fence with
4445/// (at least) [`Acquire`] ordering semantics.
4446///
4447/// ## Memory Ordering
4448///
4449/// A fence which has [`SeqCst`] ordering, in addition to having both [`Acquire`] and [`Release`]
4450/// semantics, participates in the global program order of the other [`SeqCst`] operations and/or
4451/// fences.
4452///
4453/// Accepts [`Acquire`], [`Release`], [`AcqRel`] and [`SeqCst`] orderings.
4454///
4455/// # Panics
4456///
4457/// Panics if `order` is [`Relaxed`].
4458///
4459/// # Examples
4460///
4461/// ```
4462/// use std::sync::atomic::AtomicBool;
4463/// use std::sync::atomic::fence;
4464/// use std::sync::atomic::Ordering;
4465///
4466/// // A mutual exclusion primitive based on spinlock.
4467/// pub struct Mutex {
4468/// flag: AtomicBool,
4469/// }
4470///
4471/// impl Mutex {
4472/// pub fn new() -> Mutex {
4473/// Mutex {
4474/// flag: AtomicBool::new(false),
4475/// }
4476/// }
4477///
4478/// pub fn lock(&self) {
4479/// // Wait until the old value is `false`.
4480/// while self
4481/// .flag
4482/// .compare_exchange_weak(false, true, Ordering::Relaxed, Ordering::Relaxed)
4483/// .is_err()
4484/// {}
4485/// // This fence synchronizes-with store in `unlock`.
4486/// fence(Ordering::Acquire);
4487/// }
4488///
4489/// pub fn unlock(&self) {
4490/// self.flag.store(false, Ordering::Release);
4491/// }
4492/// }
4493/// ```
4494#[inline]
4495#[stable(feature = "rust1", since = "1.0.0")]
4496#[rustc_diagnostic_item = "fence"]
4497#[doc(alias = "atomic_thread_fence")]
4498#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
4499#[ferrocene::prevalidated]
4500pub fn fence(order: Ordering) {
4501 // SAFETY: using an atomic fence is safe.
4502 unsafe {
4503 match order {
4504 Acquire => intrinsics::atomic_fence::<{ AO::Acquire }>(),
4505 Release => intrinsics::atomic_fence::<{ AO::Release }>(),
4506 AcqRel => intrinsics::atomic_fence::<{ AO::AcqRel }>(),
4507 SeqCst => intrinsics::atomic_fence::<{ AO::SeqCst }>(),
4508 Relaxed => panic!("there is no such thing as a relaxed fence"),
4509 }
4510 }
4511}
4512
4513/// An atomic fence for synchronization within a single thread.
4514///
4515/// Like [`fence`], this function establishes synchronization with other atomic operations and
4516/// fences. However, unlike [`fence`], `compiler_fence` only establishes synchronization with
4517/// operations *in the same thread*. This may at first sound rather useless, since code within a
4518/// thread is typically already totally ordered and does not need any further synchronization.
4519/// However, there are cases where code can run on the same thread without being synchronized:
4520/// - The most common case is that of a *signal handler*: a signal handler runs in the same thread
4521/// as the code it interrupted, but it is not synchronized with that code. `compiler_fence`
4522/// can be used to establish synchronization between a thread and its signal handler, the same way
4523/// that `fence` can be used to establish synchronization across threads.
4524/// - Similar situations can arise in embedded programming with interrupt handlers, or in custom
4525/// implementations of preemptive green threads. In general, `compiler_fence` can establish
4526/// synchronization with code that is guaranteed to run on the same hardware CPU.
4527///
4528/// See [`fence`] for how a fence can be used to achieve synchronization. Note that just like
4529/// [`fence`], synchronization still requires atomic operations to be used in both threads -- it is
4530/// not possible to perform synchronization entirely with fences and non-atomic operations.
4531///
4532/// `compiler_fence` does not emit any machine code. However, note that `compiler_fence` is also
4533/// *not* a "compiler barrier". It can be helpful to think of a `compiler_fence` as preventing the
4534/// compiler from reordering certain types of memory operations around it, but that is a simplified
4535/// model which fails to capture some of the nuances. The only actual guarantee made by
4536/// `compiler_fence` is establishing synchronization with signal handlers and similar kinds of code,
4537/// under the rules described in the [`fence`] documentation.
4538///
4539/// `compiler_fence` corresponds to [`atomic_signal_fence`] in C and C++.
4540///
4541/// [`atomic_signal_fence`]: https://en.cppreference.com/w/cpp/atomic/atomic_signal_fence
4542///
4543/// # Panics
4544///
4545/// Panics if `order` is [`Relaxed`].
4546///
4547/// # Examples
4548///
4549/// Without the two `compiler_fence` calls, the read of `IMPORTANT_VARIABLE` in `signal_handler`
4550/// is *undefined behavior* due to a data race, despite everything happening in a single thread.
4551/// This is because the signal handler is considered to run concurrently with its associated
4552/// thread, and explicit synchronization is required to pass data between a thread and its
4553/// signal handler. The code below uses two `compiler_fence` calls to establish the usual
4554/// release-acquire synchronization pattern (see [`fence`] for an image).
4555///
4556/// ```
4557/// use std::sync::atomic::AtomicBool;
4558/// use std::sync::atomic::Ordering;
4559/// use std::sync::atomic::compiler_fence;
4560///
4561/// static mut IMPORTANT_VARIABLE: usize = 0;
4562/// static IS_READY: AtomicBool = AtomicBool::new(false);
4563///
4564/// fn main() {
4565/// unsafe { IMPORTANT_VARIABLE = 42 };
4566/// // Marks earlier writes as being released with future relaxed stores.
4567/// compiler_fence(Ordering::Release);
4568/// IS_READY.store(true, Ordering::Relaxed);
4569/// }
4570///
4571/// fn signal_handler() {
4572/// if IS_READY.load(Ordering::Relaxed) {
4573/// // Acquires writes that were released with relaxed stores that we read from.
4574/// compiler_fence(Ordering::Acquire);
4575/// assert_eq!(unsafe { IMPORTANT_VARIABLE }, 42);
4576/// }
4577/// }
4578/// ```
4579#[inline]
4580#[stable(feature = "compiler_fences", since = "1.21.0")]
4581#[rustc_diagnostic_item = "compiler_fence"]
4582#[doc(alias = "atomic_signal_fence")]
4583#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
4584#[ferrocene::prevalidated]
4585pub fn compiler_fence(order: Ordering) {
4586 // SAFETY: using an atomic fence is safe.
4587 unsafe {
4588 match order {
4589 Acquire => intrinsics::atomic_singlethreadfence::<{ AO::Acquire }>(),
4590 Release => intrinsics::atomic_singlethreadfence::<{ AO::Release }>(),
4591 AcqRel => intrinsics::atomic_singlethreadfence::<{ AO::AcqRel }>(),
4592 SeqCst => intrinsics::atomic_singlethreadfence::<{ AO::SeqCst }>(),
4593 Relaxed => panic!("there is no such thing as a relaxed fence"),
4594 }
4595 }
4596}
4597
4598#[cfg(target_has_atomic_load_store = "8")]
4599#[stable(feature = "atomic_debug", since = "1.3.0")]
4600impl fmt::Debug for AtomicBool {
4601 #[ferrocene::prevalidated]
4602 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
4603 fmt::Debug::fmt(&self.load(Ordering::Relaxed), f)
4604 }
4605}
4606
4607#[cfg(target_has_atomic_load_store = "ptr")]
4608#[stable(feature = "atomic_debug", since = "1.3.0")]
4609impl<T> fmt::Debug for AtomicPtr<T> {
4610 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
4611 fmt::Debug::fmt(&self.load(Ordering::Relaxed), f)
4612 }
4613}
4614
4615#[cfg(target_has_atomic_load_store = "ptr")]
4616#[stable(feature = "atomic_pointer", since = "1.24.0")]
4617impl<T> fmt::Pointer for AtomicPtr<T> {
4618 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
4619 fmt::Pointer::fmt(&self.load(Ordering::Relaxed), f)
4620 }
4621}
4622
4623/// Signals the processor that it is inside a busy-wait spin-loop ("spin lock").
4624///
4625/// This function is deprecated in favor of [`hint::spin_loop`].
4626///
4627/// [`hint::spin_loop`]: crate::hint::spin_loop
4628#[inline]
4629#[stable(feature = "spin_loop_hint", since = "1.24.0")]
4630#[deprecated(since = "1.51.0", note = "use hint::spin_loop instead")]
4631pub fn spin_loop_hint() {
4632 spin_loop()
4633}