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