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