1//! Atomic types
2//!
3//! Atomic types provide primitive shared-memory communication between
4//! threads, and are the building blocks of other concurrent
5//! types.
6//!
7//! This module defines atomic versions of a select number of primitive
8//! types, including [`AtomicBool`], [`AtomicIsize`], [`AtomicUsize`],
9//! [`AtomicI8`], [`AtomicU16`], etc.
10//! Atomic types present operations that, when used correctly, synchronize
11//! updates between threads.
12//!
13//! Atomic variables are safe to share between threads (they implement [`Sync`])
14//! but they do not themselves provide the mechanism for sharing and follow the
15//! [threading model](../../../std/thread/index.html#the-threading-model) of Rust.
16//! The most common way to share an atomic variable is to put it into an [`Arc`][arc] (an
17//! atomically-reference-counted shared pointer).
18//!
19//! [arc]: ../../../std/sync/struct.Arc.html
20//!
21//! Atomic types may be stored in static variables, initialized using
22//! the constant initializers like [`AtomicBool::new`]. Atomic statics
23//! are often used for lazy global initialization.
24//!
25//! ## Memory model for atomic accesses
26//!
27//! Rust atomics currently follow the same rules as [C++20 atomics][cpp], specifically the rules
28//! from the [`intro.races`][cpp-intro.races] section, without the "consume" memory ordering. Since
29//! C++ uses an object-based memory model whereas Rust is access-based, a bit of translation work
30//! has to be done to apply the C++ rules to Rust: whenever C++ talks about "the value of an
31//! object", we understand that to mean the resulting bytes obtained when doing a read. When the C++
32//! standard talks about "the value of an atomic object", this refers to the result of doing an
33//! atomic load (via the operations provided in this module). A "modification of an atomic object"
34//! refers to an atomic store.
35//!
36//! The end result is *almost* equivalent to saying that creating a *shared reference* to one of the
37//! Rust atomic types corresponds to creating an `atomic_ref` in C++, with the `atomic_ref` being
38//! destroyed when the lifetime of the shared reference ends. The main difference is that Rust
39//! permits concurrent atomic and non-atomic reads to the same memory as those cause no issue in the
40//! C++ memory model, they are just forbidden in C++ because memory is partitioned into "atomic
41//! objects" and "non-atomic objects" (with `atomic_ref` temporarily converting a non-atomic object
42//! into an atomic object).
43//!
44//! The most important aspect of this model is that *data races* are undefined behavior. A data race
45//! is defined as conflicting non-synchronized accesses where at least one of the accesses is
46//! non-atomic. Here, accesses are *conflicting* if they affect overlapping regions of memory and at
47//! least one of them is a write. (A `compare_exchange` or `compare_exchange_weak` that does not
48//! succeed is not considered a write.) They are *non-synchronized* if neither of them
49//! *happens-before* the other, according to the happens-before order of the memory model.
50//!
51//! The other possible cause of undefined behavior in the memory model are mixed-size accesses: Rust
52//! inherits the C++ limitation that non-synchronized conflicting atomic accesses may not partially
53//! overlap. In other words, every pair of non-synchronized atomic accesses must be either disjoint,
54//! access the exact same memory (including using the same access size), or both be reads.
55//!
56//! Each atomic access takes an [`Ordering`] which defines how the operation interacts with the
57//! happens-before order. These orderings behave the same as the corresponding [C++20 atomic
58//! orderings][cpp_memory_order]. For more information, see the [nomicon].
59//!
60//! [cpp]: https://en.cppreference.com/w/cpp/atomic
61//! [cpp-intro.races]: https://timsong-cpp.github.io/cppwp/n4868/intro.multithread#intro.races
62//! [cpp_memory_order]: https://en.cppreference.com/w/cpp/atomic/memory_order
63//! [nomicon]: ../../../nomicon/atomics.html
64//!
65//! ```rust,no_run undefined_behavior
66//! use std::sync::atomic::{AtomicU16, AtomicU8, Ordering};
67//! use std::mem::transmute;
68//! use std::thread;
69//!
70//! let atomic = AtomicU16::new(0);
71//!
72//! thread::scope(|s| {
73//! // This is UB: conflicting non-synchronized accesses, at least one of which is non-atomic.
74//! s.spawn(|| atomic.store(1, Ordering::Relaxed)); // atomic store
75//! s.spawn(|| unsafe { atomic.as_ptr().write(2) }); // non-atomic write
76//! });
77//!
78//! thread::scope(|s| {
79//! // This is fine: the accesses do not conflict (as none of them performs any modification).
80//! // In C++ this would be disallowed since creating an `atomic_ref` precludes
81//! // further non-atomic accesses, but Rust does not have that limitation.
82//! s.spawn(|| atomic.load(Ordering::Relaxed)); // atomic load
83//! s.spawn(|| unsafe { atomic.as_ptr().read() }); // non-atomic read
84//! });
85//!
86//! thread::scope(|s| {
87//! // This is fine: `join` synchronizes the code in a way such that the atomic
88//! // store happens-before the non-atomic write.
89//! let handle = s.spawn(|| atomic.store(1, Ordering::Relaxed)); // atomic store
90//! handle.join().expect("thread won't panic"); // synchronize
91//! s.spawn(|| unsafe { atomic.as_ptr().write(2) }); // non-atomic write
92//! });
93//!
94//! thread::scope(|s| {
95//! // This is UB: non-synchronized conflicting differently-sized atomic accesses.
96//! s.spawn(|| atomic.store(1, Ordering::Relaxed));
97//! s.spawn(|| unsafe {
98//! let differently_sized = transmute::<&AtomicU16, &AtomicU8>(&atomic);
99//! differently_sized.store(2, Ordering::Relaxed);
100//! });
101//! });
102//!
103//! thread::scope(|s| {
104//! // This is fine: `join` synchronizes the code in a way such that
105//! // the 1-byte store happens-before the 2-byte store.
106//! let handle = s.spawn(|| atomic.store(1, Ordering::Relaxed));
107//! handle.join().expect("thread won't panic");
108//! s.spawn(|| unsafe {
109//! let differently_sized = transmute::<&AtomicU16, &AtomicU8>(&atomic);
110//! differently_sized.store(2, Ordering::Relaxed);
111//! });
112//! });
113//! ```
114//!
115//! # Portability
116//!
117//! All atomic types in this module are guaranteed to be [lock-free] if they're
118//! available. This means they don't internally acquire a global mutex. Atomic
119//! types and operations are not guaranteed to be wait-free. This means that
120//! operations like `fetch_or` may be implemented with a compare-and-swap loop.
121//!
122//! Atomic operations may be implemented at the instruction layer with
123//! larger-size atomics. For example some platforms use 4-byte atomic
124//! instructions to implement `AtomicI8`. Note that this emulation should not
125//! have an impact on correctness of code, it's just something to be aware of.
126//!
127//! The atomic types in this module might not be available on all platforms. The
128//! atomic types here are all widely available, however, and can generally be
129//! relied upon existing. Some notable exceptions are:
130//!
131//! * PowerPC and MIPS platforms with 32-bit pointers do not have `AtomicU64` or
132//! `AtomicI64` types.
133//! * Legacy ARM platforms like ARMv4T and ARMv5TE have very limited hardware
134//! support for atomics. The bare-metal targets disable this module
135//! entirely, but the Linux targets [use the kernel] to assist (which comes
136//! with a performance penalty). It's not until ARMv6K onwards that ARM CPUs
137//! have support for load/store and Compare and Swap (CAS) atomics in hardware.
138//! * ARMv6-M targets (`thumbv6m-*`) only provide `load` and `store` operations, and do
139//! not support Compare and Swap (CAS) operations, such as `swap`,
140//! `fetch_add`, etc. Full CAS support is available on ARMv7-M and ARMv8-M
141//! (`thumbv7m-*`, `thumbv7em*`, `thumbv8m.base-*` and `thumbv8m.main-*`).
142//!
143//! [use the kernel]: https://www.kernel.org/doc/Documentation/arm/kernel_user_helpers.txt
144//!
145//! Note that future platforms may be added that also do not have support for
146//! some atomic operations. Maximally portable code will want to be careful
147//! about which atomic types are used. `AtomicUsize` and `AtomicIsize` are
148//! generally the most portable, but even then they're not available everywhere.
149//! For reference, the `std` library requires `AtomicBool`s and pointer-sized atomics, although
150//! `core` does not.
151//!
152//! The `#[cfg(target_has_atomic)]` attribute can be used to conditionally
153//! compile based on the target's supported bit widths. It is a key-value
154//! option set for each supported size, with values "8", "16", "32", "64",
155//! "128", and "ptr" for pointer-sized atomics.
156//!
157//! [lock-free]: https://en.wikipedia.org/wiki/Non-blocking_algorithm
158//!
159//! # Atomic accesses to read-only memory
160//!
161//! In general, *all* atomic accesses on read-only memory are undefined behavior. For instance, attempting
162//! to do a `compare_exchange` that will definitely fail (making it conceptually a read-only
163//! operation) can still cause a segmentation fault if the underlying memory page is mapped read-only. Since
164//! atomic `load`s might be implemented using compare-exchange operations, even a `load` can fault
165//! on read-only memory.
166//!
167//! For the purpose of this section, "read-only memory" is defined as memory that is read-only in
168//! the underlying target, i.e., the pages are mapped with a read-only flag and any attempt to write
169//! will cause a page fault. In particular, an `&u128` reference that points to memory that is
170//! read-write mapped is *not* considered to point to "read-only memory". In Rust, almost all memory
171//! is read-write; the only exceptions are memory created by `const` items or `static` items without
172//! interior mutability, and memory that was specifically marked as read-only by the operating
173//! system via platform-specific APIs.
174//!
175//! As an exception from the general rule stated above, "sufficiently small" atomic loads with
176//! `Ordering::Relaxed` are implemented in a way that works on read-only memory, and are hence not
177//! undefined behavior. The exact size limit for what makes a load "sufficiently small" varies
178//! depending on the target:
179//!
180//! | `target_arch` | Size limit |
181//! |---------------|---------|
182//! | `x86`, `arm`, `loongarch32`, `mips`, `mips32r6`, `powerpc`, `riscv32`, `sparc`, `hexagon` | 4 bytes |
183//! | `x86_64`, `aarch64`, `loongarch64`, `mips64`, `mips64r6`, `powerpc64`, `riscv64`, `sparc64`, `s390x` | 8 bytes |
184//!
185//! Atomics loads that are larger than this limit as well as atomic loads with ordering other
186//! than `Relaxed`, as well as *all* atomic loads on targets not listed in the table, might still be
187//! read-only under certain conditions, but that is not a stable guarantee and should not be relied
188//! upon.
189//!
190//! If you need to do an acquire load on read-only memory, you can do a relaxed load followed by an
191//! acquire fence instead.
192//!
193//! # Examples
194//!
195//! A simple spinlock:
196//!
197//! ```ignore-wasm
198//! use std::sync::Arc;
199//! use std::sync::atomic::{AtomicUsize, Ordering};
200//! use std::{hint, thread};
201//!
202//! fn main() {
203//! let spinlock = Arc::new(AtomicUsize::new(1));
204//!
205//! let spinlock_clone = Arc::clone(&spinlock);
206//!
207//! let thread = thread::spawn(move || {
208//! spinlock_clone.store(0, Ordering::Release);
209//! });
210//!
211//! // Wait for the other thread to release the lock
212//! while spinlock.load(Ordering::Acquire) != 0 {
213//! hint::spin_loop();
214//! }
215//!
216//! if let Err(panic) = thread.join() {
217//! println!("Thread had an error: {panic:?}");
218//! }
219//! }
220//! ```
221//!
222//! Keep a global count of live threads:
223//!
224//! ```
225//! use std::sync::atomic::{AtomicUsize, Ordering};
226//!
227//! static GLOBAL_THREAD_COUNT: AtomicUsize = AtomicUsize::new(0);
228//!
229//! // Note that Relaxed ordering doesn't synchronize anything
230//! // except the global thread counter itself.
231//! let old_thread_count = GLOBAL_THREAD_COUNT.fetch_add(1, Ordering::Relaxed);
232//! // Note that this number may not be true at the moment of printing
233//! // because some other thread may have changed static value already.
234//! println!("live threads: {}", old_thread_count + 1);
235//! ```
236237#![stable(feature = "rust1", since = "1.0.0")]
238#![cfg_attr(not(target_has_atomic_load_store = "8"), allow(dead_code))]
239#![cfg_attr(not(target_has_atomic_load_store = "8"), allow(unused_imports))]
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)]
244245use self::Ordering::*;
246use crate::cell::UnsafeCell;
247use crate::hint::spin_loop;
248use crate::intrinsics::AtomicOrderingas AO;
249use crate::mem::transmute;
250use crate::{fmt, intrinsics};
251252#[unstable(
253 feature = "atomic_internals",
254 reason = "implementation detail which may disappear or be replaced at any time",
255 issue = "none"
256)]
257#[expect(missing_debug_implementations)]
258mod private {
259#[cfg(target_has_atomic_load_store = "8")]
260 #[repr(C, align(1))]
261pub struct Align1<T>(T);
262#[cfg(target_has_atomic_load_store = "16")]
263 #[repr(C, align(2))]
264pub struct Align2<T>(T);
265#[cfg(target_has_atomic_load_store = "32")]
266 #[repr(C, align(4))]
267pub struct Align4<T>(T);
268#[cfg(target_has_atomic_load_store = "64")]
269 #[repr(C, align(8))]
270pub struct Align8<T>(T);
271#[cfg(any(target_has_atomic_load_store = "128", doc))]
272 #[repr(C, align(16))]
273pub struct Align16<T>(T);
274}
275276/// A marker trait for primitive types which can be modified atomically.
277///
278/// This is an implementation detail for <code>[Atomic]\<T></code> which may disappear or be replaced at any time.
279//
280// # Safety
281//
282// Types implementing this trait must be primitives that can be modified atomically.
283//
284// The associated `Self::Storage` type must have the same size, but may have fewer validity
285// invariants or a higher alignment requirement than `Self`.
286#[unstable(
287 feature = "atomic_internals",
288 reason = "implementation detail which may disappear or be replaced at any time",
289 issue = "none"
290)]
291pub impl(self) unsafe trait AtomicPrimitive: Sized + Copy {
292/// Temporary implementation detail.
293type Storage: Sized;
294}
295296macro impl_atomic_primitive {
297 (
298 @impl [$($T:ident)?] $Primitive:ty as $Storage:ident<$Operand:ty>,
299$cfg:meta
300 ) => {
301#[unstable(
302 feature = "atomic_internals",
303 reason = "implementation detail which may disappear or be replaced at any time",
304 issue = "none"
305)]
306 #[cfg($cfg)]
307unsafe impl $(<$T>)? AtomicPrimitive for $Primitive {
308type Storage = private::$Storage<$Operand>;
309 }
310 },
311312 (
313 [$($T:ident)?] $Primitive:ty as $Storage:ident<$Operand:ty>,
314 size($size:literal)
315 ) => {
316impl_atomic_primitive!(
317 @impl [$($T)?] $Primitive as $Storage<$Operand>,
318 target_has_atomic_load_store = $size
319);
320 },
321322 (
323 [$($T:ident)?] $Primitive:ty as $Storage:ident<$Operand:ty>,
324 size($size:literal),
325 doc
326 ) => {
327impl_atomic_primitive!(
328 @impl [$($T)?] $Primitive as $Storage<$Operand>,
329 any(target_has_atomic_load_store = $size, doc)
330 );
331 },
332}
333334#[unstable(feature = "atomic_internals", reason =
"implementation detail which may disappear or be replaced at any time", issue
= "none")]
unsafe impl AtomicPrimitive for bool {
type Storage = private::Align1<u8>;
}impl_atomic_primitive!([] boolas Align1<u8>, size("8"));
335#[unstable(feature = "atomic_internals", reason =
"implementation detail which may disappear or be replaced at any time", issue
= "none")]
unsafe impl AtomicPrimitive for i8 {
type Storage = private::Align1<i8>;
}impl_atomic_primitive!([] i8as Align1<i8>, size("8"));
336#[unstable(feature = "atomic_internals", reason =
"implementation detail which may disappear or be replaced at any time", issue
= "none")]
unsafe impl AtomicPrimitive for u8 {
type Storage = private::Align1<u8>;
}impl_atomic_primitive!([] u8as Align1<u8>, size("8"));
337#[unstable(feature = "atomic_internals", reason =
"implementation detail which may disappear or be replaced at any time", issue
= "none")]
unsafe impl AtomicPrimitive for i16 {
type Storage = private::Align2<i16>;
}impl_atomic_primitive!([] i16as Align2<i16>, size("16"));
338#[unstable(feature = "atomic_internals", reason =
"implementation detail which may disappear or be replaced at any time", issue
= "none")]
unsafe impl AtomicPrimitive for u16 {
type Storage = private::Align2<u16>;
}impl_atomic_primitive!([] u16as Align2<u16>, size("16"));
339#[unstable(feature = "atomic_internals", reason =
"implementation detail which may disappear or be replaced at any time", issue
= "none")]
unsafe impl AtomicPrimitive for i32 {
type Storage = private::Align4<i32>;
}impl_atomic_primitive!([] i32as Align4<i32>, size("32"));
340#[unstable(feature = "atomic_internals", reason =
"implementation detail which may disappear or be replaced at any time", issue
= "none")]
unsafe impl AtomicPrimitive for u32 {
type Storage = private::Align4<u32>;
}impl_atomic_primitive!([] u32as Align4<u32>, size("32"));
341#[unstable(feature = "atomic_internals", reason =
"implementation detail which may disappear or be replaced at any time", issue
= "none")]
unsafe impl AtomicPrimitive for i64 {
type Storage = private::Align8<i64>;
}impl_atomic_primitive!([] i64as Align8<i64>, size("64"));
342#[unstable(feature = "atomic_internals", reason =
"implementation detail which may disappear or be replaced at any time", issue
= "none")]
unsafe impl AtomicPrimitive for u64 {
type Storage = private::Align8<u64>;
}impl_atomic_primitive!([] u64as Align8<u64>, size("64"));
343impl_atomic_primitive!([] i128 as Align16<i128>, size("128"), doc);
344impl_atomic_primitive!([] u128 as Align16<u128>, size("128"), doc);
345346#[cfg(target_pointer_width = "16")]
347impl_atomic_primitive!([] isize as Align2<isize>, size("ptr"));
348#[cfg(target_pointer_width = "32")]
349impl_atomic_primitive!([] isize as Align4<isize>, size("ptr"));
350#[cfg(target_pointer_width = "64")]
351#[unstable(feature = "atomic_internals", reason =
"implementation detail which may disappear or be replaced at any time", issue
= "none")]
unsafe impl AtomicPrimitive for isize {
type Storage = private::Align8<isize>;
}impl_atomic_primitive!([] isizeas Align8<isize>, size("ptr"));
352353#[cfg(target_pointer_width = "16")]
354impl_atomic_primitive!([] usize as Align2<usize>, size("ptr"));
355#[cfg(target_pointer_width = "32")]
356impl_atomic_primitive!([] usize as Align4<usize>, size("ptr"));
357#[cfg(target_pointer_width = "64")]
358#[unstable(feature = "atomic_internals", reason =
"implementation detail which may disappear or be replaced at any time", issue
= "none")]
unsafe impl AtomicPrimitive for usize {
type Storage = private::Align8<usize>;
}impl_atomic_primitive!([] usizeas Align8<usize>, size("ptr"));
359360#[cfg(target_pointer_width = "16")]
361impl_atomic_primitive!([T] *mut T as Align2<*mut T>, size("ptr"));
362#[cfg(target_pointer_width = "32")]
363impl_atomic_primitive!([T] *mut T as Align4<*mut T>, size("ptr"));
364#[cfg(target_pointer_width = "64")]
365#[unstable(feature = "atomic_internals", reason =
"implementation detail which may disappear or be replaced at any time", issue
= "none")]
unsafe impl<T> AtomicPrimitive for *mut T {
type Storage = private::Align8<*mut T>;
}impl_atomic_primitive!([T] *mut T as Align8<*mut T>, size("ptr"));
366367/// A memory location which can be safely modified from multiple threads.
368///
369/// This has the same size and bit validity as the underlying type `T`. However,
370/// the alignment of this type is always equal to its size, even on targets where
371/// `T` has alignment less than its size.
372///
373/// For more about the differences between atomic types and non-atomic types as
374/// well as information about the portability of this type, please see the
375/// [module-level documentation].
376///
377/// **Note:** This type is only available on platforms that support atomic loads
378/// and stores of `T`.
379///
380/// [module-level documentation]: crate::sync::atomic
381#[unstable(feature = "generic_atomic", issue = "130539")]
382#[repr(C)]
383#[rustc_diagnostic_item = "Atomic"]
384pub struct Atomic<T: AtomicPrimitive> {
385 v: UnsafeCell<T::Storage>,
386}
387388#[stable(feature = "rust1", since = "1.0.0")]
389unsafe impl<T: AtomicPrimitive> Sendfor Atomic<T> {}
390#[stable(feature = "rust1", since = "1.0.0")]
391unsafe impl<T: AtomicPrimitive> Syncfor Atomic<T> {}
392393// Some architectures don't have byte-sized atomics, which results in LLVM
394// emulating them using a LL/SC loop. However for AtomicBool we can take
395// advantage of the fact that it only ever contains 0 or 1 and use atomic OR/AND
396// instead, which LLVM can emulate using a larger atomic OR/AND operation.
397//
398// This list should only contain architectures which have word-sized atomic-or/
399// atomic-and instructions but don't natively support byte-sized atomics.
400#[cfg(target_has_atomic = "8")]
401const EMULATE_ATOMIC_BOOL: bool = falsecfg!(any(
402 target_arch = "riscv32",
403 target_arch = "riscv64",
404 target_arch = "loongarch32",
405 target_arch = "loongarch64"
406));
407408/// A boolean type which can be safely shared between threads.
409///
410/// This type has the same size, alignment, and bit validity as a [`bool`].
411///
412/// **Note**: This type is only available on platforms that support atomic
413/// loads and stores of `u8`.
414#[cfg(target_has_atomic_load_store = "8")]
415#[stable(feature = "rust1", since = "1.0.0")]
416pub type AtomicBool = Atomic<bool>;
417418#[cfg(target_has_atomic_load_store = "8")]
419#[stable(feature = "rust1", since = "1.0.0")]
420impl Defaultfor AtomicBool {
421/// Creates an `AtomicBool` initialized to `false`.
422#[inline]
423fn default() -> Self {
424Self::new(false)
425 }
426}
427428/// A raw pointer type which can be safely shared between threads.
429///
430/// This type has the same size and bit validity as a `*mut T`.
431///
432/// **Note**: This type is only available on platforms that support atomic
433/// loads and stores of pointers. Its size depends on the target pointer's size.
434#[cfg(target_has_atomic_load_store = "ptr")]
435#[stable(feature = "rust1", since = "1.0.0")]
436pub type AtomicPtr<T> = Atomic<*mut T>;
437438#[cfg(target_has_atomic_load_store = "ptr")]
439#[stable(feature = "rust1", since = "1.0.0")]
440impl<T> Defaultfor AtomicPtr<T> {
441/// Creates a null `AtomicPtr<T>`.
442fn default() -> AtomicPtr<T> {
443AtomicPtr::new(crate::ptr::null_mut())
444 }
445}
446447/// Atomic memory orderings
448///
449/// Memory orderings specify the way atomic operations synchronize memory.
450/// In its weakest [`Ordering::Relaxed`], only the memory directly touched by the
451/// operation is synchronized. On the other hand, a store-load pair of [`Ordering::SeqCst`]
452/// operations synchronize other memory while additionally preserving a total order of such
453/// operations across all threads.
454///
455/// Rust's memory orderings are [the same as those of
456/// C++20](https://en.cppreference.com/w/cpp/atomic/memory_order).
457///
458/// For more information see the [nomicon].
459///
460/// [nomicon]: ../../../nomicon/atomics.html
461#[stable(feature = "rust1", since = "1.0.0")]
462#[derive(#[automatically_derived]
#[stable(feature = "rust1", since = "1.0.0")]
impl crate::marker::Copy for Ordering { }Copy, #[automatically_derived]
#[doc(hidden)]
#[stable(feature = "rust1", since = "1.0.0")]
unsafe impl crate::clone::TrivialClone for Ordering { }
#[automatically_derived]
#[stable(feature = "rust1", since = "1.0.0")]
impl crate::clone::Clone for Ordering {
#[inline]
fn clone(&self) -> Self { *self }
}Clone, #[automatically_derived]
#[stable(feature = "rust1", since = "1.0.0")]
impl crate::fmt::Debug for Ordering {
#[inline]
fn fmt(&self, f: &mut crate::fmt::Formatter) -> crate::fmt::Result {
crate::fmt::Formatter::write_str(f,
match self {
Ordering::Relaxed => "Relaxed",
Ordering::Release => "Release",
Ordering::Acquire => "Acquire",
Ordering::AcqRel => "AcqRel",
Ordering::SeqCst => "SeqCst",
})
}
}Debug, #[automatically_derived]
#[stable(feature = "rust1", since = "1.0.0")]
impl crate::cmp::Eq for Ordering { }Eq, #[automatically_derived]
#[stable(feature = "rust1", since = "1.0.0")]
impl crate::marker::StructuralPartialEq for Ordering { }
#[automatically_derived]
#[stable(feature = "rust1", since = "1.0.0")]
impl crate::cmp::PartialEq for Ordering {
#[inline]
fn eq(&self, other: &Self) -> bool {
crate::intrinsics::discriminant_value(self) ==
crate::intrinsics::discriminant_value(other)
}
}PartialEq, #[automatically_derived]
#[stable(feature = "rust1", since = "1.0.0")]
impl crate::hash::Hash for Ordering {
#[inline]
fn hash<__H: crate::hash::Hasher>(&self, state: &mut __H) {
crate::hash::Hash::hash(&crate::intrinsics::discriminant_value(self),
state)
}
}Hash)]
463#[non_exhaustive]
464#[rustc_diagnostic_item = "Ordering"]
465pub enum Ordering {
466/// No ordering constraints, only atomic operations.
467 ///
468 /// Corresponds to [`memory_order_relaxed`] in C++20.
469 ///
470 /// [`memory_order_relaxed`]: https://en.cppreference.com/w/cpp/atomic/memory_order#Relaxed_ordering
471#[stable(feature = "rust1", since = "1.0.0")]
472Relaxed,
473/// When coupled with a store, all previous operations become ordered
474 /// before any load of this value with [`Acquire`] (or stronger) ordering.
475 /// In particular, all previous writes become visible to all threads
476 /// that perform an [`Acquire`] (or stronger) load of this value.
477 ///
478 /// Notice that using this ordering for an operation that combines loads
479 /// and stores leads to a [`Relaxed`] load operation!
480 ///
481 /// This ordering is only applicable for operations that can perform a store.
482 ///
483 /// Corresponds to [`memory_order_release`] in C++20.
484 ///
485 /// [`memory_order_release`]: https://en.cppreference.com/w/cpp/atomic/memory_order#Release-Acquire_ordering
486#[stable(feature = "rust1", since = "1.0.0")]
487Release,
488/// When coupled with a load, if the loaded value was written by a store operation with
489 /// [`Release`] (or stronger) ordering, then all subsequent operations
490 /// become ordered after that store. In particular, all subsequent loads will see data
491 /// written before the store.
492 ///
493 /// Notice that using this ordering for an operation that combines loads
494 /// and stores leads to a [`Relaxed`] store operation!
495 ///
496 /// This ordering is only applicable for operations that can perform a load.
497 ///
498 /// Corresponds to [`memory_order_acquire`] in C++20.
499 ///
500 /// [`memory_order_acquire`]: https://en.cppreference.com/w/cpp/atomic/memory_order#Release-Acquire_ordering
501#[stable(feature = "rust1", since = "1.0.0")]
502Acquire,
503/// Has the effects of both [`Acquire`] and [`Release`] together:
504 /// For loads it uses [`Acquire`] ordering. For stores it uses the [`Release`] ordering.
505 ///
506 /// Notice that in the case of `compare_and_swap`, it is possible that the operation ends up
507 /// not performing any store and hence it has just [`Acquire`] ordering. However,
508 /// `AcqRel` will never perform [`Relaxed`] accesses.
509 ///
510 /// This ordering is only applicable for operations that combine both loads and stores.
511 ///
512 /// Corresponds to [`memory_order_acq_rel`] in C++20.
513 ///
514 /// [`memory_order_acq_rel`]: https://en.cppreference.com/w/cpp/atomic/memory_order#Release-Acquire_ordering
515#[stable(feature = "rust1", since = "1.0.0")]
516AcqRel,
517/// Like [`Acquire`]/[`Release`]/[`AcqRel`] (for load, store, and load-with-store
518 /// operations, respectively) with the additional guarantee that all threads see all
519 /// sequentially consistent operations in the same order.
520 ///
521 /// Corresponds to [`memory_order_seq_cst`] in C++20.
522 ///
523 /// [`memory_order_seq_cst`]: https://en.cppreference.com/w/cpp/atomic/memory_order#Sequentially-consistent_ordering
524#[stable(feature = "rust1", since = "1.0.0")]
525SeqCst,
526}
527528/// An [`AtomicBool`] initialized to `false`.
529#[cfg(target_has_atomic_load_store = "8")]
530#[stable(feature = "rust1", since = "1.0.0")]
531#[deprecated(
532 since = "1.34.0",
533 note = "the `new` function is now preferred",
534 suggestion = "AtomicBool::new(false)"
535)]
536#[expect(clippy::declare_interior_mutable_const, reason = "legacy atomic initializer")]
537pub const ATOMIC_BOOL_INIT: AtomicBool = AtomicBool::new(false);
538539#[cfg(target_has_atomic_load_store = "8")]
540impl AtomicBool {
541/// Creates a new `AtomicBool`.
542 ///
543 /// # Examples
544 ///
545 /// ```
546 /// use std::sync::atomic::AtomicBool;
547 ///
548 /// let atomic_true = AtomicBool::new(true);
549 /// let atomic_false = AtomicBool::new(false);
550 /// ```
551#[inline]
552 #[stable(feature = "rust1", since = "1.0.0")]
553 #[rustc_const_stable(feature = "const_atomic_new", since = "1.24.0")]
554 #[must_use]
555pub const fn new(v: bool) -> AtomicBool {
556// SAFETY:
557 // `Atomic<T>` is essentially a transparent wrapper around `T`.
558unsafe { transmute(v) }
559 }
560561/// Creates a new `AtomicBool` from a pointer.
562 ///
563 /// # Examples
564 ///
565 /// ```
566 /// use std::sync::atomic::{self, AtomicBool};
567 ///
568 /// // Get a pointer to an allocated value
569 /// let ptr: *mut bool = Box::into_raw(Box::new(false));
570 ///
571 /// assert!(ptr.cast::<AtomicBool>().is_aligned());
572 ///
573 /// {
574 /// // Create an atomic view of the allocated value
575 /// let atomic = unsafe { AtomicBool::from_ptr(ptr) };
576 ///
577 /// // Use `atomic` for atomic operations, possibly share it with other threads
578 /// atomic.store(true, atomic::Ordering::Relaxed);
579 /// }
580 ///
581 /// // It's ok to non-atomically access the value behind `ptr`,
582 /// // since the reference to the atomic ended its lifetime in the block above
583 /// assert_eq!(unsafe { *ptr }, true);
584 ///
585 /// // Deallocate the value
586 /// unsafe { drop(Box::from_raw(ptr)) }
587 /// ```
588 ///
589 /// # Safety
590 ///
591 /// * `ptr` must be aligned to `align_of::<AtomicBool>()` (note that this is always true, since
592 /// `align_of::<AtomicBool>() == 1`).
593 /// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`.
594 /// * You must adhere to the [Memory model for atomic accesses]. In particular, it is not
595 /// allowed to mix conflicting atomic and non-atomic accesses, or atomic accesses of different
596 /// sizes, without synchronization.
597 ///
598 /// [valid]: crate::ptr#safety
599 /// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses
600#[inline]
601 #[stable(feature = "atomic_from_ptr", since = "1.75.0")]
602 #[rustc_const_stable(feature = "const_atomic_from_ptr", since = "1.84.0")]
603pub const unsafe fn from_ptr<'a>(ptr: *mut bool) -> &'a AtomicBool {
604// SAFETY: guaranteed by the caller
605unsafe { &*ptr.cast() }
606 }
607608/// Creates a new pointer to `AtomicBool` from a pointer.
609 ///
610 /// This is useful if you want to do volatile atomic accesses, and thus avoid creating
611 /// a reference to the destination.
612#[inline]
613 #[unstable(feature = "atomic_volatile", issue = "158947")]
614pub const fn from_ptr_raw(ptr: *mut bool) -> *const AtomicBool {
615ptr.cast_const().cast()
616 }
617618/// Returns a mutable reference to the underlying [`bool`].
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 /// use std::sync::atomic::{AtomicBool, Ordering};
627 ///
628 /// let mut some_bool = AtomicBool::new(true);
629 /// assert_eq!(*some_bool.get_mut(), true);
630 /// *some_bool.get_mut() = false;
631 /// assert_eq!(some_bool.load(Ordering::SeqCst), false);
632 /// ```
633#[inline]
634 #[stable(feature = "atomic_access", since = "1.15.0")]
635 #[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
636pub const fn get_mut(&mut self) -> &mut bool {
637// SAFETY: the mutable reference guarantees unique ownership.
638unsafe { &mut *self.as_ptr() }
639 }
640641/// Gets atomic access to a `&mut bool`.
642 ///
643 /// # Examples
644 ///
645 /// ```
646 /// use std::sync::atomic::{AtomicBool, Ordering};
647 ///
648 /// let mut some_bool = true;
649 /// let a = AtomicBool::from_mut(&mut some_bool);
650 /// a.store(false, Ordering::Relaxed);
651 /// assert_eq!(some_bool, false);
652 /// ```
653#[inline]
654 #[cfg(target_has_atomic_primitive_alignment = "8")]
655 #[stable(feature = "atomic_from_mut", since = "1.98.0")]
656 #[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
657pub const fn from_mut(v: &mut bool) -> &mut Self {
658// SAFETY: the mutable reference guarantees unique ownership, and
659 // alignment of both `bool` and `Self` is 1.
660unsafe { &mut *(vas *mut boolas *mut Self) }
661 }
662663/// Gets non-atomic access to a `&mut [AtomicBool]` slice.
664 ///
665 /// This is safe because the mutable reference guarantees that no other threads are
666 /// concurrently accessing the atomic data.
667 ///
668 /// # Examples
669 ///
670 /// ```ignore-wasm
671 /// use std::sync::atomic::{AtomicBool, Ordering};
672 ///
673 /// let mut some_bools = [const { AtomicBool::new(false) }; 10];
674 ///
675 /// let view: &mut [bool] = AtomicBool::get_mut_slice(&mut some_bools);
676 /// assert_eq!(view, [false; 10]);
677 /// view[..5].copy_from_slice(&[true; 5]);
678 ///
679 /// std::thread::scope(|s| {
680 /// for t in &some_bools[..5] {
681 /// s.spawn(move || assert_eq!(t.load(Ordering::Relaxed), true));
682 /// }
683 ///
684 /// for f in &some_bools[5..] {
685 /// s.spawn(move || assert_eq!(f.load(Ordering::Relaxed), false));
686 /// }
687 /// });
688 /// ```
689#[inline]
690 #[stable(feature = "atomic_from_mut", since = "1.98.0")]
691 #[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
692pub const fn get_mut_slice(this: &mut [Self]) -> &mut [bool] {
693// SAFETY: the mutable reference guarantees unique ownership.
694unsafe { &mut *(thisas *mut [Self] as *mut [bool]) }
695 }
696697/// Gets atomic access to a `&mut [bool]` slice.
698 ///
699 /// # Examples
700 ///
701 /// ```rust,ignore-wasm
702 /// use std::sync::atomic::{AtomicBool, Ordering};
703 ///
704 /// let mut some_bools = [false; 10];
705 /// let a = &*AtomicBool::from_mut_slice(&mut some_bools);
706 /// std::thread::scope(|s| {
707 /// for i in 0..a.len() {
708 /// s.spawn(move || a[i].store(true, Ordering::Relaxed));
709 /// }
710 /// });
711 /// assert_eq!(some_bools, [true; 10]);
712 /// ```
713#[inline]
714 #[cfg(target_has_atomic_primitive_alignment = "8")]
715 #[stable(feature = "atomic_from_mut", since = "1.98.0")]
716 #[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
717pub const fn from_mut_slice(v: &mut [bool]) -> &mut [Self] {
718// SAFETY: the mutable reference guarantees unique ownership, and
719 // alignment of both `bool` and `Self` is 1.
720unsafe { &mut *(vas *mut [bool] as *mut [Self]) }
721 }
722723/// Consumes the atomic and returns the contained value.
724 ///
725 /// This is safe because passing `self` by value guarantees that no other threads are
726 /// concurrently accessing the atomic data.
727 ///
728 /// # Examples
729 ///
730 /// ```
731 /// use std::sync::atomic::AtomicBool;
732 ///
733 /// let some_bool = AtomicBool::new(true);
734 /// assert_eq!(some_bool.into_inner(), true);
735 /// ```
736#[inline]
737 #[stable(feature = "atomic_access", since = "1.15.0")]
738 #[rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0")]
739pub const fn into_inner(self) -> bool {
740// SAFETY:
741 // * `Atomic<T>` is essentially a transparent wrapper around `T`.
742 // * all operations on `Atomic<bool>` ensure that `T::Storage` remains
743 // a valid `bool`.
744unsafe { transmute(self) }
745 }
746747/// Loads a value from the bool.
748 ///
749 /// `load` takes an [`Ordering`] argument which describes the memory ordering
750 /// of this operation. Possible values are [`SeqCst`], [`Acquire`] and [`Relaxed`].
751 ///
752 /// # Panics
753 ///
754 /// Panics if `order` is [`Release`] or [`AcqRel`].
755 ///
756 /// # Examples
757 ///
758 /// ```
759 /// use std::sync::atomic::{AtomicBool, Ordering};
760 ///
761 /// let some_bool = AtomicBool::new(true);
762 ///
763 /// assert_eq!(some_bool.load(Ordering::Relaxed), true);
764 /// ```
765#[inline]
766 #[stable(feature = "rust1", since = "1.0.0")]
767 #[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
768 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
769pub const fn load(&self, order: Ordering) -> bool {
770// SAFETY: any data races are prevented by atomic intrinsics and the raw
771 // pointer passed in is valid because we got it from a reference.
772unsafe {
773atomic_load::<_, /* VOLATILE */ false>(self.v.get().cast::<u8>(), order) != 0
774}
775 }
776777/// Perform a volatile atomic load from the bool.
778 ///
779 /// `load_volatile` takes an [`Ordering`] argument which describes the memory ordering
780 /// of this operation. Possible values are [`SeqCst`], [`Acquire`] and [`Relaxed`].
781 ///
782#[doc = "Volatile operations are intended to act on I/O memory. As such, they are considered externally\nobservable events (just like syscalls, but less opaque), and are guaranteed to not be elided or\nreordered by the compiler across other externally observable events. With this in mind, there\nare two cases of usage that need to be distinguished:\n\n- When a volatile operation is used for memory inside an [allocation], it behaves exactly\n like [`load`][Self::load], except for the additional guarantee that it won\'t be elided or\n reordered across other externally observable events (see above). This implies that the\n operation will actually access memory and not e.g. be lowered to reusing data from a\n previous load. Other than that, all the usual rules for memory accesses apply (including\n provenance).\n\n- Volatile operations, however, may also be used to access memory that is _outside_ of any Rust\n allocation. In this use-case, the pointer does *not* have to be [valid] for reads. This is\n typically used for CPU and peripheral registers that must be accessed via an I/O memory mapping,\n most commonly at fixed addresses reserved by the hardware. These often have special semantics\n associated to their manipulation, and cannot be used as general purpose memory. Here, any address\n value is possible, including 0 and [`usize::MAX`], so long as the semantics of such a read are\n well-defined by the target hardware. The provenance of the pointer is irrelevant, and it can be\n created with [`without_provenance`][crate::ptr::without_provenance]. The access is allowed to\n trap, which must immediately abort the process. It can also cause other side-effects, but those\n must not affect Rust-allocated memory in any way.\n\nIn both cases, the access is also considered atomic with the given `order`. This allows\nsynchronization with other threads or devices that share memory with this program.\n\nWhen invoked during const evaluation, this behaves like a regular atomic load. In\nparticular, such reads must always follow the first of the two cases above.\n\n[allocation]: crate::ptr#allocated-object\n"include_str!("./atomic_load_volatile.md")]
783///
784 /// # Safety
785 ///
786 /// Behavior is undefined if any of the following conditions are violated:
787 ///
788 /// * `self` must be [valid] for reads, or `self` must point to memory
789 /// outside of all Rust allocations and reading from that memory must:
790 /// - not trap, and
791 /// - not cause any memory inside a Rust allocation to be modified.
792 ///
793 /// * Reading from `self` must produce a properly initialized value of type `bool`.
794 ///
795 /// [valid]: core::ptr#safety
796 ///
797 /// # Panics
798 ///
799 /// Panics if `order` is [`Release`] or [`AcqRel`].
800#[inline]
801 #[unstable(feature = "atomic_volatile", issue = "158947")]
802 #[rustc_const_unstable(feature = "atomic_volatile", issue = "158947")]
803 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
804pub const unsafe fn load_volatile(self: *const Self, order: Ordering) -> bool {
805// SAFETY: follows from our own safety requirements.
806unsafe {
807atomic_load::<_, /* VOLATILE */ true>(self.cast::<u8>(), order) != 0
808}
809 }
810811/// Stores a value into the bool.
812 ///
813 /// `store` takes an [`Ordering`] argument which describes the memory ordering
814 /// of this operation. Possible values are [`SeqCst`], [`Release`] and [`Relaxed`].
815 ///
816 /// # Panics
817 ///
818 /// Panics if `order` is [`Acquire`] or [`AcqRel`].
819 ///
820 /// # Examples
821 ///
822 /// ```
823 /// use std::sync::atomic::{AtomicBool, Ordering};
824 ///
825 /// let some_bool = AtomicBool::new(true);
826 ///
827 /// some_bool.store(false, Ordering::Relaxed);
828 /// assert_eq!(some_bool.load(Ordering::Relaxed), false);
829 /// ```
830#[inline]
831 #[stable(feature = "rust1", since = "1.0.0")]
832 #[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
833 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
834#[rustc_should_not_be_called_on_const_items]
835pub const fn store(&self, val: bool, order: Ordering) {
836// SAFETY: any data races are prevented by atomic intrinsics and the raw
837 // pointer passed in is valid because we got it from a reference.
838unsafe {
839atomic_store::<_, /* VOLATILE */ false>(self.v.get().cast::<u8>(), valas u8, order);
840 }
841 }
842843/// Performs a volatile atomic store into the bool.
844 ///
845 /// `store_volatile` takes an [`Ordering`] argument which describes the memory ordering
846 /// of this operation. Possible values are [`SeqCst`], [`Release`] and [`Relaxed`].
847 ///
848#[doc = "Volatile operations are intended to act on I/O memory. As such, they are considered externally\nobservable events (just like syscalls), and are guaranteed to not be elided or reordered by the\ncompiler across other externally observable events. With this in mind, there are two cases of\nusage that need to be distinguished:\n\n- When a volatile operation is used for memory inside an [allocation], it behaves exactly like\n [`store`][Self::store], except for the additional guarantee that it won\'t be elided or reordered\n across other externally observable events (see above). This implies that the operation will\n actually access memory and not e.g. be lowered to a register access. Other than that, all the\n usual rules for memory accesses apply (including provenance).\n\n- Volatile operations, however, may also be used to access memory that is _outside_ of any Rust\n allocation. In this use-case, the pointer does *not* have to be [valid] for writes. This is\n typically used for CPU and peripheral registers that must be accessed via an I/O memory mapping,\n most commonly at fixed addresses reserved by the hardware. These often have special semantics\n associated to their manipulation, and cannot be used as general purpose memory. Here, any address\n value is possible, including 0 and [`usize::MAX`], so long as the semantics of such a write are\n well-defined by the target hardware. The provenance of the pointer is irrelevant, and it can be\n created with [`without_provenance_mut`][crate::ptr::without_provenance_mut]. The access is allowed\n to trap, which must immediately abort the process. It can also cause other side-effects, but those\n must not affect Rust-allocated memory in any way.\n\nIn both cases, the access is also considered atomic with the given `order`. This allows\nsynchronization with other threads or devices that share memory with this program.\n\nWhen invoked during const evaluation, this behaves like a regular atomic store. In\nparticular, such reads must always follow the first of the two cases above.\n\n[allocation]: crate::ptr#allocated-object\n"include_str!("./atomic_store_volatile.md")]
849///
850 /// # Safety
851 ///
852 /// Behavior is undefined if any of the following conditions are violated:
853 ///
854 /// * `self` must be either [valid] for writes, or `self` must point to memory
855 /// outside of all Rust allocations and writing to that memory must:
856 /// - not trap, and
857 /// - not cause any memory inside a Rust allocation to be modified.
858 ///
859 /// [valid]: core::ptr#safety
860 ///
861 /// # Panics
862 ///
863 /// Panics if `order` is [`Acquire`] or [`AcqRel`].
864#[inline]
865 #[unstable(feature = "atomic_volatile", issue = "158947")]
866 #[rustc_const_unstable(feature = "atomic_volatile", issue = "158947")]
867 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
868#[rustc_should_not_be_called_on_const_items]
869pub const unsafe fn store_volatile(self: *const Self, val: bool, order: Ordering) {
870// SAFETY: follows from our own safety requirements.
871unsafe {
872atomic_store::<_, /* VOLATILE */ true>(self.cast::<u8>().cast_mut(), valas u8, order);
873 }
874 }
875876/// Stores a value into the bool, returning the previous value.
877 ///
878 /// `swap` takes an [`Ordering`] argument which describes the memory ordering
879 /// of this operation. All ordering modes are possible. Note that using
880 /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
881 /// using [`Release`] makes the load part [`Relaxed`].
882 ///
883 /// **Note:** This method is only available on platforms that support atomic
884 /// operations on `u8`.
885 ///
886 /// # Examples
887 ///
888 /// ```
889 /// use std::sync::atomic::{AtomicBool, Ordering};
890 ///
891 /// let some_bool = AtomicBool::new(true);
892 ///
893 /// assert_eq!(some_bool.swap(false, Ordering::Relaxed), true);
894 /// assert_eq!(some_bool.load(Ordering::Relaxed), false);
895 /// ```
896#[inline]
897 #[stable(feature = "rust1", since = "1.0.0")]
898 #[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
899 #[cfg(target_has_atomic = "8")]
900 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
901#[rustc_should_not_be_called_on_const_items]
902pub const fn swap(&self, val: bool, order: Ordering) -> bool {
903if EMULATE_ATOMIC_BOOL {
904if val { self.fetch_or(true, order) } else { self.fetch_and(false, order) }
905 } else {
906// SAFETY: data races are prevented by atomic intrinsics.
907unsafe { atomic_swap(self.v.get().cast::<u8>(), valas u8, order) != 0 }
908 }
909 }
910911/// Stores a value into the [`bool`] if the current value is the same as the `current` value.
912 ///
913 /// The return value is always the previous value. If it is equal to `current`, then the value
914 /// was updated.
915 ///
916 /// `compare_and_swap` also takes an [`Ordering`] argument which describes the memory
917 /// ordering of this operation. Notice that even when using [`AcqRel`], the operation
918 /// might fail and hence just perform an `Acquire` load, but not have `Release` semantics.
919 /// Using [`Acquire`] makes the store part of this operation [`Relaxed`] if it
920 /// happens, and using [`Release`] makes the load part [`Relaxed`].
921 ///
922 /// **Note:** This method is only available on platforms that support atomic
923 /// operations on `u8`.
924 ///
925 /// # Migrating to `compare_exchange` and `compare_exchange_weak`
926 ///
927 /// `compare_and_swap` is equivalent to `compare_exchange` with the following mapping for
928 /// memory orderings:
929 ///
930 /// Original | Success | Failure
931 /// -------- | ------- | -------
932 /// Relaxed | Relaxed | Relaxed
933 /// Acquire | Acquire | Acquire
934 /// Release | Release | Relaxed
935 /// AcqRel | AcqRel | Acquire
936 /// SeqCst | SeqCst | SeqCst
937 ///
938 /// `compare_and_swap` and `compare_exchange` also differ in their return type. You can use
939 /// `compare_exchange(...).unwrap_or_else(|x| x)` to recover the behavior of `compare_and_swap`,
940 /// but in most cases it is more idiomatic to check whether the return value is `Ok` or `Err`
941 /// rather than to infer success vs failure based on the value that was read.
942 ///
943 /// During migration, consider whether it makes sense to use `compare_exchange_weak` instead.
944 /// `compare_exchange_weak` is allowed to fail spuriously even when the comparison succeeds,
945 /// which allows the compiler to generate better assembly code when the compare and swap
946 /// is used in a loop.
947 ///
948 /// # Examples
949 ///
950 /// ```
951 /// use std::sync::atomic::{AtomicBool, Ordering};
952 ///
953 /// let some_bool = AtomicBool::new(true);
954 ///
955 /// assert_eq!(some_bool.compare_and_swap(true, false, Ordering::Relaxed), true);
956 /// assert_eq!(some_bool.load(Ordering::Relaxed), false);
957 ///
958 /// assert_eq!(some_bool.compare_and_swap(true, true, Ordering::Relaxed), false);
959 /// assert_eq!(some_bool.load(Ordering::Relaxed), false);
960 /// ```
961#[inline]
962 #[stable(feature = "rust1", since = "1.0.0")]
963 #[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
964 #[deprecated(
965 since = "1.50.0",
966 note = "Use `compare_exchange` or `compare_exchange_weak` instead"
967)]
968 #[cfg(target_has_atomic = "8")]
969 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
970#[rustc_should_not_be_called_on_const_items]
971pub const fn compare_and_swap(&self, current: bool, new: bool, order: Ordering) -> bool {
972match self.compare_exchange(current, new, order, strongest_failure_ordering(order)) {
973Ok(x) => x,
974Err(x) => x,
975 }
976 }
977978/// Stores a value into the [`bool`] if the current value is the same as the `current` value.
979 ///
980 /// The return value is a result indicating whether the new value was written and containing
981 /// the previous value. On success this value is guaranteed to be equal to `current`.
982 ///
983 /// `compare_exchange` takes two [`Ordering`] arguments to describe the memory
984 /// ordering of this operation. `success` describes the required ordering for the
985 /// read-modify-write operation that takes place if the comparison with `current` succeeds.
986 /// `failure` describes the required ordering for the load operation that takes place when
987 /// the comparison fails. Using [`Acquire`] as success ordering makes the store part
988 /// of this operation [`Relaxed`], and using [`Release`] makes the successful load
989 /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
990 ///
991 /// **Note:** This method is only available on platforms that support atomic
992 /// operations on `u8`.
993 ///
994 /// # Examples
995 ///
996 /// ```
997 /// use std::sync::atomic::{AtomicBool, Ordering};
998 ///
999 /// let some_bool = AtomicBool::new(true);
1000 ///
1001 /// assert_eq!(some_bool.compare_exchange(true,
1002 /// false,
1003 /// Ordering::Acquire,
1004 /// Ordering::Relaxed),
1005 /// Ok(true));
1006 /// assert_eq!(some_bool.load(Ordering::Relaxed), false);
1007 ///
1008 /// assert_eq!(some_bool.compare_exchange(true, true,
1009 /// Ordering::SeqCst,
1010 /// Ordering::Acquire),
1011 /// Err(false));
1012 /// assert_eq!(some_bool.load(Ordering::Relaxed), false);
1013 /// ```
1014 ///
1015 /// # Considerations
1016 ///
1017 /// `compare_exchange` is a [compare-and-swap operation] and thus exhibits the usual downsides
1018 /// of CAS operations. In particular, a load of the value followed by a successful
1019 /// `compare_exchange` with the previous load *does not ensure* that other threads have not
1020 /// changed the value in the interim. This is usually important when the *equality* check in
1021 /// the `compare_exchange` is being used to check the *identity* of a value, but equality
1022 /// does not necessarily imply identity. In this case, `compare_exchange` can lead to the
1023 /// [ABA problem].
1024 ///
1025 /// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
1026 /// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
1027#[inline]
1028 #[stable(feature = "extended_compare_and_swap", since = "1.10.0")]
1029 #[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
1030 #[doc(alias = "compare_and_swap")]
1031 #[cfg(target_has_atomic = "8")]
1032 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
1033#[rustc_should_not_be_called_on_const_items]
1034pub const fn compare_exchange(
1035&self,
1036 current: bool,
1037 new: bool,
1038 success: Ordering,
1039 failure: Ordering,
1040 ) -> Result<bool, bool> {
1041if EMULATE_ATOMIC_BOOL {
1042// Pick the strongest ordering from success and failure.
1043let order = match (success, failure) {
1044 (SeqCst, _) => SeqCst,
1045 (_, SeqCst) => SeqCst,
1046 (AcqRel, _) => AcqRel,
1047 (_, AcqRel) => {
1048{
crate::panicking::panic_fmt(format_args!("there is no such thing as an acquire-release failure ordering"));
}panic!("there is no such thing as an acquire-release failure ordering")1049 }
1050 (Release, Acquire) => AcqRel,
1051 (Acquire, _) => Acquire,
1052 (_, Acquire) => Acquire,
1053 (Release, Relaxed) => Release,
1054 (_, Release) => {
crate::panicking::panic_fmt(format_args!("there is no such thing as a release failure ordering"));
}panic!("there is no such thing as a release failure ordering"),
1055 (Relaxed, Relaxed) => Relaxed,
1056 };
1057let old = if current == new {
1058// This is a no-op, but we still need to perform the operation
1059 // for memory ordering reasons.
1060self.fetch_or(false, order)
1061 } else {
1062// This sets the value to the new one and returns the old one.
1063self.swap(new, order)
1064 };
1065if old == current { Ok(old) } else { Err(old) }
1066 } else {
1067// SAFETY: data races are prevented by atomic intrinsics.
1068match unsafe {
1069atomic_compare_exchange(
1070self.v.get().cast::<u8>(),
1071currentas u8,
1072newas u8,
1073success,
1074failure,
1075 )
1076 } {
1077Ok(x) => Ok(x != 0),
1078Err(x) => Err(x != 0),
1079 }
1080 }
1081 }
10821083/// Stores a value into the [`bool`] if the current value is the same as the `current` value.
1084 ///
1085 /// Unlike [`AtomicBool::compare_exchange`], this function is allowed to spuriously fail even when the
1086 /// comparison succeeds, which can result in more efficient code on some platforms. The
1087 /// return value is a result indicating whether the new value was written and containing the
1088 /// previous value.
1089 ///
1090 /// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory
1091 /// ordering of this operation. `success` describes the required ordering for the
1092 /// read-modify-write operation that takes place if the comparison with `current` succeeds.
1093 /// `failure` describes the required ordering for the load operation that takes place when
1094 /// the comparison fails. Using [`Acquire`] as success ordering makes the store part
1095 /// of this operation [`Relaxed`], and using [`Release`] makes the successful load
1096 /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
1097 ///
1098 /// **Note:** This method is only available on platforms that support atomic
1099 /// operations on `u8`.
1100 ///
1101 /// # Examples
1102 ///
1103 /// ```
1104 /// use std::sync::atomic::{AtomicBool, Ordering};
1105 ///
1106 /// let val = AtomicBool::new(false);
1107 ///
1108 /// let new = true;
1109 /// let mut old = val.load(Ordering::Relaxed);
1110 /// loop {
1111 /// match val.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) {
1112 /// Ok(_) => break,
1113 /// Err(x) => old = x,
1114 /// }
1115 /// }
1116 /// ```
1117 ///
1118 /// # Considerations
1119 ///
1120 /// `compare_exchange` is a [compare-and-swap operation] and thus exhibits the usual downsides
1121 /// of CAS operations. In particular, a load of the value followed by a successful
1122 /// `compare_exchange` with the previous load *does not ensure* that other threads have not
1123 /// changed the value in the interim. This is usually important when the *equality* check in
1124 /// the `compare_exchange` is being used to check the *identity* of a value, but equality
1125 /// does not necessarily imply identity. In this case, `compare_exchange` can lead to the
1126 /// [ABA problem].
1127 ///
1128 /// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
1129 /// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
1130#[inline]
1131 #[stable(feature = "extended_compare_and_swap", since = "1.10.0")]
1132 #[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
1133 #[doc(alias = "compare_and_swap")]
1134 #[cfg(target_has_atomic = "8")]
1135 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
1136#[rustc_should_not_be_called_on_const_items]
1137pub const fn compare_exchange_weak(
1138&self,
1139 current: bool,
1140 new: bool,
1141 success: Ordering,
1142 failure: Ordering,
1143 ) -> Result<bool, bool> {
1144if EMULATE_ATOMIC_BOOL {
1145return self.compare_exchange(current, new, success, failure);
1146 }
11471148// SAFETY: data races are prevented by atomic intrinsics.
1149match unsafe {
1150atomic_compare_exchange_weak(
1151self.v.get().cast::<u8>(),
1152currentas u8,
1153newas u8,
1154success,
1155failure,
1156 )
1157 } {
1158Ok(x) => Ok(x != 0),
1159Err(x) => Err(x != 0),
1160 }
1161 }
11621163/// Logical "and" with a boolean value.
1164 ///
1165 /// Performs a logical "and" operation on the current value and the argument `val`, and sets
1166 /// the new value to the result.
1167 ///
1168 /// Returns the previous value.
1169 ///
1170 /// `fetch_and` takes an [`Ordering`] argument which describes the memory ordering
1171 /// of this operation. All ordering modes are possible. Note that using
1172 /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
1173 /// using [`Release`] makes the load part [`Relaxed`].
1174 ///
1175 /// **Note:** This method is only available on platforms that support atomic
1176 /// operations on `u8`.
1177 ///
1178 /// # Examples
1179 ///
1180 /// ```
1181 /// use std::sync::atomic::{AtomicBool, Ordering};
1182 ///
1183 /// let foo = AtomicBool::new(true);
1184 /// assert_eq!(foo.fetch_and(false, Ordering::SeqCst), true);
1185 /// assert_eq!(foo.load(Ordering::SeqCst), false);
1186 ///
1187 /// let foo = AtomicBool::new(true);
1188 /// assert_eq!(foo.fetch_and(true, Ordering::SeqCst), true);
1189 /// assert_eq!(foo.load(Ordering::SeqCst), true);
1190 ///
1191 /// let foo = AtomicBool::new(false);
1192 /// assert_eq!(foo.fetch_and(false, Ordering::SeqCst), false);
1193 /// assert_eq!(foo.load(Ordering::SeqCst), false);
1194 /// ```
1195#[inline]
1196 #[stable(feature = "rust1", since = "1.0.0")]
1197 #[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
1198 #[cfg(target_has_atomic = "8")]
1199 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
1200#[rustc_should_not_be_called_on_const_items]
1201pub const fn fetch_and(&self, val: bool, order: Ordering) -> bool {
1202// SAFETY: data races are prevented by atomic intrinsics.
1203unsafe { atomic_and(self.v.get().cast::<u8>(), valas u8, order) != 0 }
1204 }
12051206/// Logical "nand" with a boolean value.
1207 ///
1208 /// Performs a logical "nand" operation on the current value and the argument `val`, and sets
1209 /// the new value to the result.
1210 ///
1211 /// Returns the previous value.
1212 ///
1213 /// `fetch_nand` takes an [`Ordering`] argument which describes the memory ordering
1214 /// of this operation. All ordering modes are possible. Note that using
1215 /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
1216 /// using [`Release`] makes the load part [`Relaxed`].
1217 ///
1218 /// **Note:** This method is only available on platforms that support atomic
1219 /// operations on `u8`.
1220 ///
1221 /// # Examples
1222 ///
1223 /// ```
1224 /// use std::sync::atomic::{AtomicBool, Ordering};
1225 ///
1226 /// let foo = AtomicBool::new(true);
1227 /// assert_eq!(foo.fetch_nand(false, Ordering::SeqCst), true);
1228 /// assert_eq!(foo.load(Ordering::SeqCst), true);
1229 ///
1230 /// let foo = AtomicBool::new(true);
1231 /// assert_eq!(foo.fetch_nand(true, Ordering::SeqCst), true);
1232 /// assert_eq!(foo.load(Ordering::SeqCst) as usize, 0);
1233 /// assert_eq!(foo.load(Ordering::SeqCst), false);
1234 ///
1235 /// let foo = AtomicBool::new(false);
1236 /// assert_eq!(foo.fetch_nand(false, Ordering::SeqCst), false);
1237 /// assert_eq!(foo.load(Ordering::SeqCst), true);
1238 /// ```
1239#[inline]
1240 #[stable(feature = "rust1", since = "1.0.0")]
1241 #[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
1242 #[cfg(target_has_atomic = "8")]
1243 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
1244#[rustc_should_not_be_called_on_const_items]
1245pub const fn fetch_nand(&self, val: bool, order: Ordering) -> bool {
1246// We can't use atomic_nand here because it can result in a bool with
1247 // an invalid value. This happens because the atomic operation is done
1248 // with an 8-bit integer internally, which would set the upper 7 bits.
1249 // So we just use fetch_xor or swap instead.
1250if val {
1251// !(x & true) == !x
1252 // We must invert the bool.
1253self.fetch_xor(true, order)
1254 } else {
1255// !(x & false) == true
1256 // We must set the bool to true.
1257self.swap(true, order)
1258 }
1259 }
12601261/// Logical "or" with a boolean value.
1262 ///
1263 /// Performs a logical "or" operation on the current value and the argument `val`, and sets the
1264 /// new value to the result.
1265 ///
1266 /// Returns the previous value.
1267 ///
1268 /// `fetch_or` takes an [`Ordering`] argument which describes the memory ordering
1269 /// of this operation. All ordering modes are possible. Note that using
1270 /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
1271 /// using [`Release`] makes the load part [`Relaxed`].
1272 ///
1273 /// **Note:** This method is only available on platforms that support atomic
1274 /// operations on `u8`.
1275 ///
1276 /// # Examples
1277 ///
1278 /// ```
1279 /// use std::sync::atomic::{AtomicBool, Ordering};
1280 ///
1281 /// let foo = AtomicBool::new(true);
1282 /// assert_eq!(foo.fetch_or(false, Ordering::SeqCst), true);
1283 /// assert_eq!(foo.load(Ordering::SeqCst), true);
1284 ///
1285 /// let foo = AtomicBool::new(false);
1286 /// assert_eq!(foo.fetch_or(true, Ordering::SeqCst), false);
1287 /// assert_eq!(foo.load(Ordering::SeqCst), true);
1288 ///
1289 /// let foo = AtomicBool::new(false);
1290 /// assert_eq!(foo.fetch_or(false, Ordering::SeqCst), false);
1291 /// assert_eq!(foo.load(Ordering::SeqCst), false);
1292 /// ```
1293#[inline]
1294 #[stable(feature = "rust1", since = "1.0.0")]
1295 #[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
1296 #[cfg(target_has_atomic = "8")]
1297 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
1298#[rustc_should_not_be_called_on_const_items]
1299pub const fn fetch_or(&self, val: bool, order: Ordering) -> bool {
1300// SAFETY: data races are prevented by atomic intrinsics.
1301unsafe { atomic_or(self.v.get().cast::<u8>(), valas u8, order) != 0 }
1302 }
13031304/// Logical "xor" with a boolean value.
1305 ///
1306 /// Performs a logical "xor" operation on the current value and the argument `val`, and sets
1307 /// the new value to the result.
1308 ///
1309 /// Returns the previous value.
1310 ///
1311 /// `fetch_xor` takes an [`Ordering`] argument which describes the memory ordering
1312 /// of this operation. All ordering modes are possible. Note that using
1313 /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
1314 /// using [`Release`] makes the load part [`Relaxed`].
1315 ///
1316 /// **Note:** This method is only available on platforms that support atomic
1317 /// operations on `u8`.
1318 ///
1319 /// # Examples
1320 ///
1321 /// ```
1322 /// use std::sync::atomic::{AtomicBool, Ordering};
1323 ///
1324 /// let foo = AtomicBool::new(true);
1325 /// assert_eq!(foo.fetch_xor(false, Ordering::SeqCst), true);
1326 /// assert_eq!(foo.load(Ordering::SeqCst), true);
1327 ///
1328 /// let foo = AtomicBool::new(true);
1329 /// assert_eq!(foo.fetch_xor(true, Ordering::SeqCst), true);
1330 /// assert_eq!(foo.load(Ordering::SeqCst), false);
1331 ///
1332 /// let foo = AtomicBool::new(false);
1333 /// assert_eq!(foo.fetch_xor(false, Ordering::SeqCst), false);
1334 /// assert_eq!(foo.load(Ordering::SeqCst), false);
1335 /// ```
1336#[inline]
1337 #[stable(feature = "rust1", since = "1.0.0")]
1338 #[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
1339 #[cfg(target_has_atomic = "8")]
1340 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
1341#[rustc_should_not_be_called_on_const_items]
1342pub const fn fetch_xor(&self, val: bool, order: Ordering) -> bool {
1343// SAFETY: data races are prevented by atomic intrinsics.
1344unsafe { atomic_xor(self.v.get().cast::<u8>(), valas u8, order) != 0 }
1345 }
13461347/// Logical "not" with a boolean value.
1348 ///
1349 /// Performs a logical "not" operation on the current value, and sets
1350 /// the new value to the result.
1351 ///
1352 /// Returns the previous value.
1353 ///
1354 /// `fetch_not` takes an [`Ordering`] argument which describes the memory ordering
1355 /// of this operation. All ordering modes are possible. Note that using
1356 /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
1357 /// using [`Release`] makes the load part [`Relaxed`].
1358 ///
1359 /// **Note:** This method is only available on platforms that support atomic
1360 /// operations on `u8`.
1361 ///
1362 /// # Examples
1363 ///
1364 /// ```
1365 /// use std::sync::atomic::{AtomicBool, Ordering};
1366 ///
1367 /// let foo = AtomicBool::new(true);
1368 /// assert_eq!(foo.fetch_not(Ordering::SeqCst), true);
1369 /// assert_eq!(foo.load(Ordering::SeqCst), false);
1370 ///
1371 /// let foo = AtomicBool::new(false);
1372 /// assert_eq!(foo.fetch_not(Ordering::SeqCst), false);
1373 /// assert_eq!(foo.load(Ordering::SeqCst), true);
1374 /// ```
1375#[inline]
1376 #[stable(feature = "atomic_bool_fetch_not", since = "1.81.0")]
1377 #[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
1378 #[cfg(target_has_atomic = "8")]
1379 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
1380#[rustc_should_not_be_called_on_const_items]
1381pub const fn fetch_not(&self, order: Ordering) -> bool {
1382self.fetch_xor(true, order)
1383 }
13841385/// Returns a mutable pointer to the underlying [`bool`].
1386 ///
1387 /// Doing non-atomic reads and writes on the resulting boolean can be a data race.
1388 /// This method is mostly useful for FFI, where the function signature may use
1389 /// `*mut bool` instead of `&AtomicBool`.
1390 ///
1391 /// Returning an `*mut` pointer from a shared reference to this atomic is safe because the
1392 /// atomic types work with interior mutability. All modifications of an atomic change the value
1393 /// through a shared reference, and can do so safely as long as they use atomic operations. Any
1394 /// use of the returned raw pointer requires an `unsafe` block and still has to uphold the
1395 /// requirements of the [memory model].
1396 ///
1397 /// # Examples
1398 ///
1399 /// ```ignore (extern-declaration)
1400 /// # fn main() {
1401 /// use std::sync::atomic::AtomicBool;
1402 ///
1403 /// extern "C" {
1404 /// fn my_atomic_op(arg: *mut bool);
1405 /// }
1406 ///
1407 /// let mut atomic = AtomicBool::new(true);
1408 /// unsafe {
1409 /// my_atomic_op(atomic.as_ptr());
1410 /// }
1411 /// # }
1412 /// ```
1413 ///
1414 /// [memory model]: self#memory-model-for-atomic-accesses
1415#[inline]
1416 #[stable(feature = "atomic_as_ptr", since = "1.70.0")]
1417 #[rustc_const_stable(feature = "atomic_as_ptr", since = "1.70.0")]
1418 #[rustc_never_returns_null_ptr]
1419 #[rustc_should_not_be_called_on_const_items]
1420pub const fn as_ptr(&self) -> *mut bool {
1421self.v.get().cast()
1422 }
14231424/// An alias for [`AtomicBool::try_update`].
1425#[inline]
1426 #[stable(feature = "atomic_fetch_update", since = "1.53.0")]
1427 #[cfg(target_has_atomic = "8")]
1428 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
1429#[rustc_should_not_be_called_on_const_items]
1430 #[deprecated(
1431 since = "1.99.0",
1432 note = "renamed to `try_update` for consistency",
1433 suggestion = "try_update"
1434)]
1435pub fn fetch_update<F>(
1436&self,
1437 set_order: Ordering,
1438 fetch_order: Ordering,
1439 f: F,
1440 ) -> Result<bool, bool>
1441where
1442F: FnMut(bool) -> Option<bool>,
1443 {
1444self.try_update(set_order, fetch_order, f)
1445 }
14461447/// Fetches the value, and applies a function to it that returns an optional
1448 /// new value. Returns a `Result` of `Ok(previous_value)` if the function
1449 /// returned `Some(_)`, else `Err(previous_value)`.
1450 ///
1451 /// See also: [`update`](`AtomicBool::update`).
1452 ///
1453 /// Note: This may call the function multiple times if the value has been
1454 /// changed from other threads in the meantime, as long as the function
1455 /// returns `Some(_)`, but the function will have been applied only once to
1456 /// the stored value.
1457 ///
1458 /// `try_update` takes two [`Ordering`] arguments to describe the memory
1459 /// ordering of this operation. The first describes the required ordering for
1460 /// when the operation finally succeeds while the second describes the
1461 /// required ordering for loads. These correspond to the success and failure
1462 /// orderings of [`AtomicBool::compare_exchange`] respectively.
1463 ///
1464 /// Using [`Acquire`] as success ordering makes the store part of this
1465 /// operation [`Relaxed`], and using [`Release`] makes the final successful
1466 /// load [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`],
1467 /// [`Acquire`] or [`Relaxed`].
1468 ///
1469 /// **Note:** This method is only available on platforms that support atomic
1470 /// operations on `u8`.
1471 ///
1472 /// # Considerations
1473 ///
1474 /// This method is not magic; it is not provided by the hardware, and does not act like a
1475 /// critical section or mutex.
1476 ///
1477 /// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
1478 /// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem].
1479 ///
1480 /// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
1481 /// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
1482 ///
1483 /// # Examples
1484 ///
1485 /// ```rust
1486 /// use std::sync::atomic::{AtomicBool, Ordering};
1487 ///
1488 /// let x = AtomicBool::new(false);
1489 /// assert_eq!(x.try_update(Ordering::SeqCst, Ordering::SeqCst, |_| None), Err(false));
1490 /// assert_eq!(x.try_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(!x)), Ok(false));
1491 /// assert_eq!(x.try_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(!x)), Ok(true));
1492 /// assert_eq!(x.load(Ordering::SeqCst), false);
1493 /// ```
1494#[inline]
1495 #[stable(feature = "atomic_try_update", since = "1.95.0")]
1496 #[cfg(target_has_atomic = "8")]
1497 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
1498#[rustc_should_not_be_called_on_const_items]
1499pub fn try_update(
1500&self,
1501 set_order: Ordering,
1502 fetch_order: Ordering,
1503mut f: impl FnMut(bool) -> Option<bool>,
1504 ) -> Result<bool, bool> {
1505let mut prev = self.load(fetch_order);
1506while let Some(next) = f(prev) {
1507match self.compare_exchange_weak(prev, next, set_order, fetch_order) {
1508 x @ Ok(_) => return x,
1509Err(next_prev) => prev = next_prev,
1510 }
1511 }
1512Err(prev)
1513 }
15141515/// Fetches the value, and applies a function to it that returns a new value.
1516 /// The new value is stored and the old value is returned.
1517 ///
1518 /// See also: [`try_update`](`AtomicBool::try_update`).
1519 ///
1520 /// Note: This may call the function multiple times if the value has been changed from other threads in
1521 /// the meantime, but the function will have been applied only once to the stored value.
1522 ///
1523 /// `update` takes two [`Ordering`] arguments to describe the memory
1524 /// ordering of this operation. The first describes the required ordering for
1525 /// when the operation finally succeeds while the second describes the
1526 /// required ordering for loads. These correspond to the success and failure
1527 /// orderings of [`AtomicBool::compare_exchange`] respectively.
1528 ///
1529 /// Using [`Acquire`] as success ordering makes the store part
1530 /// of this operation [`Relaxed`], and using [`Release`] makes the final successful load
1531 /// [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
1532 ///
1533 /// **Note:** This method is only available on platforms that support atomic operations on `u8`.
1534 ///
1535 /// # Considerations
1536 ///
1537 /// This method is not magic; it is not provided by the hardware, and does not act like a
1538 /// critical section or mutex.
1539 ///
1540 /// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
1541 /// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem].
1542 ///
1543 /// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
1544 /// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
1545 ///
1546 /// # Examples
1547 ///
1548 /// ```rust
1549 ///
1550 /// use std::sync::atomic::{AtomicBool, Ordering};
1551 ///
1552 /// let x = AtomicBool::new(false);
1553 /// assert_eq!(x.update(Ordering::SeqCst, Ordering::SeqCst, |x| !x), false);
1554 /// assert_eq!(x.update(Ordering::SeqCst, Ordering::SeqCst, |x| !x), true);
1555 /// assert_eq!(x.load(Ordering::SeqCst), false);
1556 /// ```
1557#[inline]
1558 #[stable(feature = "atomic_try_update", since = "1.95.0")]
1559 #[cfg(target_has_atomic = "8")]
1560 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
1561#[rustc_should_not_be_called_on_const_items]
1562pub fn update(
1563&self,
1564 set_order: Ordering,
1565 fetch_order: Ordering,
1566mut f: impl FnMut(bool) -> bool,
1567 ) -> bool {
1568let mut prev = self.load(fetch_order);
1569loop {
1570match self.compare_exchange_weak(prev, f(prev), set_order, fetch_order) {
1571Ok(x) => break x,
1572Err(next_prev) => prev = next_prev,
1573 }
1574 }
1575 }
1576}
15771578#[cfg(target_has_atomic_load_store = "ptr")]
1579impl<T> AtomicPtr<T> {
1580/// Creates a new `AtomicPtr`.
1581 ///
1582 /// # Examples
1583 ///
1584 /// ```
1585 /// use std::sync::atomic::AtomicPtr;
1586 ///
1587 /// let ptr = &mut 5;
1588 /// let atomic_ptr = AtomicPtr::new(ptr);
1589 /// ```
1590#[inline]
1591 #[stable(feature = "rust1", since = "1.0.0")]
1592 #[rustc_const_stable(feature = "const_atomic_new", since = "1.24.0")]
1593pub const fn new(p: *mut T) -> AtomicPtr<T> {
1594// SAFETY:
1595 // `Atomic<T>` is essentially a transparent wrapper around `T`.
1596unsafe { transmute(p) }
1597 }
15981599/// Creates a new `AtomicPtr` from a pointer.
1600 ///
1601 /// # Examples
1602 ///
1603 /// ```
1604 /// use std::sync::atomic::{self, AtomicPtr};
1605 ///
1606 /// // Get a pointer to an allocated value
1607 /// let ptr: *mut *mut u8 = Box::into_raw(Box::new(std::ptr::null_mut()));
1608 ///
1609 /// assert!(ptr.cast::<AtomicPtr<u8>>().is_aligned());
1610 ///
1611 /// {
1612 /// // Create an atomic view of the allocated value
1613 /// let atomic = unsafe { AtomicPtr::from_ptr(ptr) };
1614 ///
1615 /// // Use `atomic` for atomic operations, possibly share it with other threads
1616 /// atomic.store(std::ptr::NonNull::dangling().as_ptr(), atomic::Ordering::Relaxed);
1617 /// }
1618 ///
1619 /// // It's ok to non-atomically access the value behind `ptr`,
1620 /// // since the reference to the atomic ended its lifetime in the block above
1621 /// assert!(!unsafe { *ptr }.is_null());
1622 ///
1623 /// // Deallocate the value
1624 /// unsafe { drop(Box::from_raw(ptr)) }
1625 /// ```
1626 ///
1627 /// # Safety
1628 ///
1629 /// * `ptr` must be aligned to `align_of::<AtomicPtr<T>>()` (note that on some platforms this
1630 /// can be bigger than `align_of::<*mut T>()`).
1631 /// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`.
1632 /// * You must adhere to the [Memory model for atomic accesses]. In particular, it is not
1633 /// allowed to mix conflicting atomic and non-atomic accesses, or atomic accesses of different
1634 /// sizes, without synchronization.
1635 ///
1636 /// [valid]: crate::ptr#safety
1637 /// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses
1638#[inline]
1639 #[stable(feature = "atomic_from_ptr", since = "1.75.0")]
1640 #[rustc_const_stable(feature = "const_atomic_from_ptr", since = "1.84.0")]
1641pub const unsafe fn from_ptr<'a>(ptr: *mut *mut T) -> &'a AtomicPtr<T> {
1642// SAFETY: guaranteed by the caller
1643unsafe { &*ptr.cast() }
1644 }
16451646/// Creates a new pointer to `AtomicPtr` from a pointer.
1647 ///
1648 /// This is useful if you want to do volatile atomic accesses, and thus avoid creating
1649 /// a reference to the destination.
1650#[inline]
1651 #[unstable(feature = "atomic_volatile", issue = "158947")]
1652pub const fn from_ptr_raw(ptr: *mut *mut T) -> *const AtomicPtr<T> {
1653ptr.cast_const().cast()
1654 }
16551656/// Creates a new `AtomicPtr` initialized with a null pointer.
1657 ///
1658 /// # Examples
1659 ///
1660 /// ```
1661 /// #![feature(atomic_ptr_null)]
1662 /// use std::sync::atomic::{AtomicPtr, Ordering};
1663 ///
1664 /// let atomic_ptr = AtomicPtr::<()>::null();
1665 /// assert!(atomic_ptr.load(Ordering::Relaxed).is_null());
1666 /// ```
1667#[inline]
1668 #[must_use]
1669 #[unstable(feature = "atomic_ptr_null", issue = "150733")]
1670pub const fn null() -> AtomicPtr<T> {
1671AtomicPtr::new(crate::ptr::null_mut())
1672 }
16731674/// Returns a mutable reference to the underlying pointer.
1675 ///
1676 /// This is safe because the mutable reference guarantees that no other threads are
1677 /// concurrently accessing the atomic data.
1678 ///
1679 /// # Examples
1680 ///
1681 /// ```
1682 /// use std::sync::atomic::{AtomicPtr, Ordering};
1683 ///
1684 /// let mut data = 10;
1685 /// let mut atomic_ptr = AtomicPtr::new(&mut data);
1686 /// let mut other_data = 5;
1687 /// *atomic_ptr.get_mut() = &mut other_data;
1688 /// assert_eq!(unsafe { *atomic_ptr.load(Ordering::SeqCst) }, 5);
1689 /// ```
1690#[inline]
1691 #[stable(feature = "atomic_access", since = "1.15.0")]
1692 #[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
1693pub const fn get_mut(&mut self) -> &mut *mut T {
1694// SAFETY:
1695 // `Atomic<T>` is essentially a transparent wrapper around `T`.
1696unsafe { &mut *self.as_ptr() }
1697 }
16981699/// Gets atomic access to a pointer.
1700 ///
1701 /// **Note:** This function is only available on targets where `AtomicPtr<T>` has the same alignment as `*const T`
1702 ///
1703 /// # Examples
1704 ///
1705 /// ```
1706 /// use std::sync::atomic::{AtomicPtr, Ordering};
1707 ///
1708 /// let mut data = 123;
1709 /// let mut some_ptr = &mut data as *mut i32;
1710 /// let a = AtomicPtr::from_mut(&mut some_ptr);
1711 /// let mut other_data = 456;
1712 /// a.store(&mut other_data, Ordering::Relaxed);
1713 /// assert_eq!(unsafe { *some_ptr }, 456);
1714 /// ```
1715#[inline]
1716 #[cfg(target_has_atomic_primitive_alignment = "ptr")]
1717 #[stable(feature = "atomic_from_mut", since = "1.98.0")]
1718 #[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
1719pub const fn from_mut(v: &mut *mut T) -> &mut Self {
1720let [] = [(); align_of::<AtomicPtr<()>>() - align_of::<*mut ()>()];
1721// SAFETY:
1722 // - the mutable reference guarantees unique ownership.
1723 // - the alignment of `*mut T` and `Self` is the same on all platforms
1724 // supported by rust, as verified above.
1725unsafe { &mut *(vas *mut *mut T as *mut Self) }
1726 }
17271728/// Gets non-atomic access to a `&mut [AtomicPtr]` slice.
1729 ///
1730 /// This is safe because the mutable reference guarantees that no other threads are
1731 /// concurrently accessing the atomic data.
1732 ///
1733 /// # Examples
1734 ///
1735 /// ```ignore-wasm
1736 /// use std::ptr::null_mut;
1737 /// use std::sync::atomic::{AtomicPtr, Ordering};
1738 ///
1739 /// let mut some_ptrs = [const { AtomicPtr::new(null_mut::<String>()) }; 10];
1740 ///
1741 /// let view: &mut [*mut String] = AtomicPtr::get_mut_slice(&mut some_ptrs);
1742 /// assert_eq!(view, [null_mut::<String>(); 10]);
1743 /// view
1744 /// .iter_mut()
1745 /// .enumerate()
1746 /// .for_each(|(i, ptr)| *ptr = Box::into_raw(Box::new(format!("iteration#{i}"))));
1747 ///
1748 /// std::thread::scope(|s| {
1749 /// for ptr in &some_ptrs {
1750 /// s.spawn(move || {
1751 /// let ptr = ptr.load(Ordering::Relaxed);
1752 /// assert!(!ptr.is_null());
1753 ///
1754 /// let name = unsafe { Box::from_raw(ptr) };
1755 /// println!("Hello, {name}!");
1756 /// });
1757 /// }
1758 /// });
1759 /// ```
1760#[inline]
1761 #[stable(feature = "atomic_from_mut", since = "1.98.0")]
1762 #[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
1763pub const fn get_mut_slice(this: &mut [Self]) -> &mut [*mut T] {
1764// SAFETY: the mutable reference guarantees unique ownership.
1765unsafe { &mut *(thisas *mut [Self] as *mut [*mut T]) }
1766 }
17671768/// Gets atomic access to a slice of pointers.
1769 ///
1770 /// **Note:** This function is only available on targets where `AtomicPtr<T>` has the same alignment as `*const T`
1771 ///
1772 /// # Examples
1773 ///
1774 /// ```ignore-wasm
1775 /// use std::ptr::null_mut;
1776 /// use std::sync::atomic::{AtomicPtr, Ordering};
1777 ///
1778 /// let mut some_ptrs = [null_mut::<String>(); 10];
1779 /// let a = &*AtomicPtr::from_mut_slice(&mut some_ptrs);
1780 /// std::thread::scope(|s| {
1781 /// for i in 0..a.len() {
1782 /// s.spawn(move || {
1783 /// let name = Box::new(format!("thread{i}"));
1784 /// a[i].store(Box::into_raw(name), Ordering::Relaxed);
1785 /// });
1786 /// }
1787 /// });
1788 /// for p in some_ptrs {
1789 /// assert!(!p.is_null());
1790 /// let name = unsafe { Box::from_raw(p) };
1791 /// println!("Hello, {name}!");
1792 /// }
1793 /// ```
1794#[inline]
1795 #[cfg(target_has_atomic_primitive_alignment = "ptr")]
1796 #[stable(feature = "atomic_from_mut", since = "1.98.0")]
1797 #[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
1798pub const fn from_mut_slice(v: &mut [*mut T]) -> &mut [Self] {
1799// SAFETY:
1800 // - the mutable reference guarantees unique ownership.
1801 // - the alignment of `*mut T` and `Self` is the same on all platforms
1802 // supported by rust, as verified above.
1803unsafe { &mut *(vas *mut [*mut T] as *mut [Self]) }
1804 }
18051806/// Consumes the atomic and returns the contained value.
1807 ///
1808 /// This is safe because passing `self` by value guarantees that no other threads are
1809 /// concurrently accessing the atomic data.
1810 ///
1811 /// # Examples
1812 ///
1813 /// ```
1814 /// use std::sync::atomic::AtomicPtr;
1815 ///
1816 /// let mut data = 5;
1817 /// let atomic_ptr = AtomicPtr::new(&mut data);
1818 /// assert_eq!(unsafe { *atomic_ptr.into_inner() }, 5);
1819 /// ```
1820#[inline]
1821 #[stable(feature = "atomic_access", since = "1.15.0")]
1822 #[rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0")]
1823pub const fn into_inner(self) -> *mut T {
1824// SAFETY:
1825 // `Atomic<T>` is essentially a transparent wrapper around `T`.
1826unsafe { transmute(self) }
1827 }
18281829/// Loads a value from the pointer.
1830 ///
1831 /// `load` takes an [`Ordering`] argument which describes the memory ordering
1832 /// of this operation. Possible values are [`SeqCst`], [`Acquire`] and [`Relaxed`].
1833 ///
1834 /// # Panics
1835 ///
1836 /// Panics if `order` is [`Release`] or [`AcqRel`].
1837 ///
1838 /// # Examples
1839 ///
1840 /// ```
1841 /// use std::sync::atomic::{AtomicPtr, Ordering};
1842 ///
1843 /// let ptr = &mut 5;
1844 /// let some_ptr = AtomicPtr::new(ptr);
1845 ///
1846 /// let value = some_ptr.load(Ordering::Relaxed);
1847 /// ```
1848#[inline]
1849 #[stable(feature = "rust1", since = "1.0.0")]
1850 #[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
1851 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
1852pub const fn load(&self, order: Ordering) -> *mut T {
1853// SAFETY: data races are prevented by atomic intrinsics.
1854unsafe {
1855atomic_load::<_, /* VOLATILE */ false>(self.as_ptr(), order)
1856 }
1857 }
18581859/// Perform a volatile atomic load from the pointer.
1860 ///
1861 /// `load_volatile` takes an [`Ordering`] argument which describes the memory ordering
1862 /// of this operation. Possible values are [`SeqCst`], [`Acquire`] and [`Relaxed`].
1863 ///
1864#[doc = "Volatile operations are intended to act on I/O memory. As such, they are considered externally\nobservable events (just like syscalls, but less opaque), and are guaranteed to not be elided or\nreordered by the compiler across other externally observable events. With this in mind, there\nare two cases of usage that need to be distinguished:\n\n- When a volatile operation is used for memory inside an [allocation], it behaves exactly\n like [`load`][Self::load], except for the additional guarantee that it won\'t be elided or\n reordered across other externally observable events (see above). This implies that the\n operation will actually access memory and not e.g. be lowered to reusing data from a\n previous load. Other than that, all the usual rules for memory accesses apply (including\n provenance).\n\n- Volatile operations, however, may also be used to access memory that is _outside_ of any Rust\n allocation. In this use-case, the pointer does *not* have to be [valid] for reads. This is\n typically used for CPU and peripheral registers that must be accessed via an I/O memory mapping,\n most commonly at fixed addresses reserved by the hardware. These often have special semantics\n associated to their manipulation, and cannot be used as general purpose memory. Here, any address\n value is possible, including 0 and [`usize::MAX`], so long as the semantics of such a read are\n well-defined by the target hardware. The provenance of the pointer is irrelevant, and it can be\n created with [`without_provenance`][crate::ptr::without_provenance]. The access is allowed to\n trap, which must immediately abort the process. It can also cause other side-effects, but those\n must not affect Rust-allocated memory in any way.\n\nIn both cases, the access is also considered atomic with the given `order`. This allows\nsynchronization with other threads or devices that share memory with this program.\n\nWhen invoked during const evaluation, this behaves like a regular atomic load. In\nparticular, such reads must always follow the first of the two cases above.\n\n[allocation]: crate::ptr#allocated-object\n"include_str!("./atomic_load_volatile.md")]
1865///
1866 /// # Safety
1867 ///
1868 /// Behavior is undefined if any of the following conditions are violated:
1869 ///
1870 /// * `self` must be [valid] for reads, or `self` must point to memory
1871 /// outside of all Rust allocations and reading from that memory must:
1872 /// - not trap, and
1873 /// - not cause any memory inside a Rust allocation to be modified.
1874 ///
1875 /// * `self` must be aligned to `align_of::<AtomicPtr<T>>()` (note that on some platforms this
1876 /// can be bigger than `align_of::<*mut T>()`).
1877 ///
1878 /// * Reading from `self` must produce a properly initialized value of type `*mut T`.
1879 ///
1880 /// [valid]: core::ptr#safety
1881 ///
1882 /// # Panics
1883 ///
1884 /// Panics if `order` is [`Release`] or [`AcqRel`].
1885 ///
1886 /// # Examples
1887 ///
1888 /// Assuming an MMIO region at `MMIO_ADDR` that belongs to a device with direct memory
1889 /// access, we may receive a buffer in shared memory from that device as follows:
1890 ///
1891 /// ```rust,no_run
1892 /// #![feature(atomic_volatile)]
1893 /// use std::sync::atomic::{fence, AtomicPtr, Ordering};
1894 /// use std::ptr;
1895 ///
1896 /// const MMIO_ADDR: *mut *mut u8 = ptr::without_provenance_mut(0xCAF0);
1897 /// let atomic_ptr = AtomicPtr::<u8>::from_ptr_raw(MMIO_ADDR);
1898 ///
1899 /// // Spin until we see a non-zero value.
1900 /// let buf = 'buf: loop {
1901 /// let buf = unsafe { atomic_ptr.load_volatile(Ordering::Relaxed) };
1902 /// if !buf.is_null() {
1903 /// break 'buf buf;
1904 /// }
1905 /// };
1906 /// // Synchronize with the store whose value we just read.
1907 /// // Note: a standard acquire fence may not be sufficient to synchronize with DMA devices.
1908 /// // Depending on your target, you may have to use inline assembly to emit a special fence.
1909 /// fence(Ordering::Acquire);
1910 ///
1911 /// // Now process the data in `buf`.
1912 /// ```
1913#[inline]
1914 #[unstable(feature = "atomic_volatile", issue = "158947")]
1915 #[rustc_const_unstable(feature = "atomic_volatile", issue = "158947")]
1916 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
1917pub const unsafe fn load_volatile(self: *const Self, order: Ordering) -> *mut T {
1918// SAFETY: follows from our own safety requirements.
1919unsafe {
1920atomic_load::<_, /* VOLATILE */ true>(self.cast::<*mut T>(), order)
1921 }
1922 }
19231924/// Stores a value into the pointer.
1925 ///
1926 /// `store` takes an [`Ordering`] argument which describes the memory ordering
1927 /// of this operation. Possible values are [`SeqCst`], [`Release`] and [`Relaxed`].
1928 ///
1929 /// # Panics
1930 ///
1931 /// Panics if `order` is [`Acquire`] or [`AcqRel`].
1932 ///
1933 /// # Examples
1934 ///
1935 /// ```
1936 /// use std::sync::atomic::{AtomicPtr, Ordering};
1937 ///
1938 /// let ptr = &mut 5;
1939 /// let some_ptr = AtomicPtr::new(ptr);
1940 ///
1941 /// let other_ptr = &mut 10;
1942 ///
1943 /// some_ptr.store(other_ptr, Ordering::Relaxed);
1944 /// ```
1945#[inline]
1946 #[stable(feature = "rust1", since = "1.0.0")]
1947 #[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
1948 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
1949#[rustc_should_not_be_called_on_const_items]
1950pub const fn store(&self, ptr: *mut T, order: Ordering) {
1951// SAFETY: data races are prevented by atomic intrinsics.
1952unsafe {
1953atomic_store::<_, /* VOLATILE */ false>(self.as_ptr(), ptr, order);
1954 }
1955 }
19561957/// Performs a volatile atomic store into the pointer.
1958 ///
1959 /// `store_volatile` takes an [`Ordering`] argument which describes the memory ordering
1960 /// of this operation. Possible values are [`SeqCst`], [`Release`] and [`Relaxed`].
1961 ///
1962#[doc = "Volatile operations are intended to act on I/O memory. As such, they are considered externally\nobservable events (just like syscalls), and are guaranteed to not be elided or reordered by the\ncompiler across other externally observable events. With this in mind, there are two cases of\nusage that need to be distinguished:\n\n- When a volatile operation is used for memory inside an [allocation], it behaves exactly like\n [`store`][Self::store], except for the additional guarantee that it won\'t be elided or reordered\n across other externally observable events (see above). This implies that the operation will\n actually access memory and not e.g. be lowered to a register access. Other than that, all the\n usual rules for memory accesses apply (including provenance).\n\n- Volatile operations, however, may also be used to access memory that is _outside_ of any Rust\n allocation. In this use-case, the pointer does *not* have to be [valid] for writes. This is\n typically used for CPU and peripheral registers that must be accessed via an I/O memory mapping,\n most commonly at fixed addresses reserved by the hardware. These often have special semantics\n associated to their manipulation, and cannot be used as general purpose memory. Here, any address\n value is possible, including 0 and [`usize::MAX`], so long as the semantics of such a write are\n well-defined by the target hardware. The provenance of the pointer is irrelevant, and it can be\n created with [`without_provenance_mut`][crate::ptr::without_provenance_mut]. The access is allowed\n to trap, which must immediately abort the process. It can also cause other side-effects, but those\n must not affect Rust-allocated memory in any way.\n\nIn both cases, the access is also considered atomic with the given `order`. This allows\nsynchronization with other threads or devices that share memory with this program.\n\nWhen invoked during const evaluation, this behaves like a regular atomic store. In\nparticular, such reads must always follow the first of the two cases above.\n\n[allocation]: crate::ptr#allocated-object\n"include_str!("./atomic_store_volatile.md")]
1963///
1964 /// # Safety
1965 ///
1966 /// Behavior is undefined if any of the following conditions are violated:
1967 ///
1968 /// * `self` must be either [valid] for writes, or `self` must point to memory
1969 /// outside of all Rust allocations and writing to that memory must:
1970 /// - not trap, and
1971 /// - not cause any memory inside a Rust allocation to be modified.
1972 ///
1973 /// * `self` must be aligned to `align_of::<AtomicPtr<T>>()` (note that on some platforms this
1974 /// can be bigger than `align_of::<*mut T>()`).
1975 ///
1976 /// [valid]: core::ptr#safety
1977 ///
1978 /// # Panics
1979 ///
1980 /// Panics if `order` is [`Acquire`] or [`AcqRel`].
1981 ///
1982 /// # Examples
1983 ///
1984 /// Assuming an MMIO region at `MMIO_ADDR` that belongs to a device with direct memory
1985 /// access, we may submit a buffer in shared memory to that device as follows:
1986 ///
1987 /// ```rust,no_run
1988 /// #![feature(atomic_volatile)]
1989 /// use std::sync::atomic::{fence, AtomicPtr, Ordering};
1990 /// use std::ptr;
1991 ///
1992 /// const MMIO_ADDR: *mut *mut u8 = ptr::without_provenance_mut(0xCAF0);
1993 /// let atomic_ptr = AtomicPtr::<u8>::from_ptr_raw(MMIO_ADDR);
1994 ///
1995 /// // Prepare some data for the DMA device.
1996 /// # fn get_dma_buffer() -> *mut u8 { panic!() }
1997 /// let buf = get_dma_buffer();
1998 ///
1999 /// // Ensure the other side can synchronize with the store we do below.
2000 /// // Note: a standard release fence may not be sufficient to synchronize with DMA devices.
2001 /// // Depending on your target, you may have to use inline assembly to emit a special fence.
2002 /// fence(Ordering::Release);
2003 ///
2004 /// unsafe { atomic_ptr.store_volatile(buf, Ordering::Relaxed) };
2005 /// ```
2006#[inline]
2007 #[unstable(feature = "atomic_volatile", issue = "158947")]
2008 #[rustc_const_unstable(feature = "atomic_volatile", issue = "158947")]
2009 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
2010#[rustc_should_not_be_called_on_const_items]
2011pub const unsafe fn store_volatile(self: *const Self, ptr: *mut T, order: Ordering) {
2012// SAFETY: follows from our own safety requirements.
2013unsafe {
2014atomic_store::<_, /* VOLATILE */ true>(self.cast::<*mut T>().cast_mut(), ptr, order);
2015 }
2016 }
20172018/// Stores a value into the pointer, returning the previous value.
2019 ///
2020 /// `swap` takes an [`Ordering`] argument which describes the memory ordering
2021 /// of this operation. All ordering modes are possible. Note that using
2022 /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
2023 /// using [`Release`] makes the load part [`Relaxed`].
2024 ///
2025 /// **Note:** This method is only available on platforms that support atomic
2026 /// operations on pointers.
2027 ///
2028 /// # Examples
2029 ///
2030 /// ```
2031 /// use std::sync::atomic::{AtomicPtr, Ordering};
2032 ///
2033 /// let ptr = &mut 5;
2034 /// let some_ptr = AtomicPtr::new(ptr);
2035 ///
2036 /// let other_ptr = &mut 10;
2037 ///
2038 /// let value = some_ptr.swap(other_ptr, Ordering::Relaxed);
2039 /// ```
2040#[inline]
2041 #[stable(feature = "rust1", since = "1.0.0")]
2042 #[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
2043 #[cfg(target_has_atomic = "ptr")]
2044 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
2045#[rustc_should_not_be_called_on_const_items]
2046pub const fn swap(&self, ptr: *mut T, order: Ordering) -> *mut T {
2047// SAFETY: data races are prevented by atomic intrinsics.
2048unsafe { atomic_swap(self.as_ptr(), ptr, order) }
2049 }
20502051/// Stores a value into the pointer if the current value is the same as the `current` value.
2052 ///
2053 /// The return value is always the previous value. If it is equal to `current`, then the value
2054 /// was updated.
2055 ///
2056 /// `compare_and_swap` also takes an [`Ordering`] argument which describes the memory
2057 /// ordering of this operation. Notice that even when using [`AcqRel`], the operation
2058 /// might fail and hence just perform an `Acquire` load, but not have `Release` semantics.
2059 /// Using [`Acquire`] makes the store part of this operation [`Relaxed`] if it
2060 /// happens, and using [`Release`] makes the load part [`Relaxed`].
2061 ///
2062 /// **Note:** This method is only available on platforms that support atomic
2063 /// operations on pointers.
2064 ///
2065 /// # Migrating to `compare_exchange` and `compare_exchange_weak`
2066 ///
2067 /// `compare_and_swap` is equivalent to `compare_exchange` with the following mapping for
2068 /// memory orderings:
2069 ///
2070 /// Original | Success | Failure
2071 /// -------- | ------- | -------
2072 /// Relaxed | Relaxed | Relaxed
2073 /// Acquire | Acquire | Acquire
2074 /// Release | Release | Relaxed
2075 /// AcqRel | AcqRel | Acquire
2076 /// SeqCst | SeqCst | SeqCst
2077 ///
2078 /// `compare_and_swap` and `compare_exchange` also differ in their return type. You can use
2079 /// `compare_exchange(...).unwrap_or_else(|x| x)` to recover the behavior of `compare_and_swap`,
2080 /// but in most cases it is more idiomatic to check whether the return value is `Ok` or `Err`
2081 /// rather than to infer success vs failure based on the value that was read.
2082 ///
2083 /// During migration, consider whether it makes sense to use `compare_exchange_weak` instead.
2084 /// `compare_exchange_weak` is allowed to fail spuriously even when the comparison succeeds,
2085 /// which allows the compiler to generate better assembly code when the compare and swap
2086 /// is used in a loop.
2087 ///
2088 /// # Examples
2089 ///
2090 /// ```
2091 /// use std::sync::atomic::{AtomicPtr, Ordering};
2092 ///
2093 /// let ptr = &mut 5;
2094 /// let some_ptr = AtomicPtr::new(ptr);
2095 ///
2096 /// let other_ptr = &mut 10;
2097 ///
2098 /// let value = some_ptr.compare_and_swap(ptr, other_ptr, Ordering::Relaxed);
2099 /// ```
2100#[inline]
2101 #[stable(feature = "rust1", since = "1.0.0")]
2102 #[deprecated(
2103 since = "1.50.0",
2104 note = "Use `compare_exchange` or `compare_exchange_weak` instead"
2105)]
2106 #[cfg(target_has_atomic = "ptr")]
2107 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
2108#[rustc_should_not_be_called_on_const_items]
2109pub fn compare_and_swap(&self, current: *mut T, new: *mut T, order: Ordering) -> *mut T {
2110match self.compare_exchange(current, new, order, strongest_failure_ordering(order)) {
2111Ok(x) => x,
2112Err(x) => x,
2113 }
2114 }
21152116/// Stores a value into the pointer if the current value is the same as the `current` value.
2117 ///
2118 /// The return value is a result indicating whether the new value was written and containing
2119 /// the previous value. On success this value is guaranteed to be equal to `current`.
2120 ///
2121 /// `compare_exchange` takes two [`Ordering`] arguments to describe the memory
2122 /// ordering of this operation. `success` describes the required ordering for the
2123 /// read-modify-write operation that takes place if the comparison with `current` succeeds.
2124 /// `failure` describes the required ordering for the load operation that takes place when
2125 /// the comparison fails. Using [`Acquire`] as success ordering makes the store part
2126 /// of this operation [`Relaxed`], and using [`Release`] makes the successful load
2127 /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
2128 ///
2129 /// **Note:** This method is only available on platforms that support atomic
2130 /// operations on pointers.
2131 ///
2132 /// # Examples
2133 ///
2134 /// ```
2135 /// use std::sync::atomic::{AtomicPtr, Ordering};
2136 ///
2137 /// let ptr = &mut 5;
2138 /// let some_ptr = AtomicPtr::new(ptr);
2139 ///
2140 /// let other_ptr = &mut 10;
2141 ///
2142 /// let value = some_ptr.compare_exchange(ptr, other_ptr,
2143 /// Ordering::SeqCst, Ordering::Relaxed);
2144 /// ```
2145 ///
2146 /// # Considerations
2147 ///
2148 /// `compare_exchange` is a [compare-and-swap operation] and thus exhibits the usual downsides
2149 /// of CAS operations. In particular, a load of the value followed by a successful
2150 /// `compare_exchange` with the previous load *does not ensure* that other threads have not
2151 /// changed the value in the interim. This is usually important when the *equality* check in
2152 /// the `compare_exchange` is being used to check the *identity* of a value, but equality
2153 /// does not necessarily imply identity. This is a particularly common case for pointers, as
2154 /// a pointer holding the same address does not imply that the same object exists at that
2155 /// address! In this case, `compare_exchange` can lead to the [ABA problem].
2156 ///
2157 /// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
2158 /// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
2159#[inline]
2160 #[stable(feature = "extended_compare_and_swap", since = "1.10.0")]
2161 #[cfg(target_has_atomic = "ptr")]
2162 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
2163#[rustc_should_not_be_called_on_const_items]
2164pub fn compare_exchange(
2165&self,
2166 current: *mut T,
2167 new: *mut T,
2168 success: Ordering,
2169 failure: Ordering,
2170 ) -> Result<*mut T, *mut T> {
2171// SAFETY: data races are prevented by atomic intrinsics.
2172unsafe { atomic_compare_exchange(self.as_ptr(), current, new, success, failure) }
2173 }
21742175/// Stores a value into the pointer if the current value is the same as the `current` value.
2176 ///
2177 /// Unlike [`AtomicPtr::compare_exchange`], this function is allowed to spuriously fail even when the
2178 /// comparison succeeds, which can result in more efficient code on some platforms. The
2179 /// return value is a result indicating whether the new value was written and containing the
2180 /// previous value.
2181 ///
2182 /// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory
2183 /// ordering of this operation. `success` describes the required ordering for the
2184 /// read-modify-write operation that takes place if the comparison with `current` succeeds.
2185 /// `failure` describes the required ordering for the load operation that takes place when
2186 /// the comparison fails. Using [`Acquire`] as success ordering makes the store part
2187 /// of this operation [`Relaxed`], and using [`Release`] makes the successful load
2188 /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
2189 ///
2190 /// **Note:** This method is only available on platforms that support atomic
2191 /// operations on pointers.
2192 ///
2193 /// # Examples
2194 ///
2195 /// ```
2196 /// use std::sync::atomic::{AtomicPtr, Ordering};
2197 ///
2198 /// let some_ptr = AtomicPtr::new(&mut 5);
2199 ///
2200 /// let new = &mut 10;
2201 /// let mut old = some_ptr.load(Ordering::Relaxed);
2202 /// loop {
2203 /// match some_ptr.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) {
2204 /// Ok(_) => break,
2205 /// Err(x) => old = x,
2206 /// }
2207 /// }
2208 /// ```
2209 ///
2210 /// # Considerations
2211 ///
2212 /// `compare_exchange` is a [compare-and-swap operation] and thus exhibits the usual downsides
2213 /// of CAS operations. In particular, a load of the value followed by a successful
2214 /// `compare_exchange` with the previous load *does not ensure* that other threads have not
2215 /// changed the value in the interim. This is usually important when the *equality* check in
2216 /// the `compare_exchange` is being used to check the *identity* of a value, but equality
2217 /// does not necessarily imply identity. This is a particularly common case for pointers, as
2218 /// a pointer holding the same address does not imply that the same object exists at that
2219 /// address! In this case, `compare_exchange` can lead to the [ABA problem].
2220 ///
2221 /// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
2222 /// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
2223#[inline]
2224 #[stable(feature = "extended_compare_and_swap", since = "1.10.0")]
2225 #[cfg(target_has_atomic = "ptr")]
2226 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
2227#[rustc_should_not_be_called_on_const_items]
2228pub fn compare_exchange_weak(
2229&self,
2230 current: *mut T,
2231 new: *mut T,
2232 success: Ordering,
2233 failure: Ordering,
2234 ) -> Result<*mut T, *mut T> {
2235// SAFETY: This intrinsic is unsafe because it operates on a raw pointer
2236 // but we know for sure that the pointer is valid (we just got it from
2237 // an `UnsafeCell` that we have by reference) and the atomic operation
2238 // itself allows us to safely mutate the `UnsafeCell` contents.
2239unsafe { atomic_compare_exchange_weak(self.as_ptr(), current, new, success, failure) }
2240 }
22412242/// An alias for [`AtomicPtr::try_update`].
2243#[inline]
2244 #[stable(feature = "atomic_fetch_update", since = "1.53.0")]
2245 #[cfg(target_has_atomic = "ptr")]
2246 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
2247#[rustc_should_not_be_called_on_const_items]
2248 #[deprecated(
2249 since = "1.99.0",
2250 note = "renamed to `try_update` for consistency",
2251 suggestion = "try_update"
2252)]
2253pub fn fetch_update<F>(
2254&self,
2255 set_order: Ordering,
2256 fetch_order: Ordering,
2257 f: F,
2258 ) -> Result<*mut T, *mut T>
2259where
2260F: FnMut(*mut T) -> Option<*mut T>,
2261 {
2262self.try_update(set_order, fetch_order, f)
2263 }
2264/// Fetches the value, and applies a function to it that returns an optional
2265 /// new value. Returns a `Result` of `Ok(previous_value)` if the function
2266 /// returned `Some(_)`, else `Err(previous_value)`.
2267 ///
2268 /// See also: [`update`](`AtomicPtr::update`).
2269 ///
2270 /// Note: This may call the function multiple times if the value has been
2271 /// changed from other threads in the meantime, as long as the function
2272 /// returns `Some(_)`, but the function will have been applied only once to
2273 /// the stored value.
2274 ///
2275 /// `try_update` takes two [`Ordering`] arguments to describe the memory
2276 /// ordering of this operation. The first describes the required ordering for
2277 /// when the operation finally succeeds while the second describes the
2278 /// required ordering for loads. These correspond to the success and failure
2279 /// orderings of [`AtomicPtr::compare_exchange`] respectively.
2280 ///
2281 /// Using [`Acquire`] as success ordering makes the store part of this
2282 /// operation [`Relaxed`], and using [`Release`] makes the final successful
2283 /// load [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`],
2284 /// [`Acquire`] or [`Relaxed`].
2285 ///
2286 /// **Note:** This method is only available on platforms that support atomic
2287 /// operations on pointers.
2288 ///
2289 /// # Considerations
2290 ///
2291 /// This method is not magic; it is not provided by the hardware, and does not act like a
2292 /// critical section or mutex.
2293 ///
2294 /// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
2295 /// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem],
2296 /// which is a particularly common pitfall for pointers!
2297 ///
2298 /// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
2299 /// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
2300 ///
2301 /// # Examples
2302 ///
2303 /// ```rust
2304 /// use std::sync::atomic::{AtomicPtr, Ordering};
2305 ///
2306 /// let ptr: *mut _ = &mut 5;
2307 /// let some_ptr = AtomicPtr::new(ptr);
2308 ///
2309 /// let new: *mut _ = &mut 10;
2310 /// assert_eq!(some_ptr.try_update(Ordering::SeqCst, Ordering::SeqCst, |_| None), Err(ptr));
2311 /// let result = some_ptr.try_update(Ordering::SeqCst, Ordering::SeqCst, |x| {
2312 /// if x == ptr {
2313 /// Some(new)
2314 /// } else {
2315 /// None
2316 /// }
2317 /// });
2318 /// assert_eq!(result, Ok(ptr));
2319 /// assert_eq!(some_ptr.load(Ordering::SeqCst), new);
2320 /// ```
2321#[inline]
2322 #[stable(feature = "atomic_try_update", since = "1.95.0")]
2323 #[cfg(target_has_atomic = "ptr")]
2324 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
2325#[rustc_should_not_be_called_on_const_items]
2326pub fn try_update(
2327&self,
2328 set_order: Ordering,
2329 fetch_order: Ordering,
2330mut f: impl FnMut(*mut T) -> Option<*mut T>,
2331 ) -> Result<*mut T, *mut T> {
2332let mut prev = self.load(fetch_order);
2333while let Some(next) = f(prev) {
2334match self.compare_exchange_weak(prev, next, set_order, fetch_order) {
2335 x @ Ok(_) => return x,
2336Err(next_prev) => prev = next_prev,
2337 }
2338 }
2339Err(prev)
2340 }
23412342/// Fetches the value, and applies a function to it that returns a new value.
2343 /// The new value is stored and the old value is returned.
2344 ///
2345 /// See also: [`try_update`](`AtomicPtr::try_update`).
2346 ///
2347 /// Note: This may call the function multiple times if the value has been changed from other threads in
2348 /// the meantime, but the function will have been applied only once to the stored value.
2349 ///
2350 /// `update` takes two [`Ordering`] arguments to describe the memory
2351 /// ordering of this operation. The first describes the required ordering for
2352 /// when the operation finally succeeds while the second describes the
2353 /// required ordering for loads. These correspond to the success and failure
2354 /// orderings of [`AtomicPtr::compare_exchange`] respectively.
2355 ///
2356 /// Using [`Acquire`] as success ordering makes the store part
2357 /// of this operation [`Relaxed`], and using [`Release`] makes the final successful load
2358 /// [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
2359 ///
2360 /// **Note:** This method is only available on platforms that support atomic
2361 /// operations on pointers.
2362 ///
2363 /// # Considerations
2364 ///
2365 /// This method is not magic; it is not provided by the hardware, and does not act like a
2366 /// critical section or mutex.
2367 ///
2368 /// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
2369 /// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem],
2370 /// which is a particularly common pitfall for pointers!
2371 ///
2372 /// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
2373 /// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
2374 ///
2375 /// # Examples
2376 ///
2377 /// ```rust
2378 ///
2379 /// use std::sync::atomic::{AtomicPtr, Ordering};
2380 ///
2381 /// let ptr: *mut _ = &mut 5;
2382 /// let some_ptr = AtomicPtr::new(ptr);
2383 ///
2384 /// let new: *mut _ = &mut 10;
2385 /// let result = some_ptr.update(Ordering::SeqCst, Ordering::SeqCst, |_| new);
2386 /// assert_eq!(result, ptr);
2387 /// assert_eq!(some_ptr.load(Ordering::SeqCst), new);
2388 /// ```
2389#[inline]
2390 #[stable(feature = "atomic_try_update", since = "1.95.0")]
2391 #[cfg(target_has_atomic = "ptr")]
2392 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
2393#[rustc_should_not_be_called_on_const_items]
2394pub fn update(
2395&self,
2396 set_order: Ordering,
2397 fetch_order: Ordering,
2398mut f: impl FnMut(*mut T) -> *mut T,
2399 ) -> *mut T {
2400let mut prev = self.load(fetch_order);
2401loop {
2402match self.compare_exchange_weak(prev, f(prev), set_order, fetch_order) {
2403Ok(x) => break x,
2404Err(next_prev) => prev = next_prev,
2405 }
2406 }
2407 }
24082409/// Offsets the pointer's address by adding `val` (in units of `T`),
2410 /// returning the previous pointer.
2411 ///
2412 /// This is equivalent to using [`wrapping_add`] to atomically perform the
2413 /// equivalent of `ptr = ptr.wrapping_add(val);`.
2414 ///
2415 /// This method operates in units of `T`, which means that it cannot be used
2416 /// to offset the pointer by an amount which is not a multiple of
2417 /// `size_of::<T>()`. This can sometimes be inconvenient, as you may want to
2418 /// work with a deliberately misaligned pointer. In such cases, you may use
2419 /// the [`fetch_byte_add`](Self::fetch_byte_add) method instead.
2420 ///
2421 /// `fetch_ptr_add` takes an [`Ordering`] argument which describes the
2422 /// memory ordering of this operation. All ordering modes are possible. Note
2423 /// that using [`Acquire`] makes the store part of this operation
2424 /// [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`].
2425 ///
2426 /// **Note**: This method is only available on platforms that support atomic
2427 /// operations on [`AtomicPtr`].
2428 ///
2429 /// [`wrapping_add`]: pointer::wrapping_add
2430 ///
2431 /// # Examples
2432 ///
2433 /// ```
2434 /// use core::sync::atomic::{AtomicPtr, Ordering};
2435 ///
2436 /// let atom = AtomicPtr::<i64>::new(core::ptr::null_mut());
2437 /// assert_eq!(atom.fetch_ptr_add(1, Ordering::Relaxed).addr(), 0);
2438 /// // Note: units of `size_of::<i64>()`.
2439 /// assert_eq!(atom.load(Ordering::Relaxed).addr(), 8);
2440 /// ```
2441#[inline]
2442 #[cfg(target_has_atomic = "ptr")]
2443 #[stable(feature = "strict_provenance_atomic_ptr", since = "1.91.0")]
2444 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
2445#[rustc_should_not_be_called_on_const_items]
2446pub fn fetch_ptr_add(&self, val: usize, order: Ordering) -> *mut T {
2447self.fetch_byte_add(val.wrapping_mul(size_of::<T>()), order)
2448 }
24492450/// Offsets the pointer's address by subtracting `val` (in units of `T`),
2451 /// returning the previous pointer.
2452 ///
2453 /// This is equivalent to using [`wrapping_sub`] to atomically perform the
2454 /// equivalent of `ptr = ptr.wrapping_sub(val);`.
2455 ///
2456 /// This method operates in units of `T`, which means that it cannot be used
2457 /// to offset the pointer by an amount which is not a multiple of
2458 /// `size_of::<T>()`. This can sometimes be inconvenient, as you may want to
2459 /// work with a deliberately misaligned pointer. In such cases, you may use
2460 /// the [`fetch_byte_sub`](Self::fetch_byte_sub) method instead.
2461 ///
2462 /// `fetch_ptr_sub` takes an [`Ordering`] argument which describes the memory
2463 /// ordering of this operation. All ordering modes are possible. Note that
2464 /// using [`Acquire`] makes the store part of this operation [`Relaxed`],
2465 /// and using [`Release`] makes the load part [`Relaxed`].
2466 ///
2467 /// **Note**: This method is only available on platforms that support atomic
2468 /// operations on [`AtomicPtr`].
2469 ///
2470 /// [`wrapping_sub`]: pointer::wrapping_sub
2471 ///
2472 /// # Examples
2473 ///
2474 /// ```
2475 /// use core::sync::atomic::{AtomicPtr, Ordering};
2476 ///
2477 /// let array = [1i32, 2i32];
2478 /// let atom = AtomicPtr::new(array.as_ptr().wrapping_add(1) as *mut _);
2479 ///
2480 /// assert!(core::ptr::eq(
2481 /// atom.fetch_ptr_sub(1, Ordering::Relaxed),
2482 /// &array[1],
2483 /// ));
2484 /// assert!(core::ptr::eq(atom.load(Ordering::Relaxed), &array[0]));
2485 /// ```
2486#[inline]
2487 #[cfg(target_has_atomic = "ptr")]
2488 #[stable(feature = "strict_provenance_atomic_ptr", since = "1.91.0")]
2489 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
2490#[rustc_should_not_be_called_on_const_items]
2491pub fn fetch_ptr_sub(&self, val: usize, order: Ordering) -> *mut T {
2492self.fetch_byte_sub(val.wrapping_mul(size_of::<T>()), order)
2493 }
24942495/// Offsets the pointer's address by adding `val` *bytes*, returning the
2496 /// previous pointer.
2497 ///
2498 /// This is equivalent to using [`wrapping_byte_add`] to atomically
2499 /// perform `ptr = ptr.wrapping_byte_add(val)`.
2500 ///
2501 /// `fetch_byte_add` takes an [`Ordering`] argument which describes the
2502 /// memory ordering of this operation. All ordering modes are possible. Note
2503 /// that using [`Acquire`] makes the store part of this operation
2504 /// [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`].
2505 ///
2506 /// **Note**: This method is only available on platforms that support atomic
2507 /// operations on [`AtomicPtr`].
2508 ///
2509 /// [`wrapping_byte_add`]: pointer::wrapping_byte_add
2510 ///
2511 /// # Examples
2512 ///
2513 /// ```
2514 /// use core::sync::atomic::{AtomicPtr, Ordering};
2515 ///
2516 /// let atom = AtomicPtr::<i64>::new(core::ptr::null_mut());
2517 /// assert_eq!(atom.fetch_byte_add(1, Ordering::Relaxed).addr(), 0);
2518 /// // Note: in units of bytes, not `size_of::<i64>()`.
2519 /// assert_eq!(atom.load(Ordering::Relaxed).addr(), 1);
2520 /// ```
2521#[inline]
2522 #[cfg(target_has_atomic = "ptr")]
2523 #[stable(feature = "strict_provenance_atomic_ptr", since = "1.91.0")]
2524 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
2525#[rustc_should_not_be_called_on_const_items]
2526pub fn fetch_byte_add(&self, val: usize, order: Ordering) -> *mut T {
2527// SAFETY: data races are prevented by atomic intrinsics.
2528unsafe { atomic_add(self.as_ptr(), val, order).cast() }
2529 }
25302531/// Offsets the pointer's address by subtracting `val` *bytes*, returning the
2532 /// previous pointer.
2533 ///
2534 /// This is equivalent to using [`wrapping_byte_sub`] to atomically
2535 /// perform `ptr = ptr.wrapping_byte_sub(val)`.
2536 ///
2537 /// `fetch_byte_sub` takes an [`Ordering`] argument which describes the
2538 /// memory ordering of this operation. All ordering modes are possible. Note
2539 /// that using [`Acquire`] makes the store part of this operation
2540 /// [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`].
2541 ///
2542 /// **Note**: This method is only available on platforms that support atomic
2543 /// operations on [`AtomicPtr`].
2544 ///
2545 /// [`wrapping_byte_sub`]: pointer::wrapping_byte_sub
2546 ///
2547 /// # Examples
2548 ///
2549 /// ```
2550 /// use core::sync::atomic::{AtomicPtr, Ordering};
2551 ///
2552 /// let mut arr = [0i64, 1];
2553 /// let atom = AtomicPtr::<i64>::new(&raw mut arr[1]);
2554 /// assert_eq!(atom.fetch_byte_sub(8, Ordering::Relaxed).addr(), (&raw const arr[1]).addr());
2555 /// assert_eq!(atom.load(Ordering::Relaxed).addr(), (&raw const arr[0]).addr());
2556 /// ```
2557#[inline]
2558 #[cfg(target_has_atomic = "ptr")]
2559 #[stable(feature = "strict_provenance_atomic_ptr", since = "1.91.0")]
2560 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
2561#[rustc_should_not_be_called_on_const_items]
2562pub fn fetch_byte_sub(&self, val: usize, order: Ordering) -> *mut T {
2563// SAFETY: data races are prevented by atomic intrinsics.
2564unsafe { atomic_sub(self.as_ptr(), val, order).cast() }
2565 }
25662567/// Performs a bitwise "or" operation on the address of the current pointer,
2568 /// and the argument `val`, and stores a pointer with provenance of the
2569 /// current pointer and the resulting address.
2570 ///
2571 /// This is equivalent to using [`map_addr`] to atomically perform
2572 /// `ptr = ptr.map_addr(|a| a | val)`. This can be used in tagged
2573 /// pointer schemes to atomically set tag bits.
2574 ///
2575 /// **Caveat**: This operation returns the previous value. To compute the
2576 /// stored value without losing provenance, you may use [`map_addr`]. For
2577 /// example: `a.fetch_or(val).map_addr(|a| a | val)`.
2578 ///
2579 /// `fetch_or` takes an [`Ordering`] argument which describes the memory
2580 /// ordering of this operation. All ordering modes are possible. Note that
2581 /// using [`Acquire`] makes the store part of this operation [`Relaxed`],
2582 /// and using [`Release`] makes the load part [`Relaxed`].
2583 ///
2584 /// **Note**: This method is only available on platforms that support atomic
2585 /// operations on [`AtomicPtr`].
2586 ///
2587 /// This API and its claimed semantics are part of the Strict Provenance
2588 /// experiment, see the [module documentation for `ptr`][crate::ptr] for
2589 /// details.
2590 ///
2591 /// [`map_addr`]: pointer::map_addr
2592 ///
2593 /// # Examples
2594 ///
2595 /// ```
2596 /// use core::sync::atomic::{AtomicPtr, Ordering};
2597 ///
2598 /// let pointer = &mut 3i64 as *mut i64;
2599 ///
2600 /// let atom = AtomicPtr::<i64>::new(pointer);
2601 /// // Tag the bottom bit of the pointer.
2602 /// assert_eq!(atom.fetch_or(1, Ordering::Relaxed).addr() & 1, 0);
2603 /// // Extract and untag.
2604 /// let tagged = atom.load(Ordering::Relaxed);
2605 /// assert_eq!(tagged.addr() & 1, 1);
2606 /// assert_eq!(tagged.map_addr(|p| p & !1), pointer);
2607 /// ```
2608#[inline]
2609 #[cfg(target_has_atomic = "ptr")]
2610 #[stable(feature = "strict_provenance_atomic_ptr", since = "1.91.0")]
2611 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
2612#[rustc_should_not_be_called_on_const_items]
2613pub fn fetch_or(&self, val: usize, order: Ordering) -> *mut T {
2614// SAFETY: data races are prevented by atomic intrinsics.
2615unsafe { atomic_or(self.as_ptr(), val, order).cast() }
2616 }
26172618/// Performs a bitwise "and" operation on the address of the current
2619 /// pointer, and the argument `val`, and stores a pointer with provenance of
2620 /// the current pointer and the resulting address.
2621 ///
2622 /// This is equivalent to using [`map_addr`] to atomically perform
2623 /// `ptr = ptr.map_addr(|a| a & val)`. This can be used in tagged
2624 /// pointer schemes to atomically unset tag bits.
2625 ///
2626 /// **Caveat**: This operation returns the previous value. To compute the
2627 /// stored value without losing provenance, you may use [`map_addr`]. For
2628 /// example: `a.fetch_and(val).map_addr(|a| a & val)`.
2629 ///
2630 /// `fetch_and` takes an [`Ordering`] argument which describes the memory
2631 /// ordering of this operation. All ordering modes are possible. Note that
2632 /// using [`Acquire`] makes the store part of this operation [`Relaxed`],
2633 /// and using [`Release`] makes the load part [`Relaxed`].
2634 ///
2635 /// **Note**: This method is only available on platforms that support atomic
2636 /// operations on [`AtomicPtr`].
2637 ///
2638 /// This API and its claimed semantics are part of the Strict Provenance
2639 /// experiment, see the [module documentation for `ptr`][crate::ptr] for
2640 /// details.
2641 ///
2642 /// [`map_addr`]: pointer::map_addr
2643 ///
2644 /// # Examples
2645 ///
2646 /// ```
2647 /// use core::sync::atomic::{AtomicPtr, Ordering};
2648 ///
2649 /// let pointer = &mut 3i64 as *mut i64;
2650 /// // A tagged pointer
2651 /// let atom = AtomicPtr::<i64>::new(pointer.map_addr(|a| a | 1));
2652 /// assert_eq!(atom.fetch_or(1, Ordering::Relaxed).addr() & 1, 1);
2653 /// // Untag, and extract the previously tagged pointer.
2654 /// let untagged = atom.fetch_and(!1, Ordering::Relaxed)
2655 /// .map_addr(|a| a & !1);
2656 /// assert_eq!(untagged, pointer);
2657 /// ```
2658#[inline]
2659 #[cfg(target_has_atomic = "ptr")]
2660 #[stable(feature = "strict_provenance_atomic_ptr", since = "1.91.0")]
2661 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
2662#[rustc_should_not_be_called_on_const_items]
2663pub fn fetch_and(&self, val: usize, order: Ordering) -> *mut T {
2664// SAFETY: data races are prevented by atomic intrinsics.
2665unsafe { atomic_and(self.as_ptr(), val, order).cast() }
2666 }
26672668/// Performs a bitwise "xor" operation on the address of the current
2669 /// pointer, and the argument `val`, and stores a pointer with provenance of
2670 /// the current pointer and the resulting address.
2671 ///
2672 /// This is equivalent to using [`map_addr`] to atomically perform
2673 /// `ptr = ptr.map_addr(|a| a ^ val)`. This can be used in tagged
2674 /// pointer schemes to atomically toggle tag bits.
2675 ///
2676 /// **Caveat**: This operation returns the previous value. To compute the
2677 /// stored value without losing provenance, you may use [`map_addr`]. For
2678 /// example: `a.fetch_xor(val).map_addr(|a| a ^ val)`.
2679 ///
2680 /// `fetch_xor` takes an [`Ordering`] argument which describes the memory
2681 /// ordering of this operation. All ordering modes are possible. Note that
2682 /// using [`Acquire`] makes the store part of this operation [`Relaxed`],
2683 /// and using [`Release`] makes the load part [`Relaxed`].
2684 ///
2685 /// **Note**: This method is only available on platforms that support atomic
2686 /// operations on [`AtomicPtr`].
2687 ///
2688 /// This API and its claimed semantics are part of the Strict Provenance
2689 /// experiment, see the [module documentation for `ptr`][crate::ptr] for
2690 /// details.
2691 ///
2692 /// [`map_addr`]: pointer::map_addr
2693 ///
2694 /// # Examples
2695 ///
2696 /// ```
2697 /// use core::sync::atomic::{AtomicPtr, Ordering};
2698 ///
2699 /// let pointer = &mut 3i64 as *mut i64;
2700 /// let atom = AtomicPtr::<i64>::new(pointer);
2701 ///
2702 /// // Toggle a tag bit on the pointer.
2703 /// atom.fetch_xor(1, Ordering::Relaxed);
2704 /// assert_eq!(atom.load(Ordering::Relaxed).addr() & 1, 1);
2705 /// ```
2706#[inline]
2707 #[cfg(target_has_atomic = "ptr")]
2708 #[stable(feature = "strict_provenance_atomic_ptr", since = "1.91.0")]
2709 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
2710#[rustc_should_not_be_called_on_const_items]
2711pub fn fetch_xor(&self, val: usize, order: Ordering) -> *mut T {
2712// SAFETY: data races are prevented by atomic intrinsics.
2713unsafe { atomic_xor(self.as_ptr(), val, order).cast() }
2714 }
27152716/// Returns a mutable pointer to the underlying pointer.
2717 ///
2718 /// Doing non-atomic reads and writes on the resulting pointer can be a data race.
2719 /// This method is mostly useful for FFI, where the function signature may use
2720 /// `*mut *mut T` instead of `&AtomicPtr<T>`.
2721 ///
2722 /// Returning an `*mut` pointer from a shared reference to this atomic is safe because the
2723 /// atomic types work with interior mutability. All modifications of an atomic change the value
2724 /// through a shared reference, and can do so safely as long as they use atomic operations. Any
2725 /// use of the returned raw pointer requires an `unsafe` block and still has to uphold the
2726 /// requirements of the [memory model].
2727 ///
2728 /// # Examples
2729 ///
2730 /// ```ignore (extern-declaration)
2731 /// use std::sync::atomic::AtomicPtr;
2732 ///
2733 /// extern "C" {
2734 /// fn my_atomic_op(arg: *mut *mut u32);
2735 /// }
2736 ///
2737 /// let mut value = 17;
2738 /// let atomic = AtomicPtr::new(&mut value);
2739 ///
2740 /// // SAFETY: Safe as long as `my_atomic_op` is atomic.
2741 /// unsafe {
2742 /// my_atomic_op(atomic.as_ptr());
2743 /// }
2744 /// ```
2745 ///
2746 /// [memory model]: self#memory-model-for-atomic-accesses
2747#[inline]
2748 #[stable(feature = "atomic_as_ptr", since = "1.70.0")]
2749 #[rustc_const_stable(feature = "atomic_as_ptr", since = "1.70.0")]
2750 #[rustc_never_returns_null_ptr]
2751pub const fn as_ptr(&self) -> *mut *mut T {
2752self.v.get().cast()
2753 }
2754}
27552756#[cfg(target_has_atomic_load_store = "8")]
2757#[stable(feature = "atomic_bool_from", since = "1.24.0")]
2758#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
2759const impl From<bool> for AtomicBool {
2760/// Converts a `bool` into an `AtomicBool`.
2761 ///
2762 /// # Examples
2763 ///
2764 /// ```
2765 /// use std::sync::atomic::AtomicBool;
2766 /// let atomic_bool = AtomicBool::from(true);
2767 /// assert_eq!(format!("{atomic_bool:?}"), "true")
2768 /// ```
2769#[inline]
2770fn from(b: bool) -> Self {
2771Self::new(b)
2772 }
2773}
27742775#[cfg(target_has_atomic_load_store = "ptr")]
2776#[stable(feature = "atomic_from", since = "1.23.0")]
2777#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
2778const impl<T> From<*mut T> for AtomicPtr<T> {
2779/// Converts a `*mut T` into an `AtomicPtr<T>`.
2780#[inline]
2781fn from(p: *mut T) -> Self {
2782Self::new(p)
2783 }
2784}
27852786#[allow(unused_macros)] // This macro ends up being unused on some architectures.
2787macro_rules!if_8_bit {
2788 (u8, $( yes = [$($yes:tt)*], )? $( no = [$($no:tt)*], )? ) => { concat!("", $($($yes)*)?) };
2789 (i8, $( yes = [$($yes:tt)*], )? $( no = [$($no:tt)*], )? ) => { concat!("", $($($yes)*)?) };
2790 ($_:ident, $( yes = [$($yes:tt)*], )? $( no = [$($no:tt)*], )? ) => { concat!("", $($($no)*)?) };
2791}
27922793#[cfg(target_has_atomic_load_store)]
2794macro_rules!atomic_int {
2795 ($cfg_base:meta,
2796$cfg_cas:meta,
2797$cfg_align:meta,
2798$stable:meta,
2799$stable_cxchg:meta,
2800$stable_debug:meta,
2801$stable_access:meta,
2802$stable_from:meta,
2803$stable_nand:meta,
2804$const_stable_new:meta,
2805$const_stable_into_inner:meta,
2806$s_int_type:literal,
2807$extra_feature:expr,
2808$min_fn:ident, $max_fn:ident,
2809$align:expr,
2810$int_type:ident $atomic_type:ident) => {
2811/// An integer type which can be safely shared between threads.
2812 ///
2813 /// This type has the same
2814#[doc = if_8_bit!(
2815$int_type,
2816 yes = ["size, alignment, and bit validity"],
2817 no = ["size and bit validity"],
2818 )]
2819/// as the underlying integer type, [`
2820#[doc = $s_int_type]
2821/// `].
2822#[doc = if_8_bit! {
2823$int_type,
2824 no = [
2825"However, the alignment of this type is always equal to its ",
2826"size, even on targets where [`", $s_int_type, "`] has a ",
2827"lesser alignment."
2828],
2829 }]
2830///
2831 /// For more about the differences between atomic types and
2832 /// non-atomic types as well as information about the portability of
2833 /// this type, please see the [module-level documentation].
2834 ///
2835 /// **Note:** This type is only available on platforms that support
2836 /// atomic loads and stores of [`
2837#[doc = $s_int_type]
2838/// `].
2839 ///
2840 /// [module-level documentation]: crate::sync::atomic
2841#[$stable]
2842pub type $atomic_type = Atomic<$int_type>;
28432844#[$stable]
2845impl Default for $atomic_type {
2846#[inline]
2847fn default() -> Self {
2848Self::new(Default::default())
2849 }
2850 }
28512852#[$stable_from]
2853 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
2854const impl From<$int_type> for $atomic_type {
2855#[doc = concat!("Converts an `", stringify!($int_type), "` into an `", stringify!($atomic_type), "`.")]
2856 #[inline]
2857fn from(v: $int_type) -> Self { Self::new(v) }
2858 }
28592860#[$stable_debug]
2861impl fmt::Debug for $atomic_type {
2862fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2863 fmt::Debug::fmt(&self.load(Ordering::Relaxed), f)
2864 }
2865 }
28662867impl $atomic_type {
2868/// Creates a new atomic integer.
2869 ///
2870 /// # Examples
2871 ///
2872#[cfg_attr($cfg_base, doc = "```")]
2873 #[cfg_attr(not($cfg_base), doc = "```compile_fail")]
2874 #[doc = concat!($extra_feature, "use std::sync::atomic::", stringify!($atomic_type), ";")]
2875///
2876#[doc = concat!("let atomic_forty_two = ", stringify!($atomic_type), "::new(42);")]
2877/// ```
2878#[inline]
2879 #[$stable]
2880 #[$const_stable_new]
2881 #[must_use]
2882pub const fn new(v: $int_type) -> Self {
2883// SAFETY:
2884 // `Atomic<T>` is essentially a transparent wrapper around `T`.
2885unsafe { transmute(v) }
2886 }
28872888/// Creates a new reference to an atomic integer from a pointer.
2889 ///
2890 /// # Examples
2891 ///
2892#[cfg_attr($cfg_base, doc = "```rust")]
2893 #[cfg_attr(not($cfg_base), doc = "```rust,compile_fail")]
2894 #[doc = concat!($extra_feature, "use std::sync::atomic::{self, ", stringify!($atomic_type), "};")]
2895///
2896 /// // Get a pointer to an allocated value
2897#[doc = concat!("let ptr: *mut ", stringify!($int_type), " = Box::into_raw(Box::new(0));")]
2898///
2899#[doc = concat!("assert!(ptr.cast::<", stringify!($atomic_type), ">().is_aligned());")]
2900///
2901 /// {
2902 /// // Create an atomic view of the allocated value
2903// SAFETY: this is a doc comment, tidy, it can't hurt you (also guaranteed by the construction of `ptr` and the assert above)
2904#[doc = concat!(" let atomic = unsafe {", stringify!($atomic_type), "::from_ptr(ptr) };")]
2905///
2906 /// // Use `atomic` for atomic operations, possibly share it with other threads
2907 /// atomic.store(1, atomic::Ordering::Relaxed);
2908 /// }
2909 ///
2910 /// // It's ok to non-atomically access the value behind `ptr`,
2911 /// // since the reference to the atomic ended its lifetime in the block above
2912 /// assert_eq!(unsafe { *ptr }, 1);
2913 ///
2914 /// // Deallocate the value
2915 /// unsafe { drop(Box::from_raw(ptr)) }
2916 /// ```
2917 ///
2918 /// # Safety
2919 ///
2920 /// * `ptr` must be aligned to
2921#[doc = concat!(" `align_of::<", stringify!($atomic_type), ">()`")]
2922 #[doc = if_8_bit!{
2923$int_type,
2924 yes = [
2925" (note that this is always true, since `align_of::<",
2926stringify!($atomic_type), ">() == 1`)."
2927],
2928 no = [
2929" (note that on some platforms this can be bigger than `align_of::<",
2930stringify!($int_type), ">()`)."
2931],
2932 }]
2933/// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`.
2934 /// * You must adhere to the [Memory model for atomic accesses]. In particular, it is not
2935 /// allowed to mix conflicting atomic and non-atomic accesses, or atomic accesses of different
2936 /// sizes, without synchronization.
2937 ///
2938 /// [valid]: crate::ptr#safety
2939 /// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses
2940#[inline]
2941 #[stable(feature = "atomic_from_ptr", since = "1.75.0")]
2942 #[rustc_const_stable(feature = "const_atomic_from_ptr", since = "1.84.0")]
2943pub const unsafe fn from_ptr<'a>(ptr: *mut $int_type) -> &'a $atomic_type {
2944// SAFETY: guaranteed by the caller
2945unsafe { &*ptr.cast() }
2946 }
29472948/// Creates a new pointer to an atomic integer from a pointer.
2949 ///
2950 /// This is useful if you want to do volatile atomic accesses, and thus avoid creating
2951 /// a reference to the destination.
2952#[inline]
2953 #[unstable(feature = "atomic_volatile", issue = "158947")]
2954pub const fn from_ptr_raw(ptr: *mut $int_type) -> *const $atomic_type {
2955 ptr.cast_const().cast()
2956 }
29572958/// Returns a mutable reference to the underlying integer.
2959 ///
2960 /// This is safe because the mutable reference guarantees that no other threads are
2961 /// concurrently accessing the atomic data.
2962 ///
2963 /// # Examples
2964 ///
2965#[cfg_attr($cfg_base, doc = "```")]
2966 #[cfg_attr(not($cfg_base), doc = "```compile_fail")]
2967 #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
2968///
2969#[doc = concat!("let mut some_var = ", stringify!($atomic_type), "::new(10);")]
2970/// assert_eq!(*some_var.get_mut(), 10);
2971 /// *some_var.get_mut() = 5;
2972 /// assert_eq!(some_var.load(Ordering::SeqCst), 5);
2973 /// ```
2974#[inline]
2975 #[$stable_access]
2976 #[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
2977pub const fn get_mut(&mut self) -> &mut $int_type {
2978// SAFETY:
2979 // `Atomic<T>` is essentially a transparent wrapper around `T`.
2980unsafe { &mut *self.as_ptr() }
2981 }
29822983#[doc = concat!("Get atomic access to a `&mut ", stringify!($int_type), "`.")]
2984///
2985#[doc = if_8_bit! {
2986$int_type,
2987 no = [
2988"**Note:** This function is only available on targets where `",
2989stringify!($atomic_type), "` has the same alignment as `", stringify!($int_type), "`."
2990],
2991 }]
2992///
2993 /// # Examples
2994 ///
2995#[cfg_attr($cfg_align, doc = "```rust")]
2996 #[cfg_attr(not($cfg_align), doc = "```rust,compile_fail")]
2997 #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
2998///
2999 /// let mut some_int = 123;
3000#[doc = concat!("let a = ", stringify!($atomic_type), "::from_mut(&mut some_int);")]
3001/// a.store(100, Ordering::Relaxed);
3002 /// assert_eq!(some_int, 100);
3003 /// ```
3004 ///
3005#[inline]
3006 #[cfg(any($cfg_align, doc))]
3007 #[stable(feature = "atomic_from_mut", since = "1.98.0")]
3008 #[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
3009pub const fn from_mut(v: &mut $int_type) -> &mut Self {
3010let [] = [(); align_of::<Self>() - align_of::<$int_type>()];
3011// SAFETY:
3012 // - the mutable reference guarantees unique ownership.
3013 // - the alignment of `$int_type` and `Self` is the
3014 // same, as promised by $cfg_align and verified above.
3015unsafe { &mut *(v as *mut $int_type as *mut Self) }
3016 }
30173018#[doc = concat!("Get non-atomic access to a `&mut [", stringify!($atomic_type), "]` slice")]
3019///
3020 /// This is safe because the mutable reference guarantees that no other threads are
3021 /// concurrently accessing the atomic data.
3022 ///
3023 /// # Examples
3024 ///
3025#[cfg_attr($cfg_base, doc = "```ignore-wasm")]
3026 #[cfg_attr(not($cfg_base), doc = "```ignore-wasm,compile_fail")]
3027 #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
3028///
3029#[doc = concat!("let mut some_ints = [const { ", stringify!($atomic_type), "::new(0) }; 10];")]
3030///
3031#[doc = concat!("let view: &mut [", stringify!($int_type), "] = ", stringify!($atomic_type), "::get_mut_slice(&mut some_ints);")]
3032/// assert_eq!(view, [0; 10]);
3033 /// view
3034 /// .iter_mut()
3035 /// .enumerate()
3036 /// .for_each(|(idx, int)| *int = idx as _);
3037 ///
3038 /// std::thread::scope(|s| {
3039 /// some_ints
3040 /// .iter()
3041 /// .enumerate()
3042 /// .for_each(|(idx, int)| {
3043 /// s.spawn(move || assert_eq!(int.load(Ordering::Relaxed), idx as _));
3044 /// })
3045 /// });
3046 /// ```
3047#[inline]
3048 #[stable(feature = "atomic_from_mut", since = "1.98.0")]
3049 #[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
3050pub const fn get_mut_slice(this: &mut [Self]) -> &mut [$int_type] {
3051// SAFETY: the mutable reference guarantees unique ownership.
3052unsafe { &mut *(this as *mut [Self] as *mut [$int_type]) }
3053 }
30543055#[doc = concat!("Get atomic access to a `&mut [", stringify!($int_type), "]` slice.")]
3056///
3057#[doc = if_8_bit! {
3058$int_type,
3059 no = [
3060"**Note:** This function is only available on targets where `",
3061stringify!($atomic_type), "` has the same alignment as `", stringify!($int_type), "`."
3062],
3063 }]
3064///
3065 /// # Examples
3066 ///
3067#[cfg_attr($cfg_align, doc = "```ignore-wasm")]
3068 #[cfg_attr(not($cfg_align), doc = "```ignore-wasm,compile_fail")]
3069 #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
3070///
3071 /// let mut some_ints = [0; 10];
3072#[doc = concat!("let a = &*", stringify!($atomic_type), "::from_mut_slice(&mut some_ints);")]
3073/// std::thread::scope(|s| {
3074 /// for i in 0..a.len() {
3075 /// s.spawn(move || a[i].store(i as _, Ordering::Relaxed));
3076 /// }
3077 /// });
3078 /// for (i, n) in some_ints.into_iter().enumerate() {
3079 /// assert_eq!(i, n as usize);
3080 /// }
3081 /// ```
3082#[inline]
3083 #[cfg(any($cfg_align, doc))]
3084 #[stable(feature = "atomic_from_mut", since = "1.98.0")]
3085 #[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
3086pub const fn from_mut_slice(v: &mut [$int_type]) -> &mut [Self] {
3087let [] = [(); align_of::<Self>() - align_of::<$int_type>()];
3088// SAFETY:
3089 // - the mutable reference guarantees unique ownership.
3090 // - the alignment of `$int_type` and `Self` is the
3091 // same, as promised by $cfg_align and verified above.
3092unsafe { &mut *(v as *mut [$int_type] as *mut [Self]) }
3093 }
30943095/// Consumes the atomic and returns the contained value.
3096 ///
3097 /// This is safe because passing `self` by value guarantees that no other threads are
3098 /// concurrently accessing the atomic data.
3099 ///
3100 /// # Examples
3101 ///
3102#[cfg_attr($cfg_base, doc = "```")]
3103 #[cfg_attr(not($cfg_base), doc = "```compile_fail")]
3104 #[doc = concat!($extra_feature, "use std::sync::atomic::", stringify!($atomic_type), ";")]
3105///
3106#[doc = concat!("let some_var = ", stringify!($atomic_type), "::new(5);")]
3107/// assert_eq!(some_var.into_inner(), 5);
3108 /// ```
3109#[inline]
3110 #[$stable_access]
3111 #[$const_stable_into_inner]
3112pub const fn into_inner(self) -> $int_type {
3113// SAFETY:
3114 // `Atomic<T>` is essentially a transparent wrapper around `T`.
3115unsafe { transmute(self) }
3116 }
31173118/// Loads a value from the atomic integer.
3119 ///
3120 /// `load` takes an [`Ordering`] argument which describes the memory ordering of this operation.
3121 /// Possible values are [`SeqCst`], [`Acquire`] and [`Relaxed`].
3122 ///
3123 /// # Panics
3124 ///
3125 /// Panics if `order` is [`Release`] or [`AcqRel`].
3126 ///
3127 /// # Examples
3128 ///
3129#[cfg_attr($cfg_base, doc = "```")]
3130 #[cfg_attr(not($cfg_base), doc = "```compile_fail")]
3131 #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
3132///
3133#[doc = concat!("let some_var = ", stringify!($atomic_type), "::new(5);")]
3134///
3135 /// assert_eq!(some_var.load(Ordering::Relaxed), 5);
3136 /// ```
3137#[inline]
3138 #[$stable]
3139 #[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
3140 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
3141pub const fn load(&self, order: Ordering) -> $int_type {
3142// SAFETY: data races are prevented by atomic intrinsics.
3143unsafe { atomic_load::<_, /* VOLATILE */ false>(self.as_ptr(), order) }
3144 }
31453146/// Perform a volatile load from the atomic integer.
3147 ///
3148 /// `load_volatile` takes an [`Ordering`] argument which describes the memory ordering
3149 /// of this operation. Possible values are [`SeqCst`], [`Acquire`] and [`Relaxed`].
3150 ///
3151#[doc = include_str!("./atomic_load_volatile.md")]
3152///
3153 /// # Safety
3154 ///
3155 /// Behavior is undefined if any of the following conditions are violated:
3156 ///
3157 /// * `self` must be [valid] for reads, or `self` must point to memory
3158 /// outside of all Rust allocations and reading from that memory must:
3159 /// - not trap, and
3160 /// - not cause any memory inside a Rust allocation to be modified.
3161 ///
3162 /// * `self` must be aligned to
3163#[doc = concat!(" `align_of::<", stringify!($atomic_type), ">()`")]
3164 #[doc = if_8_bit!{
3165$int_type,
3166 yes = [
3167" (note that this is always true, since `align_of::<",
3168stringify!($atomic_type), ">() == 1`)."
3169],
3170 no = [
3171" (note that on some platforms this can be bigger than `align_of::<",
3172stringify!($int_type), ">()`)."
3173],
3174 }]
3175///
3176 /// * Reading from `self` must produce a properly initialized value of the underlying
3177 /// integer type.
3178 ///
3179 /// [valid]: core::ptr#safety
3180 ///
3181 /// # Panics
3182 ///
3183 /// Panics if `order` is [`Release`] or [`AcqRel`].
3184#[inline]
3185 #[unstable(feature = "atomic_volatile", issue = "158947")]
3186 #[rustc_const_unstable(feature = "atomic_volatile", issue = "158947")]
3187 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
3188pub const unsafe fn load_volatile(self: *const Self, order: Ordering) -> $int_type {
3189// SAFETY: follows from our own safety requirements.
3190unsafe {
3191 atomic_load::<_, /* VOLATILE */ true>(self.cast::<$int_type>(), order)
3192 }
3193 }
31943195/// Stores a value into the atomic integer.
3196 ///
3197 /// `store` takes an [`Ordering`] argument which describes the memory ordering of this operation.
3198 /// Possible values are [`SeqCst`], [`Release`] and [`Relaxed`].
3199 ///
3200 /// # Panics
3201 ///
3202 /// Panics if `order` is [`Acquire`] or [`AcqRel`].
3203 ///
3204 /// # Examples
3205 ///
3206#[cfg_attr($cfg_base, doc = "```")]
3207 #[cfg_attr(not($cfg_base), doc = "```compile_fail")]
3208 #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
3209///
3210#[doc = concat!("let some_var = ", stringify!($atomic_type), "::new(5);")]
3211///
3212 /// some_var.store(10, Ordering::Relaxed);
3213 /// assert_eq!(some_var.load(Ordering::Relaxed), 10);
3214 /// ```
3215#[inline]
3216 #[$stable]
3217 #[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
3218 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
3219#[rustc_should_not_be_called_on_const_items]
3220pub const fn store(&self, val: $int_type, order: Ordering) {
3221// SAFETY: data races are prevented by atomic intrinsics.
3222unsafe { atomic_store::<_, /* VOLATILE */ false>(self.as_ptr(), val, order); }
3223 }
32243225/// Performs a volatile store into the atomic integer.
3226 ///
3227 /// `store_volatile` takes an [`Ordering`] argument which describes the memory ordering
3228 /// of this operation. Possible values are [`SeqCst`], [`Release`] and [`Relaxed`].
3229 ///
3230#[doc = include_str!("./atomic_store_volatile.md")]
3231///
3232 /// # Safety
3233 ///
3234 /// Behavior is undefined if any of the following conditions are violated:
3235 ///
3236 /// * `self` must be either [valid] for writes, or `self` must point to memory
3237 /// outside of all Rust allocations and writing to that memory must:
3238 /// - not trap, and
3239 /// - not cause any memory inside a Rust allocation to be modified.
3240 ///
3241 /// * `self` must be aligned to
3242#[doc = concat!(" `align_of::<", stringify!($atomic_type), ">()`")]
3243 #[doc = if_8_bit!{
3244$int_type,
3245 yes = [
3246" (note that this is always true, since `align_of::<",
3247stringify!($atomic_type), ">() == 1`)."
3248],
3249 no = [
3250" (note that on some platforms this can be bigger than `align_of::<",
3251stringify!($int_type), ">()`)."
3252],
3253 }]
3254///
3255 /// [valid]: core::ptr#safety
3256 ///
3257 /// # Panics
3258 ///
3259 /// Panics if `order` is [`Acquire`] or [`AcqRel`].
3260#[inline]
3261 #[unstable(feature = "atomic_volatile", issue = "158947")]
3262 #[rustc_const_unstable(feature = "atomic_volatile", issue = "158947")]
3263 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
3264#[rustc_should_not_be_called_on_const_items]
3265pub const unsafe fn store_volatile(self: *const Self, val: $int_type, order: Ordering) {
3266// SAFETY: follows from our own safety requirements.
3267unsafe {
3268 atomic_store::<_, /* VOLATILE */ true>(self.cast::<$int_type>().cast_mut(), val, order);
3269 }
3270 }
32713272/// Stores a value into the atomic integer, returning the previous value.
3273 ///
3274 /// `swap` takes an [`Ordering`] argument which describes the memory ordering
3275 /// of this operation. All ordering modes are possible. Note that using
3276 /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
3277 /// using [`Release`] makes the load part [`Relaxed`].
3278 ///
3279 /// **Note**: This method is only available on platforms that support atomic operations on
3280#[doc = concat!("[`", $s_int_type, "`].")]
3281///
3282 /// # Examples
3283 ///
3284#[cfg_attr($cfg_cas, doc = "```")]
3285 #[cfg_attr(not($cfg_cas), doc = "```compile_fail")]
3286 #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
3287///
3288#[doc = concat!("let some_var = ", stringify!($atomic_type), "::new(5);")]
3289///
3290 /// assert_eq!(some_var.swap(10, Ordering::Relaxed), 5);
3291 /// ```
3292#[inline]
3293 #[$stable]
3294 #[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
3295 #[cfg(any($cfg_cas, doc))]
3296 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
3297#[rustc_should_not_be_called_on_const_items]
3298pub const fn swap(&self, val: $int_type, order: Ordering) -> $int_type {
3299// SAFETY: data races are prevented by atomic intrinsics.
3300unsafe { atomic_swap(self.as_ptr(), val, order) }
3301 }
33023303/// Stores a value into the atomic integer if the current value is the same as
3304 /// the `current` value.
3305 ///
3306 /// The return value is always the previous value. If it is equal to `current`, then the
3307 /// value was updated.
3308 ///
3309 /// `compare_and_swap` also takes an [`Ordering`] argument which describes the memory
3310 /// ordering of this operation. Notice that even when using [`AcqRel`], the operation
3311 /// might fail and hence just perform an `Acquire` load, but not have `Release` semantics.
3312 /// Using [`Acquire`] makes the store part of this operation [`Relaxed`] if it
3313 /// happens, and using [`Release`] makes the load part [`Relaxed`].
3314 ///
3315 /// **Note**: This method is only available on platforms that support atomic operations on
3316#[doc = concat!("[`", $s_int_type, "`].")]
3317///
3318 /// # Migrating to `compare_exchange` and `compare_exchange_weak`
3319 ///
3320 /// `compare_and_swap` is equivalent to `compare_exchange` with the following mapping for
3321 /// memory orderings:
3322 ///
3323 /// Original | Success | Failure
3324 /// -------- | ------- | -------
3325 /// Relaxed | Relaxed | Relaxed
3326 /// Acquire | Acquire | Acquire
3327 /// Release | Release | Relaxed
3328 /// AcqRel | AcqRel | Acquire
3329 /// SeqCst | SeqCst | SeqCst
3330 ///
3331 /// `compare_and_swap` and `compare_exchange` also differ in their return type. You can use
3332 /// `compare_exchange(...).unwrap_or_else(|x| x)` to recover the behavior of `compare_and_swap`,
3333 /// but in most cases it is more idiomatic to check whether the return value is `Ok` or `Err`
3334 /// rather than to infer success vs failure based on the value that was read.
3335 ///
3336 /// During migration, consider whether it makes sense to use `compare_exchange_weak` instead.
3337 /// `compare_exchange_weak` is allowed to fail spuriously even when the comparison succeeds,
3338 /// which allows the compiler to generate better assembly code when the compare and swap
3339 /// is used in a loop.
3340 ///
3341 /// # Examples
3342 ///
3343#[cfg_attr($cfg_cas, doc = "```")]
3344 #[cfg_attr(not($cfg_cas), doc = "```compile_fail")]
3345 #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
3346///
3347#[doc = concat!("let some_var = ", stringify!($atomic_type), "::new(5);")]
3348///
3349 /// assert_eq!(some_var.compare_and_swap(5, 10, Ordering::Relaxed), 5);
3350 /// assert_eq!(some_var.load(Ordering::Relaxed), 10);
3351 ///
3352 /// assert_eq!(some_var.compare_and_swap(6, 12, Ordering::Relaxed), 10);
3353 /// assert_eq!(some_var.load(Ordering::Relaxed), 10);
3354 /// ```
3355#[inline]
3356 #[$stable]
3357 #[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
3358 #[deprecated(
3359 since = "1.50.0",
3360 note = "Use `compare_exchange` or `compare_exchange_weak` instead")
3361 ]
3362 #[cfg(any($cfg_cas, doc))]
3363 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
3364#[rustc_should_not_be_called_on_const_items]
3365pub const fn compare_and_swap(&self,
3366 current: $int_type,
3367 new: $int_type,
3368 order: Ordering) -> $int_type {
3369match self.compare_exchange(current,
3370 new,
3371 order,
3372 strongest_failure_ordering(order)) {
3373Ok(x) => x,
3374Err(x) => x,
3375 }
3376 }
33773378/// Stores a value into the atomic integer if the current value is the same as
3379 /// the `current` value.
3380 ///
3381 /// The return value is a result indicating whether the new value was written and
3382 /// containing the previous value. On success this value is guaranteed to be equal to
3383 /// `current`.
3384 ///
3385 /// `compare_exchange` takes two [`Ordering`] arguments to describe the memory
3386 /// ordering of this operation. `success` describes the required ordering for the
3387 /// read-modify-write operation that takes place if the comparison with `current` succeeds.
3388 /// `failure` describes the required ordering for the load operation that takes place when
3389 /// the comparison fails. Using [`Acquire`] as success ordering makes the store part
3390 /// of this operation [`Relaxed`], and using [`Release`] makes the successful load
3391 /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
3392 ///
3393 /// **Note**: This method is only available on platforms that support atomic operations on
3394#[doc = concat!("[`", $s_int_type, "`].")]
3395///
3396 /// # Examples
3397 ///
3398#[cfg_attr($cfg_cas, doc = "```")]
3399 #[cfg_attr(not($cfg_cas), doc = "```compile_fail")]
3400 #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
3401///
3402#[doc = concat!("let some_var = ", stringify!($atomic_type), "::new(5);")]
3403///
3404 /// assert_eq!(some_var.compare_exchange(5, 10,
3405 /// Ordering::Acquire,
3406 /// Ordering::Relaxed),
3407 /// Ok(5));
3408 /// assert_eq!(some_var.load(Ordering::Relaxed), 10);
3409 ///
3410 /// assert_eq!(some_var.compare_exchange(6, 12,
3411 /// Ordering::SeqCst,
3412 /// Ordering::Acquire),
3413 /// Err(10));
3414 /// assert_eq!(some_var.load(Ordering::Relaxed), 10);
3415 /// ```
3416 ///
3417 /// # Considerations
3418 ///
3419 /// `compare_exchange` is a [compare-and-swap operation] and thus exhibits the usual downsides
3420 /// of CAS operations. In particular, a load of the value followed by a successful
3421 /// `compare_exchange` with the previous load *does not ensure* that other threads have not
3422 /// changed the value in the interim! This is usually important when the *equality* check in
3423 /// the `compare_exchange` is being used to check the *identity* of a value, but equality
3424 /// does not necessarily imply identity. This is a particularly common case for pointers, as
3425 /// a pointer holding the same address does not imply that the same object exists at that
3426 /// address! In this case, `compare_exchange` can lead to the [ABA problem].
3427 ///
3428 /// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
3429 /// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
3430#[inline]
3431 #[$stable_cxchg]
3432 #[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
3433 #[cfg(any($cfg_cas, doc))]
3434 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
3435#[rustc_should_not_be_called_on_const_items]
3436pub const fn compare_exchange(&self,
3437 current: $int_type,
3438 new: $int_type,
3439 success: Ordering,
3440 failure: Ordering) -> Result<$int_type, $int_type> {
3441// SAFETY: data races are prevented by atomic intrinsics.
3442unsafe { atomic_compare_exchange(self.as_ptr(), current, new, success, failure) }
3443 }
34443445/// Stores a value into the atomic integer if the current value is the same as
3446 /// the `current` value.
3447 ///
3448#[doc = concat!("Unlike [`", stringify!($atomic_type), "::compare_exchange`],")]
3449/// this function is allowed to spuriously fail even
3450 /// when the comparison succeeds, which can result in more efficient code on some
3451 /// platforms. The return value is a result indicating whether the new value was
3452 /// written and containing the previous value.
3453 ///
3454 /// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory
3455 /// ordering of this operation. `success` describes the required ordering for the
3456 /// read-modify-write operation that takes place if the comparison with `current` succeeds.
3457 /// `failure` describes the required ordering for the load operation that takes place when
3458 /// the comparison fails. Using [`Acquire`] as success ordering makes the store part
3459 /// of this operation [`Relaxed`], and using [`Release`] makes the successful load
3460 /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
3461 ///
3462 /// **Note**: This method is only available on platforms that support atomic operations on
3463#[doc = concat!("[`", $s_int_type, "`].")]
3464///
3465 /// # Examples
3466 ///
3467#[cfg_attr($cfg_cas, doc = "```")]
3468 #[cfg_attr(not($cfg_cas), doc = "```compile_fail")]
3469 #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
3470///
3471#[doc = concat!("let val = ", stringify!($atomic_type), "::new(4);")]
3472///
3473 /// let mut old = val.load(Ordering::Relaxed);
3474 /// loop {
3475 /// let new = old * 2;
3476 /// match val.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) {
3477 /// Ok(_) => break,
3478 /// Err(x) => old = x,
3479 /// }
3480 /// }
3481 /// ```
3482 ///
3483 /// # Considerations
3484 ///
3485 /// `compare_exchange` is a [compare-and-swap operation] and thus exhibits the usual downsides
3486 /// of CAS operations. In particular, a load of the value followed by a successful
3487 /// `compare_exchange` with the previous load *does not ensure* that other threads have not
3488 /// changed the value in the interim. This is usually important when the *equality* check in
3489 /// the `compare_exchange` is being used to check the *identity* of a value, but equality
3490 /// does not necessarily imply identity. This is a particularly common case for pointers, as
3491 /// a pointer holding the same address does not imply that the same object exists at that
3492 /// address! In this case, `compare_exchange` can lead to the [ABA problem].
3493 ///
3494 /// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
3495 /// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
3496#[inline]
3497 #[$stable_cxchg]
3498 #[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
3499 #[cfg(any($cfg_cas, doc))]
3500 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
3501#[rustc_should_not_be_called_on_const_items]
3502pub const fn compare_exchange_weak(&self,
3503 current: $int_type,
3504 new: $int_type,
3505 success: Ordering,
3506 failure: Ordering) -> Result<$int_type, $int_type> {
3507// SAFETY: data races are prevented by atomic intrinsics.
3508unsafe {
3509 atomic_compare_exchange_weak(self.as_ptr(), current, new, success, failure)
3510 }
3511 }
35123513/// Adds to the current value, returning the previous value.
3514 ///
3515 /// This operation wraps around on overflow.
3516 ///
3517 /// `fetch_add` takes an [`Ordering`] argument which describes the memory ordering
3518 /// of this operation. All ordering modes are possible. Note that using
3519 /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
3520 /// using [`Release`] makes the load part [`Relaxed`].
3521 ///
3522 /// **Note**: This method is only available on platforms that support atomic operations on
3523#[doc = concat!("[`", $s_int_type, "`].")]
3524///
3525 /// # Examples
3526 ///
3527#[cfg_attr($cfg_cas, doc = "```")]
3528 #[cfg_attr(not($cfg_cas), doc = "```compile_fail")]
3529 #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
3530///
3531#[doc = concat!("let foo = ", stringify!($atomic_type), "::new(0);")]
3532/// assert_eq!(foo.fetch_add(10, Ordering::SeqCst), 0);
3533 /// assert_eq!(foo.load(Ordering::SeqCst), 10);
3534 /// ```
3535#[inline]
3536 #[$stable]
3537 #[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
3538 #[cfg(any($cfg_cas, doc))]
3539 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
3540#[rustc_should_not_be_called_on_const_items]
3541pub const fn fetch_add(&self, val: $int_type, order: Ordering) -> $int_type {
3542// SAFETY: data races are prevented by atomic intrinsics.
3543unsafe { atomic_add(self.as_ptr(), val, order) }
3544 }
35453546/// Subtracts from the current value, returning the previous value.
3547 ///
3548 /// This operation wraps around on overflow.
3549 ///
3550 /// `fetch_sub` takes an [`Ordering`] argument which describes the memory ordering
3551 /// of this operation. All ordering modes are possible. Note that using
3552 /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
3553 /// using [`Release`] makes the load part [`Relaxed`].
3554 ///
3555 /// **Note**: This method is only available on platforms that support atomic operations on
3556#[doc = concat!("[`", $s_int_type, "`].")]
3557///
3558 /// # Examples
3559 ///
3560#[cfg_attr($cfg_cas, doc = "```")]
3561 #[cfg_attr(not($cfg_cas), doc = "```compile_fail")]
3562 #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
3563///
3564#[doc = concat!("let foo = ", stringify!($atomic_type), "::new(20);")]
3565/// assert_eq!(foo.fetch_sub(10, Ordering::SeqCst), 20);
3566 /// assert_eq!(foo.load(Ordering::SeqCst), 10);
3567 /// ```
3568#[inline]
3569 #[$stable]
3570 #[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
3571 #[cfg(any($cfg_cas, doc))]
3572 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
3573#[rustc_should_not_be_called_on_const_items]
3574pub const fn fetch_sub(&self, val: $int_type, order: Ordering) -> $int_type {
3575// SAFETY: data races are prevented by atomic intrinsics.
3576unsafe { atomic_sub(self.as_ptr(), val, order) }
3577 }
35783579/// Bitwise "and" with the current value.
3580 ///
3581 /// Performs a bitwise "and" operation on the current value and the argument `val`, and
3582 /// sets the new value to the result.
3583 ///
3584 /// Returns the previous value.
3585 ///
3586 /// `fetch_and` takes an [`Ordering`] argument which describes the memory ordering
3587 /// of this operation. All ordering modes are possible. Note that using
3588 /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
3589 /// using [`Release`] makes the load part [`Relaxed`].
3590 ///
3591 /// **Note**: This method is only available on platforms that support atomic operations on
3592#[doc = concat!("[`", $s_int_type, "`].")]
3593///
3594 /// # Examples
3595 ///
3596#[cfg_attr($cfg_cas, doc = "```")]
3597 #[cfg_attr(not($cfg_cas), doc = "```compile_fail")]
3598 #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
3599///
3600#[doc = concat!("let foo = ", stringify!($atomic_type), "::new(0b101101);")]
3601/// assert_eq!(foo.fetch_and(0b110011, Ordering::SeqCst), 0b101101);
3602 /// assert_eq!(foo.load(Ordering::SeqCst), 0b100001);
3603 /// ```
3604#[inline]
3605 #[$stable]
3606 #[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
3607 #[cfg(any($cfg_cas, doc))]
3608 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
3609#[rustc_should_not_be_called_on_const_items]
3610pub const fn fetch_and(&self, val: $int_type, order: Ordering) -> $int_type {
3611// SAFETY: data races are prevented by atomic intrinsics.
3612unsafe { atomic_and(self.as_ptr(), val, order) }
3613 }
36143615/// Bitwise "nand" with the current value.
3616 ///
3617 /// Performs a bitwise "nand" operation on the current value and the argument `val`, and
3618 /// sets the new value to the result.
3619 ///
3620 /// Returns the previous value.
3621 ///
3622 /// `fetch_nand` takes an [`Ordering`] argument which describes the memory ordering
3623 /// of this operation. All ordering modes are possible. Note that using
3624 /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
3625 /// using [`Release`] makes the load part [`Relaxed`].
3626 ///
3627 /// **Note**: This method is only available on platforms that support atomic operations on
3628#[doc = concat!("[`", $s_int_type, "`].")]
3629///
3630 /// # Examples
3631 ///
3632#[cfg_attr($cfg_cas, doc = "```")]
3633 #[cfg_attr(not($cfg_cas), doc = "```compile_fail")]
3634 #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
3635///
3636#[doc = concat!("let foo = ", stringify!($atomic_type), "::new(0x13);")]
3637/// assert_eq!(foo.fetch_nand(0x31, Ordering::SeqCst), 0x13);
3638 /// assert_eq!(foo.load(Ordering::SeqCst), !(0x13 & 0x31));
3639 /// ```
3640#[inline]
3641 #[$stable_nand]
3642 #[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
3643 #[cfg(any($cfg_cas, doc))]
3644 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
3645#[rustc_should_not_be_called_on_const_items]
3646pub const fn fetch_nand(&self, val: $int_type, order: Ordering) -> $int_type {
3647// SAFETY: data races are prevented by atomic intrinsics.
3648unsafe { atomic_nand(self.as_ptr(), val, order) }
3649 }
36503651/// Bitwise "or" with the current value.
3652 ///
3653 /// Performs a bitwise "or" operation on the current value and the argument `val`, and
3654 /// sets the new value to the result.
3655 ///
3656 /// Returns the previous value.
3657 ///
3658 /// `fetch_or` takes an [`Ordering`] argument which describes the memory ordering
3659 /// of this operation. All ordering modes are possible. Note that using
3660 /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
3661 /// using [`Release`] makes the load part [`Relaxed`].
3662 ///
3663 /// **Note**: This method is only available on platforms that support atomic operations on
3664#[doc = concat!("[`", $s_int_type, "`].")]
3665///
3666 /// # Examples
3667 ///
3668#[cfg_attr($cfg_cas, doc = "```")]
3669 #[cfg_attr(not($cfg_cas), doc = "```compile_fail")]
3670 #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
3671///
3672#[doc = concat!("let foo = ", stringify!($atomic_type), "::new(0b101101);")]
3673/// assert_eq!(foo.fetch_or(0b110011, Ordering::SeqCst), 0b101101);
3674 /// assert_eq!(foo.load(Ordering::SeqCst), 0b111111);
3675 /// ```
3676#[inline]
3677 #[$stable]
3678 #[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
3679 #[cfg(any($cfg_cas, doc))]
3680 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
3681#[rustc_should_not_be_called_on_const_items]
3682pub const fn fetch_or(&self, val: $int_type, order: Ordering) -> $int_type {
3683// SAFETY: data races are prevented by atomic intrinsics.
3684unsafe { atomic_or(self.as_ptr(), val, order) }
3685 }
36863687/// Bitwise "xor" with the current value.
3688 ///
3689 /// Performs a bitwise "xor" operation on the current value and the argument `val`, and
3690 /// sets the new value to the result.
3691 ///
3692 /// Returns the previous value.
3693 ///
3694 /// `fetch_xor` takes an [`Ordering`] argument which describes the memory ordering
3695 /// of this operation. All ordering modes are possible. Note that using
3696 /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
3697 /// using [`Release`] makes the load part [`Relaxed`].
3698 ///
3699 /// **Note**: This method is only available on platforms that support atomic operations on
3700#[doc = concat!("[`", $s_int_type, "`].")]
3701///
3702 /// # Examples
3703 ///
3704#[cfg_attr($cfg_cas, doc = "```")]
3705 #[cfg_attr(not($cfg_cas), doc = "```compile_fail")]
3706 #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
3707///
3708#[doc = concat!("let foo = ", stringify!($atomic_type), "::new(0b101101);")]
3709/// assert_eq!(foo.fetch_xor(0b110011, Ordering::SeqCst), 0b101101);
3710 /// assert_eq!(foo.load(Ordering::SeqCst), 0b011110);
3711 /// ```
3712#[inline]
3713 #[$stable]
3714 #[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
3715 #[cfg(any($cfg_cas, doc))]
3716 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
3717#[rustc_should_not_be_called_on_const_items]
3718pub const fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
3719// SAFETY: data races are prevented by atomic intrinsics.
3720unsafe { atomic_xor(self.as_ptr(), val, order) }
3721 }
37223723/// An alias for
3724#[doc = concat!("[`", stringify!($atomic_type), "::try_update`]")]
3725/// .
3726#[inline]
3727 #[stable(feature = "no_more_cas", since = "1.45.0")]
3728 #[cfg(any($cfg_cas, doc))]
3729 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
3730#[rustc_should_not_be_called_on_const_items]
3731 #[deprecated(
3732 since = "1.99.0",
3733 note = "renamed to `try_update` for consistency",
3734 suggestion = "try_update"
3735)]
3736pub fn fetch_update<F>(&self,
3737 set_order: Ordering,
3738 fetch_order: Ordering,
3739 f: F) -> Result<$int_type, $int_type>
3740where F: FnMut($int_type) -> Option<$int_type> {
3741self.try_update(set_order, fetch_order, f)
3742 }
37433744/// Fetches the value, and applies a function to it that returns an optional
3745 /// new value. Returns a `Result` of `Ok(previous_value)` if the function returned `Some(_)`, else
3746 /// `Err(previous_value)`.
3747 ///
3748#[doc = concat!("See also: [`update`](`", stringify!($atomic_type), "::update`).")]
3749///
3750 /// Note: This may call the function multiple times if the value has been changed from other threads in
3751 /// the meantime, as long as the function returns `Some(_)`, but the function will have been applied
3752 /// only once to the stored value.
3753 ///
3754 /// `try_update` takes two [`Ordering`] arguments to describe the memory ordering of this operation.
3755 /// The first describes the required ordering for when the operation finally succeeds while the second
3756 /// describes the required ordering for loads. These correspond to the success and failure orderings of
3757#[doc = concat!("[`", stringify!($atomic_type), "::compare_exchange`]")]
3758/// respectively.
3759 ///
3760 /// Using [`Acquire`] as success ordering makes the store part
3761 /// of this operation [`Relaxed`], and using [`Release`] makes the final successful load
3762 /// [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
3763 ///
3764 /// **Note**: This method is only available on platforms that support atomic operations on
3765#[doc = concat!("[`", $s_int_type, "`].")]
3766///
3767 /// # Considerations
3768 ///
3769 /// This method is not magic; it is not provided by the hardware, and does not act like a
3770 /// critical section or mutex.
3771 ///
3772 /// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
3773 /// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem]
3774 /// if this atomic integer is an index or more generally if knowledge of only the *bitwise value*
3775 /// of the atomic is not in and of itself sufficient to ensure any required preconditions.
3776 ///
3777 /// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
3778 /// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
3779 ///
3780 /// # Examples
3781 ///
3782#[cfg_attr($cfg_cas, doc = "```rust")]
3783 #[cfg_attr(not($cfg_cas), doc = "```rust,compile_fail")]
3784 #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
3785///
3786#[doc = concat!("let x = ", stringify!($atomic_type), "::new(7);")]
3787/// assert_eq!(x.try_update(Ordering::SeqCst, Ordering::SeqCst, |_| None), Err(7));
3788 /// assert_eq!(x.try_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(x + 1)), Ok(7));
3789 /// assert_eq!(x.try_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(x + 1)), Ok(8));
3790 /// assert_eq!(x.load(Ordering::SeqCst), 9);
3791 /// ```
3792#[inline]
3793 #[stable(feature = "atomic_try_update", since = "1.95.0")]
3794 #[cfg(any($cfg_cas, doc))]
3795 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
3796#[rustc_should_not_be_called_on_const_items]
3797pub fn try_update(
3798&self,
3799 set_order: Ordering,
3800 fetch_order: Ordering,
3801mut f: impl FnMut($int_type) -> Option<$int_type>,
3802 ) -> Result<$int_type, $int_type> {
3803let mut prev = self.load(fetch_order);
3804while let Some(next) = f(prev) {
3805match self.compare_exchange_weak(prev, next, set_order, fetch_order) {
3806 x @ Ok(_) => return x,
3807Err(next_prev) => prev = next_prev
3808 }
3809 }
3810Err(prev)
3811 }
38123813/// Fetches the value, and applies a function to it that returns a new value.
3814 /// The new value is stored and the old value is returned.
3815 ///
3816#[doc = concat!("See also: [`try_update`](`", stringify!($atomic_type), "::try_update`).")]
3817///
3818 /// Note: This may call the function multiple times if the value has been changed from other threads in
3819 /// the meantime, but the function will have been applied only once to the stored value.
3820 ///
3821 /// `update` takes two [`Ordering`] arguments to describe the memory ordering of this operation.
3822 /// The first describes the required ordering for when the operation finally succeeds while the second
3823 /// describes the required ordering for loads. These correspond to the success and failure orderings of
3824#[doc = concat!("[`", stringify!($atomic_type), "::compare_exchange`]")]
3825/// respectively.
3826 ///
3827 /// Using [`Acquire`] as success ordering makes the store part
3828 /// of this operation [`Relaxed`], and using [`Release`] makes the final successful load
3829 /// [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
3830 ///
3831 /// **Note**: This method is only available on platforms that support atomic operations on
3832#[doc = concat!("[`", $s_int_type, "`].")]
3833///
3834 /// # Considerations
3835 ///
3836 /// [CAS operation]: https://en.wikipedia.org/wiki/Compare-and-swap
3837 /// This method is not magic; it is not provided by the hardware, and does not act like a
3838 /// critical section or mutex.
3839 ///
3840 /// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
3841 /// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem]
3842 /// if this atomic integer is an index or more generally if knowledge of only the *bitwise value*
3843 /// of the atomic is not in and of itself sufficient to ensure any required preconditions.
3844 ///
3845 /// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
3846 /// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
3847 ///
3848 /// # Examples
3849 ///
3850#[cfg_attr($cfg_cas, doc = "```rust")]
3851 #[cfg_attr(not($cfg_cas), doc = "```rust,compile_fail")]
3852 #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
3853///
3854#[doc = concat!("let x = ", stringify!($atomic_type), "::new(7);")]
3855/// assert_eq!(x.update(Ordering::SeqCst, Ordering::SeqCst, |x| x + 1), 7);
3856 /// assert_eq!(x.update(Ordering::SeqCst, Ordering::SeqCst, |x| x + 1), 8);
3857 /// assert_eq!(x.load(Ordering::SeqCst), 9);
3858 /// ```
3859#[inline]
3860 #[stable(feature = "atomic_try_update", since = "1.95.0")]
3861 #[cfg(any($cfg_cas, doc))]
3862 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
3863#[rustc_should_not_be_called_on_const_items]
3864pub fn update(
3865&self,
3866 set_order: Ordering,
3867 fetch_order: Ordering,
3868mut f: impl FnMut($int_type) -> $int_type,
3869 ) -> $int_type {
3870let mut prev = self.load(fetch_order);
3871loop {
3872match self.compare_exchange_weak(prev, f(prev), set_order, fetch_order) {
3873Ok(x) => break x,
3874Err(next_prev) => prev = next_prev,
3875 }
3876 }
3877 }
38783879/// Maximum with the current value.
3880 ///
3881 /// Finds the maximum of the current value and the argument `val`, and
3882 /// sets the new value to the result.
3883 ///
3884 /// Returns the previous value.
3885 ///
3886 /// `fetch_max` takes an [`Ordering`] argument which describes the memory ordering
3887 /// of this operation. All ordering modes are possible. Note that using
3888 /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
3889 /// using [`Release`] makes the load part [`Relaxed`].
3890 ///
3891 /// **Note**: This method is only available on platforms that support atomic operations on
3892#[doc = concat!("[`", $s_int_type, "`].")]
3893///
3894 /// # Examples
3895 ///
3896#[cfg_attr($cfg_cas, doc = "```")]
3897 #[cfg_attr(not($cfg_cas), doc = "```compile_fail")]
3898 #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
3899///
3900#[doc = concat!("let foo = ", stringify!($atomic_type), "::new(23);")]
3901/// assert_eq!(foo.fetch_max(42, Ordering::SeqCst), 23);
3902 /// assert_eq!(foo.load(Ordering::SeqCst), 42);
3903 /// ```
3904 ///
3905 /// If you want to obtain the maximum value in one step, you can use the following:
3906 ///
3907#[cfg_attr($cfg_cas, doc = "```")]
3908 #[cfg_attr(not($cfg_cas), doc = "```compile_fail")]
3909 #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
3910///
3911#[doc = concat!("let foo = ", stringify!($atomic_type), "::new(23);")]
3912/// let bar = 42;
3913 /// let max_foo = foo.fetch_max(bar, Ordering::SeqCst).max(bar);
3914 /// assert!(max_foo == 42);
3915 /// ```
3916#[inline]
3917 #[stable(feature = "atomic_min_max", since = "1.45.0")]
3918 #[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
3919 #[cfg(any($cfg_cas, doc))]
3920 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
3921#[rustc_should_not_be_called_on_const_items]
3922pub const fn fetch_max(&self, val: $int_type, order: Ordering) -> $int_type {
3923// SAFETY: data races are prevented by atomic intrinsics.
3924unsafe { $max_fn(self.as_ptr(), val, order) }
3925 }
39263927/// Minimum with the current value.
3928 ///
3929 /// Finds the minimum of the current value and the argument `val`, and
3930 /// sets the new value to the result.
3931 ///
3932 /// Returns the previous value.
3933 ///
3934 /// `fetch_min` takes an [`Ordering`] argument which describes the memory ordering
3935 /// of this operation. All ordering modes are possible. Note that using
3936 /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
3937 /// using [`Release`] makes the load part [`Relaxed`].
3938 ///
3939 /// **Note**: This method is only available on platforms that support atomic operations on
3940#[doc = concat!("[`", $s_int_type, "`].")]
3941///
3942 /// # Examples
3943 ///
3944#[cfg_attr($cfg_cas, doc = "```")]
3945 #[cfg_attr(not($cfg_cas), doc = "```compile_fail")]
3946 #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
3947///
3948#[doc = concat!("let foo = ", stringify!($atomic_type), "::new(23);")]
3949/// assert_eq!(foo.fetch_min(42, Ordering::Relaxed), 23);
3950 /// assert_eq!(foo.load(Ordering::Relaxed), 23);
3951 /// assert_eq!(foo.fetch_min(22, Ordering::Relaxed), 23);
3952 /// assert_eq!(foo.load(Ordering::Relaxed), 22);
3953 /// ```
3954 ///
3955 /// If you want to obtain the minimum value in one step, you can use the following:
3956 ///
3957#[cfg_attr($cfg_cas, doc = "```")]
3958 #[cfg_attr(not($cfg_cas), doc = "```compile_fail")]
3959 #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
3960///
3961#[doc = concat!("let foo = ", stringify!($atomic_type), "::new(23);")]
3962/// let bar = 12;
3963 /// let min_foo = foo.fetch_min(bar, Ordering::SeqCst).min(bar);
3964 /// assert_eq!(min_foo, 12);
3965 /// ```
3966#[inline]
3967 #[stable(feature = "atomic_min_max", since = "1.45.0")]
3968 #[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
3969 #[cfg(any($cfg_cas, doc))]
3970 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
3971#[rustc_should_not_be_called_on_const_items]
3972pub const fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type {
3973// SAFETY: data races are prevented by atomic intrinsics.
3974unsafe { $min_fn(self.as_ptr(), val, order) }
3975 }
39763977/// Returns a mutable pointer to the underlying integer.
3978 ///
3979 /// Doing non-atomic reads and writes on the resulting integer can be a data race.
3980 /// This method is mostly useful for FFI, where the function signature may use
3981#[doc = concat!("`*mut ", stringify!($int_type), "` instead of `&", stringify!($atomic_type), "`.")]
3982///
3983 /// Returning an `*mut` pointer from a shared reference to this atomic is safe because the
3984 /// atomic types work with interior mutability. All modifications of an atomic change the value
3985 /// through a shared reference, and can do so safely as long as they use atomic operations. Any
3986 /// use of the returned raw pointer requires an `unsafe` block and still has to uphold the
3987 /// requirements of the [memory model].
3988 ///
3989 /// # Examples
3990 ///
3991 /// ```ignore (extern-declaration)
3992 /// # fn main() {
3993#[doc = concat!($extra_feature, "use std::sync::atomic::", stringify!($atomic_type), ";")]
3994///
3995 /// extern "C" {
3996#[doc = concat!(" fn my_atomic_op(arg: *mut ", stringify!($int_type), ");")]
3997/// }
3998 ///
3999#[doc = concat!("let atomic = ", stringify!($atomic_type), "::new(1);")]
4000///
4001 /// // SAFETY: Safe as long as `my_atomic_op` is atomic.
4002 /// unsafe {
4003 /// my_atomic_op(atomic.as_ptr());
4004 /// }
4005 /// # }
4006 /// ```
4007 ///
4008 /// [memory model]: self#memory-model-for-atomic-accesses
4009#[inline]
4010 #[stable(feature = "atomic_as_ptr", since = "1.70.0")]
4011 #[rustc_const_stable(feature = "atomic_as_ptr", since = "1.70.0")]
4012 #[rustc_never_returns_null_ptr]
4013pub const fn as_ptr(&self) -> *mut $int_type {
4014self.v.get().cast()
4015 }
4016 }
4017 }
4018}
40194020#[cfg(target_has_atomic_load_store = "8")]
4021/// An integer type which can be safely shared between threads.
///
/// This type has the same
#[doc = "size, alignment, and bit validity"]
/// as the underlying integer type, [`
#[doc = "i8"]
/// `].
#[doc = ""]
///
/// For more about the differences between atomic types and
/// non-atomic types as well as information about the portability of
/// this type, please see the [module-level documentation].
///
/// **Note:** This type is only available on platforms that support
/// atomic loads and stores of [`
#[doc = "i8"]
/// `].
///
/// [module-level documentation]: crate::sync::atomic
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
pub type AtomicI8 = Atomic<i8>;
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
impl Default for AtomicI8 {
#[inline]
fn default() -> Self { Self::new(Default::default()) }
}
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
const impl From<i8> for AtomicI8 {
#[doc = "Converts an `i8` into an `AtomicI8`."]
#[inline]
fn from(v: i8) -> Self { Self::new(v) }
}
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
impl fmt::Debug for AtomicI8 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.load(Ordering::Relaxed), f)
}
}
impl AtomicI8 {
/// Creates a new atomic integer.
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::AtomicI8;"]
///
#[doc = "let atomic_forty_two = AtomicI8::new(42);"]
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0")]
#[must_use]
pub const fn new(v: i8) -> Self { unsafe { transmute(v) } }
/// Creates a new reference to an atomic integer from a pointer.
///
/// # Examples
///
#[doc = "```rust"]
#[doc = "use std::sync::atomic::{self, AtomicI8};"]
///
/// // Get a pointer to an allocated value
#[doc = "let ptr: *mut i8 = Box::into_raw(Box::new(0));"]
///
#[doc = "assert!(ptr.cast::<AtomicI8>().is_aligned());"]
///
/// {
/// // Create an atomic view of the allocated value
#[doc = " let atomic = unsafe {AtomicI8::from_ptr(ptr) };"]
///
/// // Use `atomic` for atomic operations, possibly share it with other threads
/// atomic.store(1, atomic::Ordering::Relaxed);
/// }
///
/// // It's ok to non-atomically access the value behind `ptr`,
/// // since the reference to the atomic ended its lifetime in the block above
/// assert_eq!(unsafe { *ptr }, 1);
///
/// // Deallocate the value
/// unsafe { drop(Box::from_raw(ptr)) }
/// ```
///
/// # Safety
///
/// * `ptr` must be aligned to
#[doc = " `align_of::<AtomicI8>()`"]
#[doc =
" (note that this is always true, since `align_of::<AtomicI8>() == 1`)."]
/// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`.
/// * You must adhere to the [Memory model for atomic accesses]. In particular, it is not
/// allowed to mix conflicting atomic and non-atomic accesses, or atomic accesses of different
/// sizes, without synchronization.
///
/// [valid]: crate::ptr#safety
/// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses
#[inline]
#[stable(feature = "atomic_from_ptr", since = "1.75.0")]
#[rustc_const_stable(feature = "const_atomic_from_ptr", since = "1.84.0")]
pub const unsafe fn from_ptr<'a>(ptr: *mut i8) -> &'a AtomicI8 {
unsafe { &*ptr.cast() }
}
/// Creates a new pointer to an atomic integer from a pointer.
///
/// This is useful if you want to do volatile atomic accesses, and thus avoid creating
/// a reference to the destination.
#[inline]
#[unstable(feature = "atomic_volatile", issue = "158947")]
pub const fn from_ptr_raw(ptr: *mut i8) -> *const AtomicI8 {
ptr.cast_const().cast()
}
/// Returns a mutable reference to the underlying integer.
///
/// This is safe because the mutable reference guarantees that no other threads are
/// concurrently accessing the atomic data.
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI8, Ordering};"]
///
#[doc = "let mut some_var = AtomicI8::new(10);"]
/// assert_eq!(*some_var.get_mut(), 10);
/// *some_var.get_mut() = 5;
/// assert_eq!(some_var.load(Ordering::SeqCst), 5);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
pub const fn get_mut(&mut self) -> &mut i8 {
unsafe { &mut *self.as_ptr() }
}
#[doc = "Get atomic access to a `&mut i8`."]
///
#[doc = ""]
///
/// # Examples
///
#[doc = "```rust"]
#[doc = "use std::sync::atomic::{AtomicI8, Ordering};"]
///
/// let mut some_int = 123;
#[doc = "let a = AtomicI8::from_mut(&mut some_int);"]
/// a.store(100, Ordering::Relaxed);
/// assert_eq!(some_int, 100);
/// ```
///
#[inline]
#[stable(feature = "atomic_from_mut", since = "1.98.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
pub const fn from_mut(v: &mut i8) -> &mut Self {
let [] = [(); align_of::<Self>() - align_of::<i8>()];
unsafe { &mut *(v as *mut i8 as *mut Self) }
}
#[doc = "Get non-atomic access to a `&mut [AtomicI8]` slice"]
///
/// This is safe because the mutable reference guarantees that no other threads are
/// concurrently accessing the atomic data.
///
/// # Examples
///
#[doc = "```ignore-wasm"]
#[doc = "use std::sync::atomic::{AtomicI8, Ordering};"]
///
#[doc = "let mut some_ints = [const { AtomicI8::new(0) }; 10];"]
///
#[doc = "let view: &mut [i8] = AtomicI8::get_mut_slice(&mut some_ints);"]
/// assert_eq!(view, [0; 10]);
/// view
/// .iter_mut()
/// .enumerate()
/// .for_each(|(idx, int)| *int = idx as _);
///
/// std::thread::scope(|s| {
/// some_ints
/// .iter()
/// .enumerate()
/// .for_each(|(idx, int)| {
/// s.spawn(move || assert_eq!(int.load(Ordering::Relaxed), idx as _));
/// })
/// });
/// ```
#[inline]
#[stable(feature = "atomic_from_mut", since = "1.98.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
pub const fn get_mut_slice(this: &mut [Self]) -> &mut [i8] {
unsafe { &mut *(this as *mut [Self] as *mut [i8]) }
}
#[doc = "Get atomic access to a `&mut [i8]` slice."]
///
#[doc = ""]
///
/// # Examples
///
#[doc = "```ignore-wasm"]
#[doc = "use std::sync::atomic::{AtomicI8, Ordering};"]
///
/// let mut some_ints = [0; 10];
#[doc = "let a = &*AtomicI8::from_mut_slice(&mut some_ints);"]
/// std::thread::scope(|s| {
/// for i in 0..a.len() {
/// s.spawn(move || a[i].store(i as _, Ordering::Relaxed));
/// }
/// });
/// for (i, n) in some_ints.into_iter().enumerate() {
/// assert_eq!(i, n as usize);
/// }
/// ```
#[inline]
#[stable(feature = "atomic_from_mut", since = "1.98.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
pub const fn from_mut_slice(v: &mut [i8]) -> &mut [Self] {
let [] = [(); align_of::<Self>() - align_of::<i8>()];
unsafe { &mut *(v as *mut [i8] as *mut [Self]) }
}
/// Consumes the atomic and returns the contained value.
///
/// This is safe because passing `self` by value guarantees that no other threads are
/// concurrently accessing the atomic data.
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::AtomicI8;"]
///
#[doc = "let some_var = AtomicI8::new(5);"]
/// assert_eq!(some_var.into_inner(), 5);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_stable(feature = "const_atomic_into_inner", since =
"1.79.0")]
pub const fn into_inner(self) -> i8 { unsafe { transmute(self) } }
/// Loads a value from the atomic integer.
///
/// `load` takes an [`Ordering`] argument which describes the memory ordering of this operation.
/// Possible values are [`SeqCst`], [`Acquire`] and [`Relaxed`].
///
/// # Panics
///
/// Panics if `order` is [`Release`] or [`AcqRel`].
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI8, Ordering};"]
///
#[doc = "let some_var = AtomicI8::new(5);"]
///
/// assert_eq!(some_var.load(Ordering::Relaxed), 5);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
pub const fn load(&self, order: Ordering) -> i8 {
unsafe { atomic_load::<_, false>(self.as_ptr(), order) }
}
/// Perform a volatile load from the atomic integer.
///
/// `load_volatile` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. Possible values are [`SeqCst`], [`Acquire`] and [`Relaxed`].
///
#[doc =
"Volatile operations are intended to act on I/O memory. As such, they are considered externally\nobservable events (just like syscalls, but less opaque), and are guaranteed to not be elided or\nreordered by the compiler across other externally observable events. With this in mind, there\nare two cases of usage that need to be distinguished:\n\n- When a volatile operation is used for memory inside an [allocation], it behaves exactly\n like [`load`][Self::load], except for the additional guarantee that it won\'t be elided or\n reordered across other externally observable events (see above). This implies that the\n operation will actually access memory and not e.g. be lowered to reusing data from a\n previous load. Other than that, all the usual rules for memory accesses apply (including\n provenance).\n\n- Volatile operations, however, may also be used to access memory that is _outside_ of any Rust\n allocation. In this use-case, the pointer does *not* have to be [valid] for reads. This is\n typically used for CPU and peripheral registers that must be accessed via an I/O memory mapping,\n most commonly at fixed addresses reserved by the hardware. These often have special semantics\n associated to their manipulation, and cannot be used as general purpose memory. Here, any address\n value is possible, including 0 and [`usize::MAX`], so long as the semantics of such a read are\n well-defined by the target hardware. The provenance of the pointer is irrelevant, and it can be\n created with [`without_provenance`][crate::ptr::without_provenance]. The access is allowed to\n trap, which must immediately abort the process. It can also cause other side-effects, but those\n must not affect Rust-allocated memory in any way.\n\nIn both cases, the access is also considered atomic with the given `order`. This allows\nsynchronization with other threads or devices that share memory with this program.\n\nWhen invoked during const evaluation, this behaves like a regular atomic load. In\nparticular, such reads must always follow the first of the two cases above.\n\n[allocation]: crate::ptr#allocated-object\n"]
///
/// # Safety
///
/// Behavior is undefined if any of the following conditions are violated:
///
/// * `self` must be [valid] for reads, or `self` must point to memory
/// outside of all Rust allocations and reading from that memory must:
/// - not trap, and
/// - not cause any memory inside a Rust allocation to be modified.
///
/// * `self` must be aligned to
#[doc = " `align_of::<AtomicI8>()`"]
#[doc =
" (note that this is always true, since `align_of::<AtomicI8>() == 1`)."]
///
/// * Reading from `self` must produce a properly initialized value of the underlying
/// integer type.
///
/// [valid]: core::ptr#safety
///
/// # Panics
///
/// Panics if `order` is [`Release`] or [`AcqRel`].
#[inline]
#[unstable(feature = "atomic_volatile", issue = "158947")]
#[rustc_const_unstable(feature = "atomic_volatile", issue = "158947")]
pub const unsafe fn load_volatile(self: *const Self, order: Ordering)
-> i8 {
unsafe { atomic_load::<_, true>(self.cast::<i8>(), order) }
}
/// Stores a value into the atomic integer.
///
/// `store` takes an [`Ordering`] argument which describes the memory ordering of this operation.
/// Possible values are [`SeqCst`], [`Release`] and [`Relaxed`].
///
/// # Panics
///
/// Panics if `order` is [`Acquire`] or [`AcqRel`].
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI8, Ordering};"]
///
#[doc = "let some_var = AtomicI8::new(5);"]
///
/// some_var.store(10, Ordering::Relaxed);
/// assert_eq!(some_var.load(Ordering::Relaxed), 10);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn store(&self, val: i8, order: Ordering) {
unsafe { atomic_store::<_, false>(self.as_ptr(), val, order); }
}
/// Performs a volatile store into the atomic integer.
///
/// `store_volatile` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. Possible values are [`SeqCst`], [`Release`] and [`Relaxed`].
///
#[doc =
"Volatile operations are intended to act on I/O memory. As such, they are considered externally\nobservable events (just like syscalls), and are guaranteed to not be elided or reordered by the\ncompiler across other externally observable events. With this in mind, there are two cases of\nusage that need to be distinguished:\n\n- When a volatile operation is used for memory inside an [allocation], it behaves exactly like\n [`store`][Self::store], except for the additional guarantee that it won\'t be elided or reordered\n across other externally observable events (see above). This implies that the operation will\n actually access memory and not e.g. be lowered to a register access. Other than that, all the\n usual rules for memory accesses apply (including provenance).\n\n- Volatile operations, however, may also be used to access memory that is _outside_ of any Rust\n allocation. In this use-case, the pointer does *not* have to be [valid] for writes. This is\n typically used for CPU and peripheral registers that must be accessed via an I/O memory mapping,\n most commonly at fixed addresses reserved by the hardware. These often have special semantics\n associated to their manipulation, and cannot be used as general purpose memory. Here, any address\n value is possible, including 0 and [`usize::MAX`], so long as the semantics of such a write are\n well-defined by the target hardware. The provenance of the pointer is irrelevant, and it can be\n created with [`without_provenance_mut`][crate::ptr::without_provenance_mut]. The access is allowed\n to trap, which must immediately abort the process. It can also cause other side-effects, but those\n must not affect Rust-allocated memory in any way.\n\nIn both cases, the access is also considered atomic with the given `order`. This allows\nsynchronization with other threads or devices that share memory with this program.\n\nWhen invoked during const evaluation, this behaves like a regular atomic store. In\nparticular, such reads must always follow the first of the two cases above.\n\n[allocation]: crate::ptr#allocated-object\n"]
///
/// # Safety
///
/// Behavior is undefined if any of the following conditions are violated:
///
/// * `self` must be either [valid] for writes, or `self` must point to memory
/// outside of all Rust allocations and writing to that memory must:
/// - not trap, and
/// - not cause any memory inside a Rust allocation to be modified.
///
/// * `self` must be aligned to
#[doc = " `align_of::<AtomicI8>()`"]
#[doc =
" (note that this is always true, since `align_of::<AtomicI8>() == 1`)."]
///
/// [valid]: core::ptr#safety
///
/// # Panics
///
/// Panics if `order` is [`Acquire`] or [`AcqRel`].
#[inline]
#[unstable(feature = "atomic_volatile", issue = "158947")]
#[rustc_const_unstable(feature = "atomic_volatile", issue = "158947")]
#[rustc_should_not_be_called_on_const_items]
pub const unsafe fn store_volatile(self: *const Self, val: i8,
order: Ordering) {
unsafe {
atomic_store::<_, true>(self.cast::<i8>().cast_mut(), val, order);
}
}
/// Stores a value into the atomic integer, returning the previous value.
///
/// `swap` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`i8`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI8, Ordering};"]
///
#[doc = "let some_var = AtomicI8::new(5);"]
///
/// assert_eq!(some_var.swap(10, Ordering::Relaxed), 5);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn swap(&self, val: i8, order: Ordering) -> i8 {
unsafe { atomic_swap(self.as_ptr(), val, order) }
}
/// Stores a value into the atomic integer if the current value is the same as
/// the `current` value.
///
/// The return value is always the previous value. If it is equal to `current`, then the
/// value was updated.
///
/// `compare_and_swap` also takes an [`Ordering`] argument which describes the memory
/// ordering of this operation. Notice that even when using [`AcqRel`], the operation
/// might fail and hence just perform an `Acquire` load, but not have `Release` semantics.
/// Using [`Acquire`] makes the store part of this operation [`Relaxed`] if it
/// happens, and using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`i8`]."]
///
/// # Migrating to `compare_exchange` and `compare_exchange_weak`
///
/// `compare_and_swap` is equivalent to `compare_exchange` with the following mapping for
/// memory orderings:
///
/// Original | Success | Failure
/// -------- | ------- | -------
/// Relaxed | Relaxed | Relaxed
/// Acquire | Acquire | Acquire
/// Release | Release | Relaxed
/// AcqRel | AcqRel | Acquire
/// SeqCst | SeqCst | SeqCst
///
/// `compare_and_swap` and `compare_exchange` also differ in their return type. You can use
/// `compare_exchange(...).unwrap_or_else(|x| x)` to recover the behavior of `compare_and_swap`,
/// but in most cases it is more idiomatic to check whether the return value is `Ok` or `Err`
/// rather than to infer success vs failure based on the value that was read.
///
/// During migration, consider whether it makes sense to use `compare_exchange_weak` instead.
/// `compare_exchange_weak` is allowed to fail spuriously even when the comparison succeeds,
/// which allows the compiler to generate better assembly code when the compare and swap
/// is used in a loop.
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI8, Ordering};"]
///
#[doc = "let some_var = AtomicI8::new(5);"]
///
/// assert_eq!(some_var.compare_and_swap(5, 10, Ordering::Relaxed), 5);
/// assert_eq!(some_var.load(Ordering::Relaxed), 10);
///
/// assert_eq!(some_var.compare_and_swap(6, 12, Ordering::Relaxed), 10);
/// assert_eq!(some_var.load(Ordering::Relaxed), 10);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[deprecated(since = "1.50.0", note =
"Use `compare_exchange` or `compare_exchange_weak` instead")]
#[rustc_should_not_be_called_on_const_items]
pub const fn compare_and_swap(&self, current: i8, new: i8,
order: Ordering) -> i8 {
match self.compare_exchange(current, new, order,
strongest_failure_ordering(order)) {
Ok(x) => x,
Err(x) => x,
}
}
/// Stores a value into the atomic integer if the current value is the same as
/// the `current` value.
///
/// The return value is a result indicating whether the new value was written and
/// containing the previous value. On success this value is guaranteed to be equal to
/// `current`.
///
/// `compare_exchange` takes two [`Ordering`] arguments to describe the memory
/// ordering of this operation. `success` describes the required ordering for the
/// read-modify-write operation that takes place if the comparison with `current` succeeds.
/// `failure` describes the required ordering for the load operation that takes place when
/// the comparison fails. Using [`Acquire`] as success ordering makes the store part
/// of this operation [`Relaxed`], and using [`Release`] makes the successful load
/// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`i8`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI8, Ordering};"]
///
#[doc = "let some_var = AtomicI8::new(5);"]
///
/// assert_eq!(some_var.compare_exchange(5, 10,
/// Ordering::Acquire,
/// Ordering::Relaxed),
/// Ok(5));
/// assert_eq!(some_var.load(Ordering::Relaxed), 10);
///
/// assert_eq!(some_var.compare_exchange(6, 12,
/// Ordering::SeqCst,
/// Ordering::Acquire),
/// Err(10));
/// assert_eq!(some_var.load(Ordering::Relaxed), 10);
/// ```
///
/// # Considerations
///
/// `compare_exchange` is a [compare-and-swap operation] and thus exhibits the usual downsides
/// of CAS operations. In particular, a load of the value followed by a successful
/// `compare_exchange` with the previous load *does not ensure* that other threads have not
/// changed the value in the interim! This is usually important when the *equality* check in
/// the `compare_exchange` is being used to check the *identity* of a value, but equality
/// does not necessarily imply identity. This is a particularly common case for pointers, as
/// a pointer holding the same address does not imply that the same object exists at that
/// address! In this case, `compare_exchange` can lead to the [ABA problem].
///
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn compare_exchange(&self, current: i8, new: i8,
success: Ordering, failure: Ordering) -> Result<i8, i8> {
unsafe {
atomic_compare_exchange(self.as_ptr(), current, new, success,
failure)
}
}
/// Stores a value into the atomic integer if the current value is the same as
/// the `current` value.
///
#[doc = "Unlike [`AtomicI8::compare_exchange`],"]
/// this function is allowed to spuriously fail even
/// when the comparison succeeds, which can result in more efficient code on some
/// platforms. The return value is a result indicating whether the new value was
/// written and containing the previous value.
///
/// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory
/// ordering of this operation. `success` describes the required ordering for the
/// read-modify-write operation that takes place if the comparison with `current` succeeds.
/// `failure` describes the required ordering for the load operation that takes place when
/// the comparison fails. Using [`Acquire`] as success ordering makes the store part
/// of this operation [`Relaxed`], and using [`Release`] makes the successful load
/// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`i8`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI8, Ordering};"]
///
#[doc = "let val = AtomicI8::new(4);"]
///
/// let mut old = val.load(Ordering::Relaxed);
/// loop {
/// let new = old * 2;
/// match val.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) {
/// Ok(_) => break,
/// Err(x) => old = x,
/// }
/// }
/// ```
///
/// # Considerations
///
/// `compare_exchange` is a [compare-and-swap operation] and thus exhibits the usual downsides
/// of CAS operations. In particular, a load of the value followed by a successful
/// `compare_exchange` with the previous load *does not ensure* that other threads have not
/// changed the value in the interim. This is usually important when the *equality* check in
/// the `compare_exchange` is being used to check the *identity* of a value, but equality
/// does not necessarily imply identity. This is a particularly common case for pointers, as
/// a pointer holding the same address does not imply that the same object exists at that
/// address! In this case, `compare_exchange` can lead to the [ABA problem].
///
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn compare_exchange_weak(&self, current: i8, new: i8,
success: Ordering, failure: Ordering) -> Result<i8, i8> {
unsafe {
atomic_compare_exchange_weak(self.as_ptr(), current, new, success,
failure)
}
}
/// Adds to the current value, returning the previous value.
///
/// This operation wraps around on overflow.
///
/// `fetch_add` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`i8`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI8, Ordering};"]
///
#[doc = "let foo = AtomicI8::new(0);"]
/// assert_eq!(foo.fetch_add(10, Ordering::SeqCst), 0);
/// assert_eq!(foo.load(Ordering::SeqCst), 10);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_add(&self, val: i8, order: Ordering) -> i8 {
unsafe { atomic_add(self.as_ptr(), val, order) }
}
/// Subtracts from the current value, returning the previous value.
///
/// This operation wraps around on overflow.
///
/// `fetch_sub` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`i8`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI8, Ordering};"]
///
#[doc = "let foo = AtomicI8::new(20);"]
/// assert_eq!(foo.fetch_sub(10, Ordering::SeqCst), 20);
/// assert_eq!(foo.load(Ordering::SeqCst), 10);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_sub(&self, val: i8, order: Ordering) -> i8 {
unsafe { atomic_sub(self.as_ptr(), val, order) }
}
/// Bitwise "and" with the current value.
///
/// Performs a bitwise "and" operation on the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_and` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`i8`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI8, Ordering};"]
///
#[doc = "let foo = AtomicI8::new(0b101101);"]
/// assert_eq!(foo.fetch_and(0b110011, Ordering::SeqCst), 0b101101);
/// assert_eq!(foo.load(Ordering::SeqCst), 0b100001);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_and(&self, val: i8, order: Ordering) -> i8 {
unsafe { atomic_and(self.as_ptr(), val, order) }
}
/// Bitwise "nand" with the current value.
///
/// Performs a bitwise "nand" operation on the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_nand` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`i8`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI8, Ordering};"]
///
#[doc = "let foo = AtomicI8::new(0x13);"]
/// assert_eq!(foo.fetch_nand(0x31, Ordering::SeqCst), 0x13);
/// assert_eq!(foo.load(Ordering::SeqCst), !(0x13 & 0x31));
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_nand(&self, val: i8, order: Ordering) -> i8 {
unsafe { atomic_nand(self.as_ptr(), val, order) }
}
/// Bitwise "or" with the current value.
///
/// Performs a bitwise "or" operation on the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_or` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`i8`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI8, Ordering};"]
///
#[doc = "let foo = AtomicI8::new(0b101101);"]
/// assert_eq!(foo.fetch_or(0b110011, Ordering::SeqCst), 0b101101);
/// assert_eq!(foo.load(Ordering::SeqCst), 0b111111);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_or(&self, val: i8, order: Ordering) -> i8 {
unsafe { atomic_or(self.as_ptr(), val, order) }
}
/// Bitwise "xor" with the current value.
///
/// Performs a bitwise "xor" operation on the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_xor` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`i8`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI8, Ordering};"]
///
#[doc = "let foo = AtomicI8::new(0b101101);"]
/// assert_eq!(foo.fetch_xor(0b110011, Ordering::SeqCst), 0b101101);
/// assert_eq!(foo.load(Ordering::SeqCst), 0b011110);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_xor(&self, val: i8, order: Ordering) -> i8 {
unsafe { atomic_xor(self.as_ptr(), val, order) }
}
/// An alias for
#[doc = "[`AtomicI8::try_update`]"]
/// .
#[inline]
#[stable(feature = "no_more_cas", since = "1.45.0")]
#[rustc_should_not_be_called_on_const_items]
#[deprecated(since = "1.99.0", note =
"renamed to `try_update` for consistency", suggestion = "try_update")]
pub fn fetch_update<F>(&self, set_order: Ordering, fetch_order: Ordering,
f: F) -> Result<i8, i8> where F: FnMut(i8) -> Option<i8> {
self.try_update(set_order, fetch_order, f)
}
/// Fetches the value, and applies a function to it that returns an optional
/// new value. Returns a `Result` of `Ok(previous_value)` if the function returned `Some(_)`, else
/// `Err(previous_value)`.
///
#[doc = "See also: [`update`](`AtomicI8::update`)."]
///
/// Note: This may call the function multiple times if the value has been changed from other threads in
/// the meantime, as long as the function returns `Some(_)`, but the function will have been applied
/// only once to the stored value.
///
/// `try_update` takes two [`Ordering`] arguments to describe the memory ordering of this operation.
/// The first describes the required ordering for when the operation finally succeeds while the second
/// describes the required ordering for loads. These correspond to the success and failure orderings of
#[doc = "[`AtomicI8::compare_exchange`]"]
/// respectively.
///
/// Using [`Acquire`] as success ordering makes the store part
/// of this operation [`Relaxed`], and using [`Release`] makes the final successful load
/// [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`i8`]."]
///
/// # Considerations
///
/// This method is not magic; it is not provided by the hardware, and does not act like a
/// critical section or mutex.
///
/// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
/// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem]
/// if this atomic integer is an index or more generally if knowledge of only the *bitwise value*
/// of the atomic is not in and of itself sufficient to ensure any required preconditions.
///
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
///
/// # Examples
///
#[doc = "```rust"]
#[doc = "use std::sync::atomic::{AtomicI8, Ordering};"]
///
#[doc = "let x = AtomicI8::new(7);"]
/// assert_eq!(x.try_update(Ordering::SeqCst, Ordering::SeqCst, |_| None), Err(7));
/// assert_eq!(x.try_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(x + 1)), Ok(7));
/// assert_eq!(x.try_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(x + 1)), Ok(8));
/// assert_eq!(x.load(Ordering::SeqCst), 9);
/// ```
#[inline]
#[stable(feature = "atomic_try_update", since = "1.95.0")]
#[rustc_should_not_be_called_on_const_items]
pub fn try_update(&self, set_order: Ordering, fetch_order: Ordering,
mut f: impl FnMut(i8) -> Option<i8>) -> Result<i8, i8> {
let mut prev = self.load(fetch_order);
while let Some(next) = f(prev) {
match self.compare_exchange_weak(prev, next, set_order,
fetch_order) {
x @ Ok(_) => return x,
Err(next_prev) => prev = next_prev,
}
}
Err(prev)
}
/// Fetches the value, and applies a function to it that returns a new value.
/// The new value is stored and the old value is returned.
///
#[doc = "See also: [`try_update`](`AtomicI8::try_update`)."]
///
/// Note: This may call the function multiple times if the value has been changed from other threads in
/// the meantime, but the function will have been applied only once to the stored value.
///
/// `update` takes two [`Ordering`] arguments to describe the memory ordering of this operation.
/// The first describes the required ordering for when the operation finally succeeds while the second
/// describes the required ordering for loads. These correspond to the success and failure orderings of
#[doc = "[`AtomicI8::compare_exchange`]"]
/// respectively.
///
/// Using [`Acquire`] as success ordering makes the store part
/// of this operation [`Relaxed`], and using [`Release`] makes the final successful load
/// [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`i8`]."]
///
/// # Considerations
///
/// [CAS operation]: https://en.wikipedia.org/wiki/Compare-and-swap
/// This method is not magic; it is not provided by the hardware, and does not act like a
/// critical section or mutex.
///
/// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
/// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem]
/// if this atomic integer is an index or more generally if knowledge of only the *bitwise value*
/// of the atomic is not in and of itself sufficient to ensure any required preconditions.
///
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
///
/// # Examples
///
#[doc = "```rust"]
#[doc = "use std::sync::atomic::{AtomicI8, Ordering};"]
///
#[doc = "let x = AtomicI8::new(7);"]
/// assert_eq!(x.update(Ordering::SeqCst, Ordering::SeqCst, |x| x + 1), 7);
/// assert_eq!(x.update(Ordering::SeqCst, Ordering::SeqCst, |x| x + 1), 8);
/// assert_eq!(x.load(Ordering::SeqCst), 9);
/// ```
#[inline]
#[stable(feature = "atomic_try_update", since = "1.95.0")]
#[rustc_should_not_be_called_on_const_items]
pub fn update(&self, set_order: Ordering, fetch_order: Ordering,
mut f: impl FnMut(i8) -> i8) -> i8 {
let mut prev = self.load(fetch_order);
loop {
match self.compare_exchange_weak(prev, f(prev), set_order,
fetch_order) {
Ok(x) => break x,
Err(next_prev) => prev = next_prev,
}
}
}
/// Maximum with the current value.
///
/// Finds the maximum of the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_max` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`i8`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI8, Ordering};"]
///
#[doc = "let foo = AtomicI8::new(23);"]
/// assert_eq!(foo.fetch_max(42, Ordering::SeqCst), 23);
/// assert_eq!(foo.load(Ordering::SeqCst), 42);
/// ```
///
/// If you want to obtain the maximum value in one step, you can use the following:
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI8, Ordering};"]
///
#[doc = "let foo = AtomicI8::new(23);"]
/// let bar = 42;
/// let max_foo = foo.fetch_max(bar, Ordering::SeqCst).max(bar);
/// assert!(max_foo == 42);
/// ```
#[inline]
#[stable(feature = "atomic_min_max", since = "1.45.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_max(&self, val: i8, order: Ordering) -> i8 {
unsafe { atomic_max(self.as_ptr(), val, order) }
}
/// Minimum with the current value.
///
/// Finds the minimum of the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_min` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`i8`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI8, Ordering};"]
///
#[doc = "let foo = AtomicI8::new(23);"]
/// assert_eq!(foo.fetch_min(42, Ordering::Relaxed), 23);
/// assert_eq!(foo.load(Ordering::Relaxed), 23);
/// assert_eq!(foo.fetch_min(22, Ordering::Relaxed), 23);
/// assert_eq!(foo.load(Ordering::Relaxed), 22);
/// ```
///
/// If you want to obtain the minimum value in one step, you can use the following:
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI8, Ordering};"]
///
#[doc = "let foo = AtomicI8::new(23);"]
/// let bar = 12;
/// let min_foo = foo.fetch_min(bar, Ordering::SeqCst).min(bar);
/// assert_eq!(min_foo, 12);
/// ```
#[inline]
#[stable(feature = "atomic_min_max", since = "1.45.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_min(&self, val: i8, order: Ordering) -> i8 {
unsafe { atomic_min(self.as_ptr(), val, order) }
}
/// Returns a mutable pointer to the underlying integer.
///
/// Doing non-atomic reads and writes on the resulting integer can be a data race.
/// This method is mostly useful for FFI, where the function signature may use
#[doc = "`*mut i8` instead of `&AtomicI8`."]
///
/// Returning an `*mut` pointer from a shared reference to this atomic is safe because the
/// atomic types work with interior mutability. All modifications of an atomic change the value
/// through a shared reference, and can do so safely as long as they use atomic operations. Any
/// use of the returned raw pointer requires an `unsafe` block and still has to uphold the
/// requirements of the [memory model].
///
/// # Examples
///
/// ```ignore (extern-declaration)
/// # fn main() {
#[doc = "use std::sync::atomic::AtomicI8;"]
///
/// extern "C" {
#[doc = " fn my_atomic_op(arg: *mut i8);"]
/// }
///
#[doc = "let atomic = AtomicI8::new(1);"]
///
/// // SAFETY: Safe as long as `my_atomic_op` is atomic.
/// unsafe {
/// my_atomic_op(atomic.as_ptr());
/// }
/// # }
/// ```
///
/// [memory model]: self#memory-model-for-atomic-accesses
#[inline]
#[stable(feature = "atomic_as_ptr", since = "1.70.0")]
#[rustc_const_stable(feature = "atomic_as_ptr", since = "1.70.0")]
#[rustc_never_returns_null_ptr]
pub const fn as_ptr(&self) -> *mut i8 { self.v.get().cast() }
}atomic_int! {
4022 target_has_atomic_load_store = "8",
4023 target_has_atomic = "8",
4024 target_has_atomic_primitive_alignment = "8",
4025 stable(feature = "integer_atomics_stable", since = "1.34.0"),
4026 stable(feature = "integer_atomics_stable", since = "1.34.0"),
4027 stable(feature = "integer_atomics_stable", since = "1.34.0"),
4028 stable(feature = "integer_atomics_stable", since = "1.34.0"),
4029 stable(feature = "integer_atomics_stable", since = "1.34.0"),
4030 stable(feature = "integer_atomics_stable", since = "1.34.0"),
4031 rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
4032 rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"),
4033"i8",
4034"",
4035 atomic_min, atomic_max,
40361,
4037 i8 AtomicI84038}4039#[cfg(target_has_atomic_load_store = "8")]
4040/// An integer type which can be safely shared between threads.
///
/// This type has the same
#[doc = "size, alignment, and bit validity"]
/// as the underlying integer type, [`
#[doc = "u8"]
/// `].
#[doc = ""]
///
/// For more about the differences between atomic types and
/// non-atomic types as well as information about the portability of
/// this type, please see the [module-level documentation].
///
/// **Note:** This type is only available on platforms that support
/// atomic loads and stores of [`
#[doc = "u8"]
/// `].
///
/// [module-level documentation]: crate::sync::atomic
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
pub type AtomicU8 = Atomic<u8>;
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
impl Default for AtomicU8 {
#[inline]
fn default() -> Self { Self::new(Default::default()) }
}
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
const impl From<u8> for AtomicU8 {
#[doc = "Converts an `u8` into an `AtomicU8`."]
#[inline]
fn from(v: u8) -> Self { Self::new(v) }
}
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
impl fmt::Debug for AtomicU8 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.load(Ordering::Relaxed), f)
}
}
impl AtomicU8 {
/// Creates a new atomic integer.
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::AtomicU8;"]
///
#[doc = "let atomic_forty_two = AtomicU8::new(42);"]
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0")]
#[must_use]
pub const fn new(v: u8) -> Self { unsafe { transmute(v) } }
/// Creates a new reference to an atomic integer from a pointer.
///
/// # Examples
///
#[doc = "```rust"]
#[doc = "use std::sync::atomic::{self, AtomicU8};"]
///
/// // Get a pointer to an allocated value
#[doc = "let ptr: *mut u8 = Box::into_raw(Box::new(0));"]
///
#[doc = "assert!(ptr.cast::<AtomicU8>().is_aligned());"]
///
/// {
/// // Create an atomic view of the allocated value
#[doc = " let atomic = unsafe {AtomicU8::from_ptr(ptr) };"]
///
/// // Use `atomic` for atomic operations, possibly share it with other threads
/// atomic.store(1, atomic::Ordering::Relaxed);
/// }
///
/// // It's ok to non-atomically access the value behind `ptr`,
/// // since the reference to the atomic ended its lifetime in the block above
/// assert_eq!(unsafe { *ptr }, 1);
///
/// // Deallocate the value
/// unsafe { drop(Box::from_raw(ptr)) }
/// ```
///
/// # Safety
///
/// * `ptr` must be aligned to
#[doc = " `align_of::<AtomicU8>()`"]
#[doc =
" (note that this is always true, since `align_of::<AtomicU8>() == 1`)."]
/// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`.
/// * You must adhere to the [Memory model for atomic accesses]. In particular, it is not
/// allowed to mix conflicting atomic and non-atomic accesses, or atomic accesses of different
/// sizes, without synchronization.
///
/// [valid]: crate::ptr#safety
/// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses
#[inline]
#[stable(feature = "atomic_from_ptr", since = "1.75.0")]
#[rustc_const_stable(feature = "const_atomic_from_ptr", since = "1.84.0")]
pub const unsafe fn from_ptr<'a>(ptr: *mut u8) -> &'a AtomicU8 {
unsafe { &*ptr.cast() }
}
/// Creates a new pointer to an atomic integer from a pointer.
///
/// This is useful if you want to do volatile atomic accesses, and thus avoid creating
/// a reference to the destination.
#[inline]
#[unstable(feature = "atomic_volatile", issue = "158947")]
pub const fn from_ptr_raw(ptr: *mut u8) -> *const AtomicU8 {
ptr.cast_const().cast()
}
/// Returns a mutable reference to the underlying integer.
///
/// This is safe because the mutable reference guarantees that no other threads are
/// concurrently accessing the atomic data.
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU8, Ordering};"]
///
#[doc = "let mut some_var = AtomicU8::new(10);"]
/// assert_eq!(*some_var.get_mut(), 10);
/// *some_var.get_mut() = 5;
/// assert_eq!(some_var.load(Ordering::SeqCst), 5);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
pub const fn get_mut(&mut self) -> &mut u8 {
unsafe { &mut *self.as_ptr() }
}
#[doc = "Get atomic access to a `&mut u8`."]
///
#[doc = ""]
///
/// # Examples
///
#[doc = "```rust"]
#[doc = "use std::sync::atomic::{AtomicU8, Ordering};"]
///
/// let mut some_int = 123;
#[doc = "let a = AtomicU8::from_mut(&mut some_int);"]
/// a.store(100, Ordering::Relaxed);
/// assert_eq!(some_int, 100);
/// ```
///
#[inline]
#[stable(feature = "atomic_from_mut", since = "1.98.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
pub const fn from_mut(v: &mut u8) -> &mut Self {
let [] = [(); align_of::<Self>() - align_of::<u8>()];
unsafe { &mut *(v as *mut u8 as *mut Self) }
}
#[doc = "Get non-atomic access to a `&mut [AtomicU8]` slice"]
///
/// This is safe because the mutable reference guarantees that no other threads are
/// concurrently accessing the atomic data.
///
/// # Examples
///
#[doc = "```ignore-wasm"]
#[doc = "use std::sync::atomic::{AtomicU8, Ordering};"]
///
#[doc = "let mut some_ints = [const { AtomicU8::new(0) }; 10];"]
///
#[doc = "let view: &mut [u8] = AtomicU8::get_mut_slice(&mut some_ints);"]
/// assert_eq!(view, [0; 10]);
/// view
/// .iter_mut()
/// .enumerate()
/// .for_each(|(idx, int)| *int = idx as _);
///
/// std::thread::scope(|s| {
/// some_ints
/// .iter()
/// .enumerate()
/// .for_each(|(idx, int)| {
/// s.spawn(move || assert_eq!(int.load(Ordering::Relaxed), idx as _));
/// })
/// });
/// ```
#[inline]
#[stable(feature = "atomic_from_mut", since = "1.98.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
pub const fn get_mut_slice(this: &mut [Self]) -> &mut [u8] {
unsafe { &mut *(this as *mut [Self] as *mut [u8]) }
}
#[doc = "Get atomic access to a `&mut [u8]` slice."]
///
#[doc = ""]
///
/// # Examples
///
#[doc = "```ignore-wasm"]
#[doc = "use std::sync::atomic::{AtomicU8, Ordering};"]
///
/// let mut some_ints = [0; 10];
#[doc = "let a = &*AtomicU8::from_mut_slice(&mut some_ints);"]
/// std::thread::scope(|s| {
/// for i in 0..a.len() {
/// s.spawn(move || a[i].store(i as _, Ordering::Relaxed));
/// }
/// });
/// for (i, n) in some_ints.into_iter().enumerate() {
/// assert_eq!(i, n as usize);
/// }
/// ```
#[inline]
#[stable(feature = "atomic_from_mut", since = "1.98.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
pub const fn from_mut_slice(v: &mut [u8]) -> &mut [Self] {
let [] = [(); align_of::<Self>() - align_of::<u8>()];
unsafe { &mut *(v as *mut [u8] as *mut [Self]) }
}
/// Consumes the atomic and returns the contained value.
///
/// This is safe because passing `self` by value guarantees that no other threads are
/// concurrently accessing the atomic data.
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::AtomicU8;"]
///
#[doc = "let some_var = AtomicU8::new(5);"]
/// assert_eq!(some_var.into_inner(), 5);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_stable(feature = "const_atomic_into_inner", since =
"1.79.0")]
pub const fn into_inner(self) -> u8 { unsafe { transmute(self) } }
/// Loads a value from the atomic integer.
///
/// `load` takes an [`Ordering`] argument which describes the memory ordering of this operation.
/// Possible values are [`SeqCst`], [`Acquire`] and [`Relaxed`].
///
/// # Panics
///
/// Panics if `order` is [`Release`] or [`AcqRel`].
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU8, Ordering};"]
///
#[doc = "let some_var = AtomicU8::new(5);"]
///
/// assert_eq!(some_var.load(Ordering::Relaxed), 5);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
pub const fn load(&self, order: Ordering) -> u8 {
unsafe { atomic_load::<_, false>(self.as_ptr(), order) }
}
/// Perform a volatile load from the atomic integer.
///
/// `load_volatile` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. Possible values are [`SeqCst`], [`Acquire`] and [`Relaxed`].
///
#[doc =
"Volatile operations are intended to act on I/O memory. As such, they are considered externally\nobservable events (just like syscalls, but less opaque), and are guaranteed to not be elided or\nreordered by the compiler across other externally observable events. With this in mind, there\nare two cases of usage that need to be distinguished:\n\n- When a volatile operation is used for memory inside an [allocation], it behaves exactly\n like [`load`][Self::load], except for the additional guarantee that it won\'t be elided or\n reordered across other externally observable events (see above). This implies that the\n operation will actually access memory and not e.g. be lowered to reusing data from a\n previous load. Other than that, all the usual rules for memory accesses apply (including\n provenance).\n\n- Volatile operations, however, may also be used to access memory that is _outside_ of any Rust\n allocation. In this use-case, the pointer does *not* have to be [valid] for reads. This is\n typically used for CPU and peripheral registers that must be accessed via an I/O memory mapping,\n most commonly at fixed addresses reserved by the hardware. These often have special semantics\n associated to their manipulation, and cannot be used as general purpose memory. Here, any address\n value is possible, including 0 and [`usize::MAX`], so long as the semantics of such a read are\n well-defined by the target hardware. The provenance of the pointer is irrelevant, and it can be\n created with [`without_provenance`][crate::ptr::without_provenance]. The access is allowed to\n trap, which must immediately abort the process. It can also cause other side-effects, but those\n must not affect Rust-allocated memory in any way.\n\nIn both cases, the access is also considered atomic with the given `order`. This allows\nsynchronization with other threads or devices that share memory with this program.\n\nWhen invoked during const evaluation, this behaves like a regular atomic load. In\nparticular, such reads must always follow the first of the two cases above.\n\n[allocation]: crate::ptr#allocated-object\n"]
///
/// # Safety
///
/// Behavior is undefined if any of the following conditions are violated:
///
/// * `self` must be [valid] for reads, or `self` must point to memory
/// outside of all Rust allocations and reading from that memory must:
/// - not trap, and
/// - not cause any memory inside a Rust allocation to be modified.
///
/// * `self` must be aligned to
#[doc = " `align_of::<AtomicU8>()`"]
#[doc =
" (note that this is always true, since `align_of::<AtomicU8>() == 1`)."]
///
/// * Reading from `self` must produce a properly initialized value of the underlying
/// integer type.
///
/// [valid]: core::ptr#safety
///
/// # Panics
///
/// Panics if `order` is [`Release`] or [`AcqRel`].
#[inline]
#[unstable(feature = "atomic_volatile", issue = "158947")]
#[rustc_const_unstable(feature = "atomic_volatile", issue = "158947")]
pub const unsafe fn load_volatile(self: *const Self, order: Ordering)
-> u8 {
unsafe { atomic_load::<_, true>(self.cast::<u8>(), order) }
}
/// Stores a value into the atomic integer.
///
/// `store` takes an [`Ordering`] argument which describes the memory ordering of this operation.
/// Possible values are [`SeqCst`], [`Release`] and [`Relaxed`].
///
/// # Panics
///
/// Panics if `order` is [`Acquire`] or [`AcqRel`].
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU8, Ordering};"]
///
#[doc = "let some_var = AtomicU8::new(5);"]
///
/// some_var.store(10, Ordering::Relaxed);
/// assert_eq!(some_var.load(Ordering::Relaxed), 10);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn store(&self, val: u8, order: Ordering) {
unsafe { atomic_store::<_, false>(self.as_ptr(), val, order); }
}
/// Performs a volatile store into the atomic integer.
///
/// `store_volatile` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. Possible values are [`SeqCst`], [`Release`] and [`Relaxed`].
///
#[doc =
"Volatile operations are intended to act on I/O memory. As such, they are considered externally\nobservable events (just like syscalls), and are guaranteed to not be elided or reordered by the\ncompiler across other externally observable events. With this in mind, there are two cases of\nusage that need to be distinguished:\n\n- When a volatile operation is used for memory inside an [allocation], it behaves exactly like\n [`store`][Self::store], except for the additional guarantee that it won\'t be elided or reordered\n across other externally observable events (see above). This implies that the operation will\n actually access memory and not e.g. be lowered to a register access. Other than that, all the\n usual rules for memory accesses apply (including provenance).\n\n- Volatile operations, however, may also be used to access memory that is _outside_ of any Rust\n allocation. In this use-case, the pointer does *not* have to be [valid] for writes. This is\n typically used for CPU and peripheral registers that must be accessed via an I/O memory mapping,\n most commonly at fixed addresses reserved by the hardware. These often have special semantics\n associated to their manipulation, and cannot be used as general purpose memory. Here, any address\n value is possible, including 0 and [`usize::MAX`], so long as the semantics of such a write are\n well-defined by the target hardware. The provenance of the pointer is irrelevant, and it can be\n created with [`without_provenance_mut`][crate::ptr::without_provenance_mut]. The access is allowed\n to trap, which must immediately abort the process. It can also cause other side-effects, but those\n must not affect Rust-allocated memory in any way.\n\nIn both cases, the access is also considered atomic with the given `order`. This allows\nsynchronization with other threads or devices that share memory with this program.\n\nWhen invoked during const evaluation, this behaves like a regular atomic store. In\nparticular, such reads must always follow the first of the two cases above.\n\n[allocation]: crate::ptr#allocated-object\n"]
///
/// # Safety
///
/// Behavior is undefined if any of the following conditions are violated:
///
/// * `self` must be either [valid] for writes, or `self` must point to memory
/// outside of all Rust allocations and writing to that memory must:
/// - not trap, and
/// - not cause any memory inside a Rust allocation to be modified.
///
/// * `self` must be aligned to
#[doc = " `align_of::<AtomicU8>()`"]
#[doc =
" (note that this is always true, since `align_of::<AtomicU8>() == 1`)."]
///
/// [valid]: core::ptr#safety
///
/// # Panics
///
/// Panics if `order` is [`Acquire`] or [`AcqRel`].
#[inline]
#[unstable(feature = "atomic_volatile", issue = "158947")]
#[rustc_const_unstable(feature = "atomic_volatile", issue = "158947")]
#[rustc_should_not_be_called_on_const_items]
pub const unsafe fn store_volatile(self: *const Self, val: u8,
order: Ordering) {
unsafe {
atomic_store::<_, true>(self.cast::<u8>().cast_mut(), val, order);
}
}
/// Stores a value into the atomic integer, returning the previous value.
///
/// `swap` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`u8`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU8, Ordering};"]
///
#[doc = "let some_var = AtomicU8::new(5);"]
///
/// assert_eq!(some_var.swap(10, Ordering::Relaxed), 5);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn swap(&self, val: u8, order: Ordering) -> u8 {
unsafe { atomic_swap(self.as_ptr(), val, order) }
}
/// Stores a value into the atomic integer if the current value is the same as
/// the `current` value.
///
/// The return value is always the previous value. If it is equal to `current`, then the
/// value was updated.
///
/// `compare_and_swap` also takes an [`Ordering`] argument which describes the memory
/// ordering of this operation. Notice that even when using [`AcqRel`], the operation
/// might fail and hence just perform an `Acquire` load, but not have `Release` semantics.
/// Using [`Acquire`] makes the store part of this operation [`Relaxed`] if it
/// happens, and using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`u8`]."]
///
/// # Migrating to `compare_exchange` and `compare_exchange_weak`
///
/// `compare_and_swap` is equivalent to `compare_exchange` with the following mapping for
/// memory orderings:
///
/// Original | Success | Failure
/// -------- | ------- | -------
/// Relaxed | Relaxed | Relaxed
/// Acquire | Acquire | Acquire
/// Release | Release | Relaxed
/// AcqRel | AcqRel | Acquire
/// SeqCst | SeqCst | SeqCst
///
/// `compare_and_swap` and `compare_exchange` also differ in their return type. You can use
/// `compare_exchange(...).unwrap_or_else(|x| x)` to recover the behavior of `compare_and_swap`,
/// but in most cases it is more idiomatic to check whether the return value is `Ok` or `Err`
/// rather than to infer success vs failure based on the value that was read.
///
/// During migration, consider whether it makes sense to use `compare_exchange_weak` instead.
/// `compare_exchange_weak` is allowed to fail spuriously even when the comparison succeeds,
/// which allows the compiler to generate better assembly code when the compare and swap
/// is used in a loop.
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU8, Ordering};"]
///
#[doc = "let some_var = AtomicU8::new(5);"]
///
/// assert_eq!(some_var.compare_and_swap(5, 10, Ordering::Relaxed), 5);
/// assert_eq!(some_var.load(Ordering::Relaxed), 10);
///
/// assert_eq!(some_var.compare_and_swap(6, 12, Ordering::Relaxed), 10);
/// assert_eq!(some_var.load(Ordering::Relaxed), 10);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[deprecated(since = "1.50.0", note =
"Use `compare_exchange` or `compare_exchange_weak` instead")]
#[rustc_should_not_be_called_on_const_items]
pub const fn compare_and_swap(&self, current: u8, new: u8,
order: Ordering) -> u8 {
match self.compare_exchange(current, new, order,
strongest_failure_ordering(order)) {
Ok(x) => x,
Err(x) => x,
}
}
/// Stores a value into the atomic integer if the current value is the same as
/// the `current` value.
///
/// The return value is a result indicating whether the new value was written and
/// containing the previous value. On success this value is guaranteed to be equal to
/// `current`.
///
/// `compare_exchange` takes two [`Ordering`] arguments to describe the memory
/// ordering of this operation. `success` describes the required ordering for the
/// read-modify-write operation that takes place if the comparison with `current` succeeds.
/// `failure` describes the required ordering for the load operation that takes place when
/// the comparison fails. Using [`Acquire`] as success ordering makes the store part
/// of this operation [`Relaxed`], and using [`Release`] makes the successful load
/// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`u8`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU8, Ordering};"]
///
#[doc = "let some_var = AtomicU8::new(5);"]
///
/// assert_eq!(some_var.compare_exchange(5, 10,
/// Ordering::Acquire,
/// Ordering::Relaxed),
/// Ok(5));
/// assert_eq!(some_var.load(Ordering::Relaxed), 10);
///
/// assert_eq!(some_var.compare_exchange(6, 12,
/// Ordering::SeqCst,
/// Ordering::Acquire),
/// Err(10));
/// assert_eq!(some_var.load(Ordering::Relaxed), 10);
/// ```
///
/// # Considerations
///
/// `compare_exchange` is a [compare-and-swap operation] and thus exhibits the usual downsides
/// of CAS operations. In particular, a load of the value followed by a successful
/// `compare_exchange` with the previous load *does not ensure* that other threads have not
/// changed the value in the interim! This is usually important when the *equality* check in
/// the `compare_exchange` is being used to check the *identity* of a value, but equality
/// does not necessarily imply identity. This is a particularly common case for pointers, as
/// a pointer holding the same address does not imply that the same object exists at that
/// address! In this case, `compare_exchange` can lead to the [ABA problem].
///
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn compare_exchange(&self, current: u8, new: u8,
success: Ordering, failure: Ordering) -> Result<u8, u8> {
unsafe {
atomic_compare_exchange(self.as_ptr(), current, new, success,
failure)
}
}
/// Stores a value into the atomic integer if the current value is the same as
/// the `current` value.
///
#[doc = "Unlike [`AtomicU8::compare_exchange`],"]
/// this function is allowed to spuriously fail even
/// when the comparison succeeds, which can result in more efficient code on some
/// platforms. The return value is a result indicating whether the new value was
/// written and containing the previous value.
///
/// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory
/// ordering of this operation. `success` describes the required ordering for the
/// read-modify-write operation that takes place if the comparison with `current` succeeds.
/// `failure` describes the required ordering for the load operation that takes place when
/// the comparison fails. Using [`Acquire`] as success ordering makes the store part
/// of this operation [`Relaxed`], and using [`Release`] makes the successful load
/// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`u8`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU8, Ordering};"]
///
#[doc = "let val = AtomicU8::new(4);"]
///
/// let mut old = val.load(Ordering::Relaxed);
/// loop {
/// let new = old * 2;
/// match val.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) {
/// Ok(_) => break,
/// Err(x) => old = x,
/// }
/// }
/// ```
///
/// # Considerations
///
/// `compare_exchange` is a [compare-and-swap operation] and thus exhibits the usual downsides
/// of CAS operations. In particular, a load of the value followed by a successful
/// `compare_exchange` with the previous load *does not ensure* that other threads have not
/// changed the value in the interim. This is usually important when the *equality* check in
/// the `compare_exchange` is being used to check the *identity* of a value, but equality
/// does not necessarily imply identity. This is a particularly common case for pointers, as
/// a pointer holding the same address does not imply that the same object exists at that
/// address! In this case, `compare_exchange` can lead to the [ABA problem].
///
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn compare_exchange_weak(&self, current: u8, new: u8,
success: Ordering, failure: Ordering) -> Result<u8, u8> {
unsafe {
atomic_compare_exchange_weak(self.as_ptr(), current, new, success,
failure)
}
}
/// Adds to the current value, returning the previous value.
///
/// This operation wraps around on overflow.
///
/// `fetch_add` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`u8`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU8, Ordering};"]
///
#[doc = "let foo = AtomicU8::new(0);"]
/// assert_eq!(foo.fetch_add(10, Ordering::SeqCst), 0);
/// assert_eq!(foo.load(Ordering::SeqCst), 10);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_add(&self, val: u8, order: Ordering) -> u8 {
unsafe { atomic_add(self.as_ptr(), val, order) }
}
/// Subtracts from the current value, returning the previous value.
///
/// This operation wraps around on overflow.
///
/// `fetch_sub` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`u8`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU8, Ordering};"]
///
#[doc = "let foo = AtomicU8::new(20);"]
/// assert_eq!(foo.fetch_sub(10, Ordering::SeqCst), 20);
/// assert_eq!(foo.load(Ordering::SeqCst), 10);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_sub(&self, val: u8, order: Ordering) -> u8 {
unsafe { atomic_sub(self.as_ptr(), val, order) }
}
/// Bitwise "and" with the current value.
///
/// Performs a bitwise "and" operation on the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_and` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`u8`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU8, Ordering};"]
///
#[doc = "let foo = AtomicU8::new(0b101101);"]
/// assert_eq!(foo.fetch_and(0b110011, Ordering::SeqCst), 0b101101);
/// assert_eq!(foo.load(Ordering::SeqCst), 0b100001);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_and(&self, val: u8, order: Ordering) -> u8 {
unsafe { atomic_and(self.as_ptr(), val, order) }
}
/// Bitwise "nand" with the current value.
///
/// Performs a bitwise "nand" operation on the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_nand` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`u8`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU8, Ordering};"]
///
#[doc = "let foo = AtomicU8::new(0x13);"]
/// assert_eq!(foo.fetch_nand(0x31, Ordering::SeqCst), 0x13);
/// assert_eq!(foo.load(Ordering::SeqCst), !(0x13 & 0x31));
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_nand(&self, val: u8, order: Ordering) -> u8 {
unsafe { atomic_nand(self.as_ptr(), val, order) }
}
/// Bitwise "or" with the current value.
///
/// Performs a bitwise "or" operation on the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_or` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`u8`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU8, Ordering};"]
///
#[doc = "let foo = AtomicU8::new(0b101101);"]
/// assert_eq!(foo.fetch_or(0b110011, Ordering::SeqCst), 0b101101);
/// assert_eq!(foo.load(Ordering::SeqCst), 0b111111);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_or(&self, val: u8, order: Ordering) -> u8 {
unsafe { atomic_or(self.as_ptr(), val, order) }
}
/// Bitwise "xor" with the current value.
///
/// Performs a bitwise "xor" operation on the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_xor` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`u8`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU8, Ordering};"]
///
#[doc = "let foo = AtomicU8::new(0b101101);"]
/// assert_eq!(foo.fetch_xor(0b110011, Ordering::SeqCst), 0b101101);
/// assert_eq!(foo.load(Ordering::SeqCst), 0b011110);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_xor(&self, val: u8, order: Ordering) -> u8 {
unsafe { atomic_xor(self.as_ptr(), val, order) }
}
/// An alias for
#[doc = "[`AtomicU8::try_update`]"]
/// .
#[inline]
#[stable(feature = "no_more_cas", since = "1.45.0")]
#[rustc_should_not_be_called_on_const_items]
#[deprecated(since = "1.99.0", note =
"renamed to `try_update` for consistency", suggestion = "try_update")]
pub fn fetch_update<F>(&self, set_order: Ordering, fetch_order: Ordering,
f: F) -> Result<u8, u8> where F: FnMut(u8) -> Option<u8> {
self.try_update(set_order, fetch_order, f)
}
/// Fetches the value, and applies a function to it that returns an optional
/// new value. Returns a `Result` of `Ok(previous_value)` if the function returned `Some(_)`, else
/// `Err(previous_value)`.
///
#[doc = "See also: [`update`](`AtomicU8::update`)."]
///
/// Note: This may call the function multiple times if the value has been changed from other threads in
/// the meantime, as long as the function returns `Some(_)`, but the function will have been applied
/// only once to the stored value.
///
/// `try_update` takes two [`Ordering`] arguments to describe the memory ordering of this operation.
/// The first describes the required ordering for when the operation finally succeeds while the second
/// describes the required ordering for loads. These correspond to the success and failure orderings of
#[doc = "[`AtomicU8::compare_exchange`]"]
/// respectively.
///
/// Using [`Acquire`] as success ordering makes the store part
/// of this operation [`Relaxed`], and using [`Release`] makes the final successful load
/// [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`u8`]."]
///
/// # Considerations
///
/// This method is not magic; it is not provided by the hardware, and does not act like a
/// critical section or mutex.
///
/// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
/// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem]
/// if this atomic integer is an index or more generally if knowledge of only the *bitwise value*
/// of the atomic is not in and of itself sufficient to ensure any required preconditions.
///
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
///
/// # Examples
///
#[doc = "```rust"]
#[doc = "use std::sync::atomic::{AtomicU8, Ordering};"]
///
#[doc = "let x = AtomicU8::new(7);"]
/// assert_eq!(x.try_update(Ordering::SeqCst, Ordering::SeqCst, |_| None), Err(7));
/// assert_eq!(x.try_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(x + 1)), Ok(7));
/// assert_eq!(x.try_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(x + 1)), Ok(8));
/// assert_eq!(x.load(Ordering::SeqCst), 9);
/// ```
#[inline]
#[stable(feature = "atomic_try_update", since = "1.95.0")]
#[rustc_should_not_be_called_on_const_items]
pub fn try_update(&self, set_order: Ordering, fetch_order: Ordering,
mut f: impl FnMut(u8) -> Option<u8>) -> Result<u8, u8> {
let mut prev = self.load(fetch_order);
while let Some(next) = f(prev) {
match self.compare_exchange_weak(prev, next, set_order,
fetch_order) {
x @ Ok(_) => return x,
Err(next_prev) => prev = next_prev,
}
}
Err(prev)
}
/// Fetches the value, and applies a function to it that returns a new value.
/// The new value is stored and the old value is returned.
///
#[doc = "See also: [`try_update`](`AtomicU8::try_update`)."]
///
/// Note: This may call the function multiple times if the value has been changed from other threads in
/// the meantime, but the function will have been applied only once to the stored value.
///
/// `update` takes two [`Ordering`] arguments to describe the memory ordering of this operation.
/// The first describes the required ordering for when the operation finally succeeds while the second
/// describes the required ordering for loads. These correspond to the success and failure orderings of
#[doc = "[`AtomicU8::compare_exchange`]"]
/// respectively.
///
/// Using [`Acquire`] as success ordering makes the store part
/// of this operation [`Relaxed`], and using [`Release`] makes the final successful load
/// [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`u8`]."]
///
/// # Considerations
///
/// [CAS operation]: https://en.wikipedia.org/wiki/Compare-and-swap
/// This method is not magic; it is not provided by the hardware, and does not act like a
/// critical section or mutex.
///
/// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
/// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem]
/// if this atomic integer is an index or more generally if knowledge of only the *bitwise value*
/// of the atomic is not in and of itself sufficient to ensure any required preconditions.
///
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
///
/// # Examples
///
#[doc = "```rust"]
#[doc = "use std::sync::atomic::{AtomicU8, Ordering};"]
///
#[doc = "let x = AtomicU8::new(7);"]
/// assert_eq!(x.update(Ordering::SeqCst, Ordering::SeqCst, |x| x + 1), 7);
/// assert_eq!(x.update(Ordering::SeqCst, Ordering::SeqCst, |x| x + 1), 8);
/// assert_eq!(x.load(Ordering::SeqCst), 9);
/// ```
#[inline]
#[stable(feature = "atomic_try_update", since = "1.95.0")]
#[rustc_should_not_be_called_on_const_items]
pub fn update(&self, set_order: Ordering, fetch_order: Ordering,
mut f: impl FnMut(u8) -> u8) -> u8 {
let mut prev = self.load(fetch_order);
loop {
match self.compare_exchange_weak(prev, f(prev), set_order,
fetch_order) {
Ok(x) => break x,
Err(next_prev) => prev = next_prev,
}
}
}
/// Maximum with the current value.
///
/// Finds the maximum of the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_max` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`u8`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU8, Ordering};"]
///
#[doc = "let foo = AtomicU8::new(23);"]
/// assert_eq!(foo.fetch_max(42, Ordering::SeqCst), 23);
/// assert_eq!(foo.load(Ordering::SeqCst), 42);
/// ```
///
/// If you want to obtain the maximum value in one step, you can use the following:
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU8, Ordering};"]
///
#[doc = "let foo = AtomicU8::new(23);"]
/// let bar = 42;
/// let max_foo = foo.fetch_max(bar, Ordering::SeqCst).max(bar);
/// assert!(max_foo == 42);
/// ```
#[inline]
#[stable(feature = "atomic_min_max", since = "1.45.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_max(&self, val: u8, order: Ordering) -> u8 {
unsafe { atomic_umax(self.as_ptr(), val, order) }
}
/// Minimum with the current value.
///
/// Finds the minimum of the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_min` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`u8`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU8, Ordering};"]
///
#[doc = "let foo = AtomicU8::new(23);"]
/// assert_eq!(foo.fetch_min(42, Ordering::Relaxed), 23);
/// assert_eq!(foo.load(Ordering::Relaxed), 23);
/// assert_eq!(foo.fetch_min(22, Ordering::Relaxed), 23);
/// assert_eq!(foo.load(Ordering::Relaxed), 22);
/// ```
///
/// If you want to obtain the minimum value in one step, you can use the following:
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU8, Ordering};"]
///
#[doc = "let foo = AtomicU8::new(23);"]
/// let bar = 12;
/// let min_foo = foo.fetch_min(bar, Ordering::SeqCst).min(bar);
/// assert_eq!(min_foo, 12);
/// ```
#[inline]
#[stable(feature = "atomic_min_max", since = "1.45.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_min(&self, val: u8, order: Ordering) -> u8 {
unsafe { atomic_umin(self.as_ptr(), val, order) }
}
/// Returns a mutable pointer to the underlying integer.
///
/// Doing non-atomic reads and writes on the resulting integer can be a data race.
/// This method is mostly useful for FFI, where the function signature may use
#[doc = "`*mut u8` instead of `&AtomicU8`."]
///
/// Returning an `*mut` pointer from a shared reference to this atomic is safe because the
/// atomic types work with interior mutability. All modifications of an atomic change the value
/// through a shared reference, and can do so safely as long as they use atomic operations. Any
/// use of the returned raw pointer requires an `unsafe` block and still has to uphold the
/// requirements of the [memory model].
///
/// # Examples
///
/// ```ignore (extern-declaration)
/// # fn main() {
#[doc = "use std::sync::atomic::AtomicU8;"]
///
/// extern "C" {
#[doc = " fn my_atomic_op(arg: *mut u8);"]
/// }
///
#[doc = "let atomic = AtomicU8::new(1);"]
///
/// // SAFETY: Safe as long as `my_atomic_op` is atomic.
/// unsafe {
/// my_atomic_op(atomic.as_ptr());
/// }
/// # }
/// ```
///
/// [memory model]: self#memory-model-for-atomic-accesses
#[inline]
#[stable(feature = "atomic_as_ptr", since = "1.70.0")]
#[rustc_const_stable(feature = "atomic_as_ptr", since = "1.70.0")]
#[rustc_never_returns_null_ptr]
pub const fn as_ptr(&self) -> *mut u8 { self.v.get().cast() }
}atomic_int! {
4041 target_has_atomic_load_store = "8",
4042 target_has_atomic = "8",
4043 target_has_atomic_primitive_alignment = "8",
4044 stable(feature = "integer_atomics_stable", since = "1.34.0"),
4045 stable(feature = "integer_atomics_stable", since = "1.34.0"),
4046 stable(feature = "integer_atomics_stable", since = "1.34.0"),
4047 stable(feature = "integer_atomics_stable", since = "1.34.0"),
4048 stable(feature = "integer_atomics_stable", since = "1.34.0"),
4049 stable(feature = "integer_atomics_stable", since = "1.34.0"),
4050 rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
4051 rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"),
4052"u8",
4053"",
4054 atomic_umin, atomic_umax,
40551,
4056 u8 AtomicU84057}4058#[cfg(target_has_atomic_load_store = "16")]
4059/// An integer type which can be safely shared between threads.
///
/// This type has the same
#[doc = "size and bit validity"]
/// as the underlying integer type, [`
#[doc = "i16"]
/// `].
#[doc =
"However, the alignment of this type is always equal to its size, even on targets where [`i16`] has a lesser alignment."]
///
/// For more about the differences between atomic types and
/// non-atomic types as well as information about the portability of
/// this type, please see the [module-level documentation].
///
/// **Note:** This type is only available on platforms that support
/// atomic loads and stores of [`
#[doc = "i16"]
/// `].
///
/// [module-level documentation]: crate::sync::atomic
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
pub type AtomicI16 = Atomic<i16>;
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
impl Default for AtomicI16 {
#[inline]
fn default() -> Self { Self::new(Default::default()) }
}
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
const impl From<i16> for AtomicI16 {
#[doc = "Converts an `i16` into an `AtomicI16`."]
#[inline]
fn from(v: i16) -> Self { Self::new(v) }
}
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
impl fmt::Debug for AtomicI16 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.load(Ordering::Relaxed), f)
}
}
impl AtomicI16 {
/// Creates a new atomic integer.
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::AtomicI16;"]
///
#[doc = "let atomic_forty_two = AtomicI16::new(42);"]
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0")]
#[must_use]
pub const fn new(v: i16) -> Self { unsafe { transmute(v) } }
/// Creates a new reference to an atomic integer from a pointer.
///
/// # Examples
///
#[doc = "```rust"]
#[doc = "use std::sync::atomic::{self, AtomicI16};"]
///
/// // Get a pointer to an allocated value
#[doc = "let ptr: *mut i16 = Box::into_raw(Box::new(0));"]
///
#[doc = "assert!(ptr.cast::<AtomicI16>().is_aligned());"]
///
/// {
/// // Create an atomic view of the allocated value
#[doc = " let atomic = unsafe {AtomicI16::from_ptr(ptr) };"]
///
/// // Use `atomic` for atomic operations, possibly share it with other threads
/// atomic.store(1, atomic::Ordering::Relaxed);
/// }
///
/// // It's ok to non-atomically access the value behind `ptr`,
/// // since the reference to the atomic ended its lifetime in the block above
/// assert_eq!(unsafe { *ptr }, 1);
///
/// // Deallocate the value
/// unsafe { drop(Box::from_raw(ptr)) }
/// ```
///
/// # Safety
///
/// * `ptr` must be aligned to
#[doc = " `align_of::<AtomicI16>()`"]
#[doc =
" (note that on some platforms this can be bigger than `align_of::<i16>()`)."]
/// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`.
/// * You must adhere to the [Memory model for atomic accesses]. In particular, it is not
/// allowed to mix conflicting atomic and non-atomic accesses, or atomic accesses of different
/// sizes, without synchronization.
///
/// [valid]: crate::ptr#safety
/// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses
#[inline]
#[stable(feature = "atomic_from_ptr", since = "1.75.0")]
#[rustc_const_stable(feature = "const_atomic_from_ptr", since = "1.84.0")]
pub const unsafe fn from_ptr<'a>(ptr: *mut i16) -> &'a AtomicI16 {
unsafe { &*ptr.cast() }
}
/// Creates a new pointer to an atomic integer from a pointer.
///
/// This is useful if you want to do volatile atomic accesses, and thus avoid creating
/// a reference to the destination.
#[inline]
#[unstable(feature = "atomic_volatile", issue = "158947")]
pub const fn from_ptr_raw(ptr: *mut i16) -> *const AtomicI16 {
ptr.cast_const().cast()
}
/// Returns a mutable reference to the underlying integer.
///
/// This is safe because the mutable reference guarantees that no other threads are
/// concurrently accessing the atomic data.
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI16, Ordering};"]
///
#[doc = "let mut some_var = AtomicI16::new(10);"]
/// assert_eq!(*some_var.get_mut(), 10);
/// *some_var.get_mut() = 5;
/// assert_eq!(some_var.load(Ordering::SeqCst), 5);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
pub const fn get_mut(&mut self) -> &mut i16 {
unsafe { &mut *self.as_ptr() }
}
#[doc = "Get atomic access to a `&mut i16`."]
///
#[doc =
"**Note:** This function is only available on targets where `AtomicI16` has the same alignment as `i16`."]
///
/// # Examples
///
#[doc = "```rust"]
#[doc = "use std::sync::atomic::{AtomicI16, Ordering};"]
///
/// let mut some_int = 123;
#[doc = "let a = AtomicI16::from_mut(&mut some_int);"]
/// a.store(100, Ordering::Relaxed);
/// assert_eq!(some_int, 100);
/// ```
///
#[inline]
#[stable(feature = "atomic_from_mut", since = "1.98.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
pub const fn from_mut(v: &mut i16) -> &mut Self {
let [] = [(); align_of::<Self>() - align_of::<i16>()];
unsafe { &mut *(v as *mut i16 as *mut Self) }
}
#[doc = "Get non-atomic access to a `&mut [AtomicI16]` slice"]
///
/// This is safe because the mutable reference guarantees that no other threads are
/// concurrently accessing the atomic data.
///
/// # Examples
///
#[doc = "```ignore-wasm"]
#[doc = "use std::sync::atomic::{AtomicI16, Ordering};"]
///
#[doc = "let mut some_ints = [const { AtomicI16::new(0) }; 10];"]
///
#[doc =
"let view: &mut [i16] = AtomicI16::get_mut_slice(&mut some_ints);"]
/// assert_eq!(view, [0; 10]);
/// view
/// .iter_mut()
/// .enumerate()
/// .for_each(|(idx, int)| *int = idx as _);
///
/// std::thread::scope(|s| {
/// some_ints
/// .iter()
/// .enumerate()
/// .for_each(|(idx, int)| {
/// s.spawn(move || assert_eq!(int.load(Ordering::Relaxed), idx as _));
/// })
/// });
/// ```
#[inline]
#[stable(feature = "atomic_from_mut", since = "1.98.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
pub const fn get_mut_slice(this: &mut [Self]) -> &mut [i16] {
unsafe { &mut *(this as *mut [Self] as *mut [i16]) }
}
#[doc = "Get atomic access to a `&mut [i16]` slice."]
///
#[doc =
"**Note:** This function is only available on targets where `AtomicI16` has the same alignment as `i16`."]
///
/// # Examples
///
#[doc = "```ignore-wasm"]
#[doc = "use std::sync::atomic::{AtomicI16, Ordering};"]
///
/// let mut some_ints = [0; 10];
#[doc = "let a = &*AtomicI16::from_mut_slice(&mut some_ints);"]
/// std::thread::scope(|s| {
/// for i in 0..a.len() {
/// s.spawn(move || a[i].store(i as _, Ordering::Relaxed));
/// }
/// });
/// for (i, n) in some_ints.into_iter().enumerate() {
/// assert_eq!(i, n as usize);
/// }
/// ```
#[inline]
#[stable(feature = "atomic_from_mut", since = "1.98.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
pub const fn from_mut_slice(v: &mut [i16]) -> &mut [Self] {
let [] = [(); align_of::<Self>() - align_of::<i16>()];
unsafe { &mut *(v as *mut [i16] as *mut [Self]) }
}
/// Consumes the atomic and returns the contained value.
///
/// This is safe because passing `self` by value guarantees that no other threads are
/// concurrently accessing the atomic data.
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::AtomicI16;"]
///
#[doc = "let some_var = AtomicI16::new(5);"]
/// assert_eq!(some_var.into_inner(), 5);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_stable(feature = "const_atomic_into_inner", since =
"1.79.0")]
pub const fn into_inner(self) -> i16 { unsafe { transmute(self) } }
/// Loads a value from the atomic integer.
///
/// `load` takes an [`Ordering`] argument which describes the memory ordering of this operation.
/// Possible values are [`SeqCst`], [`Acquire`] and [`Relaxed`].
///
/// # Panics
///
/// Panics if `order` is [`Release`] or [`AcqRel`].
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI16, Ordering};"]
///
#[doc = "let some_var = AtomicI16::new(5);"]
///
/// assert_eq!(some_var.load(Ordering::Relaxed), 5);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
pub const fn load(&self, order: Ordering) -> i16 {
unsafe { atomic_load::<_, false>(self.as_ptr(), order) }
}
/// Perform a volatile load from the atomic integer.
///
/// `load_volatile` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. Possible values are [`SeqCst`], [`Acquire`] and [`Relaxed`].
///
#[doc =
"Volatile operations are intended to act on I/O memory. As such, they are considered externally\nobservable events (just like syscalls, but less opaque), and are guaranteed to not be elided or\nreordered by the compiler across other externally observable events. With this in mind, there\nare two cases of usage that need to be distinguished:\n\n- When a volatile operation is used for memory inside an [allocation], it behaves exactly\n like [`load`][Self::load], except for the additional guarantee that it won\'t be elided or\n reordered across other externally observable events (see above). This implies that the\n operation will actually access memory and not e.g. be lowered to reusing data from a\n previous load. Other than that, all the usual rules for memory accesses apply (including\n provenance).\n\n- Volatile operations, however, may also be used to access memory that is _outside_ of any Rust\n allocation. In this use-case, the pointer does *not* have to be [valid] for reads. This is\n typically used for CPU and peripheral registers that must be accessed via an I/O memory mapping,\n most commonly at fixed addresses reserved by the hardware. These often have special semantics\n associated to their manipulation, and cannot be used as general purpose memory. Here, any address\n value is possible, including 0 and [`usize::MAX`], so long as the semantics of such a read are\n well-defined by the target hardware. The provenance of the pointer is irrelevant, and it can be\n created with [`without_provenance`][crate::ptr::without_provenance]. The access is allowed to\n trap, which must immediately abort the process. It can also cause other side-effects, but those\n must not affect Rust-allocated memory in any way.\n\nIn both cases, the access is also considered atomic with the given `order`. This allows\nsynchronization with other threads or devices that share memory with this program.\n\nWhen invoked during const evaluation, this behaves like a regular atomic load. In\nparticular, such reads must always follow the first of the two cases above.\n\n[allocation]: crate::ptr#allocated-object\n"]
///
/// # Safety
///
/// Behavior is undefined if any of the following conditions are violated:
///
/// * `self` must be [valid] for reads, or `self` must point to memory
/// outside of all Rust allocations and reading from that memory must:
/// - not trap, and
/// - not cause any memory inside a Rust allocation to be modified.
///
/// * `self` must be aligned to
#[doc = " `align_of::<AtomicI16>()`"]
#[doc =
" (note that on some platforms this can be bigger than `align_of::<i16>()`)."]
///
/// * Reading from `self` must produce a properly initialized value of the underlying
/// integer type.
///
/// [valid]: core::ptr#safety
///
/// # Panics
///
/// Panics if `order` is [`Release`] or [`AcqRel`].
#[inline]
#[unstable(feature = "atomic_volatile", issue = "158947")]
#[rustc_const_unstable(feature = "atomic_volatile", issue = "158947")]
pub const unsafe fn load_volatile(self: *const Self, order: Ordering)
-> i16 {
unsafe { atomic_load::<_, true>(self.cast::<i16>(), order) }
}
/// Stores a value into the atomic integer.
///
/// `store` takes an [`Ordering`] argument which describes the memory ordering of this operation.
/// Possible values are [`SeqCst`], [`Release`] and [`Relaxed`].
///
/// # Panics
///
/// Panics if `order` is [`Acquire`] or [`AcqRel`].
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI16, Ordering};"]
///
#[doc = "let some_var = AtomicI16::new(5);"]
///
/// some_var.store(10, Ordering::Relaxed);
/// assert_eq!(some_var.load(Ordering::Relaxed), 10);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn store(&self, val: i16, order: Ordering) {
unsafe { atomic_store::<_, false>(self.as_ptr(), val, order); }
}
/// Performs a volatile store into the atomic integer.
///
/// `store_volatile` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. Possible values are [`SeqCst`], [`Release`] and [`Relaxed`].
///
#[doc =
"Volatile operations are intended to act on I/O memory. As such, they are considered externally\nobservable events (just like syscalls), and are guaranteed to not be elided or reordered by the\ncompiler across other externally observable events. With this in mind, there are two cases of\nusage that need to be distinguished:\n\n- When a volatile operation is used for memory inside an [allocation], it behaves exactly like\n [`store`][Self::store], except for the additional guarantee that it won\'t be elided or reordered\n across other externally observable events (see above). This implies that the operation will\n actually access memory and not e.g. be lowered to a register access. Other than that, all the\n usual rules for memory accesses apply (including provenance).\n\n- Volatile operations, however, may also be used to access memory that is _outside_ of any Rust\n allocation. In this use-case, the pointer does *not* have to be [valid] for writes. This is\n typically used for CPU and peripheral registers that must be accessed via an I/O memory mapping,\n most commonly at fixed addresses reserved by the hardware. These often have special semantics\n associated to their manipulation, and cannot be used as general purpose memory. Here, any address\n value is possible, including 0 and [`usize::MAX`], so long as the semantics of such a write are\n well-defined by the target hardware. The provenance of the pointer is irrelevant, and it can be\n created with [`without_provenance_mut`][crate::ptr::without_provenance_mut]. The access is allowed\n to trap, which must immediately abort the process. It can also cause other side-effects, but those\n must not affect Rust-allocated memory in any way.\n\nIn both cases, the access is also considered atomic with the given `order`. This allows\nsynchronization with other threads or devices that share memory with this program.\n\nWhen invoked during const evaluation, this behaves like a regular atomic store. In\nparticular, such reads must always follow the first of the two cases above.\n\n[allocation]: crate::ptr#allocated-object\n"]
///
/// # Safety
///
/// Behavior is undefined if any of the following conditions are violated:
///
/// * `self` must be either [valid] for writes, or `self` must point to memory
/// outside of all Rust allocations and writing to that memory must:
/// - not trap, and
/// - not cause any memory inside a Rust allocation to be modified.
///
/// * `self` must be aligned to
#[doc = " `align_of::<AtomicI16>()`"]
#[doc =
" (note that on some platforms this can be bigger than `align_of::<i16>()`)."]
///
/// [valid]: core::ptr#safety
///
/// # Panics
///
/// Panics if `order` is [`Acquire`] or [`AcqRel`].
#[inline]
#[unstable(feature = "atomic_volatile", issue = "158947")]
#[rustc_const_unstable(feature = "atomic_volatile", issue = "158947")]
#[rustc_should_not_be_called_on_const_items]
pub const unsafe fn store_volatile(self: *const Self, val: i16,
order: Ordering) {
unsafe {
atomic_store::<_,
true>(self.cast::<i16>().cast_mut(), val, order);
}
}
/// Stores a value into the atomic integer, returning the previous value.
///
/// `swap` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`i16`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI16, Ordering};"]
///
#[doc = "let some_var = AtomicI16::new(5);"]
///
/// assert_eq!(some_var.swap(10, Ordering::Relaxed), 5);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn swap(&self, val: i16, order: Ordering) -> i16 {
unsafe { atomic_swap(self.as_ptr(), val, order) }
}
/// Stores a value into the atomic integer if the current value is the same as
/// the `current` value.
///
/// The return value is always the previous value. If it is equal to `current`, then the
/// value was updated.
///
/// `compare_and_swap` also takes an [`Ordering`] argument which describes the memory
/// ordering of this operation. Notice that even when using [`AcqRel`], the operation
/// might fail and hence just perform an `Acquire` load, but not have `Release` semantics.
/// Using [`Acquire`] makes the store part of this operation [`Relaxed`] if it
/// happens, and using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`i16`]."]
///
/// # Migrating to `compare_exchange` and `compare_exchange_weak`
///
/// `compare_and_swap` is equivalent to `compare_exchange` with the following mapping for
/// memory orderings:
///
/// Original | Success | Failure
/// -------- | ------- | -------
/// Relaxed | Relaxed | Relaxed
/// Acquire | Acquire | Acquire
/// Release | Release | Relaxed
/// AcqRel | AcqRel | Acquire
/// SeqCst | SeqCst | SeqCst
///
/// `compare_and_swap` and `compare_exchange` also differ in their return type. You can use
/// `compare_exchange(...).unwrap_or_else(|x| x)` to recover the behavior of `compare_and_swap`,
/// but in most cases it is more idiomatic to check whether the return value is `Ok` or `Err`
/// rather than to infer success vs failure based on the value that was read.
///
/// During migration, consider whether it makes sense to use `compare_exchange_weak` instead.
/// `compare_exchange_weak` is allowed to fail spuriously even when the comparison succeeds,
/// which allows the compiler to generate better assembly code when the compare and swap
/// is used in a loop.
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI16, Ordering};"]
///
#[doc = "let some_var = AtomicI16::new(5);"]
///
/// assert_eq!(some_var.compare_and_swap(5, 10, Ordering::Relaxed), 5);
/// assert_eq!(some_var.load(Ordering::Relaxed), 10);
///
/// assert_eq!(some_var.compare_and_swap(6, 12, Ordering::Relaxed), 10);
/// assert_eq!(some_var.load(Ordering::Relaxed), 10);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[deprecated(since = "1.50.0", note =
"Use `compare_exchange` or `compare_exchange_weak` instead")]
#[rustc_should_not_be_called_on_const_items]
pub const fn compare_and_swap(&self, current: i16, new: i16,
order: Ordering) -> i16 {
match self.compare_exchange(current, new, order,
strongest_failure_ordering(order)) {
Ok(x) => x,
Err(x) => x,
}
}
/// Stores a value into the atomic integer if the current value is the same as
/// the `current` value.
///
/// The return value is a result indicating whether the new value was written and
/// containing the previous value. On success this value is guaranteed to be equal to
/// `current`.
///
/// `compare_exchange` takes two [`Ordering`] arguments to describe the memory
/// ordering of this operation. `success` describes the required ordering for the
/// read-modify-write operation that takes place if the comparison with `current` succeeds.
/// `failure` describes the required ordering for the load operation that takes place when
/// the comparison fails. Using [`Acquire`] as success ordering makes the store part
/// of this operation [`Relaxed`], and using [`Release`] makes the successful load
/// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`i16`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI16, Ordering};"]
///
#[doc = "let some_var = AtomicI16::new(5);"]
///
/// assert_eq!(some_var.compare_exchange(5, 10,
/// Ordering::Acquire,
/// Ordering::Relaxed),
/// Ok(5));
/// assert_eq!(some_var.load(Ordering::Relaxed), 10);
///
/// assert_eq!(some_var.compare_exchange(6, 12,
/// Ordering::SeqCst,
/// Ordering::Acquire),
/// Err(10));
/// assert_eq!(some_var.load(Ordering::Relaxed), 10);
/// ```
///
/// # Considerations
///
/// `compare_exchange` is a [compare-and-swap operation] and thus exhibits the usual downsides
/// of CAS operations. In particular, a load of the value followed by a successful
/// `compare_exchange` with the previous load *does not ensure* that other threads have not
/// changed the value in the interim! This is usually important when the *equality* check in
/// the `compare_exchange` is being used to check the *identity* of a value, but equality
/// does not necessarily imply identity. This is a particularly common case for pointers, as
/// a pointer holding the same address does not imply that the same object exists at that
/// address! In this case, `compare_exchange` can lead to the [ABA problem].
///
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn compare_exchange(&self, current: i16, new: i16,
success: Ordering, failure: Ordering) -> Result<i16, i16> {
unsafe {
atomic_compare_exchange(self.as_ptr(), current, new, success,
failure)
}
}
/// Stores a value into the atomic integer if the current value is the same as
/// the `current` value.
///
#[doc = "Unlike [`AtomicI16::compare_exchange`],"]
/// this function is allowed to spuriously fail even
/// when the comparison succeeds, which can result in more efficient code on some
/// platforms. The return value is a result indicating whether the new value was
/// written and containing the previous value.
///
/// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory
/// ordering of this operation. `success` describes the required ordering for the
/// read-modify-write operation that takes place if the comparison with `current` succeeds.
/// `failure` describes the required ordering for the load operation that takes place when
/// the comparison fails. Using [`Acquire`] as success ordering makes the store part
/// of this operation [`Relaxed`], and using [`Release`] makes the successful load
/// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`i16`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI16, Ordering};"]
///
#[doc = "let val = AtomicI16::new(4);"]
///
/// let mut old = val.load(Ordering::Relaxed);
/// loop {
/// let new = old * 2;
/// match val.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) {
/// Ok(_) => break,
/// Err(x) => old = x,
/// }
/// }
/// ```
///
/// # Considerations
///
/// `compare_exchange` is a [compare-and-swap operation] and thus exhibits the usual downsides
/// of CAS operations. In particular, a load of the value followed by a successful
/// `compare_exchange` with the previous load *does not ensure* that other threads have not
/// changed the value in the interim. This is usually important when the *equality* check in
/// the `compare_exchange` is being used to check the *identity* of a value, but equality
/// does not necessarily imply identity. This is a particularly common case for pointers, as
/// a pointer holding the same address does not imply that the same object exists at that
/// address! In this case, `compare_exchange` can lead to the [ABA problem].
///
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn compare_exchange_weak(&self, current: i16, new: i16,
success: Ordering, failure: Ordering) -> Result<i16, i16> {
unsafe {
atomic_compare_exchange_weak(self.as_ptr(), current, new, success,
failure)
}
}
/// Adds to the current value, returning the previous value.
///
/// This operation wraps around on overflow.
///
/// `fetch_add` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`i16`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI16, Ordering};"]
///
#[doc = "let foo = AtomicI16::new(0);"]
/// assert_eq!(foo.fetch_add(10, Ordering::SeqCst), 0);
/// assert_eq!(foo.load(Ordering::SeqCst), 10);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_add(&self, val: i16, order: Ordering) -> i16 {
unsafe { atomic_add(self.as_ptr(), val, order) }
}
/// Subtracts from the current value, returning the previous value.
///
/// This operation wraps around on overflow.
///
/// `fetch_sub` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`i16`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI16, Ordering};"]
///
#[doc = "let foo = AtomicI16::new(20);"]
/// assert_eq!(foo.fetch_sub(10, Ordering::SeqCst), 20);
/// assert_eq!(foo.load(Ordering::SeqCst), 10);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_sub(&self, val: i16, order: Ordering) -> i16 {
unsafe { atomic_sub(self.as_ptr(), val, order) }
}
/// Bitwise "and" with the current value.
///
/// Performs a bitwise "and" operation on the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_and` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`i16`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI16, Ordering};"]
///
#[doc = "let foo = AtomicI16::new(0b101101);"]
/// assert_eq!(foo.fetch_and(0b110011, Ordering::SeqCst), 0b101101);
/// assert_eq!(foo.load(Ordering::SeqCst), 0b100001);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_and(&self, val: i16, order: Ordering) -> i16 {
unsafe { atomic_and(self.as_ptr(), val, order) }
}
/// Bitwise "nand" with the current value.
///
/// Performs a bitwise "nand" operation on the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_nand` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`i16`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI16, Ordering};"]
///
#[doc = "let foo = AtomicI16::new(0x13);"]
/// assert_eq!(foo.fetch_nand(0x31, Ordering::SeqCst), 0x13);
/// assert_eq!(foo.load(Ordering::SeqCst), !(0x13 & 0x31));
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_nand(&self, val: i16, order: Ordering) -> i16 {
unsafe { atomic_nand(self.as_ptr(), val, order) }
}
/// Bitwise "or" with the current value.
///
/// Performs a bitwise "or" operation on the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_or` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`i16`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI16, Ordering};"]
///
#[doc = "let foo = AtomicI16::new(0b101101);"]
/// assert_eq!(foo.fetch_or(0b110011, Ordering::SeqCst), 0b101101);
/// assert_eq!(foo.load(Ordering::SeqCst), 0b111111);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_or(&self, val: i16, order: Ordering) -> i16 {
unsafe { atomic_or(self.as_ptr(), val, order) }
}
/// Bitwise "xor" with the current value.
///
/// Performs a bitwise "xor" operation on the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_xor` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`i16`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI16, Ordering};"]
///
#[doc = "let foo = AtomicI16::new(0b101101);"]
/// assert_eq!(foo.fetch_xor(0b110011, Ordering::SeqCst), 0b101101);
/// assert_eq!(foo.load(Ordering::SeqCst), 0b011110);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_xor(&self, val: i16, order: Ordering) -> i16 {
unsafe { atomic_xor(self.as_ptr(), val, order) }
}
/// An alias for
#[doc = "[`AtomicI16::try_update`]"]
/// .
#[inline]
#[stable(feature = "no_more_cas", since = "1.45.0")]
#[rustc_should_not_be_called_on_const_items]
#[deprecated(since = "1.99.0", note =
"renamed to `try_update` for consistency", suggestion = "try_update")]
pub fn fetch_update<F>(&self, set_order: Ordering, fetch_order: Ordering,
f: F) -> Result<i16, i16> where F: FnMut(i16) -> Option<i16> {
self.try_update(set_order, fetch_order, f)
}
/// Fetches the value, and applies a function to it that returns an optional
/// new value. Returns a `Result` of `Ok(previous_value)` if the function returned `Some(_)`, else
/// `Err(previous_value)`.
///
#[doc = "See also: [`update`](`AtomicI16::update`)."]
///
/// Note: This may call the function multiple times if the value has been changed from other threads in
/// the meantime, as long as the function returns `Some(_)`, but the function will have been applied
/// only once to the stored value.
///
/// `try_update` takes two [`Ordering`] arguments to describe the memory ordering of this operation.
/// The first describes the required ordering for when the operation finally succeeds while the second
/// describes the required ordering for loads. These correspond to the success and failure orderings of
#[doc = "[`AtomicI16::compare_exchange`]"]
/// respectively.
///
/// Using [`Acquire`] as success ordering makes the store part
/// of this operation [`Relaxed`], and using [`Release`] makes the final successful load
/// [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`i16`]."]
///
/// # Considerations
///
/// This method is not magic; it is not provided by the hardware, and does not act like a
/// critical section or mutex.
///
/// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
/// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem]
/// if this atomic integer is an index or more generally if knowledge of only the *bitwise value*
/// of the atomic is not in and of itself sufficient to ensure any required preconditions.
///
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
///
/// # Examples
///
#[doc = "```rust"]
#[doc = "use std::sync::atomic::{AtomicI16, Ordering};"]
///
#[doc = "let x = AtomicI16::new(7);"]
/// assert_eq!(x.try_update(Ordering::SeqCst, Ordering::SeqCst, |_| None), Err(7));
/// assert_eq!(x.try_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(x + 1)), Ok(7));
/// assert_eq!(x.try_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(x + 1)), Ok(8));
/// assert_eq!(x.load(Ordering::SeqCst), 9);
/// ```
#[inline]
#[stable(feature = "atomic_try_update", since = "1.95.0")]
#[rustc_should_not_be_called_on_const_items]
pub fn try_update(&self, set_order: Ordering, fetch_order: Ordering,
mut f: impl FnMut(i16) -> Option<i16>) -> Result<i16, i16> {
let mut prev = self.load(fetch_order);
while let Some(next) = f(prev) {
match self.compare_exchange_weak(prev, next, set_order,
fetch_order) {
x @ Ok(_) => return x,
Err(next_prev) => prev = next_prev,
}
}
Err(prev)
}
/// Fetches the value, and applies a function to it that returns a new value.
/// The new value is stored and the old value is returned.
///
#[doc = "See also: [`try_update`](`AtomicI16::try_update`)."]
///
/// Note: This may call the function multiple times if the value has been changed from other threads in
/// the meantime, but the function will have been applied only once to the stored value.
///
/// `update` takes two [`Ordering`] arguments to describe the memory ordering of this operation.
/// The first describes the required ordering for when the operation finally succeeds while the second
/// describes the required ordering for loads. These correspond to the success and failure orderings of
#[doc = "[`AtomicI16::compare_exchange`]"]
/// respectively.
///
/// Using [`Acquire`] as success ordering makes the store part
/// of this operation [`Relaxed`], and using [`Release`] makes the final successful load
/// [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`i16`]."]
///
/// # Considerations
///
/// [CAS operation]: https://en.wikipedia.org/wiki/Compare-and-swap
/// This method is not magic; it is not provided by the hardware, and does not act like a
/// critical section or mutex.
///
/// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
/// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem]
/// if this atomic integer is an index or more generally if knowledge of only the *bitwise value*
/// of the atomic is not in and of itself sufficient to ensure any required preconditions.
///
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
///
/// # Examples
///
#[doc = "```rust"]
#[doc = "use std::sync::atomic::{AtomicI16, Ordering};"]
///
#[doc = "let x = AtomicI16::new(7);"]
/// assert_eq!(x.update(Ordering::SeqCst, Ordering::SeqCst, |x| x + 1), 7);
/// assert_eq!(x.update(Ordering::SeqCst, Ordering::SeqCst, |x| x + 1), 8);
/// assert_eq!(x.load(Ordering::SeqCst), 9);
/// ```
#[inline]
#[stable(feature = "atomic_try_update", since = "1.95.0")]
#[rustc_should_not_be_called_on_const_items]
pub fn update(&self, set_order: Ordering, fetch_order: Ordering,
mut f: impl FnMut(i16) -> i16) -> i16 {
let mut prev = self.load(fetch_order);
loop {
match self.compare_exchange_weak(prev, f(prev), set_order,
fetch_order) {
Ok(x) => break x,
Err(next_prev) => prev = next_prev,
}
}
}
/// Maximum with the current value.
///
/// Finds the maximum of the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_max` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`i16`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI16, Ordering};"]
///
#[doc = "let foo = AtomicI16::new(23);"]
/// assert_eq!(foo.fetch_max(42, Ordering::SeqCst), 23);
/// assert_eq!(foo.load(Ordering::SeqCst), 42);
/// ```
///
/// If you want to obtain the maximum value in one step, you can use the following:
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI16, Ordering};"]
///
#[doc = "let foo = AtomicI16::new(23);"]
/// let bar = 42;
/// let max_foo = foo.fetch_max(bar, Ordering::SeqCst).max(bar);
/// assert!(max_foo == 42);
/// ```
#[inline]
#[stable(feature = "atomic_min_max", since = "1.45.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_max(&self, val: i16, order: Ordering) -> i16 {
unsafe { atomic_max(self.as_ptr(), val, order) }
}
/// Minimum with the current value.
///
/// Finds the minimum of the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_min` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`i16`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI16, Ordering};"]
///
#[doc = "let foo = AtomicI16::new(23);"]
/// assert_eq!(foo.fetch_min(42, Ordering::Relaxed), 23);
/// assert_eq!(foo.load(Ordering::Relaxed), 23);
/// assert_eq!(foo.fetch_min(22, Ordering::Relaxed), 23);
/// assert_eq!(foo.load(Ordering::Relaxed), 22);
/// ```
///
/// If you want to obtain the minimum value in one step, you can use the following:
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI16, Ordering};"]
///
#[doc = "let foo = AtomicI16::new(23);"]
/// let bar = 12;
/// let min_foo = foo.fetch_min(bar, Ordering::SeqCst).min(bar);
/// assert_eq!(min_foo, 12);
/// ```
#[inline]
#[stable(feature = "atomic_min_max", since = "1.45.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_min(&self, val: i16, order: Ordering) -> i16 {
unsafe { atomic_min(self.as_ptr(), val, order) }
}
/// Returns a mutable pointer to the underlying integer.
///
/// Doing non-atomic reads and writes on the resulting integer can be a data race.
/// This method is mostly useful for FFI, where the function signature may use
#[doc = "`*mut i16` instead of `&AtomicI16`."]
///
/// Returning an `*mut` pointer from a shared reference to this atomic is safe because the
/// atomic types work with interior mutability. All modifications of an atomic change the value
/// through a shared reference, and can do so safely as long as they use atomic operations. Any
/// use of the returned raw pointer requires an `unsafe` block and still has to uphold the
/// requirements of the [memory model].
///
/// # Examples
///
/// ```ignore (extern-declaration)
/// # fn main() {
#[doc = "use std::sync::atomic::AtomicI16;"]
///
/// extern "C" {
#[doc = " fn my_atomic_op(arg: *mut i16);"]
/// }
///
#[doc = "let atomic = AtomicI16::new(1);"]
///
/// // SAFETY: Safe as long as `my_atomic_op` is atomic.
/// unsafe {
/// my_atomic_op(atomic.as_ptr());
/// }
/// # }
/// ```
///
/// [memory model]: self#memory-model-for-atomic-accesses
#[inline]
#[stable(feature = "atomic_as_ptr", since = "1.70.0")]
#[rustc_const_stable(feature = "atomic_as_ptr", since = "1.70.0")]
#[rustc_never_returns_null_ptr]
pub const fn as_ptr(&self) -> *mut i16 { self.v.get().cast() }
}atomic_int! {
4060 target_has_atomic_load_store = "16",
4061 target_has_atomic = "16",
4062 target_has_atomic_primitive_alignment = "16",
4063 stable(feature = "integer_atomics_stable", since = "1.34.0"),
4064 stable(feature = "integer_atomics_stable", since = "1.34.0"),
4065 stable(feature = "integer_atomics_stable", since = "1.34.0"),
4066 stable(feature = "integer_atomics_stable", since = "1.34.0"),
4067 stable(feature = "integer_atomics_stable", since = "1.34.0"),
4068 stable(feature = "integer_atomics_stable", since = "1.34.0"),
4069 rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
4070 rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"),
4071"i16",
4072"",
4073 atomic_min, atomic_max,
40742,
4075 i16 AtomicI164076}4077#[cfg(target_has_atomic_load_store = "16")]
4078/// An integer type which can be safely shared between threads.
///
/// This type has the same
#[doc = "size and bit validity"]
/// as the underlying integer type, [`
#[doc = "u16"]
/// `].
#[doc =
"However, the alignment of this type is always equal to its size, even on targets where [`u16`] has a lesser alignment."]
///
/// For more about the differences between atomic types and
/// non-atomic types as well as information about the portability of
/// this type, please see the [module-level documentation].
///
/// **Note:** This type is only available on platforms that support
/// atomic loads and stores of [`
#[doc = "u16"]
/// `].
///
/// [module-level documentation]: crate::sync::atomic
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
pub type AtomicU16 = Atomic<u16>;
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
impl Default for AtomicU16 {
#[inline]
fn default() -> Self { Self::new(Default::default()) }
}
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
const impl From<u16> for AtomicU16 {
#[doc = "Converts an `u16` into an `AtomicU16`."]
#[inline]
fn from(v: u16) -> Self { Self::new(v) }
}
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
impl fmt::Debug for AtomicU16 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.load(Ordering::Relaxed), f)
}
}
impl AtomicU16 {
/// Creates a new atomic integer.
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::AtomicU16;"]
///
#[doc = "let atomic_forty_two = AtomicU16::new(42);"]
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0")]
#[must_use]
pub const fn new(v: u16) -> Self { unsafe { transmute(v) } }
/// Creates a new reference to an atomic integer from a pointer.
///
/// # Examples
///
#[doc = "```rust"]
#[doc = "use std::sync::atomic::{self, AtomicU16};"]
///
/// // Get a pointer to an allocated value
#[doc = "let ptr: *mut u16 = Box::into_raw(Box::new(0));"]
///
#[doc = "assert!(ptr.cast::<AtomicU16>().is_aligned());"]
///
/// {
/// // Create an atomic view of the allocated value
#[doc = " let atomic = unsafe {AtomicU16::from_ptr(ptr) };"]
///
/// // Use `atomic` for atomic operations, possibly share it with other threads
/// atomic.store(1, atomic::Ordering::Relaxed);
/// }
///
/// // It's ok to non-atomically access the value behind `ptr`,
/// // since the reference to the atomic ended its lifetime in the block above
/// assert_eq!(unsafe { *ptr }, 1);
///
/// // Deallocate the value
/// unsafe { drop(Box::from_raw(ptr)) }
/// ```
///
/// # Safety
///
/// * `ptr` must be aligned to
#[doc = " `align_of::<AtomicU16>()`"]
#[doc =
" (note that on some platforms this can be bigger than `align_of::<u16>()`)."]
/// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`.
/// * You must adhere to the [Memory model for atomic accesses]. In particular, it is not
/// allowed to mix conflicting atomic and non-atomic accesses, or atomic accesses of different
/// sizes, without synchronization.
///
/// [valid]: crate::ptr#safety
/// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses
#[inline]
#[stable(feature = "atomic_from_ptr", since = "1.75.0")]
#[rustc_const_stable(feature = "const_atomic_from_ptr", since = "1.84.0")]
pub const unsafe fn from_ptr<'a>(ptr: *mut u16) -> &'a AtomicU16 {
unsafe { &*ptr.cast() }
}
/// Creates a new pointer to an atomic integer from a pointer.
///
/// This is useful if you want to do volatile atomic accesses, and thus avoid creating
/// a reference to the destination.
#[inline]
#[unstable(feature = "atomic_volatile", issue = "158947")]
pub const fn from_ptr_raw(ptr: *mut u16) -> *const AtomicU16 {
ptr.cast_const().cast()
}
/// Returns a mutable reference to the underlying integer.
///
/// This is safe because the mutable reference guarantees that no other threads are
/// concurrently accessing the atomic data.
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU16, Ordering};"]
///
#[doc = "let mut some_var = AtomicU16::new(10);"]
/// assert_eq!(*some_var.get_mut(), 10);
/// *some_var.get_mut() = 5;
/// assert_eq!(some_var.load(Ordering::SeqCst), 5);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
pub const fn get_mut(&mut self) -> &mut u16 {
unsafe { &mut *self.as_ptr() }
}
#[doc = "Get atomic access to a `&mut u16`."]
///
#[doc =
"**Note:** This function is only available on targets where `AtomicU16` has the same alignment as `u16`."]
///
/// # Examples
///
#[doc = "```rust"]
#[doc = "use std::sync::atomic::{AtomicU16, Ordering};"]
///
/// let mut some_int = 123;
#[doc = "let a = AtomicU16::from_mut(&mut some_int);"]
/// a.store(100, Ordering::Relaxed);
/// assert_eq!(some_int, 100);
/// ```
///
#[inline]
#[stable(feature = "atomic_from_mut", since = "1.98.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
pub const fn from_mut(v: &mut u16) -> &mut Self {
let [] = [(); align_of::<Self>() - align_of::<u16>()];
unsafe { &mut *(v as *mut u16 as *mut Self) }
}
#[doc = "Get non-atomic access to a `&mut [AtomicU16]` slice"]
///
/// This is safe because the mutable reference guarantees that no other threads are
/// concurrently accessing the atomic data.
///
/// # Examples
///
#[doc = "```ignore-wasm"]
#[doc = "use std::sync::atomic::{AtomicU16, Ordering};"]
///
#[doc = "let mut some_ints = [const { AtomicU16::new(0) }; 10];"]
///
#[doc =
"let view: &mut [u16] = AtomicU16::get_mut_slice(&mut some_ints);"]
/// assert_eq!(view, [0; 10]);
/// view
/// .iter_mut()
/// .enumerate()
/// .for_each(|(idx, int)| *int = idx as _);
///
/// std::thread::scope(|s| {
/// some_ints
/// .iter()
/// .enumerate()
/// .for_each(|(idx, int)| {
/// s.spawn(move || assert_eq!(int.load(Ordering::Relaxed), idx as _));
/// })
/// });
/// ```
#[inline]
#[stable(feature = "atomic_from_mut", since = "1.98.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
pub const fn get_mut_slice(this: &mut [Self]) -> &mut [u16] {
unsafe { &mut *(this as *mut [Self] as *mut [u16]) }
}
#[doc = "Get atomic access to a `&mut [u16]` slice."]
///
#[doc =
"**Note:** This function is only available on targets where `AtomicU16` has the same alignment as `u16`."]
///
/// # Examples
///
#[doc = "```ignore-wasm"]
#[doc = "use std::sync::atomic::{AtomicU16, Ordering};"]
///
/// let mut some_ints = [0; 10];
#[doc = "let a = &*AtomicU16::from_mut_slice(&mut some_ints);"]
/// std::thread::scope(|s| {
/// for i in 0..a.len() {
/// s.spawn(move || a[i].store(i as _, Ordering::Relaxed));
/// }
/// });
/// for (i, n) in some_ints.into_iter().enumerate() {
/// assert_eq!(i, n as usize);
/// }
/// ```
#[inline]
#[stable(feature = "atomic_from_mut", since = "1.98.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
pub const fn from_mut_slice(v: &mut [u16]) -> &mut [Self] {
let [] = [(); align_of::<Self>() - align_of::<u16>()];
unsafe { &mut *(v as *mut [u16] as *mut [Self]) }
}
/// Consumes the atomic and returns the contained value.
///
/// This is safe because passing `self` by value guarantees that no other threads are
/// concurrently accessing the atomic data.
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::AtomicU16;"]
///
#[doc = "let some_var = AtomicU16::new(5);"]
/// assert_eq!(some_var.into_inner(), 5);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_stable(feature = "const_atomic_into_inner", since =
"1.79.0")]
pub const fn into_inner(self) -> u16 { unsafe { transmute(self) } }
/// Loads a value from the atomic integer.
///
/// `load` takes an [`Ordering`] argument which describes the memory ordering of this operation.
/// Possible values are [`SeqCst`], [`Acquire`] and [`Relaxed`].
///
/// # Panics
///
/// Panics if `order` is [`Release`] or [`AcqRel`].
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU16, Ordering};"]
///
#[doc = "let some_var = AtomicU16::new(5);"]
///
/// assert_eq!(some_var.load(Ordering::Relaxed), 5);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
pub const fn load(&self, order: Ordering) -> u16 {
unsafe { atomic_load::<_, false>(self.as_ptr(), order) }
}
/// Perform a volatile load from the atomic integer.
///
/// `load_volatile` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. Possible values are [`SeqCst`], [`Acquire`] and [`Relaxed`].
///
#[doc =
"Volatile operations are intended to act on I/O memory. As such, they are considered externally\nobservable events (just like syscalls, but less opaque), and are guaranteed to not be elided or\nreordered by the compiler across other externally observable events. With this in mind, there\nare two cases of usage that need to be distinguished:\n\n- When a volatile operation is used for memory inside an [allocation], it behaves exactly\n like [`load`][Self::load], except for the additional guarantee that it won\'t be elided or\n reordered across other externally observable events (see above). This implies that the\n operation will actually access memory and not e.g. be lowered to reusing data from a\n previous load. Other than that, all the usual rules for memory accesses apply (including\n provenance).\n\n- Volatile operations, however, may also be used to access memory that is _outside_ of any Rust\n allocation. In this use-case, the pointer does *not* have to be [valid] for reads. This is\n typically used for CPU and peripheral registers that must be accessed via an I/O memory mapping,\n most commonly at fixed addresses reserved by the hardware. These often have special semantics\n associated to their manipulation, and cannot be used as general purpose memory. Here, any address\n value is possible, including 0 and [`usize::MAX`], so long as the semantics of such a read are\n well-defined by the target hardware. The provenance of the pointer is irrelevant, and it can be\n created with [`without_provenance`][crate::ptr::without_provenance]. The access is allowed to\n trap, which must immediately abort the process. It can also cause other side-effects, but those\n must not affect Rust-allocated memory in any way.\n\nIn both cases, the access is also considered atomic with the given `order`. This allows\nsynchronization with other threads or devices that share memory with this program.\n\nWhen invoked during const evaluation, this behaves like a regular atomic load. In\nparticular, such reads must always follow the first of the two cases above.\n\n[allocation]: crate::ptr#allocated-object\n"]
///
/// # Safety
///
/// Behavior is undefined if any of the following conditions are violated:
///
/// * `self` must be [valid] for reads, or `self` must point to memory
/// outside of all Rust allocations and reading from that memory must:
/// - not trap, and
/// - not cause any memory inside a Rust allocation to be modified.
///
/// * `self` must be aligned to
#[doc = " `align_of::<AtomicU16>()`"]
#[doc =
" (note that on some platforms this can be bigger than `align_of::<u16>()`)."]
///
/// * Reading from `self` must produce a properly initialized value of the underlying
/// integer type.
///
/// [valid]: core::ptr#safety
///
/// # Panics
///
/// Panics if `order` is [`Release`] or [`AcqRel`].
#[inline]
#[unstable(feature = "atomic_volatile", issue = "158947")]
#[rustc_const_unstable(feature = "atomic_volatile", issue = "158947")]
pub const unsafe fn load_volatile(self: *const Self, order: Ordering)
-> u16 {
unsafe { atomic_load::<_, true>(self.cast::<u16>(), order) }
}
/// Stores a value into the atomic integer.
///
/// `store` takes an [`Ordering`] argument which describes the memory ordering of this operation.
/// Possible values are [`SeqCst`], [`Release`] and [`Relaxed`].
///
/// # Panics
///
/// Panics if `order` is [`Acquire`] or [`AcqRel`].
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU16, Ordering};"]
///
#[doc = "let some_var = AtomicU16::new(5);"]
///
/// some_var.store(10, Ordering::Relaxed);
/// assert_eq!(some_var.load(Ordering::Relaxed), 10);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn store(&self, val: u16, order: Ordering) {
unsafe { atomic_store::<_, false>(self.as_ptr(), val, order); }
}
/// Performs a volatile store into the atomic integer.
///
/// `store_volatile` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. Possible values are [`SeqCst`], [`Release`] and [`Relaxed`].
///
#[doc =
"Volatile operations are intended to act on I/O memory. As such, they are considered externally\nobservable events (just like syscalls), and are guaranteed to not be elided or reordered by the\ncompiler across other externally observable events. With this in mind, there are two cases of\nusage that need to be distinguished:\n\n- When a volatile operation is used for memory inside an [allocation], it behaves exactly like\n [`store`][Self::store], except for the additional guarantee that it won\'t be elided or reordered\n across other externally observable events (see above). This implies that the operation will\n actually access memory and not e.g. be lowered to a register access. Other than that, all the\n usual rules for memory accesses apply (including provenance).\n\n- Volatile operations, however, may also be used to access memory that is _outside_ of any Rust\n allocation. In this use-case, the pointer does *not* have to be [valid] for writes. This is\n typically used for CPU and peripheral registers that must be accessed via an I/O memory mapping,\n most commonly at fixed addresses reserved by the hardware. These often have special semantics\n associated to their manipulation, and cannot be used as general purpose memory. Here, any address\n value is possible, including 0 and [`usize::MAX`], so long as the semantics of such a write are\n well-defined by the target hardware. The provenance of the pointer is irrelevant, and it can be\n created with [`without_provenance_mut`][crate::ptr::without_provenance_mut]. The access is allowed\n to trap, which must immediately abort the process. It can also cause other side-effects, but those\n must not affect Rust-allocated memory in any way.\n\nIn both cases, the access is also considered atomic with the given `order`. This allows\nsynchronization with other threads or devices that share memory with this program.\n\nWhen invoked during const evaluation, this behaves like a regular atomic store. In\nparticular, such reads must always follow the first of the two cases above.\n\n[allocation]: crate::ptr#allocated-object\n"]
///
/// # Safety
///
/// Behavior is undefined if any of the following conditions are violated:
///
/// * `self` must be either [valid] for writes, or `self` must point to memory
/// outside of all Rust allocations and writing to that memory must:
/// - not trap, and
/// - not cause any memory inside a Rust allocation to be modified.
///
/// * `self` must be aligned to
#[doc = " `align_of::<AtomicU16>()`"]
#[doc =
" (note that on some platforms this can be bigger than `align_of::<u16>()`)."]
///
/// [valid]: core::ptr#safety
///
/// # Panics
///
/// Panics if `order` is [`Acquire`] or [`AcqRel`].
#[inline]
#[unstable(feature = "atomic_volatile", issue = "158947")]
#[rustc_const_unstable(feature = "atomic_volatile", issue = "158947")]
#[rustc_should_not_be_called_on_const_items]
pub const unsafe fn store_volatile(self: *const Self, val: u16,
order: Ordering) {
unsafe {
atomic_store::<_,
true>(self.cast::<u16>().cast_mut(), val, order);
}
}
/// Stores a value into the atomic integer, returning the previous value.
///
/// `swap` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`u16`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU16, Ordering};"]
///
#[doc = "let some_var = AtomicU16::new(5);"]
///
/// assert_eq!(some_var.swap(10, Ordering::Relaxed), 5);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn swap(&self, val: u16, order: Ordering) -> u16 {
unsafe { atomic_swap(self.as_ptr(), val, order) }
}
/// Stores a value into the atomic integer if the current value is the same as
/// the `current` value.
///
/// The return value is always the previous value. If it is equal to `current`, then the
/// value was updated.
///
/// `compare_and_swap` also takes an [`Ordering`] argument which describes the memory
/// ordering of this operation. Notice that even when using [`AcqRel`], the operation
/// might fail and hence just perform an `Acquire` load, but not have `Release` semantics.
/// Using [`Acquire`] makes the store part of this operation [`Relaxed`] if it
/// happens, and using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`u16`]."]
///
/// # Migrating to `compare_exchange` and `compare_exchange_weak`
///
/// `compare_and_swap` is equivalent to `compare_exchange` with the following mapping for
/// memory orderings:
///
/// Original | Success | Failure
/// -------- | ------- | -------
/// Relaxed | Relaxed | Relaxed
/// Acquire | Acquire | Acquire
/// Release | Release | Relaxed
/// AcqRel | AcqRel | Acquire
/// SeqCst | SeqCst | SeqCst
///
/// `compare_and_swap` and `compare_exchange` also differ in their return type. You can use
/// `compare_exchange(...).unwrap_or_else(|x| x)` to recover the behavior of `compare_and_swap`,
/// but in most cases it is more idiomatic to check whether the return value is `Ok` or `Err`
/// rather than to infer success vs failure based on the value that was read.
///
/// During migration, consider whether it makes sense to use `compare_exchange_weak` instead.
/// `compare_exchange_weak` is allowed to fail spuriously even when the comparison succeeds,
/// which allows the compiler to generate better assembly code when the compare and swap
/// is used in a loop.
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU16, Ordering};"]
///
#[doc = "let some_var = AtomicU16::new(5);"]
///
/// assert_eq!(some_var.compare_and_swap(5, 10, Ordering::Relaxed), 5);
/// assert_eq!(some_var.load(Ordering::Relaxed), 10);
///
/// assert_eq!(some_var.compare_and_swap(6, 12, Ordering::Relaxed), 10);
/// assert_eq!(some_var.load(Ordering::Relaxed), 10);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[deprecated(since = "1.50.0", note =
"Use `compare_exchange` or `compare_exchange_weak` instead")]
#[rustc_should_not_be_called_on_const_items]
pub const fn compare_and_swap(&self, current: u16, new: u16,
order: Ordering) -> u16 {
match self.compare_exchange(current, new, order,
strongest_failure_ordering(order)) {
Ok(x) => x,
Err(x) => x,
}
}
/// Stores a value into the atomic integer if the current value is the same as
/// the `current` value.
///
/// The return value is a result indicating whether the new value was written and
/// containing the previous value. On success this value is guaranteed to be equal to
/// `current`.
///
/// `compare_exchange` takes two [`Ordering`] arguments to describe the memory
/// ordering of this operation. `success` describes the required ordering for the
/// read-modify-write operation that takes place if the comparison with `current` succeeds.
/// `failure` describes the required ordering for the load operation that takes place when
/// the comparison fails. Using [`Acquire`] as success ordering makes the store part
/// of this operation [`Relaxed`], and using [`Release`] makes the successful load
/// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`u16`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU16, Ordering};"]
///
#[doc = "let some_var = AtomicU16::new(5);"]
///
/// assert_eq!(some_var.compare_exchange(5, 10,
/// Ordering::Acquire,
/// Ordering::Relaxed),
/// Ok(5));
/// assert_eq!(some_var.load(Ordering::Relaxed), 10);
///
/// assert_eq!(some_var.compare_exchange(6, 12,
/// Ordering::SeqCst,
/// Ordering::Acquire),
/// Err(10));
/// assert_eq!(some_var.load(Ordering::Relaxed), 10);
/// ```
///
/// # Considerations
///
/// `compare_exchange` is a [compare-and-swap operation] and thus exhibits the usual downsides
/// of CAS operations. In particular, a load of the value followed by a successful
/// `compare_exchange` with the previous load *does not ensure* that other threads have not
/// changed the value in the interim! This is usually important when the *equality* check in
/// the `compare_exchange` is being used to check the *identity* of a value, but equality
/// does not necessarily imply identity. This is a particularly common case for pointers, as
/// a pointer holding the same address does not imply that the same object exists at that
/// address! In this case, `compare_exchange` can lead to the [ABA problem].
///
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn compare_exchange(&self, current: u16, new: u16,
success: Ordering, failure: Ordering) -> Result<u16, u16> {
unsafe {
atomic_compare_exchange(self.as_ptr(), current, new, success,
failure)
}
}
/// Stores a value into the atomic integer if the current value is the same as
/// the `current` value.
///
#[doc = "Unlike [`AtomicU16::compare_exchange`],"]
/// this function is allowed to spuriously fail even
/// when the comparison succeeds, which can result in more efficient code on some
/// platforms. The return value is a result indicating whether the new value was
/// written and containing the previous value.
///
/// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory
/// ordering of this operation. `success` describes the required ordering for the
/// read-modify-write operation that takes place if the comparison with `current` succeeds.
/// `failure` describes the required ordering for the load operation that takes place when
/// the comparison fails. Using [`Acquire`] as success ordering makes the store part
/// of this operation [`Relaxed`], and using [`Release`] makes the successful load
/// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`u16`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU16, Ordering};"]
///
#[doc = "let val = AtomicU16::new(4);"]
///
/// let mut old = val.load(Ordering::Relaxed);
/// loop {
/// let new = old * 2;
/// match val.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) {
/// Ok(_) => break,
/// Err(x) => old = x,
/// }
/// }
/// ```
///
/// # Considerations
///
/// `compare_exchange` is a [compare-and-swap operation] and thus exhibits the usual downsides
/// of CAS operations. In particular, a load of the value followed by a successful
/// `compare_exchange` with the previous load *does not ensure* that other threads have not
/// changed the value in the interim. This is usually important when the *equality* check in
/// the `compare_exchange` is being used to check the *identity* of a value, but equality
/// does not necessarily imply identity. This is a particularly common case for pointers, as
/// a pointer holding the same address does not imply that the same object exists at that
/// address! In this case, `compare_exchange` can lead to the [ABA problem].
///
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn compare_exchange_weak(&self, current: u16, new: u16,
success: Ordering, failure: Ordering) -> Result<u16, u16> {
unsafe {
atomic_compare_exchange_weak(self.as_ptr(), current, new, success,
failure)
}
}
/// Adds to the current value, returning the previous value.
///
/// This operation wraps around on overflow.
///
/// `fetch_add` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`u16`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU16, Ordering};"]
///
#[doc = "let foo = AtomicU16::new(0);"]
/// assert_eq!(foo.fetch_add(10, Ordering::SeqCst), 0);
/// assert_eq!(foo.load(Ordering::SeqCst), 10);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_add(&self, val: u16, order: Ordering) -> u16 {
unsafe { atomic_add(self.as_ptr(), val, order) }
}
/// Subtracts from the current value, returning the previous value.
///
/// This operation wraps around on overflow.
///
/// `fetch_sub` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`u16`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU16, Ordering};"]
///
#[doc = "let foo = AtomicU16::new(20);"]
/// assert_eq!(foo.fetch_sub(10, Ordering::SeqCst), 20);
/// assert_eq!(foo.load(Ordering::SeqCst), 10);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_sub(&self, val: u16, order: Ordering) -> u16 {
unsafe { atomic_sub(self.as_ptr(), val, order) }
}
/// Bitwise "and" with the current value.
///
/// Performs a bitwise "and" operation on the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_and` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`u16`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU16, Ordering};"]
///
#[doc = "let foo = AtomicU16::new(0b101101);"]
/// assert_eq!(foo.fetch_and(0b110011, Ordering::SeqCst), 0b101101);
/// assert_eq!(foo.load(Ordering::SeqCst), 0b100001);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_and(&self, val: u16, order: Ordering) -> u16 {
unsafe { atomic_and(self.as_ptr(), val, order) }
}
/// Bitwise "nand" with the current value.
///
/// Performs a bitwise "nand" operation on the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_nand` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`u16`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU16, Ordering};"]
///
#[doc = "let foo = AtomicU16::new(0x13);"]
/// assert_eq!(foo.fetch_nand(0x31, Ordering::SeqCst), 0x13);
/// assert_eq!(foo.load(Ordering::SeqCst), !(0x13 & 0x31));
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_nand(&self, val: u16, order: Ordering) -> u16 {
unsafe { atomic_nand(self.as_ptr(), val, order) }
}
/// Bitwise "or" with the current value.
///
/// Performs a bitwise "or" operation on the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_or` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`u16`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU16, Ordering};"]
///
#[doc = "let foo = AtomicU16::new(0b101101);"]
/// assert_eq!(foo.fetch_or(0b110011, Ordering::SeqCst), 0b101101);
/// assert_eq!(foo.load(Ordering::SeqCst), 0b111111);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_or(&self, val: u16, order: Ordering) -> u16 {
unsafe { atomic_or(self.as_ptr(), val, order) }
}
/// Bitwise "xor" with the current value.
///
/// Performs a bitwise "xor" operation on the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_xor` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`u16`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU16, Ordering};"]
///
#[doc = "let foo = AtomicU16::new(0b101101);"]
/// assert_eq!(foo.fetch_xor(0b110011, Ordering::SeqCst), 0b101101);
/// assert_eq!(foo.load(Ordering::SeqCst), 0b011110);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_xor(&self, val: u16, order: Ordering) -> u16 {
unsafe { atomic_xor(self.as_ptr(), val, order) }
}
/// An alias for
#[doc = "[`AtomicU16::try_update`]"]
/// .
#[inline]
#[stable(feature = "no_more_cas", since = "1.45.0")]
#[rustc_should_not_be_called_on_const_items]
#[deprecated(since = "1.99.0", note =
"renamed to `try_update` for consistency", suggestion = "try_update")]
pub fn fetch_update<F>(&self, set_order: Ordering, fetch_order: Ordering,
f: F) -> Result<u16, u16> where F: FnMut(u16) -> Option<u16> {
self.try_update(set_order, fetch_order, f)
}
/// Fetches the value, and applies a function to it that returns an optional
/// new value. Returns a `Result` of `Ok(previous_value)` if the function returned `Some(_)`, else
/// `Err(previous_value)`.
///
#[doc = "See also: [`update`](`AtomicU16::update`)."]
///
/// Note: This may call the function multiple times if the value has been changed from other threads in
/// the meantime, as long as the function returns `Some(_)`, but the function will have been applied
/// only once to the stored value.
///
/// `try_update` takes two [`Ordering`] arguments to describe the memory ordering of this operation.
/// The first describes the required ordering for when the operation finally succeeds while the second
/// describes the required ordering for loads. These correspond to the success and failure orderings of
#[doc = "[`AtomicU16::compare_exchange`]"]
/// respectively.
///
/// Using [`Acquire`] as success ordering makes the store part
/// of this operation [`Relaxed`], and using [`Release`] makes the final successful load
/// [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`u16`]."]
///
/// # Considerations
///
/// This method is not magic; it is not provided by the hardware, and does not act like a
/// critical section or mutex.
///
/// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
/// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem]
/// if this atomic integer is an index or more generally if knowledge of only the *bitwise value*
/// of the atomic is not in and of itself sufficient to ensure any required preconditions.
///
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
///
/// # Examples
///
#[doc = "```rust"]
#[doc = "use std::sync::atomic::{AtomicU16, Ordering};"]
///
#[doc = "let x = AtomicU16::new(7);"]
/// assert_eq!(x.try_update(Ordering::SeqCst, Ordering::SeqCst, |_| None), Err(7));
/// assert_eq!(x.try_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(x + 1)), Ok(7));
/// assert_eq!(x.try_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(x + 1)), Ok(8));
/// assert_eq!(x.load(Ordering::SeqCst), 9);
/// ```
#[inline]
#[stable(feature = "atomic_try_update", since = "1.95.0")]
#[rustc_should_not_be_called_on_const_items]
pub fn try_update(&self, set_order: Ordering, fetch_order: Ordering,
mut f: impl FnMut(u16) -> Option<u16>) -> Result<u16, u16> {
let mut prev = self.load(fetch_order);
while let Some(next) = f(prev) {
match self.compare_exchange_weak(prev, next, set_order,
fetch_order) {
x @ Ok(_) => return x,
Err(next_prev) => prev = next_prev,
}
}
Err(prev)
}
/// Fetches the value, and applies a function to it that returns a new value.
/// The new value is stored and the old value is returned.
///
#[doc = "See also: [`try_update`](`AtomicU16::try_update`)."]
///
/// Note: This may call the function multiple times if the value has been changed from other threads in
/// the meantime, but the function will have been applied only once to the stored value.
///
/// `update` takes two [`Ordering`] arguments to describe the memory ordering of this operation.
/// The first describes the required ordering for when the operation finally succeeds while the second
/// describes the required ordering for loads. These correspond to the success and failure orderings of
#[doc = "[`AtomicU16::compare_exchange`]"]
/// respectively.
///
/// Using [`Acquire`] as success ordering makes the store part
/// of this operation [`Relaxed`], and using [`Release`] makes the final successful load
/// [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`u16`]."]
///
/// # Considerations
///
/// [CAS operation]: https://en.wikipedia.org/wiki/Compare-and-swap
/// This method is not magic; it is not provided by the hardware, and does not act like a
/// critical section or mutex.
///
/// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
/// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem]
/// if this atomic integer is an index or more generally if knowledge of only the *bitwise value*
/// of the atomic is not in and of itself sufficient to ensure any required preconditions.
///
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
///
/// # Examples
///
#[doc = "```rust"]
#[doc = "use std::sync::atomic::{AtomicU16, Ordering};"]
///
#[doc = "let x = AtomicU16::new(7);"]
/// assert_eq!(x.update(Ordering::SeqCst, Ordering::SeqCst, |x| x + 1), 7);
/// assert_eq!(x.update(Ordering::SeqCst, Ordering::SeqCst, |x| x + 1), 8);
/// assert_eq!(x.load(Ordering::SeqCst), 9);
/// ```
#[inline]
#[stable(feature = "atomic_try_update", since = "1.95.0")]
#[rustc_should_not_be_called_on_const_items]
pub fn update(&self, set_order: Ordering, fetch_order: Ordering,
mut f: impl FnMut(u16) -> u16) -> u16 {
let mut prev = self.load(fetch_order);
loop {
match self.compare_exchange_weak(prev, f(prev), set_order,
fetch_order) {
Ok(x) => break x,
Err(next_prev) => prev = next_prev,
}
}
}
/// Maximum with the current value.
///
/// Finds the maximum of the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_max` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`u16`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU16, Ordering};"]
///
#[doc = "let foo = AtomicU16::new(23);"]
/// assert_eq!(foo.fetch_max(42, Ordering::SeqCst), 23);
/// assert_eq!(foo.load(Ordering::SeqCst), 42);
/// ```
///
/// If you want to obtain the maximum value in one step, you can use the following:
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU16, Ordering};"]
///
#[doc = "let foo = AtomicU16::new(23);"]
/// let bar = 42;
/// let max_foo = foo.fetch_max(bar, Ordering::SeqCst).max(bar);
/// assert!(max_foo == 42);
/// ```
#[inline]
#[stable(feature = "atomic_min_max", since = "1.45.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_max(&self, val: u16, order: Ordering) -> u16 {
unsafe { atomic_umax(self.as_ptr(), val, order) }
}
/// Minimum with the current value.
///
/// Finds the minimum of the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_min` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`u16`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU16, Ordering};"]
///
#[doc = "let foo = AtomicU16::new(23);"]
/// assert_eq!(foo.fetch_min(42, Ordering::Relaxed), 23);
/// assert_eq!(foo.load(Ordering::Relaxed), 23);
/// assert_eq!(foo.fetch_min(22, Ordering::Relaxed), 23);
/// assert_eq!(foo.load(Ordering::Relaxed), 22);
/// ```
///
/// If you want to obtain the minimum value in one step, you can use the following:
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU16, Ordering};"]
///
#[doc = "let foo = AtomicU16::new(23);"]
/// let bar = 12;
/// let min_foo = foo.fetch_min(bar, Ordering::SeqCst).min(bar);
/// assert_eq!(min_foo, 12);
/// ```
#[inline]
#[stable(feature = "atomic_min_max", since = "1.45.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_min(&self, val: u16, order: Ordering) -> u16 {
unsafe { atomic_umin(self.as_ptr(), val, order) }
}
/// Returns a mutable pointer to the underlying integer.
///
/// Doing non-atomic reads and writes on the resulting integer can be a data race.
/// This method is mostly useful for FFI, where the function signature may use
#[doc = "`*mut u16` instead of `&AtomicU16`."]
///
/// Returning an `*mut` pointer from a shared reference to this atomic is safe because the
/// atomic types work with interior mutability. All modifications of an atomic change the value
/// through a shared reference, and can do so safely as long as they use atomic operations. Any
/// use of the returned raw pointer requires an `unsafe` block and still has to uphold the
/// requirements of the [memory model].
///
/// # Examples
///
/// ```ignore (extern-declaration)
/// # fn main() {
#[doc = "use std::sync::atomic::AtomicU16;"]
///
/// extern "C" {
#[doc = " fn my_atomic_op(arg: *mut u16);"]
/// }
///
#[doc = "let atomic = AtomicU16::new(1);"]
///
/// // SAFETY: Safe as long as `my_atomic_op` is atomic.
/// unsafe {
/// my_atomic_op(atomic.as_ptr());
/// }
/// # }
/// ```
///
/// [memory model]: self#memory-model-for-atomic-accesses
#[inline]
#[stable(feature = "atomic_as_ptr", since = "1.70.0")]
#[rustc_const_stable(feature = "atomic_as_ptr", since = "1.70.0")]
#[rustc_never_returns_null_ptr]
pub const fn as_ptr(&self) -> *mut u16 { self.v.get().cast() }
}atomic_int! {
4079 target_has_atomic_load_store = "16",
4080 target_has_atomic = "16",
4081 target_has_atomic_primitive_alignment = "16",
4082 stable(feature = "integer_atomics_stable", since = "1.34.0"),
4083 stable(feature = "integer_atomics_stable", since = "1.34.0"),
4084 stable(feature = "integer_atomics_stable", since = "1.34.0"),
4085 stable(feature = "integer_atomics_stable", since = "1.34.0"),
4086 stable(feature = "integer_atomics_stable", since = "1.34.0"),
4087 stable(feature = "integer_atomics_stable", since = "1.34.0"),
4088 rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
4089 rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"),
4090"u16",
4091"",
4092 atomic_umin, atomic_umax,
40932,
4094 u16 AtomicU164095}4096#[cfg(target_has_atomic_load_store = "32")]
4097/// An integer type which can be safely shared between threads.
///
/// This type has the same
#[doc = "size and bit validity"]
/// as the underlying integer type, [`
#[doc = "i32"]
/// `].
#[doc =
"However, the alignment of this type is always equal to its size, even on targets where [`i32`] has a lesser alignment."]
///
/// For more about the differences between atomic types and
/// non-atomic types as well as information about the portability of
/// this type, please see the [module-level documentation].
///
/// **Note:** This type is only available on platforms that support
/// atomic loads and stores of [`
#[doc = "i32"]
/// `].
///
/// [module-level documentation]: crate::sync::atomic
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
pub type AtomicI32 = Atomic<i32>;
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
impl Default for AtomicI32 {
#[inline]
fn default() -> Self { Self::new(Default::default()) }
}
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
const impl From<i32> for AtomicI32 {
#[doc = "Converts an `i32` into an `AtomicI32`."]
#[inline]
fn from(v: i32) -> Self { Self::new(v) }
}
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
impl fmt::Debug for AtomicI32 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.load(Ordering::Relaxed), f)
}
}
impl AtomicI32 {
/// Creates a new atomic integer.
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::AtomicI32;"]
///
#[doc = "let atomic_forty_two = AtomicI32::new(42);"]
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0")]
#[must_use]
pub const fn new(v: i32) -> Self { unsafe { transmute(v) } }
/// Creates a new reference to an atomic integer from a pointer.
///
/// # Examples
///
#[doc = "```rust"]
#[doc = "use std::sync::atomic::{self, AtomicI32};"]
///
/// // Get a pointer to an allocated value
#[doc = "let ptr: *mut i32 = Box::into_raw(Box::new(0));"]
///
#[doc = "assert!(ptr.cast::<AtomicI32>().is_aligned());"]
///
/// {
/// // Create an atomic view of the allocated value
#[doc = " let atomic = unsafe {AtomicI32::from_ptr(ptr) };"]
///
/// // Use `atomic` for atomic operations, possibly share it with other threads
/// atomic.store(1, atomic::Ordering::Relaxed);
/// }
///
/// // It's ok to non-atomically access the value behind `ptr`,
/// // since the reference to the atomic ended its lifetime in the block above
/// assert_eq!(unsafe { *ptr }, 1);
///
/// // Deallocate the value
/// unsafe { drop(Box::from_raw(ptr)) }
/// ```
///
/// # Safety
///
/// * `ptr` must be aligned to
#[doc = " `align_of::<AtomicI32>()`"]
#[doc =
" (note that on some platforms this can be bigger than `align_of::<i32>()`)."]
/// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`.
/// * You must adhere to the [Memory model for atomic accesses]. In particular, it is not
/// allowed to mix conflicting atomic and non-atomic accesses, or atomic accesses of different
/// sizes, without synchronization.
///
/// [valid]: crate::ptr#safety
/// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses
#[inline]
#[stable(feature = "atomic_from_ptr", since = "1.75.0")]
#[rustc_const_stable(feature = "const_atomic_from_ptr", since = "1.84.0")]
pub const unsafe fn from_ptr<'a>(ptr: *mut i32) -> &'a AtomicI32 {
unsafe { &*ptr.cast() }
}
/// Creates a new pointer to an atomic integer from a pointer.
///
/// This is useful if you want to do volatile atomic accesses, and thus avoid creating
/// a reference to the destination.
#[inline]
#[unstable(feature = "atomic_volatile", issue = "158947")]
pub const fn from_ptr_raw(ptr: *mut i32) -> *const AtomicI32 {
ptr.cast_const().cast()
}
/// Returns a mutable reference to the underlying integer.
///
/// This is safe because the mutable reference guarantees that no other threads are
/// concurrently accessing the atomic data.
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI32, Ordering};"]
///
#[doc = "let mut some_var = AtomicI32::new(10);"]
/// assert_eq!(*some_var.get_mut(), 10);
/// *some_var.get_mut() = 5;
/// assert_eq!(some_var.load(Ordering::SeqCst), 5);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
pub const fn get_mut(&mut self) -> &mut i32 {
unsafe { &mut *self.as_ptr() }
}
#[doc = "Get atomic access to a `&mut i32`."]
///
#[doc =
"**Note:** This function is only available on targets where `AtomicI32` has the same alignment as `i32`."]
///
/// # Examples
///
#[doc = "```rust"]
#[doc = "use std::sync::atomic::{AtomicI32, Ordering};"]
///
/// let mut some_int = 123;
#[doc = "let a = AtomicI32::from_mut(&mut some_int);"]
/// a.store(100, Ordering::Relaxed);
/// assert_eq!(some_int, 100);
/// ```
///
#[inline]
#[stable(feature = "atomic_from_mut", since = "1.98.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
pub const fn from_mut(v: &mut i32) -> &mut Self {
let [] = [(); align_of::<Self>() - align_of::<i32>()];
unsafe { &mut *(v as *mut i32 as *mut Self) }
}
#[doc = "Get non-atomic access to a `&mut [AtomicI32]` slice"]
///
/// This is safe because the mutable reference guarantees that no other threads are
/// concurrently accessing the atomic data.
///
/// # Examples
///
#[doc = "```ignore-wasm"]
#[doc = "use std::sync::atomic::{AtomicI32, Ordering};"]
///
#[doc = "let mut some_ints = [const { AtomicI32::new(0) }; 10];"]
///
#[doc =
"let view: &mut [i32] = AtomicI32::get_mut_slice(&mut some_ints);"]
/// assert_eq!(view, [0; 10]);
/// view
/// .iter_mut()
/// .enumerate()
/// .for_each(|(idx, int)| *int = idx as _);
///
/// std::thread::scope(|s| {
/// some_ints
/// .iter()
/// .enumerate()
/// .for_each(|(idx, int)| {
/// s.spawn(move || assert_eq!(int.load(Ordering::Relaxed), idx as _));
/// })
/// });
/// ```
#[inline]
#[stable(feature = "atomic_from_mut", since = "1.98.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
pub const fn get_mut_slice(this: &mut [Self]) -> &mut [i32] {
unsafe { &mut *(this as *mut [Self] as *mut [i32]) }
}
#[doc = "Get atomic access to a `&mut [i32]` slice."]
///
#[doc =
"**Note:** This function is only available on targets where `AtomicI32` has the same alignment as `i32`."]
///
/// # Examples
///
#[doc = "```ignore-wasm"]
#[doc = "use std::sync::atomic::{AtomicI32, Ordering};"]
///
/// let mut some_ints = [0; 10];
#[doc = "let a = &*AtomicI32::from_mut_slice(&mut some_ints);"]
/// std::thread::scope(|s| {
/// for i in 0..a.len() {
/// s.spawn(move || a[i].store(i as _, Ordering::Relaxed));
/// }
/// });
/// for (i, n) in some_ints.into_iter().enumerate() {
/// assert_eq!(i, n as usize);
/// }
/// ```
#[inline]
#[stable(feature = "atomic_from_mut", since = "1.98.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
pub const fn from_mut_slice(v: &mut [i32]) -> &mut [Self] {
let [] = [(); align_of::<Self>() - align_of::<i32>()];
unsafe { &mut *(v as *mut [i32] as *mut [Self]) }
}
/// Consumes the atomic and returns the contained value.
///
/// This is safe because passing `self` by value guarantees that no other threads are
/// concurrently accessing the atomic data.
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::AtomicI32;"]
///
#[doc = "let some_var = AtomicI32::new(5);"]
/// assert_eq!(some_var.into_inner(), 5);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_stable(feature = "const_atomic_into_inner", since =
"1.79.0")]
pub const fn into_inner(self) -> i32 { unsafe { transmute(self) } }
/// Loads a value from the atomic integer.
///
/// `load` takes an [`Ordering`] argument which describes the memory ordering of this operation.
/// Possible values are [`SeqCst`], [`Acquire`] and [`Relaxed`].
///
/// # Panics
///
/// Panics if `order` is [`Release`] or [`AcqRel`].
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI32, Ordering};"]
///
#[doc = "let some_var = AtomicI32::new(5);"]
///
/// assert_eq!(some_var.load(Ordering::Relaxed), 5);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
pub const fn load(&self, order: Ordering) -> i32 {
unsafe { atomic_load::<_, false>(self.as_ptr(), order) }
}
/// Perform a volatile load from the atomic integer.
///
/// `load_volatile` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. Possible values are [`SeqCst`], [`Acquire`] and [`Relaxed`].
///
#[doc =
"Volatile operations are intended to act on I/O memory. As such, they are considered externally\nobservable events (just like syscalls, but less opaque), and are guaranteed to not be elided or\nreordered by the compiler across other externally observable events. With this in mind, there\nare two cases of usage that need to be distinguished:\n\n- When a volatile operation is used for memory inside an [allocation], it behaves exactly\n like [`load`][Self::load], except for the additional guarantee that it won\'t be elided or\n reordered across other externally observable events (see above). This implies that the\n operation will actually access memory and not e.g. be lowered to reusing data from a\n previous load. Other than that, all the usual rules for memory accesses apply (including\n provenance).\n\n- Volatile operations, however, may also be used to access memory that is _outside_ of any Rust\n allocation. In this use-case, the pointer does *not* have to be [valid] for reads. This is\n typically used for CPU and peripheral registers that must be accessed via an I/O memory mapping,\n most commonly at fixed addresses reserved by the hardware. These often have special semantics\n associated to their manipulation, and cannot be used as general purpose memory. Here, any address\n value is possible, including 0 and [`usize::MAX`], so long as the semantics of such a read are\n well-defined by the target hardware. The provenance of the pointer is irrelevant, and it can be\n created with [`without_provenance`][crate::ptr::without_provenance]. The access is allowed to\n trap, which must immediately abort the process. It can also cause other side-effects, but those\n must not affect Rust-allocated memory in any way.\n\nIn both cases, the access is also considered atomic with the given `order`. This allows\nsynchronization with other threads or devices that share memory with this program.\n\nWhen invoked during const evaluation, this behaves like a regular atomic load. In\nparticular, such reads must always follow the first of the two cases above.\n\n[allocation]: crate::ptr#allocated-object\n"]
///
/// # Safety
///
/// Behavior is undefined if any of the following conditions are violated:
///
/// * `self` must be [valid] for reads, or `self` must point to memory
/// outside of all Rust allocations and reading from that memory must:
/// - not trap, and
/// - not cause any memory inside a Rust allocation to be modified.
///
/// * `self` must be aligned to
#[doc = " `align_of::<AtomicI32>()`"]
#[doc =
" (note that on some platforms this can be bigger than `align_of::<i32>()`)."]
///
/// * Reading from `self` must produce a properly initialized value of the underlying
/// integer type.
///
/// [valid]: core::ptr#safety
///
/// # Panics
///
/// Panics if `order` is [`Release`] or [`AcqRel`].
#[inline]
#[unstable(feature = "atomic_volatile", issue = "158947")]
#[rustc_const_unstable(feature = "atomic_volatile", issue = "158947")]
pub const unsafe fn load_volatile(self: *const Self, order: Ordering)
-> i32 {
unsafe { atomic_load::<_, true>(self.cast::<i32>(), order) }
}
/// Stores a value into the atomic integer.
///
/// `store` takes an [`Ordering`] argument which describes the memory ordering of this operation.
/// Possible values are [`SeqCst`], [`Release`] and [`Relaxed`].
///
/// # Panics
///
/// Panics if `order` is [`Acquire`] or [`AcqRel`].
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI32, Ordering};"]
///
#[doc = "let some_var = AtomicI32::new(5);"]
///
/// some_var.store(10, Ordering::Relaxed);
/// assert_eq!(some_var.load(Ordering::Relaxed), 10);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn store(&self, val: i32, order: Ordering) {
unsafe { atomic_store::<_, false>(self.as_ptr(), val, order); }
}
/// Performs a volatile store into the atomic integer.
///
/// `store_volatile` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. Possible values are [`SeqCst`], [`Release`] and [`Relaxed`].
///
#[doc =
"Volatile operations are intended to act on I/O memory. As such, they are considered externally\nobservable events (just like syscalls), and are guaranteed to not be elided or reordered by the\ncompiler across other externally observable events. With this in mind, there are two cases of\nusage that need to be distinguished:\n\n- When a volatile operation is used for memory inside an [allocation], it behaves exactly like\n [`store`][Self::store], except for the additional guarantee that it won\'t be elided or reordered\n across other externally observable events (see above). This implies that the operation will\n actually access memory and not e.g. be lowered to a register access. Other than that, all the\n usual rules for memory accesses apply (including provenance).\n\n- Volatile operations, however, may also be used to access memory that is _outside_ of any Rust\n allocation. In this use-case, the pointer does *not* have to be [valid] for writes. This is\n typically used for CPU and peripheral registers that must be accessed via an I/O memory mapping,\n most commonly at fixed addresses reserved by the hardware. These often have special semantics\n associated to their manipulation, and cannot be used as general purpose memory. Here, any address\n value is possible, including 0 and [`usize::MAX`], so long as the semantics of such a write are\n well-defined by the target hardware. The provenance of the pointer is irrelevant, and it can be\n created with [`without_provenance_mut`][crate::ptr::without_provenance_mut]. The access is allowed\n to trap, which must immediately abort the process. It can also cause other side-effects, but those\n must not affect Rust-allocated memory in any way.\n\nIn both cases, the access is also considered atomic with the given `order`. This allows\nsynchronization with other threads or devices that share memory with this program.\n\nWhen invoked during const evaluation, this behaves like a regular atomic store. In\nparticular, such reads must always follow the first of the two cases above.\n\n[allocation]: crate::ptr#allocated-object\n"]
///
/// # Safety
///
/// Behavior is undefined if any of the following conditions are violated:
///
/// * `self` must be either [valid] for writes, or `self` must point to memory
/// outside of all Rust allocations and writing to that memory must:
/// - not trap, and
/// - not cause any memory inside a Rust allocation to be modified.
///
/// * `self` must be aligned to
#[doc = " `align_of::<AtomicI32>()`"]
#[doc =
" (note that on some platforms this can be bigger than `align_of::<i32>()`)."]
///
/// [valid]: core::ptr#safety
///
/// # Panics
///
/// Panics if `order` is [`Acquire`] or [`AcqRel`].
#[inline]
#[unstable(feature = "atomic_volatile", issue = "158947")]
#[rustc_const_unstable(feature = "atomic_volatile", issue = "158947")]
#[rustc_should_not_be_called_on_const_items]
pub const unsafe fn store_volatile(self: *const Self, val: i32,
order: Ordering) {
unsafe {
atomic_store::<_,
true>(self.cast::<i32>().cast_mut(), val, order);
}
}
/// Stores a value into the atomic integer, returning the previous value.
///
/// `swap` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`i32`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI32, Ordering};"]
///
#[doc = "let some_var = AtomicI32::new(5);"]
///
/// assert_eq!(some_var.swap(10, Ordering::Relaxed), 5);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn swap(&self, val: i32, order: Ordering) -> i32 {
unsafe { atomic_swap(self.as_ptr(), val, order) }
}
/// Stores a value into the atomic integer if the current value is the same as
/// the `current` value.
///
/// The return value is always the previous value. If it is equal to `current`, then the
/// value was updated.
///
/// `compare_and_swap` also takes an [`Ordering`] argument which describes the memory
/// ordering of this operation. Notice that even when using [`AcqRel`], the operation
/// might fail and hence just perform an `Acquire` load, but not have `Release` semantics.
/// Using [`Acquire`] makes the store part of this operation [`Relaxed`] if it
/// happens, and using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`i32`]."]
///
/// # Migrating to `compare_exchange` and `compare_exchange_weak`
///
/// `compare_and_swap` is equivalent to `compare_exchange` with the following mapping for
/// memory orderings:
///
/// Original | Success | Failure
/// -------- | ------- | -------
/// Relaxed | Relaxed | Relaxed
/// Acquire | Acquire | Acquire
/// Release | Release | Relaxed
/// AcqRel | AcqRel | Acquire
/// SeqCst | SeqCst | SeqCst
///
/// `compare_and_swap` and `compare_exchange` also differ in their return type. You can use
/// `compare_exchange(...).unwrap_or_else(|x| x)` to recover the behavior of `compare_and_swap`,
/// but in most cases it is more idiomatic to check whether the return value is `Ok` or `Err`
/// rather than to infer success vs failure based on the value that was read.
///
/// During migration, consider whether it makes sense to use `compare_exchange_weak` instead.
/// `compare_exchange_weak` is allowed to fail spuriously even when the comparison succeeds,
/// which allows the compiler to generate better assembly code when the compare and swap
/// is used in a loop.
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI32, Ordering};"]
///
#[doc = "let some_var = AtomicI32::new(5);"]
///
/// assert_eq!(some_var.compare_and_swap(5, 10, Ordering::Relaxed), 5);
/// assert_eq!(some_var.load(Ordering::Relaxed), 10);
///
/// assert_eq!(some_var.compare_and_swap(6, 12, Ordering::Relaxed), 10);
/// assert_eq!(some_var.load(Ordering::Relaxed), 10);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[deprecated(since = "1.50.0", note =
"Use `compare_exchange` or `compare_exchange_weak` instead")]
#[rustc_should_not_be_called_on_const_items]
pub const fn compare_and_swap(&self, current: i32, new: i32,
order: Ordering) -> i32 {
match self.compare_exchange(current, new, order,
strongest_failure_ordering(order)) {
Ok(x) => x,
Err(x) => x,
}
}
/// Stores a value into the atomic integer if the current value is the same as
/// the `current` value.
///
/// The return value is a result indicating whether the new value was written and
/// containing the previous value. On success this value is guaranteed to be equal to
/// `current`.
///
/// `compare_exchange` takes two [`Ordering`] arguments to describe the memory
/// ordering of this operation. `success` describes the required ordering for the
/// read-modify-write operation that takes place if the comparison with `current` succeeds.
/// `failure` describes the required ordering for the load operation that takes place when
/// the comparison fails. Using [`Acquire`] as success ordering makes the store part
/// of this operation [`Relaxed`], and using [`Release`] makes the successful load
/// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`i32`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI32, Ordering};"]
///
#[doc = "let some_var = AtomicI32::new(5);"]
///
/// assert_eq!(some_var.compare_exchange(5, 10,
/// Ordering::Acquire,
/// Ordering::Relaxed),
/// Ok(5));
/// assert_eq!(some_var.load(Ordering::Relaxed), 10);
///
/// assert_eq!(some_var.compare_exchange(6, 12,
/// Ordering::SeqCst,
/// Ordering::Acquire),
/// Err(10));
/// assert_eq!(some_var.load(Ordering::Relaxed), 10);
/// ```
///
/// # Considerations
///
/// `compare_exchange` is a [compare-and-swap operation] and thus exhibits the usual downsides
/// of CAS operations. In particular, a load of the value followed by a successful
/// `compare_exchange` with the previous load *does not ensure* that other threads have not
/// changed the value in the interim! This is usually important when the *equality* check in
/// the `compare_exchange` is being used to check the *identity* of a value, but equality
/// does not necessarily imply identity. This is a particularly common case for pointers, as
/// a pointer holding the same address does not imply that the same object exists at that
/// address! In this case, `compare_exchange` can lead to the [ABA problem].
///
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn compare_exchange(&self, current: i32, new: i32,
success: Ordering, failure: Ordering) -> Result<i32, i32> {
unsafe {
atomic_compare_exchange(self.as_ptr(), current, new, success,
failure)
}
}
/// Stores a value into the atomic integer if the current value is the same as
/// the `current` value.
///
#[doc = "Unlike [`AtomicI32::compare_exchange`],"]
/// this function is allowed to spuriously fail even
/// when the comparison succeeds, which can result in more efficient code on some
/// platforms. The return value is a result indicating whether the new value was
/// written and containing the previous value.
///
/// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory
/// ordering of this operation. `success` describes the required ordering for the
/// read-modify-write operation that takes place if the comparison with `current` succeeds.
/// `failure` describes the required ordering for the load operation that takes place when
/// the comparison fails. Using [`Acquire`] as success ordering makes the store part
/// of this operation [`Relaxed`], and using [`Release`] makes the successful load
/// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`i32`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI32, Ordering};"]
///
#[doc = "let val = AtomicI32::new(4);"]
///
/// let mut old = val.load(Ordering::Relaxed);
/// loop {
/// let new = old * 2;
/// match val.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) {
/// Ok(_) => break,
/// Err(x) => old = x,
/// }
/// }
/// ```
///
/// # Considerations
///
/// `compare_exchange` is a [compare-and-swap operation] and thus exhibits the usual downsides
/// of CAS operations. In particular, a load of the value followed by a successful
/// `compare_exchange` with the previous load *does not ensure* that other threads have not
/// changed the value in the interim. This is usually important when the *equality* check in
/// the `compare_exchange` is being used to check the *identity* of a value, but equality
/// does not necessarily imply identity. This is a particularly common case for pointers, as
/// a pointer holding the same address does not imply that the same object exists at that
/// address! In this case, `compare_exchange` can lead to the [ABA problem].
///
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn compare_exchange_weak(&self, current: i32, new: i32,
success: Ordering, failure: Ordering) -> Result<i32, i32> {
unsafe {
atomic_compare_exchange_weak(self.as_ptr(), current, new, success,
failure)
}
}
/// Adds to the current value, returning the previous value.
///
/// This operation wraps around on overflow.
///
/// `fetch_add` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`i32`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI32, Ordering};"]
///
#[doc = "let foo = AtomicI32::new(0);"]
/// assert_eq!(foo.fetch_add(10, Ordering::SeqCst), 0);
/// assert_eq!(foo.load(Ordering::SeqCst), 10);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_add(&self, val: i32, order: Ordering) -> i32 {
unsafe { atomic_add(self.as_ptr(), val, order) }
}
/// Subtracts from the current value, returning the previous value.
///
/// This operation wraps around on overflow.
///
/// `fetch_sub` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`i32`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI32, Ordering};"]
///
#[doc = "let foo = AtomicI32::new(20);"]
/// assert_eq!(foo.fetch_sub(10, Ordering::SeqCst), 20);
/// assert_eq!(foo.load(Ordering::SeqCst), 10);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_sub(&self, val: i32, order: Ordering) -> i32 {
unsafe { atomic_sub(self.as_ptr(), val, order) }
}
/// Bitwise "and" with the current value.
///
/// Performs a bitwise "and" operation on the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_and` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`i32`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI32, Ordering};"]
///
#[doc = "let foo = AtomicI32::new(0b101101);"]
/// assert_eq!(foo.fetch_and(0b110011, Ordering::SeqCst), 0b101101);
/// assert_eq!(foo.load(Ordering::SeqCst), 0b100001);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_and(&self, val: i32, order: Ordering) -> i32 {
unsafe { atomic_and(self.as_ptr(), val, order) }
}
/// Bitwise "nand" with the current value.
///
/// Performs a bitwise "nand" operation on the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_nand` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`i32`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI32, Ordering};"]
///
#[doc = "let foo = AtomicI32::new(0x13);"]
/// assert_eq!(foo.fetch_nand(0x31, Ordering::SeqCst), 0x13);
/// assert_eq!(foo.load(Ordering::SeqCst), !(0x13 & 0x31));
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_nand(&self, val: i32, order: Ordering) -> i32 {
unsafe { atomic_nand(self.as_ptr(), val, order) }
}
/// Bitwise "or" with the current value.
///
/// Performs a bitwise "or" operation on the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_or` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`i32`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI32, Ordering};"]
///
#[doc = "let foo = AtomicI32::new(0b101101);"]
/// assert_eq!(foo.fetch_or(0b110011, Ordering::SeqCst), 0b101101);
/// assert_eq!(foo.load(Ordering::SeqCst), 0b111111);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_or(&self, val: i32, order: Ordering) -> i32 {
unsafe { atomic_or(self.as_ptr(), val, order) }
}
/// Bitwise "xor" with the current value.
///
/// Performs a bitwise "xor" operation on the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_xor` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`i32`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI32, Ordering};"]
///
#[doc = "let foo = AtomicI32::new(0b101101);"]
/// assert_eq!(foo.fetch_xor(0b110011, Ordering::SeqCst), 0b101101);
/// assert_eq!(foo.load(Ordering::SeqCst), 0b011110);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_xor(&self, val: i32, order: Ordering) -> i32 {
unsafe { atomic_xor(self.as_ptr(), val, order) }
}
/// An alias for
#[doc = "[`AtomicI32::try_update`]"]
/// .
#[inline]
#[stable(feature = "no_more_cas", since = "1.45.0")]
#[rustc_should_not_be_called_on_const_items]
#[deprecated(since = "1.99.0", note =
"renamed to `try_update` for consistency", suggestion = "try_update")]
pub fn fetch_update<F>(&self, set_order: Ordering, fetch_order: Ordering,
f: F) -> Result<i32, i32> where F: FnMut(i32) -> Option<i32> {
self.try_update(set_order, fetch_order, f)
}
/// Fetches the value, and applies a function to it that returns an optional
/// new value. Returns a `Result` of `Ok(previous_value)` if the function returned `Some(_)`, else
/// `Err(previous_value)`.
///
#[doc = "See also: [`update`](`AtomicI32::update`)."]
///
/// Note: This may call the function multiple times if the value has been changed from other threads in
/// the meantime, as long as the function returns `Some(_)`, but the function will have been applied
/// only once to the stored value.
///
/// `try_update` takes two [`Ordering`] arguments to describe the memory ordering of this operation.
/// The first describes the required ordering for when the operation finally succeeds while the second
/// describes the required ordering for loads. These correspond to the success and failure orderings of
#[doc = "[`AtomicI32::compare_exchange`]"]
/// respectively.
///
/// Using [`Acquire`] as success ordering makes the store part
/// of this operation [`Relaxed`], and using [`Release`] makes the final successful load
/// [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`i32`]."]
///
/// # Considerations
///
/// This method is not magic; it is not provided by the hardware, and does not act like a
/// critical section or mutex.
///
/// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
/// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem]
/// if this atomic integer is an index or more generally if knowledge of only the *bitwise value*
/// of the atomic is not in and of itself sufficient to ensure any required preconditions.
///
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
///
/// # Examples
///
#[doc = "```rust"]
#[doc = "use std::sync::atomic::{AtomicI32, Ordering};"]
///
#[doc = "let x = AtomicI32::new(7);"]
/// assert_eq!(x.try_update(Ordering::SeqCst, Ordering::SeqCst, |_| None), Err(7));
/// assert_eq!(x.try_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(x + 1)), Ok(7));
/// assert_eq!(x.try_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(x + 1)), Ok(8));
/// assert_eq!(x.load(Ordering::SeqCst), 9);
/// ```
#[inline]
#[stable(feature = "atomic_try_update", since = "1.95.0")]
#[rustc_should_not_be_called_on_const_items]
pub fn try_update(&self, set_order: Ordering, fetch_order: Ordering,
mut f: impl FnMut(i32) -> Option<i32>) -> Result<i32, i32> {
let mut prev = self.load(fetch_order);
while let Some(next) = f(prev) {
match self.compare_exchange_weak(prev, next, set_order,
fetch_order) {
x @ Ok(_) => return x,
Err(next_prev) => prev = next_prev,
}
}
Err(prev)
}
/// Fetches the value, and applies a function to it that returns a new value.
/// The new value is stored and the old value is returned.
///
#[doc = "See also: [`try_update`](`AtomicI32::try_update`)."]
///
/// Note: This may call the function multiple times if the value has been changed from other threads in
/// the meantime, but the function will have been applied only once to the stored value.
///
/// `update` takes two [`Ordering`] arguments to describe the memory ordering of this operation.
/// The first describes the required ordering for when the operation finally succeeds while the second
/// describes the required ordering for loads. These correspond to the success and failure orderings of
#[doc = "[`AtomicI32::compare_exchange`]"]
/// respectively.
///
/// Using [`Acquire`] as success ordering makes the store part
/// of this operation [`Relaxed`], and using [`Release`] makes the final successful load
/// [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`i32`]."]
///
/// # Considerations
///
/// [CAS operation]: https://en.wikipedia.org/wiki/Compare-and-swap
/// This method is not magic; it is not provided by the hardware, and does not act like a
/// critical section or mutex.
///
/// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
/// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem]
/// if this atomic integer is an index or more generally if knowledge of only the *bitwise value*
/// of the atomic is not in and of itself sufficient to ensure any required preconditions.
///
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
///
/// # Examples
///
#[doc = "```rust"]
#[doc = "use std::sync::atomic::{AtomicI32, Ordering};"]
///
#[doc = "let x = AtomicI32::new(7);"]
/// assert_eq!(x.update(Ordering::SeqCst, Ordering::SeqCst, |x| x + 1), 7);
/// assert_eq!(x.update(Ordering::SeqCst, Ordering::SeqCst, |x| x + 1), 8);
/// assert_eq!(x.load(Ordering::SeqCst), 9);
/// ```
#[inline]
#[stable(feature = "atomic_try_update", since = "1.95.0")]
#[rustc_should_not_be_called_on_const_items]
pub fn update(&self, set_order: Ordering, fetch_order: Ordering,
mut f: impl FnMut(i32) -> i32) -> i32 {
let mut prev = self.load(fetch_order);
loop {
match self.compare_exchange_weak(prev, f(prev), set_order,
fetch_order) {
Ok(x) => break x,
Err(next_prev) => prev = next_prev,
}
}
}
/// Maximum with the current value.
///
/// Finds the maximum of the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_max` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`i32`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI32, Ordering};"]
///
#[doc = "let foo = AtomicI32::new(23);"]
/// assert_eq!(foo.fetch_max(42, Ordering::SeqCst), 23);
/// assert_eq!(foo.load(Ordering::SeqCst), 42);
/// ```
///
/// If you want to obtain the maximum value in one step, you can use the following:
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI32, Ordering};"]
///
#[doc = "let foo = AtomicI32::new(23);"]
/// let bar = 42;
/// let max_foo = foo.fetch_max(bar, Ordering::SeqCst).max(bar);
/// assert!(max_foo == 42);
/// ```
#[inline]
#[stable(feature = "atomic_min_max", since = "1.45.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_max(&self, val: i32, order: Ordering) -> i32 {
unsafe { atomic_max(self.as_ptr(), val, order) }
}
/// Minimum with the current value.
///
/// Finds the minimum of the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_min` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`i32`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI32, Ordering};"]
///
#[doc = "let foo = AtomicI32::new(23);"]
/// assert_eq!(foo.fetch_min(42, Ordering::Relaxed), 23);
/// assert_eq!(foo.load(Ordering::Relaxed), 23);
/// assert_eq!(foo.fetch_min(22, Ordering::Relaxed), 23);
/// assert_eq!(foo.load(Ordering::Relaxed), 22);
/// ```
///
/// If you want to obtain the minimum value in one step, you can use the following:
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI32, Ordering};"]
///
#[doc = "let foo = AtomicI32::new(23);"]
/// let bar = 12;
/// let min_foo = foo.fetch_min(bar, Ordering::SeqCst).min(bar);
/// assert_eq!(min_foo, 12);
/// ```
#[inline]
#[stable(feature = "atomic_min_max", since = "1.45.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_min(&self, val: i32, order: Ordering) -> i32 {
unsafe { atomic_min(self.as_ptr(), val, order) }
}
/// Returns a mutable pointer to the underlying integer.
///
/// Doing non-atomic reads and writes on the resulting integer can be a data race.
/// This method is mostly useful for FFI, where the function signature may use
#[doc = "`*mut i32` instead of `&AtomicI32`."]
///
/// Returning an `*mut` pointer from a shared reference to this atomic is safe because the
/// atomic types work with interior mutability. All modifications of an atomic change the value
/// through a shared reference, and can do so safely as long as they use atomic operations. Any
/// use of the returned raw pointer requires an `unsafe` block and still has to uphold the
/// requirements of the [memory model].
///
/// # Examples
///
/// ```ignore (extern-declaration)
/// # fn main() {
#[doc = "use std::sync::atomic::AtomicI32;"]
///
/// extern "C" {
#[doc = " fn my_atomic_op(arg: *mut i32);"]
/// }
///
#[doc = "let atomic = AtomicI32::new(1);"]
///
/// // SAFETY: Safe as long as `my_atomic_op` is atomic.
/// unsafe {
/// my_atomic_op(atomic.as_ptr());
/// }
/// # }
/// ```
///
/// [memory model]: self#memory-model-for-atomic-accesses
#[inline]
#[stable(feature = "atomic_as_ptr", since = "1.70.0")]
#[rustc_const_stable(feature = "atomic_as_ptr", since = "1.70.0")]
#[rustc_never_returns_null_ptr]
pub const fn as_ptr(&self) -> *mut i32 { self.v.get().cast() }
}atomic_int! {
4098 target_has_atomic_load_store = "32",
4099 target_has_atomic = "32",
4100 target_has_atomic_primitive_alignment = "32",
4101 stable(feature = "integer_atomics_stable", since = "1.34.0"),
4102 stable(feature = "integer_atomics_stable", since = "1.34.0"),
4103 stable(feature = "integer_atomics_stable", since = "1.34.0"),
4104 stable(feature = "integer_atomics_stable", since = "1.34.0"),
4105 stable(feature = "integer_atomics_stable", since = "1.34.0"),
4106 stable(feature = "integer_atomics_stable", since = "1.34.0"),
4107 rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
4108 rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"),
4109"i32",
4110"",
4111 atomic_min, atomic_max,
41124,
4113 i32 AtomicI324114}4115#[cfg(target_has_atomic_load_store = "32")]
4116/// An integer type which can be safely shared between threads.
///
/// This type has the same
#[doc = "size and bit validity"]
/// as the underlying integer type, [`
#[doc = "u32"]
/// `].
#[doc =
"However, the alignment of this type is always equal to its size, even on targets where [`u32`] has a lesser alignment."]
///
/// For more about the differences between atomic types and
/// non-atomic types as well as information about the portability of
/// this type, please see the [module-level documentation].
///
/// **Note:** This type is only available on platforms that support
/// atomic loads and stores of [`
#[doc = "u32"]
/// `].
///
/// [module-level documentation]: crate::sync::atomic
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
pub type AtomicU32 = Atomic<u32>;
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
impl Default for AtomicU32 {
#[inline]
fn default() -> Self { Self::new(Default::default()) }
}
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
const impl From<u32> for AtomicU32 {
#[doc = "Converts an `u32` into an `AtomicU32`."]
#[inline]
fn from(v: u32) -> Self { Self::new(v) }
}
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
impl fmt::Debug for AtomicU32 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.load(Ordering::Relaxed), f)
}
}
impl AtomicU32 {
/// Creates a new atomic integer.
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::AtomicU32;"]
///
#[doc = "let atomic_forty_two = AtomicU32::new(42);"]
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0")]
#[must_use]
pub const fn new(v: u32) -> Self { unsafe { transmute(v) } }
/// Creates a new reference to an atomic integer from a pointer.
///
/// # Examples
///
#[doc = "```rust"]
#[doc = "use std::sync::atomic::{self, AtomicU32};"]
///
/// // Get a pointer to an allocated value
#[doc = "let ptr: *mut u32 = Box::into_raw(Box::new(0));"]
///
#[doc = "assert!(ptr.cast::<AtomicU32>().is_aligned());"]
///
/// {
/// // Create an atomic view of the allocated value
#[doc = " let atomic = unsafe {AtomicU32::from_ptr(ptr) };"]
///
/// // Use `atomic` for atomic operations, possibly share it with other threads
/// atomic.store(1, atomic::Ordering::Relaxed);
/// }
///
/// // It's ok to non-atomically access the value behind `ptr`,
/// // since the reference to the atomic ended its lifetime in the block above
/// assert_eq!(unsafe { *ptr }, 1);
///
/// // Deallocate the value
/// unsafe { drop(Box::from_raw(ptr)) }
/// ```
///
/// # Safety
///
/// * `ptr` must be aligned to
#[doc = " `align_of::<AtomicU32>()`"]
#[doc =
" (note that on some platforms this can be bigger than `align_of::<u32>()`)."]
/// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`.
/// * You must adhere to the [Memory model for atomic accesses]. In particular, it is not
/// allowed to mix conflicting atomic and non-atomic accesses, or atomic accesses of different
/// sizes, without synchronization.
///
/// [valid]: crate::ptr#safety
/// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses
#[inline]
#[stable(feature = "atomic_from_ptr", since = "1.75.0")]
#[rustc_const_stable(feature = "const_atomic_from_ptr", since = "1.84.0")]
pub const unsafe fn from_ptr<'a>(ptr: *mut u32) -> &'a AtomicU32 {
unsafe { &*ptr.cast() }
}
/// Creates a new pointer to an atomic integer from a pointer.
///
/// This is useful if you want to do volatile atomic accesses, and thus avoid creating
/// a reference to the destination.
#[inline]
#[unstable(feature = "atomic_volatile", issue = "158947")]
pub const fn from_ptr_raw(ptr: *mut u32) -> *const AtomicU32 {
ptr.cast_const().cast()
}
/// Returns a mutable reference to the underlying integer.
///
/// This is safe because the mutable reference guarantees that no other threads are
/// concurrently accessing the atomic data.
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU32, Ordering};"]
///
#[doc = "let mut some_var = AtomicU32::new(10);"]
/// assert_eq!(*some_var.get_mut(), 10);
/// *some_var.get_mut() = 5;
/// assert_eq!(some_var.load(Ordering::SeqCst), 5);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
pub const fn get_mut(&mut self) -> &mut u32 {
unsafe { &mut *self.as_ptr() }
}
#[doc = "Get atomic access to a `&mut u32`."]
///
#[doc =
"**Note:** This function is only available on targets where `AtomicU32` has the same alignment as `u32`."]
///
/// # Examples
///
#[doc = "```rust"]
#[doc = "use std::sync::atomic::{AtomicU32, Ordering};"]
///
/// let mut some_int = 123;
#[doc = "let a = AtomicU32::from_mut(&mut some_int);"]
/// a.store(100, Ordering::Relaxed);
/// assert_eq!(some_int, 100);
/// ```
///
#[inline]
#[stable(feature = "atomic_from_mut", since = "1.98.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
pub const fn from_mut(v: &mut u32) -> &mut Self {
let [] = [(); align_of::<Self>() - align_of::<u32>()];
unsafe { &mut *(v as *mut u32 as *mut Self) }
}
#[doc = "Get non-atomic access to a `&mut [AtomicU32]` slice"]
///
/// This is safe because the mutable reference guarantees that no other threads are
/// concurrently accessing the atomic data.
///
/// # Examples
///
#[doc = "```ignore-wasm"]
#[doc = "use std::sync::atomic::{AtomicU32, Ordering};"]
///
#[doc = "let mut some_ints = [const { AtomicU32::new(0) }; 10];"]
///
#[doc =
"let view: &mut [u32] = AtomicU32::get_mut_slice(&mut some_ints);"]
/// assert_eq!(view, [0; 10]);
/// view
/// .iter_mut()
/// .enumerate()
/// .for_each(|(idx, int)| *int = idx as _);
///
/// std::thread::scope(|s| {
/// some_ints
/// .iter()
/// .enumerate()
/// .for_each(|(idx, int)| {
/// s.spawn(move || assert_eq!(int.load(Ordering::Relaxed), idx as _));
/// })
/// });
/// ```
#[inline]
#[stable(feature = "atomic_from_mut", since = "1.98.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
pub const fn get_mut_slice(this: &mut [Self]) -> &mut [u32] {
unsafe { &mut *(this as *mut [Self] as *mut [u32]) }
}
#[doc = "Get atomic access to a `&mut [u32]` slice."]
///
#[doc =
"**Note:** This function is only available on targets where `AtomicU32` has the same alignment as `u32`."]
///
/// # Examples
///
#[doc = "```ignore-wasm"]
#[doc = "use std::sync::atomic::{AtomicU32, Ordering};"]
///
/// let mut some_ints = [0; 10];
#[doc = "let a = &*AtomicU32::from_mut_slice(&mut some_ints);"]
/// std::thread::scope(|s| {
/// for i in 0..a.len() {
/// s.spawn(move || a[i].store(i as _, Ordering::Relaxed));
/// }
/// });
/// for (i, n) in some_ints.into_iter().enumerate() {
/// assert_eq!(i, n as usize);
/// }
/// ```
#[inline]
#[stable(feature = "atomic_from_mut", since = "1.98.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
pub const fn from_mut_slice(v: &mut [u32]) -> &mut [Self] {
let [] = [(); align_of::<Self>() - align_of::<u32>()];
unsafe { &mut *(v as *mut [u32] as *mut [Self]) }
}
/// Consumes the atomic and returns the contained value.
///
/// This is safe because passing `self` by value guarantees that no other threads are
/// concurrently accessing the atomic data.
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::AtomicU32;"]
///
#[doc = "let some_var = AtomicU32::new(5);"]
/// assert_eq!(some_var.into_inner(), 5);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_stable(feature = "const_atomic_into_inner", since =
"1.79.0")]
pub const fn into_inner(self) -> u32 { unsafe { transmute(self) } }
/// Loads a value from the atomic integer.
///
/// `load` takes an [`Ordering`] argument which describes the memory ordering of this operation.
/// Possible values are [`SeqCst`], [`Acquire`] and [`Relaxed`].
///
/// # Panics
///
/// Panics if `order` is [`Release`] or [`AcqRel`].
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU32, Ordering};"]
///
#[doc = "let some_var = AtomicU32::new(5);"]
///
/// assert_eq!(some_var.load(Ordering::Relaxed), 5);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
pub const fn load(&self, order: Ordering) -> u32 {
unsafe { atomic_load::<_, false>(self.as_ptr(), order) }
}
/// Perform a volatile load from the atomic integer.
///
/// `load_volatile` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. Possible values are [`SeqCst`], [`Acquire`] and [`Relaxed`].
///
#[doc =
"Volatile operations are intended to act on I/O memory. As such, they are considered externally\nobservable events (just like syscalls, but less opaque), and are guaranteed to not be elided or\nreordered by the compiler across other externally observable events. With this in mind, there\nare two cases of usage that need to be distinguished:\n\n- When a volatile operation is used for memory inside an [allocation], it behaves exactly\n like [`load`][Self::load], except for the additional guarantee that it won\'t be elided or\n reordered across other externally observable events (see above). This implies that the\n operation will actually access memory and not e.g. be lowered to reusing data from a\n previous load. Other than that, all the usual rules for memory accesses apply (including\n provenance).\n\n- Volatile operations, however, may also be used to access memory that is _outside_ of any Rust\n allocation. In this use-case, the pointer does *not* have to be [valid] for reads. This is\n typically used for CPU and peripheral registers that must be accessed via an I/O memory mapping,\n most commonly at fixed addresses reserved by the hardware. These often have special semantics\n associated to their manipulation, and cannot be used as general purpose memory. Here, any address\n value is possible, including 0 and [`usize::MAX`], so long as the semantics of such a read are\n well-defined by the target hardware. The provenance of the pointer is irrelevant, and it can be\n created with [`without_provenance`][crate::ptr::without_provenance]. The access is allowed to\n trap, which must immediately abort the process. It can also cause other side-effects, but those\n must not affect Rust-allocated memory in any way.\n\nIn both cases, the access is also considered atomic with the given `order`. This allows\nsynchronization with other threads or devices that share memory with this program.\n\nWhen invoked during const evaluation, this behaves like a regular atomic load. In\nparticular, such reads must always follow the first of the two cases above.\n\n[allocation]: crate::ptr#allocated-object\n"]
///
/// # Safety
///
/// Behavior is undefined if any of the following conditions are violated:
///
/// * `self` must be [valid] for reads, or `self` must point to memory
/// outside of all Rust allocations and reading from that memory must:
/// - not trap, and
/// - not cause any memory inside a Rust allocation to be modified.
///
/// * `self` must be aligned to
#[doc = " `align_of::<AtomicU32>()`"]
#[doc =
" (note that on some platforms this can be bigger than `align_of::<u32>()`)."]
///
/// * Reading from `self` must produce a properly initialized value of the underlying
/// integer type.
///
/// [valid]: core::ptr#safety
///
/// # Panics
///
/// Panics if `order` is [`Release`] or [`AcqRel`].
#[inline]
#[unstable(feature = "atomic_volatile", issue = "158947")]
#[rustc_const_unstable(feature = "atomic_volatile", issue = "158947")]
pub const unsafe fn load_volatile(self: *const Self, order: Ordering)
-> u32 {
unsafe { atomic_load::<_, true>(self.cast::<u32>(), order) }
}
/// Stores a value into the atomic integer.
///
/// `store` takes an [`Ordering`] argument which describes the memory ordering of this operation.
/// Possible values are [`SeqCst`], [`Release`] and [`Relaxed`].
///
/// # Panics
///
/// Panics if `order` is [`Acquire`] or [`AcqRel`].
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU32, Ordering};"]
///
#[doc = "let some_var = AtomicU32::new(5);"]
///
/// some_var.store(10, Ordering::Relaxed);
/// assert_eq!(some_var.load(Ordering::Relaxed), 10);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn store(&self, val: u32, order: Ordering) {
unsafe { atomic_store::<_, false>(self.as_ptr(), val, order); }
}
/// Performs a volatile store into the atomic integer.
///
/// `store_volatile` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. Possible values are [`SeqCst`], [`Release`] and [`Relaxed`].
///
#[doc =
"Volatile operations are intended to act on I/O memory. As such, they are considered externally\nobservable events (just like syscalls), and are guaranteed to not be elided or reordered by the\ncompiler across other externally observable events. With this in mind, there are two cases of\nusage that need to be distinguished:\n\n- When a volatile operation is used for memory inside an [allocation], it behaves exactly like\n [`store`][Self::store], except for the additional guarantee that it won\'t be elided or reordered\n across other externally observable events (see above). This implies that the operation will\n actually access memory and not e.g. be lowered to a register access. Other than that, all the\n usual rules for memory accesses apply (including provenance).\n\n- Volatile operations, however, may also be used to access memory that is _outside_ of any Rust\n allocation. In this use-case, the pointer does *not* have to be [valid] for writes. This is\n typically used for CPU and peripheral registers that must be accessed via an I/O memory mapping,\n most commonly at fixed addresses reserved by the hardware. These often have special semantics\n associated to their manipulation, and cannot be used as general purpose memory. Here, any address\n value is possible, including 0 and [`usize::MAX`], so long as the semantics of such a write are\n well-defined by the target hardware. The provenance of the pointer is irrelevant, and it can be\n created with [`without_provenance_mut`][crate::ptr::without_provenance_mut]. The access is allowed\n to trap, which must immediately abort the process. It can also cause other side-effects, but those\n must not affect Rust-allocated memory in any way.\n\nIn both cases, the access is also considered atomic with the given `order`. This allows\nsynchronization with other threads or devices that share memory with this program.\n\nWhen invoked during const evaluation, this behaves like a regular atomic store. In\nparticular, such reads must always follow the first of the two cases above.\n\n[allocation]: crate::ptr#allocated-object\n"]
///
/// # Safety
///
/// Behavior is undefined if any of the following conditions are violated:
///
/// * `self` must be either [valid] for writes, or `self` must point to memory
/// outside of all Rust allocations and writing to that memory must:
/// - not trap, and
/// - not cause any memory inside a Rust allocation to be modified.
///
/// * `self` must be aligned to
#[doc = " `align_of::<AtomicU32>()`"]
#[doc =
" (note that on some platforms this can be bigger than `align_of::<u32>()`)."]
///
/// [valid]: core::ptr#safety
///
/// # Panics
///
/// Panics if `order` is [`Acquire`] or [`AcqRel`].
#[inline]
#[unstable(feature = "atomic_volatile", issue = "158947")]
#[rustc_const_unstable(feature = "atomic_volatile", issue = "158947")]
#[rustc_should_not_be_called_on_const_items]
pub const unsafe fn store_volatile(self: *const Self, val: u32,
order: Ordering) {
unsafe {
atomic_store::<_,
true>(self.cast::<u32>().cast_mut(), val, order);
}
}
/// Stores a value into the atomic integer, returning the previous value.
///
/// `swap` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`u32`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU32, Ordering};"]
///
#[doc = "let some_var = AtomicU32::new(5);"]
///
/// assert_eq!(some_var.swap(10, Ordering::Relaxed), 5);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn swap(&self, val: u32, order: Ordering) -> u32 {
unsafe { atomic_swap(self.as_ptr(), val, order) }
}
/// Stores a value into the atomic integer if the current value is the same as
/// the `current` value.
///
/// The return value is always the previous value. If it is equal to `current`, then the
/// value was updated.
///
/// `compare_and_swap` also takes an [`Ordering`] argument which describes the memory
/// ordering of this operation. Notice that even when using [`AcqRel`], the operation
/// might fail and hence just perform an `Acquire` load, but not have `Release` semantics.
/// Using [`Acquire`] makes the store part of this operation [`Relaxed`] if it
/// happens, and using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`u32`]."]
///
/// # Migrating to `compare_exchange` and `compare_exchange_weak`
///
/// `compare_and_swap` is equivalent to `compare_exchange` with the following mapping for
/// memory orderings:
///
/// Original | Success | Failure
/// -------- | ------- | -------
/// Relaxed | Relaxed | Relaxed
/// Acquire | Acquire | Acquire
/// Release | Release | Relaxed
/// AcqRel | AcqRel | Acquire
/// SeqCst | SeqCst | SeqCst
///
/// `compare_and_swap` and `compare_exchange` also differ in their return type. You can use
/// `compare_exchange(...).unwrap_or_else(|x| x)` to recover the behavior of `compare_and_swap`,
/// but in most cases it is more idiomatic to check whether the return value is `Ok` or `Err`
/// rather than to infer success vs failure based on the value that was read.
///
/// During migration, consider whether it makes sense to use `compare_exchange_weak` instead.
/// `compare_exchange_weak` is allowed to fail spuriously even when the comparison succeeds,
/// which allows the compiler to generate better assembly code when the compare and swap
/// is used in a loop.
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU32, Ordering};"]
///
#[doc = "let some_var = AtomicU32::new(5);"]
///
/// assert_eq!(some_var.compare_and_swap(5, 10, Ordering::Relaxed), 5);
/// assert_eq!(some_var.load(Ordering::Relaxed), 10);
///
/// assert_eq!(some_var.compare_and_swap(6, 12, Ordering::Relaxed), 10);
/// assert_eq!(some_var.load(Ordering::Relaxed), 10);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[deprecated(since = "1.50.0", note =
"Use `compare_exchange` or `compare_exchange_weak` instead")]
#[rustc_should_not_be_called_on_const_items]
pub const fn compare_and_swap(&self, current: u32, new: u32,
order: Ordering) -> u32 {
match self.compare_exchange(current, new, order,
strongest_failure_ordering(order)) {
Ok(x) => x,
Err(x) => x,
}
}
/// Stores a value into the atomic integer if the current value is the same as
/// the `current` value.
///
/// The return value is a result indicating whether the new value was written and
/// containing the previous value. On success this value is guaranteed to be equal to
/// `current`.
///
/// `compare_exchange` takes two [`Ordering`] arguments to describe the memory
/// ordering of this operation. `success` describes the required ordering for the
/// read-modify-write operation that takes place if the comparison with `current` succeeds.
/// `failure` describes the required ordering for the load operation that takes place when
/// the comparison fails. Using [`Acquire`] as success ordering makes the store part
/// of this operation [`Relaxed`], and using [`Release`] makes the successful load
/// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`u32`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU32, Ordering};"]
///
#[doc = "let some_var = AtomicU32::new(5);"]
///
/// assert_eq!(some_var.compare_exchange(5, 10,
/// Ordering::Acquire,
/// Ordering::Relaxed),
/// Ok(5));
/// assert_eq!(some_var.load(Ordering::Relaxed), 10);
///
/// assert_eq!(some_var.compare_exchange(6, 12,
/// Ordering::SeqCst,
/// Ordering::Acquire),
/// Err(10));
/// assert_eq!(some_var.load(Ordering::Relaxed), 10);
/// ```
///
/// # Considerations
///
/// `compare_exchange` is a [compare-and-swap operation] and thus exhibits the usual downsides
/// of CAS operations. In particular, a load of the value followed by a successful
/// `compare_exchange` with the previous load *does not ensure* that other threads have not
/// changed the value in the interim! This is usually important when the *equality* check in
/// the `compare_exchange` is being used to check the *identity* of a value, but equality
/// does not necessarily imply identity. This is a particularly common case for pointers, as
/// a pointer holding the same address does not imply that the same object exists at that
/// address! In this case, `compare_exchange` can lead to the [ABA problem].
///
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn compare_exchange(&self, current: u32, new: u32,
success: Ordering, failure: Ordering) -> Result<u32, u32> {
unsafe {
atomic_compare_exchange(self.as_ptr(), current, new, success,
failure)
}
}
/// Stores a value into the atomic integer if the current value is the same as
/// the `current` value.
///
#[doc = "Unlike [`AtomicU32::compare_exchange`],"]
/// this function is allowed to spuriously fail even
/// when the comparison succeeds, which can result in more efficient code on some
/// platforms. The return value is a result indicating whether the new value was
/// written and containing the previous value.
///
/// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory
/// ordering of this operation. `success` describes the required ordering for the
/// read-modify-write operation that takes place if the comparison with `current` succeeds.
/// `failure` describes the required ordering for the load operation that takes place when
/// the comparison fails. Using [`Acquire`] as success ordering makes the store part
/// of this operation [`Relaxed`], and using [`Release`] makes the successful load
/// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`u32`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU32, Ordering};"]
///
#[doc = "let val = AtomicU32::new(4);"]
///
/// let mut old = val.load(Ordering::Relaxed);
/// loop {
/// let new = old * 2;
/// match val.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) {
/// Ok(_) => break,
/// Err(x) => old = x,
/// }
/// }
/// ```
///
/// # Considerations
///
/// `compare_exchange` is a [compare-and-swap operation] and thus exhibits the usual downsides
/// of CAS operations. In particular, a load of the value followed by a successful
/// `compare_exchange` with the previous load *does not ensure* that other threads have not
/// changed the value in the interim. This is usually important when the *equality* check in
/// the `compare_exchange` is being used to check the *identity* of a value, but equality
/// does not necessarily imply identity. This is a particularly common case for pointers, as
/// a pointer holding the same address does not imply that the same object exists at that
/// address! In this case, `compare_exchange` can lead to the [ABA problem].
///
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn compare_exchange_weak(&self, current: u32, new: u32,
success: Ordering, failure: Ordering) -> Result<u32, u32> {
unsafe {
atomic_compare_exchange_weak(self.as_ptr(), current, new, success,
failure)
}
}
/// Adds to the current value, returning the previous value.
///
/// This operation wraps around on overflow.
///
/// `fetch_add` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`u32`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU32, Ordering};"]
///
#[doc = "let foo = AtomicU32::new(0);"]
/// assert_eq!(foo.fetch_add(10, Ordering::SeqCst), 0);
/// assert_eq!(foo.load(Ordering::SeqCst), 10);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_add(&self, val: u32, order: Ordering) -> u32 {
unsafe { atomic_add(self.as_ptr(), val, order) }
}
/// Subtracts from the current value, returning the previous value.
///
/// This operation wraps around on overflow.
///
/// `fetch_sub` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`u32`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU32, Ordering};"]
///
#[doc = "let foo = AtomicU32::new(20);"]
/// assert_eq!(foo.fetch_sub(10, Ordering::SeqCst), 20);
/// assert_eq!(foo.load(Ordering::SeqCst), 10);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_sub(&self, val: u32, order: Ordering) -> u32 {
unsafe { atomic_sub(self.as_ptr(), val, order) }
}
/// Bitwise "and" with the current value.
///
/// Performs a bitwise "and" operation on the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_and` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`u32`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU32, Ordering};"]
///
#[doc = "let foo = AtomicU32::new(0b101101);"]
/// assert_eq!(foo.fetch_and(0b110011, Ordering::SeqCst), 0b101101);
/// assert_eq!(foo.load(Ordering::SeqCst), 0b100001);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_and(&self, val: u32, order: Ordering) -> u32 {
unsafe { atomic_and(self.as_ptr(), val, order) }
}
/// Bitwise "nand" with the current value.
///
/// Performs a bitwise "nand" operation on the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_nand` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`u32`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU32, Ordering};"]
///
#[doc = "let foo = AtomicU32::new(0x13);"]
/// assert_eq!(foo.fetch_nand(0x31, Ordering::SeqCst), 0x13);
/// assert_eq!(foo.load(Ordering::SeqCst), !(0x13 & 0x31));
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_nand(&self, val: u32, order: Ordering) -> u32 {
unsafe { atomic_nand(self.as_ptr(), val, order) }
}
/// Bitwise "or" with the current value.
///
/// Performs a bitwise "or" operation on the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_or` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`u32`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU32, Ordering};"]
///
#[doc = "let foo = AtomicU32::new(0b101101);"]
/// assert_eq!(foo.fetch_or(0b110011, Ordering::SeqCst), 0b101101);
/// assert_eq!(foo.load(Ordering::SeqCst), 0b111111);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_or(&self, val: u32, order: Ordering) -> u32 {
unsafe { atomic_or(self.as_ptr(), val, order) }
}
/// Bitwise "xor" with the current value.
///
/// Performs a bitwise "xor" operation on the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_xor` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`u32`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU32, Ordering};"]
///
#[doc = "let foo = AtomicU32::new(0b101101);"]
/// assert_eq!(foo.fetch_xor(0b110011, Ordering::SeqCst), 0b101101);
/// assert_eq!(foo.load(Ordering::SeqCst), 0b011110);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_xor(&self, val: u32, order: Ordering) -> u32 {
unsafe { atomic_xor(self.as_ptr(), val, order) }
}
/// An alias for
#[doc = "[`AtomicU32::try_update`]"]
/// .
#[inline]
#[stable(feature = "no_more_cas", since = "1.45.0")]
#[rustc_should_not_be_called_on_const_items]
#[deprecated(since = "1.99.0", note =
"renamed to `try_update` for consistency", suggestion = "try_update")]
pub fn fetch_update<F>(&self, set_order: Ordering, fetch_order: Ordering,
f: F) -> Result<u32, u32> where F: FnMut(u32) -> Option<u32> {
self.try_update(set_order, fetch_order, f)
}
/// Fetches the value, and applies a function to it that returns an optional
/// new value. Returns a `Result` of `Ok(previous_value)` if the function returned `Some(_)`, else
/// `Err(previous_value)`.
///
#[doc = "See also: [`update`](`AtomicU32::update`)."]
///
/// Note: This may call the function multiple times if the value has been changed from other threads in
/// the meantime, as long as the function returns `Some(_)`, but the function will have been applied
/// only once to the stored value.
///
/// `try_update` takes two [`Ordering`] arguments to describe the memory ordering of this operation.
/// The first describes the required ordering for when the operation finally succeeds while the second
/// describes the required ordering for loads. These correspond to the success and failure orderings of
#[doc = "[`AtomicU32::compare_exchange`]"]
/// respectively.
///
/// Using [`Acquire`] as success ordering makes the store part
/// of this operation [`Relaxed`], and using [`Release`] makes the final successful load
/// [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`u32`]."]
///
/// # Considerations
///
/// This method is not magic; it is not provided by the hardware, and does not act like a
/// critical section or mutex.
///
/// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
/// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem]
/// if this atomic integer is an index or more generally if knowledge of only the *bitwise value*
/// of the atomic is not in and of itself sufficient to ensure any required preconditions.
///
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
///
/// # Examples
///
#[doc = "```rust"]
#[doc = "use std::sync::atomic::{AtomicU32, Ordering};"]
///
#[doc = "let x = AtomicU32::new(7);"]
/// assert_eq!(x.try_update(Ordering::SeqCst, Ordering::SeqCst, |_| None), Err(7));
/// assert_eq!(x.try_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(x + 1)), Ok(7));
/// assert_eq!(x.try_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(x + 1)), Ok(8));
/// assert_eq!(x.load(Ordering::SeqCst), 9);
/// ```
#[inline]
#[stable(feature = "atomic_try_update", since = "1.95.0")]
#[rustc_should_not_be_called_on_const_items]
pub fn try_update(&self, set_order: Ordering, fetch_order: Ordering,
mut f: impl FnMut(u32) -> Option<u32>) -> Result<u32, u32> {
let mut prev = self.load(fetch_order);
while let Some(next) = f(prev) {
match self.compare_exchange_weak(prev, next, set_order,
fetch_order) {
x @ Ok(_) => return x,
Err(next_prev) => prev = next_prev,
}
}
Err(prev)
}
/// Fetches the value, and applies a function to it that returns a new value.
/// The new value is stored and the old value is returned.
///
#[doc = "See also: [`try_update`](`AtomicU32::try_update`)."]
///
/// Note: This may call the function multiple times if the value has been changed from other threads in
/// the meantime, but the function will have been applied only once to the stored value.
///
/// `update` takes two [`Ordering`] arguments to describe the memory ordering of this operation.
/// The first describes the required ordering for when the operation finally succeeds while the second
/// describes the required ordering for loads. These correspond to the success and failure orderings of
#[doc = "[`AtomicU32::compare_exchange`]"]
/// respectively.
///
/// Using [`Acquire`] as success ordering makes the store part
/// of this operation [`Relaxed`], and using [`Release`] makes the final successful load
/// [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`u32`]."]
///
/// # Considerations
///
/// [CAS operation]: https://en.wikipedia.org/wiki/Compare-and-swap
/// This method is not magic; it is not provided by the hardware, and does not act like a
/// critical section or mutex.
///
/// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
/// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem]
/// if this atomic integer is an index or more generally if knowledge of only the *bitwise value*
/// of the atomic is not in and of itself sufficient to ensure any required preconditions.
///
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
///
/// # Examples
///
#[doc = "```rust"]
#[doc = "use std::sync::atomic::{AtomicU32, Ordering};"]
///
#[doc = "let x = AtomicU32::new(7);"]
/// assert_eq!(x.update(Ordering::SeqCst, Ordering::SeqCst, |x| x + 1), 7);
/// assert_eq!(x.update(Ordering::SeqCst, Ordering::SeqCst, |x| x + 1), 8);
/// assert_eq!(x.load(Ordering::SeqCst), 9);
/// ```
#[inline]
#[stable(feature = "atomic_try_update", since = "1.95.0")]
#[rustc_should_not_be_called_on_const_items]
pub fn update(&self, set_order: Ordering, fetch_order: Ordering,
mut f: impl FnMut(u32) -> u32) -> u32 {
let mut prev = self.load(fetch_order);
loop {
match self.compare_exchange_weak(prev, f(prev), set_order,
fetch_order) {
Ok(x) => break x,
Err(next_prev) => prev = next_prev,
}
}
}
/// Maximum with the current value.
///
/// Finds the maximum of the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_max` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`u32`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU32, Ordering};"]
///
#[doc = "let foo = AtomicU32::new(23);"]
/// assert_eq!(foo.fetch_max(42, Ordering::SeqCst), 23);
/// assert_eq!(foo.load(Ordering::SeqCst), 42);
/// ```
///
/// If you want to obtain the maximum value in one step, you can use the following:
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU32, Ordering};"]
///
#[doc = "let foo = AtomicU32::new(23);"]
/// let bar = 42;
/// let max_foo = foo.fetch_max(bar, Ordering::SeqCst).max(bar);
/// assert!(max_foo == 42);
/// ```
#[inline]
#[stable(feature = "atomic_min_max", since = "1.45.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_max(&self, val: u32, order: Ordering) -> u32 {
unsafe { atomic_umax(self.as_ptr(), val, order) }
}
/// Minimum with the current value.
///
/// Finds the minimum of the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_min` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`u32`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU32, Ordering};"]
///
#[doc = "let foo = AtomicU32::new(23);"]
/// assert_eq!(foo.fetch_min(42, Ordering::Relaxed), 23);
/// assert_eq!(foo.load(Ordering::Relaxed), 23);
/// assert_eq!(foo.fetch_min(22, Ordering::Relaxed), 23);
/// assert_eq!(foo.load(Ordering::Relaxed), 22);
/// ```
///
/// If you want to obtain the minimum value in one step, you can use the following:
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU32, Ordering};"]
///
#[doc = "let foo = AtomicU32::new(23);"]
/// let bar = 12;
/// let min_foo = foo.fetch_min(bar, Ordering::SeqCst).min(bar);
/// assert_eq!(min_foo, 12);
/// ```
#[inline]
#[stable(feature = "atomic_min_max", since = "1.45.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_min(&self, val: u32, order: Ordering) -> u32 {
unsafe { atomic_umin(self.as_ptr(), val, order) }
}
/// Returns a mutable pointer to the underlying integer.
///
/// Doing non-atomic reads and writes on the resulting integer can be a data race.
/// This method is mostly useful for FFI, where the function signature may use
#[doc = "`*mut u32` instead of `&AtomicU32`."]
///
/// Returning an `*mut` pointer from a shared reference to this atomic is safe because the
/// atomic types work with interior mutability. All modifications of an atomic change the value
/// through a shared reference, and can do so safely as long as they use atomic operations. Any
/// use of the returned raw pointer requires an `unsafe` block and still has to uphold the
/// requirements of the [memory model].
///
/// # Examples
///
/// ```ignore (extern-declaration)
/// # fn main() {
#[doc = "use std::sync::atomic::AtomicU32;"]
///
/// extern "C" {
#[doc = " fn my_atomic_op(arg: *mut u32);"]
/// }
///
#[doc = "let atomic = AtomicU32::new(1);"]
///
/// // SAFETY: Safe as long as `my_atomic_op` is atomic.
/// unsafe {
/// my_atomic_op(atomic.as_ptr());
/// }
/// # }
/// ```
///
/// [memory model]: self#memory-model-for-atomic-accesses
#[inline]
#[stable(feature = "atomic_as_ptr", since = "1.70.0")]
#[rustc_const_stable(feature = "atomic_as_ptr", since = "1.70.0")]
#[rustc_never_returns_null_ptr]
pub const fn as_ptr(&self) -> *mut u32 { self.v.get().cast() }
}atomic_int! {
4117 target_has_atomic_load_store = "32",
4118 target_has_atomic = "32",
4119 target_has_atomic_primitive_alignment = "32",
4120 stable(feature = "integer_atomics_stable", since = "1.34.0"),
4121 stable(feature = "integer_atomics_stable", since = "1.34.0"),
4122 stable(feature = "integer_atomics_stable", since = "1.34.0"),
4123 stable(feature = "integer_atomics_stable", since = "1.34.0"),
4124 stable(feature = "integer_atomics_stable", since = "1.34.0"),
4125 stable(feature = "integer_atomics_stable", since = "1.34.0"),
4126 rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
4127 rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"),
4128"u32",
4129"",
4130 atomic_umin, atomic_umax,
41314,
4132 u32 AtomicU324133}4134#[cfg(target_has_atomic_load_store = "64")]
4135/// An integer type which can be safely shared between threads.
///
/// This type has the same
#[doc = "size and bit validity"]
/// as the underlying integer type, [`
#[doc = "i64"]
/// `].
#[doc =
"However, the alignment of this type is always equal to its size, even on targets where [`i64`] has a lesser alignment."]
///
/// For more about the differences between atomic types and
/// non-atomic types as well as information about the portability of
/// this type, please see the [module-level documentation].
///
/// **Note:** This type is only available on platforms that support
/// atomic loads and stores of [`
#[doc = "i64"]
/// `].
///
/// [module-level documentation]: crate::sync::atomic
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
pub type AtomicI64 = Atomic<i64>;
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
impl Default for AtomicI64 {
#[inline]
fn default() -> Self { Self::new(Default::default()) }
}
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
const impl From<i64> for AtomicI64 {
#[doc = "Converts an `i64` into an `AtomicI64`."]
#[inline]
fn from(v: i64) -> Self { Self::new(v) }
}
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
impl fmt::Debug for AtomicI64 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.load(Ordering::Relaxed), f)
}
}
impl AtomicI64 {
/// Creates a new atomic integer.
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::AtomicI64;"]
///
#[doc = "let atomic_forty_two = AtomicI64::new(42);"]
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0")]
#[must_use]
pub const fn new(v: i64) -> Self { unsafe { transmute(v) } }
/// Creates a new reference to an atomic integer from a pointer.
///
/// # Examples
///
#[doc = "```rust"]
#[doc = "use std::sync::atomic::{self, AtomicI64};"]
///
/// // Get a pointer to an allocated value
#[doc = "let ptr: *mut i64 = Box::into_raw(Box::new(0));"]
///
#[doc = "assert!(ptr.cast::<AtomicI64>().is_aligned());"]
///
/// {
/// // Create an atomic view of the allocated value
#[doc = " let atomic = unsafe {AtomicI64::from_ptr(ptr) };"]
///
/// // Use `atomic` for atomic operations, possibly share it with other threads
/// atomic.store(1, atomic::Ordering::Relaxed);
/// }
///
/// // It's ok to non-atomically access the value behind `ptr`,
/// // since the reference to the atomic ended its lifetime in the block above
/// assert_eq!(unsafe { *ptr }, 1);
///
/// // Deallocate the value
/// unsafe { drop(Box::from_raw(ptr)) }
/// ```
///
/// # Safety
///
/// * `ptr` must be aligned to
#[doc = " `align_of::<AtomicI64>()`"]
#[doc =
" (note that on some platforms this can be bigger than `align_of::<i64>()`)."]
/// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`.
/// * You must adhere to the [Memory model for atomic accesses]. In particular, it is not
/// allowed to mix conflicting atomic and non-atomic accesses, or atomic accesses of different
/// sizes, without synchronization.
///
/// [valid]: crate::ptr#safety
/// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses
#[inline]
#[stable(feature = "atomic_from_ptr", since = "1.75.0")]
#[rustc_const_stable(feature = "const_atomic_from_ptr", since = "1.84.0")]
pub const unsafe fn from_ptr<'a>(ptr: *mut i64) -> &'a AtomicI64 {
unsafe { &*ptr.cast() }
}
/// Creates a new pointer to an atomic integer from a pointer.
///
/// This is useful if you want to do volatile atomic accesses, and thus avoid creating
/// a reference to the destination.
#[inline]
#[unstable(feature = "atomic_volatile", issue = "158947")]
pub const fn from_ptr_raw(ptr: *mut i64) -> *const AtomicI64 {
ptr.cast_const().cast()
}
/// Returns a mutable reference to the underlying integer.
///
/// This is safe because the mutable reference guarantees that no other threads are
/// concurrently accessing the atomic data.
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI64, Ordering};"]
///
#[doc = "let mut some_var = AtomicI64::new(10);"]
/// assert_eq!(*some_var.get_mut(), 10);
/// *some_var.get_mut() = 5;
/// assert_eq!(some_var.load(Ordering::SeqCst), 5);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
pub const fn get_mut(&mut self) -> &mut i64 {
unsafe { &mut *self.as_ptr() }
}
#[doc = "Get atomic access to a `&mut i64`."]
///
#[doc =
"**Note:** This function is only available on targets where `AtomicI64` has the same alignment as `i64`."]
///
/// # Examples
///
#[doc = "```rust"]
#[doc = "use std::sync::atomic::{AtomicI64, Ordering};"]
///
/// let mut some_int = 123;
#[doc = "let a = AtomicI64::from_mut(&mut some_int);"]
/// a.store(100, Ordering::Relaxed);
/// assert_eq!(some_int, 100);
/// ```
///
#[inline]
#[stable(feature = "atomic_from_mut", since = "1.98.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
pub const fn from_mut(v: &mut i64) -> &mut Self {
let [] = [(); align_of::<Self>() - align_of::<i64>()];
unsafe { &mut *(v as *mut i64 as *mut Self) }
}
#[doc = "Get non-atomic access to a `&mut [AtomicI64]` slice"]
///
/// This is safe because the mutable reference guarantees that no other threads are
/// concurrently accessing the atomic data.
///
/// # Examples
///
#[doc = "```ignore-wasm"]
#[doc = "use std::sync::atomic::{AtomicI64, Ordering};"]
///
#[doc = "let mut some_ints = [const { AtomicI64::new(0) }; 10];"]
///
#[doc =
"let view: &mut [i64] = AtomicI64::get_mut_slice(&mut some_ints);"]
/// assert_eq!(view, [0; 10]);
/// view
/// .iter_mut()
/// .enumerate()
/// .for_each(|(idx, int)| *int = idx as _);
///
/// std::thread::scope(|s| {
/// some_ints
/// .iter()
/// .enumerate()
/// .for_each(|(idx, int)| {
/// s.spawn(move || assert_eq!(int.load(Ordering::Relaxed), idx as _));
/// })
/// });
/// ```
#[inline]
#[stable(feature = "atomic_from_mut", since = "1.98.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
pub const fn get_mut_slice(this: &mut [Self]) -> &mut [i64] {
unsafe { &mut *(this as *mut [Self] as *mut [i64]) }
}
#[doc = "Get atomic access to a `&mut [i64]` slice."]
///
#[doc =
"**Note:** This function is only available on targets where `AtomicI64` has the same alignment as `i64`."]
///
/// # Examples
///
#[doc = "```ignore-wasm"]
#[doc = "use std::sync::atomic::{AtomicI64, Ordering};"]
///
/// let mut some_ints = [0; 10];
#[doc = "let a = &*AtomicI64::from_mut_slice(&mut some_ints);"]
/// std::thread::scope(|s| {
/// for i in 0..a.len() {
/// s.spawn(move || a[i].store(i as _, Ordering::Relaxed));
/// }
/// });
/// for (i, n) in some_ints.into_iter().enumerate() {
/// assert_eq!(i, n as usize);
/// }
/// ```
#[inline]
#[stable(feature = "atomic_from_mut", since = "1.98.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
pub const fn from_mut_slice(v: &mut [i64]) -> &mut [Self] {
let [] = [(); align_of::<Self>() - align_of::<i64>()];
unsafe { &mut *(v as *mut [i64] as *mut [Self]) }
}
/// Consumes the atomic and returns the contained value.
///
/// This is safe because passing `self` by value guarantees that no other threads are
/// concurrently accessing the atomic data.
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::AtomicI64;"]
///
#[doc = "let some_var = AtomicI64::new(5);"]
/// assert_eq!(some_var.into_inner(), 5);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_stable(feature = "const_atomic_into_inner", since =
"1.79.0")]
pub const fn into_inner(self) -> i64 { unsafe { transmute(self) } }
/// Loads a value from the atomic integer.
///
/// `load` takes an [`Ordering`] argument which describes the memory ordering of this operation.
/// Possible values are [`SeqCst`], [`Acquire`] and [`Relaxed`].
///
/// # Panics
///
/// Panics if `order` is [`Release`] or [`AcqRel`].
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI64, Ordering};"]
///
#[doc = "let some_var = AtomicI64::new(5);"]
///
/// assert_eq!(some_var.load(Ordering::Relaxed), 5);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
pub const fn load(&self, order: Ordering) -> i64 {
unsafe { atomic_load::<_, false>(self.as_ptr(), order) }
}
/// Perform a volatile load from the atomic integer.
///
/// `load_volatile` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. Possible values are [`SeqCst`], [`Acquire`] and [`Relaxed`].
///
#[doc =
"Volatile operations are intended to act on I/O memory. As such, they are considered externally\nobservable events (just like syscalls, but less opaque), and are guaranteed to not be elided or\nreordered by the compiler across other externally observable events. With this in mind, there\nare two cases of usage that need to be distinguished:\n\n- When a volatile operation is used for memory inside an [allocation], it behaves exactly\n like [`load`][Self::load], except for the additional guarantee that it won\'t be elided or\n reordered across other externally observable events (see above). This implies that the\n operation will actually access memory and not e.g. be lowered to reusing data from a\n previous load. Other than that, all the usual rules for memory accesses apply (including\n provenance).\n\n- Volatile operations, however, may also be used to access memory that is _outside_ of any Rust\n allocation. In this use-case, the pointer does *not* have to be [valid] for reads. This is\n typically used for CPU and peripheral registers that must be accessed via an I/O memory mapping,\n most commonly at fixed addresses reserved by the hardware. These often have special semantics\n associated to their manipulation, and cannot be used as general purpose memory. Here, any address\n value is possible, including 0 and [`usize::MAX`], so long as the semantics of such a read are\n well-defined by the target hardware. The provenance of the pointer is irrelevant, and it can be\n created with [`without_provenance`][crate::ptr::without_provenance]. The access is allowed to\n trap, which must immediately abort the process. It can also cause other side-effects, but those\n must not affect Rust-allocated memory in any way.\n\nIn both cases, the access is also considered atomic with the given `order`. This allows\nsynchronization with other threads or devices that share memory with this program.\n\nWhen invoked during const evaluation, this behaves like a regular atomic load. In\nparticular, such reads must always follow the first of the two cases above.\n\n[allocation]: crate::ptr#allocated-object\n"]
///
/// # Safety
///
/// Behavior is undefined if any of the following conditions are violated:
///
/// * `self` must be [valid] for reads, or `self` must point to memory
/// outside of all Rust allocations and reading from that memory must:
/// - not trap, and
/// - not cause any memory inside a Rust allocation to be modified.
///
/// * `self` must be aligned to
#[doc = " `align_of::<AtomicI64>()`"]
#[doc =
" (note that on some platforms this can be bigger than `align_of::<i64>()`)."]
///
/// * Reading from `self` must produce a properly initialized value of the underlying
/// integer type.
///
/// [valid]: core::ptr#safety
///
/// # Panics
///
/// Panics if `order` is [`Release`] or [`AcqRel`].
#[inline]
#[unstable(feature = "atomic_volatile", issue = "158947")]
#[rustc_const_unstable(feature = "atomic_volatile", issue = "158947")]
pub const unsafe fn load_volatile(self: *const Self, order: Ordering)
-> i64 {
unsafe { atomic_load::<_, true>(self.cast::<i64>(), order) }
}
/// Stores a value into the atomic integer.
///
/// `store` takes an [`Ordering`] argument which describes the memory ordering of this operation.
/// Possible values are [`SeqCst`], [`Release`] and [`Relaxed`].
///
/// # Panics
///
/// Panics if `order` is [`Acquire`] or [`AcqRel`].
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI64, Ordering};"]
///
#[doc = "let some_var = AtomicI64::new(5);"]
///
/// some_var.store(10, Ordering::Relaxed);
/// assert_eq!(some_var.load(Ordering::Relaxed), 10);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn store(&self, val: i64, order: Ordering) {
unsafe { atomic_store::<_, false>(self.as_ptr(), val, order); }
}
/// Performs a volatile store into the atomic integer.
///
/// `store_volatile` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. Possible values are [`SeqCst`], [`Release`] and [`Relaxed`].
///
#[doc =
"Volatile operations are intended to act on I/O memory. As such, they are considered externally\nobservable events (just like syscalls), and are guaranteed to not be elided or reordered by the\ncompiler across other externally observable events. With this in mind, there are two cases of\nusage that need to be distinguished:\n\n- When a volatile operation is used for memory inside an [allocation], it behaves exactly like\n [`store`][Self::store], except for the additional guarantee that it won\'t be elided or reordered\n across other externally observable events (see above). This implies that the operation will\n actually access memory and not e.g. be lowered to a register access. Other than that, all the\n usual rules for memory accesses apply (including provenance).\n\n- Volatile operations, however, may also be used to access memory that is _outside_ of any Rust\n allocation. In this use-case, the pointer does *not* have to be [valid] for writes. This is\n typically used for CPU and peripheral registers that must be accessed via an I/O memory mapping,\n most commonly at fixed addresses reserved by the hardware. These often have special semantics\n associated to their manipulation, and cannot be used as general purpose memory. Here, any address\n value is possible, including 0 and [`usize::MAX`], so long as the semantics of such a write are\n well-defined by the target hardware. The provenance of the pointer is irrelevant, and it can be\n created with [`without_provenance_mut`][crate::ptr::without_provenance_mut]. The access is allowed\n to trap, which must immediately abort the process. It can also cause other side-effects, but those\n must not affect Rust-allocated memory in any way.\n\nIn both cases, the access is also considered atomic with the given `order`. This allows\nsynchronization with other threads or devices that share memory with this program.\n\nWhen invoked during const evaluation, this behaves like a regular atomic store. In\nparticular, such reads must always follow the first of the two cases above.\n\n[allocation]: crate::ptr#allocated-object\n"]
///
/// # Safety
///
/// Behavior is undefined if any of the following conditions are violated:
///
/// * `self` must be either [valid] for writes, or `self` must point to memory
/// outside of all Rust allocations and writing to that memory must:
/// - not trap, and
/// - not cause any memory inside a Rust allocation to be modified.
///
/// * `self` must be aligned to
#[doc = " `align_of::<AtomicI64>()`"]
#[doc =
" (note that on some platforms this can be bigger than `align_of::<i64>()`)."]
///
/// [valid]: core::ptr#safety
///
/// # Panics
///
/// Panics if `order` is [`Acquire`] or [`AcqRel`].
#[inline]
#[unstable(feature = "atomic_volatile", issue = "158947")]
#[rustc_const_unstable(feature = "atomic_volatile", issue = "158947")]
#[rustc_should_not_be_called_on_const_items]
pub const unsafe fn store_volatile(self: *const Self, val: i64,
order: Ordering) {
unsafe {
atomic_store::<_,
true>(self.cast::<i64>().cast_mut(), val, order);
}
}
/// Stores a value into the atomic integer, returning the previous value.
///
/// `swap` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`i64`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI64, Ordering};"]
///
#[doc = "let some_var = AtomicI64::new(5);"]
///
/// assert_eq!(some_var.swap(10, Ordering::Relaxed), 5);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn swap(&self, val: i64, order: Ordering) -> i64 {
unsafe { atomic_swap(self.as_ptr(), val, order) }
}
/// Stores a value into the atomic integer if the current value is the same as
/// the `current` value.
///
/// The return value is always the previous value. If it is equal to `current`, then the
/// value was updated.
///
/// `compare_and_swap` also takes an [`Ordering`] argument which describes the memory
/// ordering of this operation. Notice that even when using [`AcqRel`], the operation
/// might fail and hence just perform an `Acquire` load, but not have `Release` semantics.
/// Using [`Acquire`] makes the store part of this operation [`Relaxed`] if it
/// happens, and using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`i64`]."]
///
/// # Migrating to `compare_exchange` and `compare_exchange_weak`
///
/// `compare_and_swap` is equivalent to `compare_exchange` with the following mapping for
/// memory orderings:
///
/// Original | Success | Failure
/// -------- | ------- | -------
/// Relaxed | Relaxed | Relaxed
/// Acquire | Acquire | Acquire
/// Release | Release | Relaxed
/// AcqRel | AcqRel | Acquire
/// SeqCst | SeqCst | SeqCst
///
/// `compare_and_swap` and `compare_exchange` also differ in their return type. You can use
/// `compare_exchange(...).unwrap_or_else(|x| x)` to recover the behavior of `compare_and_swap`,
/// but in most cases it is more idiomatic to check whether the return value is `Ok` or `Err`
/// rather than to infer success vs failure based on the value that was read.
///
/// During migration, consider whether it makes sense to use `compare_exchange_weak` instead.
/// `compare_exchange_weak` is allowed to fail spuriously even when the comparison succeeds,
/// which allows the compiler to generate better assembly code when the compare and swap
/// is used in a loop.
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI64, Ordering};"]
///
#[doc = "let some_var = AtomicI64::new(5);"]
///
/// assert_eq!(some_var.compare_and_swap(5, 10, Ordering::Relaxed), 5);
/// assert_eq!(some_var.load(Ordering::Relaxed), 10);
///
/// assert_eq!(some_var.compare_and_swap(6, 12, Ordering::Relaxed), 10);
/// assert_eq!(some_var.load(Ordering::Relaxed), 10);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[deprecated(since = "1.50.0", note =
"Use `compare_exchange` or `compare_exchange_weak` instead")]
#[rustc_should_not_be_called_on_const_items]
pub const fn compare_and_swap(&self, current: i64, new: i64,
order: Ordering) -> i64 {
match self.compare_exchange(current, new, order,
strongest_failure_ordering(order)) {
Ok(x) => x,
Err(x) => x,
}
}
/// Stores a value into the atomic integer if the current value is the same as
/// the `current` value.
///
/// The return value is a result indicating whether the new value was written and
/// containing the previous value. On success this value is guaranteed to be equal to
/// `current`.
///
/// `compare_exchange` takes two [`Ordering`] arguments to describe the memory
/// ordering of this operation. `success` describes the required ordering for the
/// read-modify-write operation that takes place if the comparison with `current` succeeds.
/// `failure` describes the required ordering for the load operation that takes place when
/// the comparison fails. Using [`Acquire`] as success ordering makes the store part
/// of this operation [`Relaxed`], and using [`Release`] makes the successful load
/// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`i64`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI64, Ordering};"]
///
#[doc = "let some_var = AtomicI64::new(5);"]
///
/// assert_eq!(some_var.compare_exchange(5, 10,
/// Ordering::Acquire,
/// Ordering::Relaxed),
/// Ok(5));
/// assert_eq!(some_var.load(Ordering::Relaxed), 10);
///
/// assert_eq!(some_var.compare_exchange(6, 12,
/// Ordering::SeqCst,
/// Ordering::Acquire),
/// Err(10));
/// assert_eq!(some_var.load(Ordering::Relaxed), 10);
/// ```
///
/// # Considerations
///
/// `compare_exchange` is a [compare-and-swap operation] and thus exhibits the usual downsides
/// of CAS operations. In particular, a load of the value followed by a successful
/// `compare_exchange` with the previous load *does not ensure* that other threads have not
/// changed the value in the interim! This is usually important when the *equality* check in
/// the `compare_exchange` is being used to check the *identity* of a value, but equality
/// does not necessarily imply identity. This is a particularly common case for pointers, as
/// a pointer holding the same address does not imply that the same object exists at that
/// address! In this case, `compare_exchange` can lead to the [ABA problem].
///
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn compare_exchange(&self, current: i64, new: i64,
success: Ordering, failure: Ordering) -> Result<i64, i64> {
unsafe {
atomic_compare_exchange(self.as_ptr(), current, new, success,
failure)
}
}
/// Stores a value into the atomic integer if the current value is the same as
/// the `current` value.
///
#[doc = "Unlike [`AtomicI64::compare_exchange`],"]
/// this function is allowed to spuriously fail even
/// when the comparison succeeds, which can result in more efficient code on some
/// platforms. The return value is a result indicating whether the new value was
/// written and containing the previous value.
///
/// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory
/// ordering of this operation. `success` describes the required ordering for the
/// read-modify-write operation that takes place if the comparison with `current` succeeds.
/// `failure` describes the required ordering for the load operation that takes place when
/// the comparison fails. Using [`Acquire`] as success ordering makes the store part
/// of this operation [`Relaxed`], and using [`Release`] makes the successful load
/// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`i64`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI64, Ordering};"]
///
#[doc = "let val = AtomicI64::new(4);"]
///
/// let mut old = val.load(Ordering::Relaxed);
/// loop {
/// let new = old * 2;
/// match val.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) {
/// Ok(_) => break,
/// Err(x) => old = x,
/// }
/// }
/// ```
///
/// # Considerations
///
/// `compare_exchange` is a [compare-and-swap operation] and thus exhibits the usual downsides
/// of CAS operations. In particular, a load of the value followed by a successful
/// `compare_exchange` with the previous load *does not ensure* that other threads have not
/// changed the value in the interim. This is usually important when the *equality* check in
/// the `compare_exchange` is being used to check the *identity* of a value, but equality
/// does not necessarily imply identity. This is a particularly common case for pointers, as
/// a pointer holding the same address does not imply that the same object exists at that
/// address! In this case, `compare_exchange` can lead to the [ABA problem].
///
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn compare_exchange_weak(&self, current: i64, new: i64,
success: Ordering, failure: Ordering) -> Result<i64, i64> {
unsafe {
atomic_compare_exchange_weak(self.as_ptr(), current, new, success,
failure)
}
}
/// Adds to the current value, returning the previous value.
///
/// This operation wraps around on overflow.
///
/// `fetch_add` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`i64`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI64, Ordering};"]
///
#[doc = "let foo = AtomicI64::new(0);"]
/// assert_eq!(foo.fetch_add(10, Ordering::SeqCst), 0);
/// assert_eq!(foo.load(Ordering::SeqCst), 10);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_add(&self, val: i64, order: Ordering) -> i64 {
unsafe { atomic_add(self.as_ptr(), val, order) }
}
/// Subtracts from the current value, returning the previous value.
///
/// This operation wraps around on overflow.
///
/// `fetch_sub` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`i64`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI64, Ordering};"]
///
#[doc = "let foo = AtomicI64::new(20);"]
/// assert_eq!(foo.fetch_sub(10, Ordering::SeqCst), 20);
/// assert_eq!(foo.load(Ordering::SeqCst), 10);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_sub(&self, val: i64, order: Ordering) -> i64 {
unsafe { atomic_sub(self.as_ptr(), val, order) }
}
/// Bitwise "and" with the current value.
///
/// Performs a bitwise "and" operation on the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_and` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`i64`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI64, Ordering};"]
///
#[doc = "let foo = AtomicI64::new(0b101101);"]
/// assert_eq!(foo.fetch_and(0b110011, Ordering::SeqCst), 0b101101);
/// assert_eq!(foo.load(Ordering::SeqCst), 0b100001);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_and(&self, val: i64, order: Ordering) -> i64 {
unsafe { atomic_and(self.as_ptr(), val, order) }
}
/// Bitwise "nand" with the current value.
///
/// Performs a bitwise "nand" operation on the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_nand` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`i64`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI64, Ordering};"]
///
#[doc = "let foo = AtomicI64::new(0x13);"]
/// assert_eq!(foo.fetch_nand(0x31, Ordering::SeqCst), 0x13);
/// assert_eq!(foo.load(Ordering::SeqCst), !(0x13 & 0x31));
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_nand(&self, val: i64, order: Ordering) -> i64 {
unsafe { atomic_nand(self.as_ptr(), val, order) }
}
/// Bitwise "or" with the current value.
///
/// Performs a bitwise "or" operation on the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_or` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`i64`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI64, Ordering};"]
///
#[doc = "let foo = AtomicI64::new(0b101101);"]
/// assert_eq!(foo.fetch_or(0b110011, Ordering::SeqCst), 0b101101);
/// assert_eq!(foo.load(Ordering::SeqCst), 0b111111);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_or(&self, val: i64, order: Ordering) -> i64 {
unsafe { atomic_or(self.as_ptr(), val, order) }
}
/// Bitwise "xor" with the current value.
///
/// Performs a bitwise "xor" operation on the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_xor` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`i64`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI64, Ordering};"]
///
#[doc = "let foo = AtomicI64::new(0b101101);"]
/// assert_eq!(foo.fetch_xor(0b110011, Ordering::SeqCst), 0b101101);
/// assert_eq!(foo.load(Ordering::SeqCst), 0b011110);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_xor(&self, val: i64, order: Ordering) -> i64 {
unsafe { atomic_xor(self.as_ptr(), val, order) }
}
/// An alias for
#[doc = "[`AtomicI64::try_update`]"]
/// .
#[inline]
#[stable(feature = "no_more_cas", since = "1.45.0")]
#[rustc_should_not_be_called_on_const_items]
#[deprecated(since = "1.99.0", note =
"renamed to `try_update` for consistency", suggestion = "try_update")]
pub fn fetch_update<F>(&self, set_order: Ordering, fetch_order: Ordering,
f: F) -> Result<i64, i64> where F: FnMut(i64) -> Option<i64> {
self.try_update(set_order, fetch_order, f)
}
/// Fetches the value, and applies a function to it that returns an optional
/// new value. Returns a `Result` of `Ok(previous_value)` if the function returned `Some(_)`, else
/// `Err(previous_value)`.
///
#[doc = "See also: [`update`](`AtomicI64::update`)."]
///
/// Note: This may call the function multiple times if the value has been changed from other threads in
/// the meantime, as long as the function returns `Some(_)`, but the function will have been applied
/// only once to the stored value.
///
/// `try_update` takes two [`Ordering`] arguments to describe the memory ordering of this operation.
/// The first describes the required ordering for when the operation finally succeeds while the second
/// describes the required ordering for loads. These correspond to the success and failure orderings of
#[doc = "[`AtomicI64::compare_exchange`]"]
/// respectively.
///
/// Using [`Acquire`] as success ordering makes the store part
/// of this operation [`Relaxed`], and using [`Release`] makes the final successful load
/// [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`i64`]."]
///
/// # Considerations
///
/// This method is not magic; it is not provided by the hardware, and does not act like a
/// critical section or mutex.
///
/// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
/// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem]
/// if this atomic integer is an index or more generally if knowledge of only the *bitwise value*
/// of the atomic is not in and of itself sufficient to ensure any required preconditions.
///
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
///
/// # Examples
///
#[doc = "```rust"]
#[doc = "use std::sync::atomic::{AtomicI64, Ordering};"]
///
#[doc = "let x = AtomicI64::new(7);"]
/// assert_eq!(x.try_update(Ordering::SeqCst, Ordering::SeqCst, |_| None), Err(7));
/// assert_eq!(x.try_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(x + 1)), Ok(7));
/// assert_eq!(x.try_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(x + 1)), Ok(8));
/// assert_eq!(x.load(Ordering::SeqCst), 9);
/// ```
#[inline]
#[stable(feature = "atomic_try_update", since = "1.95.0")]
#[rustc_should_not_be_called_on_const_items]
pub fn try_update(&self, set_order: Ordering, fetch_order: Ordering,
mut f: impl FnMut(i64) -> Option<i64>) -> Result<i64, i64> {
let mut prev = self.load(fetch_order);
while let Some(next) = f(prev) {
match self.compare_exchange_weak(prev, next, set_order,
fetch_order) {
x @ Ok(_) => return x,
Err(next_prev) => prev = next_prev,
}
}
Err(prev)
}
/// Fetches the value, and applies a function to it that returns a new value.
/// The new value is stored and the old value is returned.
///
#[doc = "See also: [`try_update`](`AtomicI64::try_update`)."]
///
/// Note: This may call the function multiple times if the value has been changed from other threads in
/// the meantime, but the function will have been applied only once to the stored value.
///
/// `update` takes two [`Ordering`] arguments to describe the memory ordering of this operation.
/// The first describes the required ordering for when the operation finally succeeds while the second
/// describes the required ordering for loads. These correspond to the success and failure orderings of
#[doc = "[`AtomicI64::compare_exchange`]"]
/// respectively.
///
/// Using [`Acquire`] as success ordering makes the store part
/// of this operation [`Relaxed`], and using [`Release`] makes the final successful load
/// [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`i64`]."]
///
/// # Considerations
///
/// [CAS operation]: https://en.wikipedia.org/wiki/Compare-and-swap
/// This method is not magic; it is not provided by the hardware, and does not act like a
/// critical section or mutex.
///
/// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
/// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem]
/// if this atomic integer is an index or more generally if knowledge of only the *bitwise value*
/// of the atomic is not in and of itself sufficient to ensure any required preconditions.
///
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
///
/// # Examples
///
#[doc = "```rust"]
#[doc = "use std::sync::atomic::{AtomicI64, Ordering};"]
///
#[doc = "let x = AtomicI64::new(7);"]
/// assert_eq!(x.update(Ordering::SeqCst, Ordering::SeqCst, |x| x + 1), 7);
/// assert_eq!(x.update(Ordering::SeqCst, Ordering::SeqCst, |x| x + 1), 8);
/// assert_eq!(x.load(Ordering::SeqCst), 9);
/// ```
#[inline]
#[stable(feature = "atomic_try_update", since = "1.95.0")]
#[rustc_should_not_be_called_on_const_items]
pub fn update(&self, set_order: Ordering, fetch_order: Ordering,
mut f: impl FnMut(i64) -> i64) -> i64 {
let mut prev = self.load(fetch_order);
loop {
match self.compare_exchange_weak(prev, f(prev), set_order,
fetch_order) {
Ok(x) => break x,
Err(next_prev) => prev = next_prev,
}
}
}
/// Maximum with the current value.
///
/// Finds the maximum of the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_max` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`i64`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI64, Ordering};"]
///
#[doc = "let foo = AtomicI64::new(23);"]
/// assert_eq!(foo.fetch_max(42, Ordering::SeqCst), 23);
/// assert_eq!(foo.load(Ordering::SeqCst), 42);
/// ```
///
/// If you want to obtain the maximum value in one step, you can use the following:
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI64, Ordering};"]
///
#[doc = "let foo = AtomicI64::new(23);"]
/// let bar = 42;
/// let max_foo = foo.fetch_max(bar, Ordering::SeqCst).max(bar);
/// assert!(max_foo == 42);
/// ```
#[inline]
#[stable(feature = "atomic_min_max", since = "1.45.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_max(&self, val: i64, order: Ordering) -> i64 {
unsafe { atomic_max(self.as_ptr(), val, order) }
}
/// Minimum with the current value.
///
/// Finds the minimum of the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_min` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`i64`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI64, Ordering};"]
///
#[doc = "let foo = AtomicI64::new(23);"]
/// assert_eq!(foo.fetch_min(42, Ordering::Relaxed), 23);
/// assert_eq!(foo.load(Ordering::Relaxed), 23);
/// assert_eq!(foo.fetch_min(22, Ordering::Relaxed), 23);
/// assert_eq!(foo.load(Ordering::Relaxed), 22);
/// ```
///
/// If you want to obtain the minimum value in one step, you can use the following:
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicI64, Ordering};"]
///
#[doc = "let foo = AtomicI64::new(23);"]
/// let bar = 12;
/// let min_foo = foo.fetch_min(bar, Ordering::SeqCst).min(bar);
/// assert_eq!(min_foo, 12);
/// ```
#[inline]
#[stable(feature = "atomic_min_max", since = "1.45.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_min(&self, val: i64, order: Ordering) -> i64 {
unsafe { atomic_min(self.as_ptr(), val, order) }
}
/// Returns a mutable pointer to the underlying integer.
///
/// Doing non-atomic reads and writes on the resulting integer can be a data race.
/// This method is mostly useful for FFI, where the function signature may use
#[doc = "`*mut i64` instead of `&AtomicI64`."]
///
/// Returning an `*mut` pointer from a shared reference to this atomic is safe because the
/// atomic types work with interior mutability. All modifications of an atomic change the value
/// through a shared reference, and can do so safely as long as they use atomic operations. Any
/// use of the returned raw pointer requires an `unsafe` block and still has to uphold the
/// requirements of the [memory model].
///
/// # Examples
///
/// ```ignore (extern-declaration)
/// # fn main() {
#[doc = "use std::sync::atomic::AtomicI64;"]
///
/// extern "C" {
#[doc = " fn my_atomic_op(arg: *mut i64);"]
/// }
///
#[doc = "let atomic = AtomicI64::new(1);"]
///
/// // SAFETY: Safe as long as `my_atomic_op` is atomic.
/// unsafe {
/// my_atomic_op(atomic.as_ptr());
/// }
/// # }
/// ```
///
/// [memory model]: self#memory-model-for-atomic-accesses
#[inline]
#[stable(feature = "atomic_as_ptr", since = "1.70.0")]
#[rustc_const_stable(feature = "atomic_as_ptr", since = "1.70.0")]
#[rustc_never_returns_null_ptr]
pub const fn as_ptr(&self) -> *mut i64 { self.v.get().cast() }
}atomic_int! {
4136 target_has_atomic_load_store = "64",
4137 target_has_atomic = "64",
4138 target_has_atomic_primitive_alignment = "64",
4139 stable(feature = "integer_atomics_stable", since = "1.34.0"),
4140 stable(feature = "integer_atomics_stable", since = "1.34.0"),
4141 stable(feature = "integer_atomics_stable", since = "1.34.0"),
4142 stable(feature = "integer_atomics_stable", since = "1.34.0"),
4143 stable(feature = "integer_atomics_stable", since = "1.34.0"),
4144 stable(feature = "integer_atomics_stable", since = "1.34.0"),
4145 rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
4146 rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"),
4147"i64",
4148"",
4149 atomic_min, atomic_max,
41508,
4151 i64 AtomicI644152}4153#[cfg(target_has_atomic_load_store = "64")]
4154/// An integer type which can be safely shared between threads.
///
/// This type has the same
#[doc = "size and bit validity"]
/// as the underlying integer type, [`
#[doc = "u64"]
/// `].
#[doc =
"However, the alignment of this type is always equal to its size, even on targets where [`u64`] has a lesser alignment."]
///
/// For more about the differences between atomic types and
/// non-atomic types as well as information about the portability of
/// this type, please see the [module-level documentation].
///
/// **Note:** This type is only available on platforms that support
/// atomic loads and stores of [`
#[doc = "u64"]
/// `].
///
/// [module-level documentation]: crate::sync::atomic
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
pub type AtomicU64 = Atomic<u64>;
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
impl Default for AtomicU64 {
#[inline]
fn default() -> Self { Self::new(Default::default()) }
}
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
const impl From<u64> for AtomicU64 {
#[doc = "Converts an `u64` into an `AtomicU64`."]
#[inline]
fn from(v: u64) -> Self { Self::new(v) }
}
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
impl fmt::Debug for AtomicU64 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.load(Ordering::Relaxed), f)
}
}
impl AtomicU64 {
/// Creates a new atomic integer.
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::AtomicU64;"]
///
#[doc = "let atomic_forty_two = AtomicU64::new(42);"]
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0")]
#[must_use]
pub const fn new(v: u64) -> Self { unsafe { transmute(v) } }
/// Creates a new reference to an atomic integer from a pointer.
///
/// # Examples
///
#[doc = "```rust"]
#[doc = "use std::sync::atomic::{self, AtomicU64};"]
///
/// // Get a pointer to an allocated value
#[doc = "let ptr: *mut u64 = Box::into_raw(Box::new(0));"]
///
#[doc = "assert!(ptr.cast::<AtomicU64>().is_aligned());"]
///
/// {
/// // Create an atomic view of the allocated value
#[doc = " let atomic = unsafe {AtomicU64::from_ptr(ptr) };"]
///
/// // Use `atomic` for atomic operations, possibly share it with other threads
/// atomic.store(1, atomic::Ordering::Relaxed);
/// }
///
/// // It's ok to non-atomically access the value behind `ptr`,
/// // since the reference to the atomic ended its lifetime in the block above
/// assert_eq!(unsafe { *ptr }, 1);
///
/// // Deallocate the value
/// unsafe { drop(Box::from_raw(ptr)) }
/// ```
///
/// # Safety
///
/// * `ptr` must be aligned to
#[doc = " `align_of::<AtomicU64>()`"]
#[doc =
" (note that on some platforms this can be bigger than `align_of::<u64>()`)."]
/// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`.
/// * You must adhere to the [Memory model for atomic accesses]. In particular, it is not
/// allowed to mix conflicting atomic and non-atomic accesses, or atomic accesses of different
/// sizes, without synchronization.
///
/// [valid]: crate::ptr#safety
/// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses
#[inline]
#[stable(feature = "atomic_from_ptr", since = "1.75.0")]
#[rustc_const_stable(feature = "const_atomic_from_ptr", since = "1.84.0")]
pub const unsafe fn from_ptr<'a>(ptr: *mut u64) -> &'a AtomicU64 {
unsafe { &*ptr.cast() }
}
/// Creates a new pointer to an atomic integer from a pointer.
///
/// This is useful if you want to do volatile atomic accesses, and thus avoid creating
/// a reference to the destination.
#[inline]
#[unstable(feature = "atomic_volatile", issue = "158947")]
pub const fn from_ptr_raw(ptr: *mut u64) -> *const AtomicU64 {
ptr.cast_const().cast()
}
/// Returns a mutable reference to the underlying integer.
///
/// This is safe because the mutable reference guarantees that no other threads are
/// concurrently accessing the atomic data.
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU64, Ordering};"]
///
#[doc = "let mut some_var = AtomicU64::new(10);"]
/// assert_eq!(*some_var.get_mut(), 10);
/// *some_var.get_mut() = 5;
/// assert_eq!(some_var.load(Ordering::SeqCst), 5);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
pub const fn get_mut(&mut self) -> &mut u64 {
unsafe { &mut *self.as_ptr() }
}
#[doc = "Get atomic access to a `&mut u64`."]
///
#[doc =
"**Note:** This function is only available on targets where `AtomicU64` has the same alignment as `u64`."]
///
/// # Examples
///
#[doc = "```rust"]
#[doc = "use std::sync::atomic::{AtomicU64, Ordering};"]
///
/// let mut some_int = 123;
#[doc = "let a = AtomicU64::from_mut(&mut some_int);"]
/// a.store(100, Ordering::Relaxed);
/// assert_eq!(some_int, 100);
/// ```
///
#[inline]
#[stable(feature = "atomic_from_mut", since = "1.98.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
pub const fn from_mut(v: &mut u64) -> &mut Self {
let [] = [(); align_of::<Self>() - align_of::<u64>()];
unsafe { &mut *(v as *mut u64 as *mut Self) }
}
#[doc = "Get non-atomic access to a `&mut [AtomicU64]` slice"]
///
/// This is safe because the mutable reference guarantees that no other threads are
/// concurrently accessing the atomic data.
///
/// # Examples
///
#[doc = "```ignore-wasm"]
#[doc = "use std::sync::atomic::{AtomicU64, Ordering};"]
///
#[doc = "let mut some_ints = [const { AtomicU64::new(0) }; 10];"]
///
#[doc =
"let view: &mut [u64] = AtomicU64::get_mut_slice(&mut some_ints);"]
/// assert_eq!(view, [0; 10]);
/// view
/// .iter_mut()
/// .enumerate()
/// .for_each(|(idx, int)| *int = idx as _);
///
/// std::thread::scope(|s| {
/// some_ints
/// .iter()
/// .enumerate()
/// .for_each(|(idx, int)| {
/// s.spawn(move || assert_eq!(int.load(Ordering::Relaxed), idx as _));
/// })
/// });
/// ```
#[inline]
#[stable(feature = "atomic_from_mut", since = "1.98.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
pub const fn get_mut_slice(this: &mut [Self]) -> &mut [u64] {
unsafe { &mut *(this as *mut [Self] as *mut [u64]) }
}
#[doc = "Get atomic access to a `&mut [u64]` slice."]
///
#[doc =
"**Note:** This function is only available on targets where `AtomicU64` has the same alignment as `u64`."]
///
/// # Examples
///
#[doc = "```ignore-wasm"]
#[doc = "use std::sync::atomic::{AtomicU64, Ordering};"]
///
/// let mut some_ints = [0; 10];
#[doc = "let a = &*AtomicU64::from_mut_slice(&mut some_ints);"]
/// std::thread::scope(|s| {
/// for i in 0..a.len() {
/// s.spawn(move || a[i].store(i as _, Ordering::Relaxed));
/// }
/// });
/// for (i, n) in some_ints.into_iter().enumerate() {
/// assert_eq!(i, n as usize);
/// }
/// ```
#[inline]
#[stable(feature = "atomic_from_mut", since = "1.98.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
pub const fn from_mut_slice(v: &mut [u64]) -> &mut [Self] {
let [] = [(); align_of::<Self>() - align_of::<u64>()];
unsafe { &mut *(v as *mut [u64] as *mut [Self]) }
}
/// Consumes the atomic and returns the contained value.
///
/// This is safe because passing `self` by value guarantees that no other threads are
/// concurrently accessing the atomic data.
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::AtomicU64;"]
///
#[doc = "let some_var = AtomicU64::new(5);"]
/// assert_eq!(some_var.into_inner(), 5);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_stable(feature = "const_atomic_into_inner", since =
"1.79.0")]
pub const fn into_inner(self) -> u64 { unsafe { transmute(self) } }
/// Loads a value from the atomic integer.
///
/// `load` takes an [`Ordering`] argument which describes the memory ordering of this operation.
/// Possible values are [`SeqCst`], [`Acquire`] and [`Relaxed`].
///
/// # Panics
///
/// Panics if `order` is [`Release`] or [`AcqRel`].
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU64, Ordering};"]
///
#[doc = "let some_var = AtomicU64::new(5);"]
///
/// assert_eq!(some_var.load(Ordering::Relaxed), 5);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
pub const fn load(&self, order: Ordering) -> u64 {
unsafe { atomic_load::<_, false>(self.as_ptr(), order) }
}
/// Perform a volatile load from the atomic integer.
///
/// `load_volatile` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. Possible values are [`SeqCst`], [`Acquire`] and [`Relaxed`].
///
#[doc =
"Volatile operations are intended to act on I/O memory. As such, they are considered externally\nobservable events (just like syscalls, but less opaque), and are guaranteed to not be elided or\nreordered by the compiler across other externally observable events. With this in mind, there\nare two cases of usage that need to be distinguished:\n\n- When a volatile operation is used for memory inside an [allocation], it behaves exactly\n like [`load`][Self::load], except for the additional guarantee that it won\'t be elided or\n reordered across other externally observable events (see above). This implies that the\n operation will actually access memory and not e.g. be lowered to reusing data from a\n previous load. Other than that, all the usual rules for memory accesses apply (including\n provenance).\n\n- Volatile operations, however, may also be used to access memory that is _outside_ of any Rust\n allocation. In this use-case, the pointer does *not* have to be [valid] for reads. This is\n typically used for CPU and peripheral registers that must be accessed via an I/O memory mapping,\n most commonly at fixed addresses reserved by the hardware. These often have special semantics\n associated to their manipulation, and cannot be used as general purpose memory. Here, any address\n value is possible, including 0 and [`usize::MAX`], so long as the semantics of such a read are\n well-defined by the target hardware. The provenance of the pointer is irrelevant, and it can be\n created with [`without_provenance`][crate::ptr::without_provenance]. The access is allowed to\n trap, which must immediately abort the process. It can also cause other side-effects, but those\n must not affect Rust-allocated memory in any way.\n\nIn both cases, the access is also considered atomic with the given `order`. This allows\nsynchronization with other threads or devices that share memory with this program.\n\nWhen invoked during const evaluation, this behaves like a regular atomic load. In\nparticular, such reads must always follow the first of the two cases above.\n\n[allocation]: crate::ptr#allocated-object\n"]
///
/// # Safety
///
/// Behavior is undefined if any of the following conditions are violated:
///
/// * `self` must be [valid] for reads, or `self` must point to memory
/// outside of all Rust allocations and reading from that memory must:
/// - not trap, and
/// - not cause any memory inside a Rust allocation to be modified.
///
/// * `self` must be aligned to
#[doc = " `align_of::<AtomicU64>()`"]
#[doc =
" (note that on some platforms this can be bigger than `align_of::<u64>()`)."]
///
/// * Reading from `self` must produce a properly initialized value of the underlying
/// integer type.
///
/// [valid]: core::ptr#safety
///
/// # Panics
///
/// Panics if `order` is [`Release`] or [`AcqRel`].
#[inline]
#[unstable(feature = "atomic_volatile", issue = "158947")]
#[rustc_const_unstable(feature = "atomic_volatile", issue = "158947")]
pub const unsafe fn load_volatile(self: *const Self, order: Ordering)
-> u64 {
unsafe { atomic_load::<_, true>(self.cast::<u64>(), order) }
}
/// Stores a value into the atomic integer.
///
/// `store` takes an [`Ordering`] argument which describes the memory ordering of this operation.
/// Possible values are [`SeqCst`], [`Release`] and [`Relaxed`].
///
/// # Panics
///
/// Panics if `order` is [`Acquire`] or [`AcqRel`].
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU64, Ordering};"]
///
#[doc = "let some_var = AtomicU64::new(5);"]
///
/// some_var.store(10, Ordering::Relaxed);
/// assert_eq!(some_var.load(Ordering::Relaxed), 10);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn store(&self, val: u64, order: Ordering) {
unsafe { atomic_store::<_, false>(self.as_ptr(), val, order); }
}
/// Performs a volatile store into the atomic integer.
///
/// `store_volatile` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. Possible values are [`SeqCst`], [`Release`] and [`Relaxed`].
///
#[doc =
"Volatile operations are intended to act on I/O memory. As such, they are considered externally\nobservable events (just like syscalls), and are guaranteed to not be elided or reordered by the\ncompiler across other externally observable events. With this in mind, there are two cases of\nusage that need to be distinguished:\n\n- When a volatile operation is used for memory inside an [allocation], it behaves exactly like\n [`store`][Self::store], except for the additional guarantee that it won\'t be elided or reordered\n across other externally observable events (see above). This implies that the operation will\n actually access memory and not e.g. be lowered to a register access. Other than that, all the\n usual rules for memory accesses apply (including provenance).\n\n- Volatile operations, however, may also be used to access memory that is _outside_ of any Rust\n allocation. In this use-case, the pointer does *not* have to be [valid] for writes. This is\n typically used for CPU and peripheral registers that must be accessed via an I/O memory mapping,\n most commonly at fixed addresses reserved by the hardware. These often have special semantics\n associated to their manipulation, and cannot be used as general purpose memory. Here, any address\n value is possible, including 0 and [`usize::MAX`], so long as the semantics of such a write are\n well-defined by the target hardware. The provenance of the pointer is irrelevant, and it can be\n created with [`without_provenance_mut`][crate::ptr::without_provenance_mut]. The access is allowed\n to trap, which must immediately abort the process. It can also cause other side-effects, but those\n must not affect Rust-allocated memory in any way.\n\nIn both cases, the access is also considered atomic with the given `order`. This allows\nsynchronization with other threads or devices that share memory with this program.\n\nWhen invoked during const evaluation, this behaves like a regular atomic store. In\nparticular, such reads must always follow the first of the two cases above.\n\n[allocation]: crate::ptr#allocated-object\n"]
///
/// # Safety
///
/// Behavior is undefined if any of the following conditions are violated:
///
/// * `self` must be either [valid] for writes, or `self` must point to memory
/// outside of all Rust allocations and writing to that memory must:
/// - not trap, and
/// - not cause any memory inside a Rust allocation to be modified.
///
/// * `self` must be aligned to
#[doc = " `align_of::<AtomicU64>()`"]
#[doc =
" (note that on some platforms this can be bigger than `align_of::<u64>()`)."]
///
/// [valid]: core::ptr#safety
///
/// # Panics
///
/// Panics if `order` is [`Acquire`] or [`AcqRel`].
#[inline]
#[unstable(feature = "atomic_volatile", issue = "158947")]
#[rustc_const_unstable(feature = "atomic_volatile", issue = "158947")]
#[rustc_should_not_be_called_on_const_items]
pub const unsafe fn store_volatile(self: *const Self, val: u64,
order: Ordering) {
unsafe {
atomic_store::<_,
true>(self.cast::<u64>().cast_mut(), val, order);
}
}
/// Stores a value into the atomic integer, returning the previous value.
///
/// `swap` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`u64`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU64, Ordering};"]
///
#[doc = "let some_var = AtomicU64::new(5);"]
///
/// assert_eq!(some_var.swap(10, Ordering::Relaxed), 5);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn swap(&self, val: u64, order: Ordering) -> u64 {
unsafe { atomic_swap(self.as_ptr(), val, order) }
}
/// Stores a value into the atomic integer if the current value is the same as
/// the `current` value.
///
/// The return value is always the previous value. If it is equal to `current`, then the
/// value was updated.
///
/// `compare_and_swap` also takes an [`Ordering`] argument which describes the memory
/// ordering of this operation. Notice that even when using [`AcqRel`], the operation
/// might fail and hence just perform an `Acquire` load, but not have `Release` semantics.
/// Using [`Acquire`] makes the store part of this operation [`Relaxed`] if it
/// happens, and using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`u64`]."]
///
/// # Migrating to `compare_exchange` and `compare_exchange_weak`
///
/// `compare_and_swap` is equivalent to `compare_exchange` with the following mapping for
/// memory orderings:
///
/// Original | Success | Failure
/// -------- | ------- | -------
/// Relaxed | Relaxed | Relaxed
/// Acquire | Acquire | Acquire
/// Release | Release | Relaxed
/// AcqRel | AcqRel | Acquire
/// SeqCst | SeqCst | SeqCst
///
/// `compare_and_swap` and `compare_exchange` also differ in their return type. You can use
/// `compare_exchange(...).unwrap_or_else(|x| x)` to recover the behavior of `compare_and_swap`,
/// but in most cases it is more idiomatic to check whether the return value is `Ok` or `Err`
/// rather than to infer success vs failure based on the value that was read.
///
/// During migration, consider whether it makes sense to use `compare_exchange_weak` instead.
/// `compare_exchange_weak` is allowed to fail spuriously even when the comparison succeeds,
/// which allows the compiler to generate better assembly code when the compare and swap
/// is used in a loop.
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU64, Ordering};"]
///
#[doc = "let some_var = AtomicU64::new(5);"]
///
/// assert_eq!(some_var.compare_and_swap(5, 10, Ordering::Relaxed), 5);
/// assert_eq!(some_var.load(Ordering::Relaxed), 10);
///
/// assert_eq!(some_var.compare_and_swap(6, 12, Ordering::Relaxed), 10);
/// assert_eq!(some_var.load(Ordering::Relaxed), 10);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[deprecated(since = "1.50.0", note =
"Use `compare_exchange` or `compare_exchange_weak` instead")]
#[rustc_should_not_be_called_on_const_items]
pub const fn compare_and_swap(&self, current: u64, new: u64,
order: Ordering) -> u64 {
match self.compare_exchange(current, new, order,
strongest_failure_ordering(order)) {
Ok(x) => x,
Err(x) => x,
}
}
/// Stores a value into the atomic integer if the current value is the same as
/// the `current` value.
///
/// The return value is a result indicating whether the new value was written and
/// containing the previous value. On success this value is guaranteed to be equal to
/// `current`.
///
/// `compare_exchange` takes two [`Ordering`] arguments to describe the memory
/// ordering of this operation. `success` describes the required ordering for the
/// read-modify-write operation that takes place if the comparison with `current` succeeds.
/// `failure` describes the required ordering for the load operation that takes place when
/// the comparison fails. Using [`Acquire`] as success ordering makes the store part
/// of this operation [`Relaxed`], and using [`Release`] makes the successful load
/// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`u64`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU64, Ordering};"]
///
#[doc = "let some_var = AtomicU64::new(5);"]
///
/// assert_eq!(some_var.compare_exchange(5, 10,
/// Ordering::Acquire,
/// Ordering::Relaxed),
/// Ok(5));
/// assert_eq!(some_var.load(Ordering::Relaxed), 10);
///
/// assert_eq!(some_var.compare_exchange(6, 12,
/// Ordering::SeqCst,
/// Ordering::Acquire),
/// Err(10));
/// assert_eq!(some_var.load(Ordering::Relaxed), 10);
/// ```
///
/// # Considerations
///
/// `compare_exchange` is a [compare-and-swap operation] and thus exhibits the usual downsides
/// of CAS operations. In particular, a load of the value followed by a successful
/// `compare_exchange` with the previous load *does not ensure* that other threads have not
/// changed the value in the interim! This is usually important when the *equality* check in
/// the `compare_exchange` is being used to check the *identity* of a value, but equality
/// does not necessarily imply identity. This is a particularly common case for pointers, as
/// a pointer holding the same address does not imply that the same object exists at that
/// address! In this case, `compare_exchange` can lead to the [ABA problem].
///
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn compare_exchange(&self, current: u64, new: u64,
success: Ordering, failure: Ordering) -> Result<u64, u64> {
unsafe {
atomic_compare_exchange(self.as_ptr(), current, new, success,
failure)
}
}
/// Stores a value into the atomic integer if the current value is the same as
/// the `current` value.
///
#[doc = "Unlike [`AtomicU64::compare_exchange`],"]
/// this function is allowed to spuriously fail even
/// when the comparison succeeds, which can result in more efficient code on some
/// platforms. The return value is a result indicating whether the new value was
/// written and containing the previous value.
///
/// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory
/// ordering of this operation. `success` describes the required ordering for the
/// read-modify-write operation that takes place if the comparison with `current` succeeds.
/// `failure` describes the required ordering for the load operation that takes place when
/// the comparison fails. Using [`Acquire`] as success ordering makes the store part
/// of this operation [`Relaxed`], and using [`Release`] makes the successful load
/// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`u64`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU64, Ordering};"]
///
#[doc = "let val = AtomicU64::new(4);"]
///
/// let mut old = val.load(Ordering::Relaxed);
/// loop {
/// let new = old * 2;
/// match val.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) {
/// Ok(_) => break,
/// Err(x) => old = x,
/// }
/// }
/// ```
///
/// # Considerations
///
/// `compare_exchange` is a [compare-and-swap operation] and thus exhibits the usual downsides
/// of CAS operations. In particular, a load of the value followed by a successful
/// `compare_exchange` with the previous load *does not ensure* that other threads have not
/// changed the value in the interim. This is usually important when the *equality* check in
/// the `compare_exchange` is being used to check the *identity* of a value, but equality
/// does not necessarily imply identity. This is a particularly common case for pointers, as
/// a pointer holding the same address does not imply that the same object exists at that
/// address! In this case, `compare_exchange` can lead to the [ABA problem].
///
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn compare_exchange_weak(&self, current: u64, new: u64,
success: Ordering, failure: Ordering) -> Result<u64, u64> {
unsafe {
atomic_compare_exchange_weak(self.as_ptr(), current, new, success,
failure)
}
}
/// Adds to the current value, returning the previous value.
///
/// This operation wraps around on overflow.
///
/// `fetch_add` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`u64`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU64, Ordering};"]
///
#[doc = "let foo = AtomicU64::new(0);"]
/// assert_eq!(foo.fetch_add(10, Ordering::SeqCst), 0);
/// assert_eq!(foo.load(Ordering::SeqCst), 10);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_add(&self, val: u64, order: Ordering) -> u64 {
unsafe { atomic_add(self.as_ptr(), val, order) }
}
/// Subtracts from the current value, returning the previous value.
///
/// This operation wraps around on overflow.
///
/// `fetch_sub` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`u64`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU64, Ordering};"]
///
#[doc = "let foo = AtomicU64::new(20);"]
/// assert_eq!(foo.fetch_sub(10, Ordering::SeqCst), 20);
/// assert_eq!(foo.load(Ordering::SeqCst), 10);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_sub(&self, val: u64, order: Ordering) -> u64 {
unsafe { atomic_sub(self.as_ptr(), val, order) }
}
/// Bitwise "and" with the current value.
///
/// Performs a bitwise "and" operation on the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_and` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`u64`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU64, Ordering};"]
///
#[doc = "let foo = AtomicU64::new(0b101101);"]
/// assert_eq!(foo.fetch_and(0b110011, Ordering::SeqCst), 0b101101);
/// assert_eq!(foo.load(Ordering::SeqCst), 0b100001);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_and(&self, val: u64, order: Ordering) -> u64 {
unsafe { atomic_and(self.as_ptr(), val, order) }
}
/// Bitwise "nand" with the current value.
///
/// Performs a bitwise "nand" operation on the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_nand` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`u64`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU64, Ordering};"]
///
#[doc = "let foo = AtomicU64::new(0x13);"]
/// assert_eq!(foo.fetch_nand(0x31, Ordering::SeqCst), 0x13);
/// assert_eq!(foo.load(Ordering::SeqCst), !(0x13 & 0x31));
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_nand(&self, val: u64, order: Ordering) -> u64 {
unsafe { atomic_nand(self.as_ptr(), val, order) }
}
/// Bitwise "or" with the current value.
///
/// Performs a bitwise "or" operation on the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_or` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`u64`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU64, Ordering};"]
///
#[doc = "let foo = AtomicU64::new(0b101101);"]
/// assert_eq!(foo.fetch_or(0b110011, Ordering::SeqCst), 0b101101);
/// assert_eq!(foo.load(Ordering::SeqCst), 0b111111);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_or(&self, val: u64, order: Ordering) -> u64 {
unsafe { atomic_or(self.as_ptr(), val, order) }
}
/// Bitwise "xor" with the current value.
///
/// Performs a bitwise "xor" operation on the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_xor` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`u64`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU64, Ordering};"]
///
#[doc = "let foo = AtomicU64::new(0b101101);"]
/// assert_eq!(foo.fetch_xor(0b110011, Ordering::SeqCst), 0b101101);
/// assert_eq!(foo.load(Ordering::SeqCst), 0b011110);
/// ```
#[inline]
#[stable(feature = "integer_atomics_stable", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_xor(&self, val: u64, order: Ordering) -> u64 {
unsafe { atomic_xor(self.as_ptr(), val, order) }
}
/// An alias for
#[doc = "[`AtomicU64::try_update`]"]
/// .
#[inline]
#[stable(feature = "no_more_cas", since = "1.45.0")]
#[rustc_should_not_be_called_on_const_items]
#[deprecated(since = "1.99.0", note =
"renamed to `try_update` for consistency", suggestion = "try_update")]
pub fn fetch_update<F>(&self, set_order: Ordering, fetch_order: Ordering,
f: F) -> Result<u64, u64> where F: FnMut(u64) -> Option<u64> {
self.try_update(set_order, fetch_order, f)
}
/// Fetches the value, and applies a function to it that returns an optional
/// new value. Returns a `Result` of `Ok(previous_value)` if the function returned `Some(_)`, else
/// `Err(previous_value)`.
///
#[doc = "See also: [`update`](`AtomicU64::update`)."]
///
/// Note: This may call the function multiple times if the value has been changed from other threads in
/// the meantime, as long as the function returns `Some(_)`, but the function will have been applied
/// only once to the stored value.
///
/// `try_update` takes two [`Ordering`] arguments to describe the memory ordering of this operation.
/// The first describes the required ordering for when the operation finally succeeds while the second
/// describes the required ordering for loads. These correspond to the success and failure orderings of
#[doc = "[`AtomicU64::compare_exchange`]"]
/// respectively.
///
/// Using [`Acquire`] as success ordering makes the store part
/// of this operation [`Relaxed`], and using [`Release`] makes the final successful load
/// [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`u64`]."]
///
/// # Considerations
///
/// This method is not magic; it is not provided by the hardware, and does not act like a
/// critical section or mutex.
///
/// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
/// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem]
/// if this atomic integer is an index or more generally if knowledge of only the *bitwise value*
/// of the atomic is not in and of itself sufficient to ensure any required preconditions.
///
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
///
/// # Examples
///
#[doc = "```rust"]
#[doc = "use std::sync::atomic::{AtomicU64, Ordering};"]
///
#[doc = "let x = AtomicU64::new(7);"]
/// assert_eq!(x.try_update(Ordering::SeqCst, Ordering::SeqCst, |_| None), Err(7));
/// assert_eq!(x.try_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(x + 1)), Ok(7));
/// assert_eq!(x.try_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(x + 1)), Ok(8));
/// assert_eq!(x.load(Ordering::SeqCst), 9);
/// ```
#[inline]
#[stable(feature = "atomic_try_update", since = "1.95.0")]
#[rustc_should_not_be_called_on_const_items]
pub fn try_update(&self, set_order: Ordering, fetch_order: Ordering,
mut f: impl FnMut(u64) -> Option<u64>) -> Result<u64, u64> {
let mut prev = self.load(fetch_order);
while let Some(next) = f(prev) {
match self.compare_exchange_weak(prev, next, set_order,
fetch_order) {
x @ Ok(_) => return x,
Err(next_prev) => prev = next_prev,
}
}
Err(prev)
}
/// Fetches the value, and applies a function to it that returns a new value.
/// The new value is stored and the old value is returned.
///
#[doc = "See also: [`try_update`](`AtomicU64::try_update`)."]
///
/// Note: This may call the function multiple times if the value has been changed from other threads in
/// the meantime, but the function will have been applied only once to the stored value.
///
/// `update` takes two [`Ordering`] arguments to describe the memory ordering of this operation.
/// The first describes the required ordering for when the operation finally succeeds while the second
/// describes the required ordering for loads. These correspond to the success and failure orderings of
#[doc = "[`AtomicU64::compare_exchange`]"]
/// respectively.
///
/// Using [`Acquire`] as success ordering makes the store part
/// of this operation [`Relaxed`], and using [`Release`] makes the final successful load
/// [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`u64`]."]
///
/// # Considerations
///
/// [CAS operation]: https://en.wikipedia.org/wiki/Compare-and-swap
/// This method is not magic; it is not provided by the hardware, and does not act like a
/// critical section or mutex.
///
/// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
/// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem]
/// if this atomic integer is an index or more generally if knowledge of only the *bitwise value*
/// of the atomic is not in and of itself sufficient to ensure any required preconditions.
///
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
///
/// # Examples
///
#[doc = "```rust"]
#[doc = "use std::sync::atomic::{AtomicU64, Ordering};"]
///
#[doc = "let x = AtomicU64::new(7);"]
/// assert_eq!(x.update(Ordering::SeqCst, Ordering::SeqCst, |x| x + 1), 7);
/// assert_eq!(x.update(Ordering::SeqCst, Ordering::SeqCst, |x| x + 1), 8);
/// assert_eq!(x.load(Ordering::SeqCst), 9);
/// ```
#[inline]
#[stable(feature = "atomic_try_update", since = "1.95.0")]
#[rustc_should_not_be_called_on_const_items]
pub fn update(&self, set_order: Ordering, fetch_order: Ordering,
mut f: impl FnMut(u64) -> u64) -> u64 {
let mut prev = self.load(fetch_order);
loop {
match self.compare_exchange_weak(prev, f(prev), set_order,
fetch_order) {
Ok(x) => break x,
Err(next_prev) => prev = next_prev,
}
}
}
/// Maximum with the current value.
///
/// Finds the maximum of the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_max` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`u64`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU64, Ordering};"]
///
#[doc = "let foo = AtomicU64::new(23);"]
/// assert_eq!(foo.fetch_max(42, Ordering::SeqCst), 23);
/// assert_eq!(foo.load(Ordering::SeqCst), 42);
/// ```
///
/// If you want to obtain the maximum value in one step, you can use the following:
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU64, Ordering};"]
///
#[doc = "let foo = AtomicU64::new(23);"]
/// let bar = 42;
/// let max_foo = foo.fetch_max(bar, Ordering::SeqCst).max(bar);
/// assert!(max_foo == 42);
/// ```
#[inline]
#[stable(feature = "atomic_min_max", since = "1.45.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_max(&self, val: u64, order: Ordering) -> u64 {
unsafe { atomic_umax(self.as_ptr(), val, order) }
}
/// Minimum with the current value.
///
/// Finds the minimum of the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_min` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`u64`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU64, Ordering};"]
///
#[doc = "let foo = AtomicU64::new(23);"]
/// assert_eq!(foo.fetch_min(42, Ordering::Relaxed), 23);
/// assert_eq!(foo.load(Ordering::Relaxed), 23);
/// assert_eq!(foo.fetch_min(22, Ordering::Relaxed), 23);
/// assert_eq!(foo.load(Ordering::Relaxed), 22);
/// ```
///
/// If you want to obtain the minimum value in one step, you can use the following:
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicU64, Ordering};"]
///
#[doc = "let foo = AtomicU64::new(23);"]
/// let bar = 12;
/// let min_foo = foo.fetch_min(bar, Ordering::SeqCst).min(bar);
/// assert_eq!(min_foo, 12);
/// ```
#[inline]
#[stable(feature = "atomic_min_max", since = "1.45.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_min(&self, val: u64, order: Ordering) -> u64 {
unsafe { atomic_umin(self.as_ptr(), val, order) }
}
/// Returns a mutable pointer to the underlying integer.
///
/// Doing non-atomic reads and writes on the resulting integer can be a data race.
/// This method is mostly useful for FFI, where the function signature may use
#[doc = "`*mut u64` instead of `&AtomicU64`."]
///
/// Returning an `*mut` pointer from a shared reference to this atomic is safe because the
/// atomic types work with interior mutability. All modifications of an atomic change the value
/// through a shared reference, and can do so safely as long as they use atomic operations. Any
/// use of the returned raw pointer requires an `unsafe` block and still has to uphold the
/// requirements of the [memory model].
///
/// # Examples
///
/// ```ignore (extern-declaration)
/// # fn main() {
#[doc = "use std::sync::atomic::AtomicU64;"]
///
/// extern "C" {
#[doc = " fn my_atomic_op(arg: *mut u64);"]
/// }
///
#[doc = "let atomic = AtomicU64::new(1);"]
///
/// // SAFETY: Safe as long as `my_atomic_op` is atomic.
/// unsafe {
/// my_atomic_op(atomic.as_ptr());
/// }
/// # }
/// ```
///
/// [memory model]: self#memory-model-for-atomic-accesses
#[inline]
#[stable(feature = "atomic_as_ptr", since = "1.70.0")]
#[rustc_const_stable(feature = "atomic_as_ptr", since = "1.70.0")]
#[rustc_never_returns_null_ptr]
pub const fn as_ptr(&self) -> *mut u64 { self.v.get().cast() }
}atomic_int! {
4155 target_has_atomic_load_store = "64",
4156 target_has_atomic = "64",
4157 target_has_atomic_primitive_alignment = "64",
4158 stable(feature = "integer_atomics_stable", since = "1.34.0"),
4159 stable(feature = "integer_atomics_stable", since = "1.34.0"),
4160 stable(feature = "integer_atomics_stable", since = "1.34.0"),
4161 stable(feature = "integer_atomics_stable", since = "1.34.0"),
4162 stable(feature = "integer_atomics_stable", since = "1.34.0"),
4163 stable(feature = "integer_atomics_stable", since = "1.34.0"),
4164 rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
4165 rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"),
4166"u64",
4167"",
4168 atomic_umin, atomic_umax,
41698,
4170 u64 AtomicU644171}4172#[cfg(any(target_has_atomic_load_store = "128", doc))]
4173atomic_int! {
4174 target_has_atomic_load_store = "128",
4175 target_has_atomic = "128",
4176 target_has_atomic_primitive_alignment = "128",
4177 unstable(feature = "integer_atomics", issue = "99069"),
4178 unstable(feature = "integer_atomics", issue = "99069"),
4179 unstable(feature = "integer_atomics", issue = "99069"),
4180 unstable(feature = "integer_atomics", issue = "99069"),
4181 unstable(feature = "integer_atomics", issue = "99069"),
4182 unstable(feature = "integer_atomics", issue = "99069"),
4183 rustc_const_unstable(feature = "integer_atomics", issue = "99069"),
4184 rustc_const_unstable(feature = "integer_atomics", issue = "99069"),
4185"i128",
4186"#![feature(integer_atomics)]\n\n",
4187 atomic_min, atomic_max,
418816,
4189 i128 AtomicI128
4190}
4191#[cfg(any(target_has_atomic_load_store = "128", doc))]
4192atomic_int! {
4193 target_has_atomic_load_store = "128",
4194 target_has_atomic = "128",
4195 target_has_atomic_primitive_alignment = "128",
4196 unstable(feature = "integer_atomics", issue = "99069"),
4197 unstable(feature = "integer_atomics", issue = "99069"),
4198 unstable(feature = "integer_atomics", issue = "99069"),
4199 unstable(feature = "integer_atomics", issue = "99069"),
4200 unstable(feature = "integer_atomics", issue = "99069"),
4201 unstable(feature = "integer_atomics", issue = "99069"),
4202 rustc_const_unstable(feature = "integer_atomics", issue = "99069"),
4203 rustc_const_unstable(feature = "integer_atomics", issue = "99069"),
4204"u128",
4205"#![feature(integer_atomics)]\n\n",
4206 atomic_umin, atomic_umax,
420716,
4208 u128 AtomicU128
4209}
42104211#[cfg(target_has_atomic_load_store = "ptr")]
4212macro_rules!atomic_int_ptr_sized {
4213 ( $($target_pointer_width:literal $align:literal)* ) => { $(
4214#[cfg(target_pointer_width = $target_pointer_width)]
4215atomic_int! {
4216 target_has_atomic_load_store = "ptr",
4217 target_has_atomic = "ptr",
4218 target_has_atomic_primitive_alignment = "ptr",
4219 stable(feature = "rust1", since = "1.0.0"),
4220 stable(feature = "extended_compare_and_swap", since = "1.10.0"),
4221 stable(feature = "atomic_debug", since = "1.3.0"),
4222 stable(feature = "atomic_access", since = "1.15.0"),
4223 stable(feature = "atomic_from", since = "1.23.0"),
4224 stable(feature = "atomic_nand", since = "1.27.0"),
4225 rustc_const_stable(feature = "const_ptr_sized_atomics", since = "1.24.0"),
4226 rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"),
4227"isize",
4228"",
4229 atomic_min, atomic_max,
4230$align,
4231 isize AtomicIsize4232 }
4233#[cfg(target_pointer_width = $target_pointer_width)]
4234atomic_int! {
4235 target_has_atomic_load_store = "ptr",
4236 target_has_atomic = "ptr",
4237 target_has_atomic_primitive_alignment = "ptr",
4238 stable(feature = "rust1", since = "1.0.0"),
4239 stable(feature = "extended_compare_and_swap", since = "1.10.0"),
4240 stable(feature = "atomic_debug", since = "1.3.0"),
4241 stable(feature = "atomic_access", since = "1.15.0"),
4242 stable(feature = "atomic_from", since = "1.23.0"),
4243 stable(feature = "atomic_nand", since = "1.27.0"),
4244 rustc_const_stable(feature = "const_ptr_sized_atomics", since = "1.24.0"),
4245 rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"),
4246"usize",
4247"",
4248 atomic_umin, atomic_umax,
4249$align,
4250 usize AtomicUsize4251 }
42524253/// An [`AtomicIsize`] initialized to `0`.
4254#[cfg(target_pointer_width = $target_pointer_width)]
4255 #[stable(feature = "rust1", since = "1.0.0")]
4256 #[deprecated(
4257 since = "1.34.0",
4258 note = "the `new` function is now preferred",
4259 suggestion = "AtomicIsize::new(0)",
4260 )]
4261 #[expect(clippy::declare_interior_mutable_const, reason = "legacy atomic initializer")]
4262pub const ATOMIC_ISIZE_INIT: AtomicIsize = AtomicIsize::new(0);
42634264/// An [`AtomicUsize`] initialized to `0`.
4265#[cfg(target_pointer_width = $target_pointer_width)]
4266 #[stable(feature = "rust1", since = "1.0.0")]
4267 #[deprecated(
4268 since = "1.34.0",
4269 note = "the `new` function is now preferred",
4270 suggestion = "AtomicUsize::new(0)",
4271 )]
4272 #[expect(clippy::declare_interior_mutable_const, reason = "legacy atomic initializer")]
4273pub const ATOMIC_USIZE_INIT: AtomicUsize = AtomicUsize::new(0);
4274 )* };
4275}
42764277#[cfg(target_has_atomic_load_store = "ptr")]
4278/// An integer type which can be safely shared between threads.
///
/// This type has the same
#[doc = "size and bit validity"]
/// as the underlying integer type, [`
#[doc = "isize"]
/// `].
#[doc =
"However, the alignment of this type is always equal to its size, even on targets where [`isize`] has a lesser alignment."]
///
/// For more about the differences between atomic types and
/// non-atomic types as well as information about the portability of
/// this type, please see the [module-level documentation].
///
/// **Note:** This type is only available on platforms that support
/// atomic loads and stores of [`
#[doc = "isize"]
/// `].
///
/// [module-level documentation]: crate::sync::atomic
#[stable(feature = "rust1", since = "1.0.0")]
pub type AtomicIsize = Atomic<isize>;
#[stable(feature = "rust1", since = "1.0.0")]
impl Default for AtomicIsize {
#[inline]
fn default() -> Self { Self::new(Default::default()) }
}
#[stable(feature = "atomic_from", since = "1.23.0")]
#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
const impl From<isize> for AtomicIsize {
#[doc = "Converts an `isize` into an `AtomicIsize`."]
#[inline]
fn from(v: isize) -> Self { Self::new(v) }
}
#[stable(feature = "atomic_debug", since = "1.3.0")]
impl fmt::Debug for AtomicIsize {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.load(Ordering::Relaxed), f)
}
}
impl AtomicIsize {
/// Creates a new atomic integer.
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::AtomicIsize;"]
///
#[doc = "let atomic_forty_two = AtomicIsize::new(42);"]
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "const_ptr_sized_atomics", since =
"1.24.0")]
#[must_use]
pub const fn new(v: isize) -> Self { unsafe { transmute(v) } }
/// Creates a new reference to an atomic integer from a pointer.
///
/// # Examples
///
#[doc = "```rust"]
#[doc = "use std::sync::atomic::{self, AtomicIsize};"]
///
/// // Get a pointer to an allocated value
#[doc = "let ptr: *mut isize = Box::into_raw(Box::new(0));"]
///
#[doc = "assert!(ptr.cast::<AtomicIsize>().is_aligned());"]
///
/// {
/// // Create an atomic view of the allocated value
#[doc = " let atomic = unsafe {AtomicIsize::from_ptr(ptr) };"]
///
/// // Use `atomic` for atomic operations, possibly share it with other threads
/// atomic.store(1, atomic::Ordering::Relaxed);
/// }
///
/// // It's ok to non-atomically access the value behind `ptr`,
/// // since the reference to the atomic ended its lifetime in the block above
/// assert_eq!(unsafe { *ptr }, 1);
///
/// // Deallocate the value
/// unsafe { drop(Box::from_raw(ptr)) }
/// ```
///
/// # Safety
///
/// * `ptr` must be aligned to
#[doc = " `align_of::<AtomicIsize>()`"]
#[doc =
" (note that on some platforms this can be bigger than `align_of::<isize>()`)."]
/// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`.
/// * You must adhere to the [Memory model for atomic accesses]. In particular, it is not
/// allowed to mix conflicting atomic and non-atomic accesses, or atomic accesses of different
/// sizes, without synchronization.
///
/// [valid]: crate::ptr#safety
/// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses
#[inline]
#[stable(feature = "atomic_from_ptr", since = "1.75.0")]
#[rustc_const_stable(feature = "const_atomic_from_ptr", since = "1.84.0")]
pub const unsafe fn from_ptr<'a>(ptr: *mut isize) -> &'a AtomicIsize {
unsafe { &*ptr.cast() }
}
/// Creates a new pointer to an atomic integer from a pointer.
///
/// This is useful if you want to do volatile atomic accesses, and thus avoid creating
/// a reference to the destination.
#[inline]
#[unstable(feature = "atomic_volatile", issue = "158947")]
pub const fn from_ptr_raw(ptr: *mut isize) -> *const AtomicIsize {
ptr.cast_const().cast()
}
/// Returns a mutable reference to the underlying integer.
///
/// This is safe because the mutable reference guarantees that no other threads are
/// concurrently accessing the atomic data.
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicIsize, Ordering};"]
///
#[doc = "let mut some_var = AtomicIsize::new(10);"]
/// assert_eq!(*some_var.get_mut(), 10);
/// *some_var.get_mut() = 5;
/// assert_eq!(some_var.load(Ordering::SeqCst), 5);
/// ```
#[inline]
#[stable(feature = "atomic_access", since = "1.15.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
pub const fn get_mut(&mut self) -> &mut isize {
unsafe { &mut *self.as_ptr() }
}
#[doc = "Get atomic access to a `&mut isize`."]
///
#[doc =
"**Note:** This function is only available on targets where `AtomicIsize` has the same alignment as `isize`."]
///
/// # Examples
///
#[doc = "```rust"]
#[doc = "use std::sync::atomic::{AtomicIsize, Ordering};"]
///
/// let mut some_int = 123;
#[doc = "let a = AtomicIsize::from_mut(&mut some_int);"]
/// a.store(100, Ordering::Relaxed);
/// assert_eq!(some_int, 100);
/// ```
///
#[inline]
#[stable(feature = "atomic_from_mut", since = "1.98.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
pub const fn from_mut(v: &mut isize) -> &mut Self {
let [] = [(); align_of::<Self>() - align_of::<isize>()];
unsafe { &mut *(v as *mut isize as *mut Self) }
}
#[doc = "Get non-atomic access to a `&mut [AtomicIsize]` slice"]
///
/// This is safe because the mutable reference guarantees that no other threads are
/// concurrently accessing the atomic data.
///
/// # Examples
///
#[doc = "```ignore-wasm"]
#[doc = "use std::sync::atomic::{AtomicIsize, Ordering};"]
///
#[doc = "let mut some_ints = [const { AtomicIsize::new(0) }; 10];"]
///
#[doc =
"let view: &mut [isize] = AtomicIsize::get_mut_slice(&mut some_ints);"]
/// assert_eq!(view, [0; 10]);
/// view
/// .iter_mut()
/// .enumerate()
/// .for_each(|(idx, int)| *int = idx as _);
///
/// std::thread::scope(|s| {
/// some_ints
/// .iter()
/// .enumerate()
/// .for_each(|(idx, int)| {
/// s.spawn(move || assert_eq!(int.load(Ordering::Relaxed), idx as _));
/// })
/// });
/// ```
#[inline]
#[stable(feature = "atomic_from_mut", since = "1.98.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
pub const fn get_mut_slice(this: &mut [Self]) -> &mut [isize] {
unsafe { &mut *(this as *mut [Self] as *mut [isize]) }
}
#[doc = "Get atomic access to a `&mut [isize]` slice."]
///
#[doc =
"**Note:** This function is only available on targets where `AtomicIsize` has the same alignment as `isize`."]
///
/// # Examples
///
#[doc = "```ignore-wasm"]
#[doc = "use std::sync::atomic::{AtomicIsize, Ordering};"]
///
/// let mut some_ints = [0; 10];
#[doc = "let a = &*AtomicIsize::from_mut_slice(&mut some_ints);"]
/// std::thread::scope(|s| {
/// for i in 0..a.len() {
/// s.spawn(move || a[i].store(i as _, Ordering::Relaxed));
/// }
/// });
/// for (i, n) in some_ints.into_iter().enumerate() {
/// assert_eq!(i, n as usize);
/// }
/// ```
#[inline]
#[stable(feature = "atomic_from_mut", since = "1.98.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
pub const fn from_mut_slice(v: &mut [isize]) -> &mut [Self] {
let [] = [(); align_of::<Self>() - align_of::<isize>()];
unsafe { &mut *(v as *mut [isize] as *mut [Self]) }
}
/// Consumes the atomic and returns the contained value.
///
/// This is safe because passing `self` by value guarantees that no other threads are
/// concurrently accessing the atomic data.
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::AtomicIsize;"]
///
#[doc = "let some_var = AtomicIsize::new(5);"]
/// assert_eq!(some_var.into_inner(), 5);
/// ```
#[inline]
#[stable(feature = "atomic_access", since = "1.15.0")]
#[rustc_const_stable(feature = "const_atomic_into_inner", since =
"1.79.0")]
pub const fn into_inner(self) -> isize { unsafe { transmute(self) } }
/// Loads a value from the atomic integer.
///
/// `load` takes an [`Ordering`] argument which describes the memory ordering of this operation.
/// Possible values are [`SeqCst`], [`Acquire`] and [`Relaxed`].
///
/// # Panics
///
/// Panics if `order` is [`Release`] or [`AcqRel`].
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicIsize, Ordering};"]
///
#[doc = "let some_var = AtomicIsize::new(5);"]
///
/// assert_eq!(some_var.load(Ordering::Relaxed), 5);
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
pub const fn load(&self, order: Ordering) -> isize {
unsafe { atomic_load::<_, false>(self.as_ptr(), order) }
}
/// Perform a volatile load from the atomic integer.
///
/// `load_volatile` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. Possible values are [`SeqCst`], [`Acquire`] and [`Relaxed`].
///
#[doc =
"Volatile operations are intended to act on I/O memory. As such, they are considered externally\nobservable events (just like syscalls, but less opaque), and are guaranteed to not be elided or\nreordered by the compiler across other externally observable events. With this in mind, there\nare two cases of usage that need to be distinguished:\n\n- When a volatile operation is used for memory inside an [allocation], it behaves exactly\n like [`load`][Self::load], except for the additional guarantee that it won\'t be elided or\n reordered across other externally observable events (see above). This implies that the\n operation will actually access memory and not e.g. be lowered to reusing data from a\n previous load. Other than that, all the usual rules for memory accesses apply (including\n provenance).\n\n- Volatile operations, however, may also be used to access memory that is _outside_ of any Rust\n allocation. In this use-case, the pointer does *not* have to be [valid] for reads. This is\n typically used for CPU and peripheral registers that must be accessed via an I/O memory mapping,\n most commonly at fixed addresses reserved by the hardware. These often have special semantics\n associated to their manipulation, and cannot be used as general purpose memory. Here, any address\n value is possible, including 0 and [`usize::MAX`], so long as the semantics of such a read are\n well-defined by the target hardware. The provenance of the pointer is irrelevant, and it can be\n created with [`without_provenance`][crate::ptr::without_provenance]. The access is allowed to\n trap, which must immediately abort the process. It can also cause other side-effects, but those\n must not affect Rust-allocated memory in any way.\n\nIn both cases, the access is also considered atomic with the given `order`. This allows\nsynchronization with other threads or devices that share memory with this program.\n\nWhen invoked during const evaluation, this behaves like a regular atomic load. In\nparticular, such reads must always follow the first of the two cases above.\n\n[allocation]: crate::ptr#allocated-object\n"]
///
/// # Safety
///
/// Behavior is undefined if any of the following conditions are violated:
///
/// * `self` must be [valid] for reads, or `self` must point to memory
/// outside of all Rust allocations and reading from that memory must:
/// - not trap, and
/// - not cause any memory inside a Rust allocation to be modified.
///
/// * `self` must be aligned to
#[doc = " `align_of::<AtomicIsize>()`"]
#[doc =
" (note that on some platforms this can be bigger than `align_of::<isize>()`)."]
///
/// * Reading from `self` must produce a properly initialized value of the underlying
/// integer type.
///
/// [valid]: core::ptr#safety
///
/// # Panics
///
/// Panics if `order` is [`Release`] or [`AcqRel`].
#[inline]
#[unstable(feature = "atomic_volatile", issue = "158947")]
#[rustc_const_unstable(feature = "atomic_volatile", issue = "158947")]
pub const unsafe fn load_volatile(self: *const Self, order: Ordering)
-> isize {
unsafe { atomic_load::<_, true>(self.cast::<isize>(), order) }
}
/// Stores a value into the atomic integer.
///
/// `store` takes an [`Ordering`] argument which describes the memory ordering of this operation.
/// Possible values are [`SeqCst`], [`Release`] and [`Relaxed`].
///
/// # Panics
///
/// Panics if `order` is [`Acquire`] or [`AcqRel`].
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicIsize, Ordering};"]
///
#[doc = "let some_var = AtomicIsize::new(5);"]
///
/// some_var.store(10, Ordering::Relaxed);
/// assert_eq!(some_var.load(Ordering::Relaxed), 10);
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn store(&self, val: isize, order: Ordering) {
unsafe { atomic_store::<_, false>(self.as_ptr(), val, order); }
}
/// Performs a volatile store into the atomic integer.
///
/// `store_volatile` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. Possible values are [`SeqCst`], [`Release`] and [`Relaxed`].
///
#[doc =
"Volatile operations are intended to act on I/O memory. As such, they are considered externally\nobservable events (just like syscalls), and are guaranteed to not be elided or reordered by the\ncompiler across other externally observable events. With this in mind, there are two cases of\nusage that need to be distinguished:\n\n- When a volatile operation is used for memory inside an [allocation], it behaves exactly like\n [`store`][Self::store], except for the additional guarantee that it won\'t be elided or reordered\n across other externally observable events (see above). This implies that the operation will\n actually access memory and not e.g. be lowered to a register access. Other than that, all the\n usual rules for memory accesses apply (including provenance).\n\n- Volatile operations, however, may also be used to access memory that is _outside_ of any Rust\n allocation. In this use-case, the pointer does *not* have to be [valid] for writes. This is\n typically used for CPU and peripheral registers that must be accessed via an I/O memory mapping,\n most commonly at fixed addresses reserved by the hardware. These often have special semantics\n associated to their manipulation, and cannot be used as general purpose memory. Here, any address\n value is possible, including 0 and [`usize::MAX`], so long as the semantics of such a write are\n well-defined by the target hardware. The provenance of the pointer is irrelevant, and it can be\n created with [`without_provenance_mut`][crate::ptr::without_provenance_mut]. The access is allowed\n to trap, which must immediately abort the process. It can also cause other side-effects, but those\n must not affect Rust-allocated memory in any way.\n\nIn both cases, the access is also considered atomic with the given `order`. This allows\nsynchronization with other threads or devices that share memory with this program.\n\nWhen invoked during const evaluation, this behaves like a regular atomic store. In\nparticular, such reads must always follow the first of the two cases above.\n\n[allocation]: crate::ptr#allocated-object\n"]
///
/// # Safety
///
/// Behavior is undefined if any of the following conditions are violated:
///
/// * `self` must be either [valid] for writes, or `self` must point to memory
/// outside of all Rust allocations and writing to that memory must:
/// - not trap, and
/// - not cause any memory inside a Rust allocation to be modified.
///
/// * `self` must be aligned to
#[doc = " `align_of::<AtomicIsize>()`"]
#[doc =
" (note that on some platforms this can be bigger than `align_of::<isize>()`)."]
///
/// [valid]: core::ptr#safety
///
/// # Panics
///
/// Panics if `order` is [`Acquire`] or [`AcqRel`].
#[inline]
#[unstable(feature = "atomic_volatile", issue = "158947")]
#[rustc_const_unstable(feature = "atomic_volatile", issue = "158947")]
#[rustc_should_not_be_called_on_const_items]
pub const unsafe fn store_volatile(self: *const Self, val: isize,
order: Ordering) {
unsafe {
atomic_store::<_,
true>(self.cast::<isize>().cast_mut(), val, order);
}
}
/// Stores a value into the atomic integer, returning the previous value.
///
/// `swap` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`isize`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicIsize, Ordering};"]
///
#[doc = "let some_var = AtomicIsize::new(5);"]
///
/// assert_eq!(some_var.swap(10, Ordering::Relaxed), 5);
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn swap(&self, val: isize, order: Ordering) -> isize {
unsafe { atomic_swap(self.as_ptr(), val, order) }
}
/// Stores a value into the atomic integer if the current value is the same as
/// the `current` value.
///
/// The return value is always the previous value. If it is equal to `current`, then the
/// value was updated.
///
/// `compare_and_swap` also takes an [`Ordering`] argument which describes the memory
/// ordering of this operation. Notice that even when using [`AcqRel`], the operation
/// might fail and hence just perform an `Acquire` load, but not have `Release` semantics.
/// Using [`Acquire`] makes the store part of this operation [`Relaxed`] if it
/// happens, and using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`isize`]."]
///
/// # Migrating to `compare_exchange` and `compare_exchange_weak`
///
/// `compare_and_swap` is equivalent to `compare_exchange` with the following mapping for
/// memory orderings:
///
/// Original | Success | Failure
/// -------- | ------- | -------
/// Relaxed | Relaxed | Relaxed
/// Acquire | Acquire | Acquire
/// Release | Release | Relaxed
/// AcqRel | AcqRel | Acquire
/// SeqCst | SeqCst | SeqCst
///
/// `compare_and_swap` and `compare_exchange` also differ in their return type. You can use
/// `compare_exchange(...).unwrap_or_else(|x| x)` to recover the behavior of `compare_and_swap`,
/// but in most cases it is more idiomatic to check whether the return value is `Ok` or `Err`
/// rather than to infer success vs failure based on the value that was read.
///
/// During migration, consider whether it makes sense to use `compare_exchange_weak` instead.
/// `compare_exchange_weak` is allowed to fail spuriously even when the comparison succeeds,
/// which allows the compiler to generate better assembly code when the compare and swap
/// is used in a loop.
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicIsize, Ordering};"]
///
#[doc = "let some_var = AtomicIsize::new(5);"]
///
/// assert_eq!(some_var.compare_and_swap(5, 10, Ordering::Relaxed), 5);
/// assert_eq!(some_var.load(Ordering::Relaxed), 10);
///
/// assert_eq!(some_var.compare_and_swap(6, 12, Ordering::Relaxed), 10);
/// assert_eq!(some_var.load(Ordering::Relaxed), 10);
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[deprecated(since = "1.50.0", note =
"Use `compare_exchange` or `compare_exchange_weak` instead")]
#[rustc_should_not_be_called_on_const_items]
pub const fn compare_and_swap(&self, current: isize, new: isize,
order: Ordering) -> isize {
match self.compare_exchange(current, new, order,
strongest_failure_ordering(order)) {
Ok(x) => x,
Err(x) => x,
}
}
/// Stores a value into the atomic integer if the current value is the same as
/// the `current` value.
///
/// The return value is a result indicating whether the new value was written and
/// containing the previous value. On success this value is guaranteed to be equal to
/// `current`.
///
/// `compare_exchange` takes two [`Ordering`] arguments to describe the memory
/// ordering of this operation. `success` describes the required ordering for the
/// read-modify-write operation that takes place if the comparison with `current` succeeds.
/// `failure` describes the required ordering for the load operation that takes place when
/// the comparison fails. Using [`Acquire`] as success ordering makes the store part
/// of this operation [`Relaxed`], and using [`Release`] makes the successful load
/// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`isize`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicIsize, Ordering};"]
///
#[doc = "let some_var = AtomicIsize::new(5);"]
///
/// assert_eq!(some_var.compare_exchange(5, 10,
/// Ordering::Acquire,
/// Ordering::Relaxed),
/// Ok(5));
/// assert_eq!(some_var.load(Ordering::Relaxed), 10);
///
/// assert_eq!(some_var.compare_exchange(6, 12,
/// Ordering::SeqCst,
/// Ordering::Acquire),
/// Err(10));
/// assert_eq!(some_var.load(Ordering::Relaxed), 10);
/// ```
///
/// # Considerations
///
/// `compare_exchange` is a [compare-and-swap operation] and thus exhibits the usual downsides
/// of CAS operations. In particular, a load of the value followed by a successful
/// `compare_exchange` with the previous load *does not ensure* that other threads have not
/// changed the value in the interim! This is usually important when the *equality* check in
/// the `compare_exchange` is being used to check the *identity* of a value, but equality
/// does not necessarily imply identity. This is a particularly common case for pointers, as
/// a pointer holding the same address does not imply that the same object exists at that
/// address! In this case, `compare_exchange` can lead to the [ABA problem].
///
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
#[inline]
#[stable(feature = "extended_compare_and_swap", since = "1.10.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn compare_exchange(&self, current: isize, new: isize,
success: Ordering, failure: Ordering) -> Result<isize, isize> {
unsafe {
atomic_compare_exchange(self.as_ptr(), current, new, success,
failure)
}
}
/// Stores a value into the atomic integer if the current value is the same as
/// the `current` value.
///
#[doc = "Unlike [`AtomicIsize::compare_exchange`],"]
/// this function is allowed to spuriously fail even
/// when the comparison succeeds, which can result in more efficient code on some
/// platforms. The return value is a result indicating whether the new value was
/// written and containing the previous value.
///
/// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory
/// ordering of this operation. `success` describes the required ordering for the
/// read-modify-write operation that takes place if the comparison with `current` succeeds.
/// `failure` describes the required ordering for the load operation that takes place when
/// the comparison fails. Using [`Acquire`] as success ordering makes the store part
/// of this operation [`Relaxed`], and using [`Release`] makes the successful load
/// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`isize`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicIsize, Ordering};"]
///
#[doc = "let val = AtomicIsize::new(4);"]
///
/// let mut old = val.load(Ordering::Relaxed);
/// loop {
/// let new = old * 2;
/// match val.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) {
/// Ok(_) => break,
/// Err(x) => old = x,
/// }
/// }
/// ```
///
/// # Considerations
///
/// `compare_exchange` is a [compare-and-swap operation] and thus exhibits the usual downsides
/// of CAS operations. In particular, a load of the value followed by a successful
/// `compare_exchange` with the previous load *does not ensure* that other threads have not
/// changed the value in the interim. This is usually important when the *equality* check in
/// the `compare_exchange` is being used to check the *identity* of a value, but equality
/// does not necessarily imply identity. This is a particularly common case for pointers, as
/// a pointer holding the same address does not imply that the same object exists at that
/// address! In this case, `compare_exchange` can lead to the [ABA problem].
///
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
#[inline]
#[stable(feature = "extended_compare_and_swap", since = "1.10.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn compare_exchange_weak(&self, current: isize, new: isize,
success: Ordering, failure: Ordering) -> Result<isize, isize> {
unsafe {
atomic_compare_exchange_weak(self.as_ptr(), current, new, success,
failure)
}
}
/// Adds to the current value, returning the previous value.
///
/// This operation wraps around on overflow.
///
/// `fetch_add` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`isize`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicIsize, Ordering};"]
///
#[doc = "let foo = AtomicIsize::new(0);"]
/// assert_eq!(foo.fetch_add(10, Ordering::SeqCst), 0);
/// assert_eq!(foo.load(Ordering::SeqCst), 10);
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_add(&self, val: isize, order: Ordering) -> isize {
unsafe { atomic_add(self.as_ptr(), val, order) }
}
/// Subtracts from the current value, returning the previous value.
///
/// This operation wraps around on overflow.
///
/// `fetch_sub` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`isize`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicIsize, Ordering};"]
///
#[doc = "let foo = AtomicIsize::new(20);"]
/// assert_eq!(foo.fetch_sub(10, Ordering::SeqCst), 20);
/// assert_eq!(foo.load(Ordering::SeqCst), 10);
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_sub(&self, val: isize, order: Ordering) -> isize {
unsafe { atomic_sub(self.as_ptr(), val, order) }
}
/// Bitwise "and" with the current value.
///
/// Performs a bitwise "and" operation on the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_and` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`isize`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicIsize, Ordering};"]
///
#[doc = "let foo = AtomicIsize::new(0b101101);"]
/// assert_eq!(foo.fetch_and(0b110011, Ordering::SeqCst), 0b101101);
/// assert_eq!(foo.load(Ordering::SeqCst), 0b100001);
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_and(&self, val: isize, order: Ordering) -> isize {
unsafe { atomic_and(self.as_ptr(), val, order) }
}
/// Bitwise "nand" with the current value.
///
/// Performs a bitwise "nand" operation on the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_nand` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`isize`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicIsize, Ordering};"]
///
#[doc = "let foo = AtomicIsize::new(0x13);"]
/// assert_eq!(foo.fetch_nand(0x31, Ordering::SeqCst), 0x13);
/// assert_eq!(foo.load(Ordering::SeqCst), !(0x13 & 0x31));
/// ```
#[inline]
#[stable(feature = "atomic_nand", since = "1.27.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_nand(&self, val: isize, order: Ordering) -> isize {
unsafe { atomic_nand(self.as_ptr(), val, order) }
}
/// Bitwise "or" with the current value.
///
/// Performs a bitwise "or" operation on the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_or` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`isize`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicIsize, Ordering};"]
///
#[doc = "let foo = AtomicIsize::new(0b101101);"]
/// assert_eq!(foo.fetch_or(0b110011, Ordering::SeqCst), 0b101101);
/// assert_eq!(foo.load(Ordering::SeqCst), 0b111111);
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_or(&self, val: isize, order: Ordering) -> isize {
unsafe { atomic_or(self.as_ptr(), val, order) }
}
/// Bitwise "xor" with the current value.
///
/// Performs a bitwise "xor" operation on the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_xor` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`isize`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicIsize, Ordering};"]
///
#[doc = "let foo = AtomicIsize::new(0b101101);"]
/// assert_eq!(foo.fetch_xor(0b110011, Ordering::SeqCst), 0b101101);
/// assert_eq!(foo.load(Ordering::SeqCst), 0b011110);
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_xor(&self, val: isize, order: Ordering) -> isize {
unsafe { atomic_xor(self.as_ptr(), val, order) }
}
/// An alias for
#[doc = "[`AtomicIsize::try_update`]"]
/// .
#[inline]
#[stable(feature = "no_more_cas", since = "1.45.0")]
#[rustc_should_not_be_called_on_const_items]
#[deprecated(since = "1.99.0", note =
"renamed to `try_update` for consistency", suggestion = "try_update")]
pub fn fetch_update<F>(&self, set_order: Ordering, fetch_order: Ordering,
f: F) -> Result<isize, isize> where F: FnMut(isize) -> Option<isize> {
self.try_update(set_order, fetch_order, f)
}
/// Fetches the value, and applies a function to it that returns an optional
/// new value. Returns a `Result` of `Ok(previous_value)` if the function returned `Some(_)`, else
/// `Err(previous_value)`.
///
#[doc = "See also: [`update`](`AtomicIsize::update`)."]
///
/// Note: This may call the function multiple times if the value has been changed from other threads in
/// the meantime, as long as the function returns `Some(_)`, but the function will have been applied
/// only once to the stored value.
///
/// `try_update` takes two [`Ordering`] arguments to describe the memory ordering of this operation.
/// The first describes the required ordering for when the operation finally succeeds while the second
/// describes the required ordering for loads. These correspond to the success and failure orderings of
#[doc = "[`AtomicIsize::compare_exchange`]"]
/// respectively.
///
/// Using [`Acquire`] as success ordering makes the store part
/// of this operation [`Relaxed`], and using [`Release`] makes the final successful load
/// [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`isize`]."]
///
/// # Considerations
///
/// This method is not magic; it is not provided by the hardware, and does not act like a
/// critical section or mutex.
///
/// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
/// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem]
/// if this atomic integer is an index or more generally if knowledge of only the *bitwise value*
/// of the atomic is not in and of itself sufficient to ensure any required preconditions.
///
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
///
/// # Examples
///
#[doc = "```rust"]
#[doc = "use std::sync::atomic::{AtomicIsize, Ordering};"]
///
#[doc = "let x = AtomicIsize::new(7);"]
/// assert_eq!(x.try_update(Ordering::SeqCst, Ordering::SeqCst, |_| None), Err(7));
/// assert_eq!(x.try_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(x + 1)), Ok(7));
/// assert_eq!(x.try_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(x + 1)), Ok(8));
/// assert_eq!(x.load(Ordering::SeqCst), 9);
/// ```
#[inline]
#[stable(feature = "atomic_try_update", since = "1.95.0")]
#[rustc_should_not_be_called_on_const_items]
pub fn try_update(&self, set_order: Ordering, fetch_order: Ordering,
mut f: impl FnMut(isize) -> Option<isize>) -> Result<isize, isize> {
let mut prev = self.load(fetch_order);
while let Some(next) = f(prev) {
match self.compare_exchange_weak(prev, next, set_order,
fetch_order) {
x @ Ok(_) => return x,
Err(next_prev) => prev = next_prev,
}
}
Err(prev)
}
/// Fetches the value, and applies a function to it that returns a new value.
/// The new value is stored and the old value is returned.
///
#[doc = "See also: [`try_update`](`AtomicIsize::try_update`)."]
///
/// Note: This may call the function multiple times if the value has been changed from other threads in
/// the meantime, but the function will have been applied only once to the stored value.
///
/// `update` takes two [`Ordering`] arguments to describe the memory ordering of this operation.
/// The first describes the required ordering for when the operation finally succeeds while the second
/// describes the required ordering for loads. These correspond to the success and failure orderings of
#[doc = "[`AtomicIsize::compare_exchange`]"]
/// respectively.
///
/// Using [`Acquire`] as success ordering makes the store part
/// of this operation [`Relaxed`], and using [`Release`] makes the final successful load
/// [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`isize`]."]
///
/// # Considerations
///
/// [CAS operation]: https://en.wikipedia.org/wiki/Compare-and-swap
/// This method is not magic; it is not provided by the hardware, and does not act like a
/// critical section or mutex.
///
/// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
/// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem]
/// if this atomic integer is an index or more generally if knowledge of only the *bitwise value*
/// of the atomic is not in and of itself sufficient to ensure any required preconditions.
///
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
///
/// # Examples
///
#[doc = "```rust"]
#[doc = "use std::sync::atomic::{AtomicIsize, Ordering};"]
///
#[doc = "let x = AtomicIsize::new(7);"]
/// assert_eq!(x.update(Ordering::SeqCst, Ordering::SeqCst, |x| x + 1), 7);
/// assert_eq!(x.update(Ordering::SeqCst, Ordering::SeqCst, |x| x + 1), 8);
/// assert_eq!(x.load(Ordering::SeqCst), 9);
/// ```
#[inline]
#[stable(feature = "atomic_try_update", since = "1.95.0")]
#[rustc_should_not_be_called_on_const_items]
pub fn update(&self, set_order: Ordering, fetch_order: Ordering,
mut f: impl FnMut(isize) -> isize) -> isize {
let mut prev = self.load(fetch_order);
loop {
match self.compare_exchange_weak(prev, f(prev), set_order,
fetch_order) {
Ok(x) => break x,
Err(next_prev) => prev = next_prev,
}
}
}
/// Maximum with the current value.
///
/// Finds the maximum of the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_max` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`isize`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicIsize, Ordering};"]
///
#[doc = "let foo = AtomicIsize::new(23);"]
/// assert_eq!(foo.fetch_max(42, Ordering::SeqCst), 23);
/// assert_eq!(foo.load(Ordering::SeqCst), 42);
/// ```
///
/// If you want to obtain the maximum value in one step, you can use the following:
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicIsize, Ordering};"]
///
#[doc = "let foo = AtomicIsize::new(23);"]
/// let bar = 42;
/// let max_foo = foo.fetch_max(bar, Ordering::SeqCst).max(bar);
/// assert!(max_foo == 42);
/// ```
#[inline]
#[stable(feature = "atomic_min_max", since = "1.45.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_max(&self, val: isize, order: Ordering) -> isize {
unsafe { atomic_max(self.as_ptr(), val, order) }
}
/// Minimum with the current value.
///
/// Finds the minimum of the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_min` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`isize`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicIsize, Ordering};"]
///
#[doc = "let foo = AtomicIsize::new(23);"]
/// assert_eq!(foo.fetch_min(42, Ordering::Relaxed), 23);
/// assert_eq!(foo.load(Ordering::Relaxed), 23);
/// assert_eq!(foo.fetch_min(22, Ordering::Relaxed), 23);
/// assert_eq!(foo.load(Ordering::Relaxed), 22);
/// ```
///
/// If you want to obtain the minimum value in one step, you can use the following:
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicIsize, Ordering};"]
///
#[doc = "let foo = AtomicIsize::new(23);"]
/// let bar = 12;
/// let min_foo = foo.fetch_min(bar, Ordering::SeqCst).min(bar);
/// assert_eq!(min_foo, 12);
/// ```
#[inline]
#[stable(feature = "atomic_min_max", since = "1.45.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_min(&self, val: isize, order: Ordering) -> isize {
unsafe { atomic_min(self.as_ptr(), val, order) }
}
/// Returns a mutable pointer to the underlying integer.
///
/// Doing non-atomic reads and writes on the resulting integer can be a data race.
/// This method is mostly useful for FFI, where the function signature may use
#[doc = "`*mut isize` instead of `&AtomicIsize`."]
///
/// Returning an `*mut` pointer from a shared reference to this atomic is safe because the
/// atomic types work with interior mutability. All modifications of an atomic change the value
/// through a shared reference, and can do so safely as long as they use atomic operations. Any
/// use of the returned raw pointer requires an `unsafe` block and still has to uphold the
/// requirements of the [memory model].
///
/// # Examples
///
/// ```ignore (extern-declaration)
/// # fn main() {
#[doc = "use std::sync::atomic::AtomicIsize;"]
///
/// extern "C" {
#[doc = " fn my_atomic_op(arg: *mut isize);"]
/// }
///
#[doc = "let atomic = AtomicIsize::new(1);"]
///
/// // SAFETY: Safe as long as `my_atomic_op` is atomic.
/// unsafe {
/// my_atomic_op(atomic.as_ptr());
/// }
/// # }
/// ```
///
/// [memory model]: self#memory-model-for-atomic-accesses
#[inline]
#[stable(feature = "atomic_as_ptr", since = "1.70.0")]
#[rustc_const_stable(feature = "atomic_as_ptr", since = "1.70.0")]
#[rustc_never_returns_null_ptr]
pub const fn as_ptr(&self) -> *mut isize { self.v.get().cast() }
}
/// An integer type which can be safely shared between threads.
///
/// This type has the same
#[doc = "size and bit validity"]
/// as the underlying integer type, [`
#[doc = "usize"]
/// `].
#[doc =
"However, the alignment of this type is always equal to its size, even on targets where [`usize`] has a lesser alignment."]
///
/// For more about the differences between atomic types and
/// non-atomic types as well as information about the portability of
/// this type, please see the [module-level documentation].
///
/// **Note:** This type is only available on platforms that support
/// atomic loads and stores of [`
#[doc = "usize"]
/// `].
///
/// [module-level documentation]: crate::sync::atomic
#[stable(feature = "rust1", since = "1.0.0")]
pub type AtomicUsize = Atomic<usize>;
#[stable(feature = "rust1", since = "1.0.0")]
impl Default for AtomicUsize {
#[inline]
fn default() -> Self { Self::new(Default::default()) }
}
#[stable(feature = "atomic_from", since = "1.23.0")]
#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
const impl From<usize> for AtomicUsize {
#[doc = "Converts an `usize` into an `AtomicUsize`."]
#[inline]
fn from(v: usize) -> Self { Self::new(v) }
}
#[stable(feature = "atomic_debug", since = "1.3.0")]
impl fmt::Debug for AtomicUsize {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.load(Ordering::Relaxed), f)
}
}
impl AtomicUsize {
/// Creates a new atomic integer.
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::AtomicUsize;"]
///
#[doc = "let atomic_forty_two = AtomicUsize::new(42);"]
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "const_ptr_sized_atomics", since =
"1.24.0")]
#[must_use]
pub const fn new(v: usize) -> Self { unsafe { transmute(v) } }
/// Creates a new reference to an atomic integer from a pointer.
///
/// # Examples
///
#[doc = "```rust"]
#[doc = "use std::sync::atomic::{self, AtomicUsize};"]
///
/// // Get a pointer to an allocated value
#[doc = "let ptr: *mut usize = Box::into_raw(Box::new(0));"]
///
#[doc = "assert!(ptr.cast::<AtomicUsize>().is_aligned());"]
///
/// {
/// // Create an atomic view of the allocated value
#[doc = " let atomic = unsafe {AtomicUsize::from_ptr(ptr) };"]
///
/// // Use `atomic` for atomic operations, possibly share it with other threads
/// atomic.store(1, atomic::Ordering::Relaxed);
/// }
///
/// // It's ok to non-atomically access the value behind `ptr`,
/// // since the reference to the atomic ended its lifetime in the block above
/// assert_eq!(unsafe { *ptr }, 1);
///
/// // Deallocate the value
/// unsafe { drop(Box::from_raw(ptr)) }
/// ```
///
/// # Safety
///
/// * `ptr` must be aligned to
#[doc = " `align_of::<AtomicUsize>()`"]
#[doc =
" (note that on some platforms this can be bigger than `align_of::<usize>()`)."]
/// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`.
/// * You must adhere to the [Memory model for atomic accesses]. In particular, it is not
/// allowed to mix conflicting atomic and non-atomic accesses, or atomic accesses of different
/// sizes, without synchronization.
///
/// [valid]: crate::ptr#safety
/// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses
#[inline]
#[stable(feature = "atomic_from_ptr", since = "1.75.0")]
#[rustc_const_stable(feature = "const_atomic_from_ptr", since = "1.84.0")]
pub const unsafe fn from_ptr<'a>(ptr: *mut usize) -> &'a AtomicUsize {
unsafe { &*ptr.cast() }
}
/// Creates a new pointer to an atomic integer from a pointer.
///
/// This is useful if you want to do volatile atomic accesses, and thus avoid creating
/// a reference to the destination.
#[inline]
#[unstable(feature = "atomic_volatile", issue = "158947")]
pub const fn from_ptr_raw(ptr: *mut usize) -> *const AtomicUsize {
ptr.cast_const().cast()
}
/// Returns a mutable reference to the underlying integer.
///
/// This is safe because the mutable reference guarantees that no other threads are
/// concurrently accessing the atomic data.
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicUsize, Ordering};"]
///
#[doc = "let mut some_var = AtomicUsize::new(10);"]
/// assert_eq!(*some_var.get_mut(), 10);
/// *some_var.get_mut() = 5;
/// assert_eq!(some_var.load(Ordering::SeqCst), 5);
/// ```
#[inline]
#[stable(feature = "atomic_access", since = "1.15.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
pub const fn get_mut(&mut self) -> &mut usize {
unsafe { &mut *self.as_ptr() }
}
#[doc = "Get atomic access to a `&mut usize`."]
///
#[doc =
"**Note:** This function is only available on targets where `AtomicUsize` has the same alignment as `usize`."]
///
/// # Examples
///
#[doc = "```rust"]
#[doc = "use std::sync::atomic::{AtomicUsize, Ordering};"]
///
/// let mut some_int = 123;
#[doc = "let a = AtomicUsize::from_mut(&mut some_int);"]
/// a.store(100, Ordering::Relaxed);
/// assert_eq!(some_int, 100);
/// ```
///
#[inline]
#[stable(feature = "atomic_from_mut", since = "1.98.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
pub const fn from_mut(v: &mut usize) -> &mut Self {
let [] = [(); align_of::<Self>() - align_of::<usize>()];
unsafe { &mut *(v as *mut usize as *mut Self) }
}
#[doc = "Get non-atomic access to a `&mut [AtomicUsize]` slice"]
///
/// This is safe because the mutable reference guarantees that no other threads are
/// concurrently accessing the atomic data.
///
/// # Examples
///
#[doc = "```ignore-wasm"]
#[doc = "use std::sync::atomic::{AtomicUsize, Ordering};"]
///
#[doc = "let mut some_ints = [const { AtomicUsize::new(0) }; 10];"]
///
#[doc =
"let view: &mut [usize] = AtomicUsize::get_mut_slice(&mut some_ints);"]
/// assert_eq!(view, [0; 10]);
/// view
/// .iter_mut()
/// .enumerate()
/// .for_each(|(idx, int)| *int = idx as _);
///
/// std::thread::scope(|s| {
/// some_ints
/// .iter()
/// .enumerate()
/// .for_each(|(idx, int)| {
/// s.spawn(move || assert_eq!(int.load(Ordering::Relaxed), idx as _));
/// })
/// });
/// ```
#[inline]
#[stable(feature = "atomic_from_mut", since = "1.98.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
pub const fn get_mut_slice(this: &mut [Self]) -> &mut [usize] {
unsafe { &mut *(this as *mut [Self] as *mut [usize]) }
}
#[doc = "Get atomic access to a `&mut [usize]` slice."]
///
#[doc =
"**Note:** This function is only available on targets where `AtomicUsize` has the same alignment as `usize`."]
///
/// # Examples
///
#[doc = "```ignore-wasm"]
#[doc = "use std::sync::atomic::{AtomicUsize, Ordering};"]
///
/// let mut some_ints = [0; 10];
#[doc = "let a = &*AtomicUsize::from_mut_slice(&mut some_ints);"]
/// std::thread::scope(|s| {
/// for i in 0..a.len() {
/// s.spawn(move || a[i].store(i as _, Ordering::Relaxed));
/// }
/// });
/// for (i, n) in some_ints.into_iter().enumerate() {
/// assert_eq!(i, n as usize);
/// }
/// ```
#[inline]
#[stable(feature = "atomic_from_mut", since = "1.98.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
pub const fn from_mut_slice(v: &mut [usize]) -> &mut [Self] {
let [] = [(); align_of::<Self>() - align_of::<usize>()];
unsafe { &mut *(v as *mut [usize] as *mut [Self]) }
}
/// Consumes the atomic and returns the contained value.
///
/// This is safe because passing `self` by value guarantees that no other threads are
/// concurrently accessing the atomic data.
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::AtomicUsize;"]
///
#[doc = "let some_var = AtomicUsize::new(5);"]
/// assert_eq!(some_var.into_inner(), 5);
/// ```
#[inline]
#[stable(feature = "atomic_access", since = "1.15.0")]
#[rustc_const_stable(feature = "const_atomic_into_inner", since =
"1.79.0")]
pub const fn into_inner(self) -> usize { unsafe { transmute(self) } }
/// Loads a value from the atomic integer.
///
/// `load` takes an [`Ordering`] argument which describes the memory ordering of this operation.
/// Possible values are [`SeqCst`], [`Acquire`] and [`Relaxed`].
///
/// # Panics
///
/// Panics if `order` is [`Release`] or [`AcqRel`].
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicUsize, Ordering};"]
///
#[doc = "let some_var = AtomicUsize::new(5);"]
///
/// assert_eq!(some_var.load(Ordering::Relaxed), 5);
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
pub const fn load(&self, order: Ordering) -> usize {
unsafe { atomic_load::<_, false>(self.as_ptr(), order) }
}
/// Perform a volatile load from the atomic integer.
///
/// `load_volatile` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. Possible values are [`SeqCst`], [`Acquire`] and [`Relaxed`].
///
#[doc =
"Volatile operations are intended to act on I/O memory. As such, they are considered externally\nobservable events (just like syscalls, but less opaque), and are guaranteed to not be elided or\nreordered by the compiler across other externally observable events. With this in mind, there\nare two cases of usage that need to be distinguished:\n\n- When a volatile operation is used for memory inside an [allocation], it behaves exactly\n like [`load`][Self::load], except for the additional guarantee that it won\'t be elided or\n reordered across other externally observable events (see above). This implies that the\n operation will actually access memory and not e.g. be lowered to reusing data from a\n previous load. Other than that, all the usual rules for memory accesses apply (including\n provenance).\n\n- Volatile operations, however, may also be used to access memory that is _outside_ of any Rust\n allocation. In this use-case, the pointer does *not* have to be [valid] for reads. This is\n typically used for CPU and peripheral registers that must be accessed via an I/O memory mapping,\n most commonly at fixed addresses reserved by the hardware. These often have special semantics\n associated to their manipulation, and cannot be used as general purpose memory. Here, any address\n value is possible, including 0 and [`usize::MAX`], so long as the semantics of such a read are\n well-defined by the target hardware. The provenance of the pointer is irrelevant, and it can be\n created with [`without_provenance`][crate::ptr::without_provenance]. The access is allowed to\n trap, which must immediately abort the process. It can also cause other side-effects, but those\n must not affect Rust-allocated memory in any way.\n\nIn both cases, the access is also considered atomic with the given `order`. This allows\nsynchronization with other threads or devices that share memory with this program.\n\nWhen invoked during const evaluation, this behaves like a regular atomic load. In\nparticular, such reads must always follow the first of the two cases above.\n\n[allocation]: crate::ptr#allocated-object\n"]
///
/// # Safety
///
/// Behavior is undefined if any of the following conditions are violated:
///
/// * `self` must be [valid] for reads, or `self` must point to memory
/// outside of all Rust allocations and reading from that memory must:
/// - not trap, and
/// - not cause any memory inside a Rust allocation to be modified.
///
/// * `self` must be aligned to
#[doc = " `align_of::<AtomicUsize>()`"]
#[doc =
" (note that on some platforms this can be bigger than `align_of::<usize>()`)."]
///
/// * Reading from `self` must produce a properly initialized value of the underlying
/// integer type.
///
/// [valid]: core::ptr#safety
///
/// # Panics
///
/// Panics if `order` is [`Release`] or [`AcqRel`].
#[inline]
#[unstable(feature = "atomic_volatile", issue = "158947")]
#[rustc_const_unstable(feature = "atomic_volatile", issue = "158947")]
pub const unsafe fn load_volatile(self: *const Self, order: Ordering)
-> usize {
unsafe { atomic_load::<_, true>(self.cast::<usize>(), order) }
}
/// Stores a value into the atomic integer.
///
/// `store` takes an [`Ordering`] argument which describes the memory ordering of this operation.
/// Possible values are [`SeqCst`], [`Release`] and [`Relaxed`].
///
/// # Panics
///
/// Panics if `order` is [`Acquire`] or [`AcqRel`].
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicUsize, Ordering};"]
///
#[doc = "let some_var = AtomicUsize::new(5);"]
///
/// some_var.store(10, Ordering::Relaxed);
/// assert_eq!(some_var.load(Ordering::Relaxed), 10);
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn store(&self, val: usize, order: Ordering) {
unsafe { atomic_store::<_, false>(self.as_ptr(), val, order); }
}
/// Performs a volatile store into the atomic integer.
///
/// `store_volatile` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. Possible values are [`SeqCst`], [`Release`] and [`Relaxed`].
///
#[doc =
"Volatile operations are intended to act on I/O memory. As such, they are considered externally\nobservable events (just like syscalls), and are guaranteed to not be elided or reordered by the\ncompiler across other externally observable events. With this in mind, there are two cases of\nusage that need to be distinguished:\n\n- When a volatile operation is used for memory inside an [allocation], it behaves exactly like\n [`store`][Self::store], except for the additional guarantee that it won\'t be elided or reordered\n across other externally observable events (see above). This implies that the operation will\n actually access memory and not e.g. be lowered to a register access. Other than that, all the\n usual rules for memory accesses apply (including provenance).\n\n- Volatile operations, however, may also be used to access memory that is _outside_ of any Rust\n allocation. In this use-case, the pointer does *not* have to be [valid] for writes. This is\n typically used for CPU and peripheral registers that must be accessed via an I/O memory mapping,\n most commonly at fixed addresses reserved by the hardware. These often have special semantics\n associated to their manipulation, and cannot be used as general purpose memory. Here, any address\n value is possible, including 0 and [`usize::MAX`], so long as the semantics of such a write are\n well-defined by the target hardware. The provenance of the pointer is irrelevant, and it can be\n created with [`without_provenance_mut`][crate::ptr::without_provenance_mut]. The access is allowed\n to trap, which must immediately abort the process. It can also cause other side-effects, but those\n must not affect Rust-allocated memory in any way.\n\nIn both cases, the access is also considered atomic with the given `order`. This allows\nsynchronization with other threads or devices that share memory with this program.\n\nWhen invoked during const evaluation, this behaves like a regular atomic store. In\nparticular, such reads must always follow the first of the two cases above.\n\n[allocation]: crate::ptr#allocated-object\n"]
///
/// # Safety
///
/// Behavior is undefined if any of the following conditions are violated:
///
/// * `self` must be either [valid] for writes, or `self` must point to memory
/// outside of all Rust allocations and writing to that memory must:
/// - not trap, and
/// - not cause any memory inside a Rust allocation to be modified.
///
/// * `self` must be aligned to
#[doc = " `align_of::<AtomicUsize>()`"]
#[doc =
" (note that on some platforms this can be bigger than `align_of::<usize>()`)."]
///
/// [valid]: core::ptr#safety
///
/// # Panics
///
/// Panics if `order` is [`Acquire`] or [`AcqRel`].
#[inline]
#[unstable(feature = "atomic_volatile", issue = "158947")]
#[rustc_const_unstable(feature = "atomic_volatile", issue = "158947")]
#[rustc_should_not_be_called_on_const_items]
pub const unsafe fn store_volatile(self: *const Self, val: usize,
order: Ordering) {
unsafe {
atomic_store::<_,
true>(self.cast::<usize>().cast_mut(), val, order);
}
}
/// Stores a value into the atomic integer, returning the previous value.
///
/// `swap` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`usize`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicUsize, Ordering};"]
///
#[doc = "let some_var = AtomicUsize::new(5);"]
///
/// assert_eq!(some_var.swap(10, Ordering::Relaxed), 5);
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn swap(&self, val: usize, order: Ordering) -> usize {
unsafe { atomic_swap(self.as_ptr(), val, order) }
}
/// Stores a value into the atomic integer if the current value is the same as
/// the `current` value.
///
/// The return value is always the previous value. If it is equal to `current`, then the
/// value was updated.
///
/// `compare_and_swap` also takes an [`Ordering`] argument which describes the memory
/// ordering of this operation. Notice that even when using [`AcqRel`], the operation
/// might fail and hence just perform an `Acquire` load, but not have `Release` semantics.
/// Using [`Acquire`] makes the store part of this operation [`Relaxed`] if it
/// happens, and using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`usize`]."]
///
/// # Migrating to `compare_exchange` and `compare_exchange_weak`
///
/// `compare_and_swap` is equivalent to `compare_exchange` with the following mapping for
/// memory orderings:
///
/// Original | Success | Failure
/// -------- | ------- | -------
/// Relaxed | Relaxed | Relaxed
/// Acquire | Acquire | Acquire
/// Release | Release | Relaxed
/// AcqRel | AcqRel | Acquire
/// SeqCst | SeqCst | SeqCst
///
/// `compare_and_swap` and `compare_exchange` also differ in their return type. You can use
/// `compare_exchange(...).unwrap_or_else(|x| x)` to recover the behavior of `compare_and_swap`,
/// but in most cases it is more idiomatic to check whether the return value is `Ok` or `Err`
/// rather than to infer success vs failure based on the value that was read.
///
/// During migration, consider whether it makes sense to use `compare_exchange_weak` instead.
/// `compare_exchange_weak` is allowed to fail spuriously even when the comparison succeeds,
/// which allows the compiler to generate better assembly code when the compare and swap
/// is used in a loop.
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicUsize, Ordering};"]
///
#[doc = "let some_var = AtomicUsize::new(5);"]
///
/// assert_eq!(some_var.compare_and_swap(5, 10, Ordering::Relaxed), 5);
/// assert_eq!(some_var.load(Ordering::Relaxed), 10);
///
/// assert_eq!(some_var.compare_and_swap(6, 12, Ordering::Relaxed), 10);
/// assert_eq!(some_var.load(Ordering::Relaxed), 10);
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[deprecated(since = "1.50.0", note =
"Use `compare_exchange` or `compare_exchange_weak` instead")]
#[rustc_should_not_be_called_on_const_items]
pub const fn compare_and_swap(&self, current: usize, new: usize,
order: Ordering) -> usize {
match self.compare_exchange(current, new, order,
strongest_failure_ordering(order)) {
Ok(x) => x,
Err(x) => x,
}
}
/// Stores a value into the atomic integer if the current value is the same as
/// the `current` value.
///
/// The return value is a result indicating whether the new value was written and
/// containing the previous value. On success this value is guaranteed to be equal to
/// `current`.
///
/// `compare_exchange` takes two [`Ordering`] arguments to describe the memory
/// ordering of this operation. `success` describes the required ordering for the
/// read-modify-write operation that takes place if the comparison with `current` succeeds.
/// `failure` describes the required ordering for the load operation that takes place when
/// the comparison fails. Using [`Acquire`] as success ordering makes the store part
/// of this operation [`Relaxed`], and using [`Release`] makes the successful load
/// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`usize`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicUsize, Ordering};"]
///
#[doc = "let some_var = AtomicUsize::new(5);"]
///
/// assert_eq!(some_var.compare_exchange(5, 10,
/// Ordering::Acquire,
/// Ordering::Relaxed),
/// Ok(5));
/// assert_eq!(some_var.load(Ordering::Relaxed), 10);
///
/// assert_eq!(some_var.compare_exchange(6, 12,
/// Ordering::SeqCst,
/// Ordering::Acquire),
/// Err(10));
/// assert_eq!(some_var.load(Ordering::Relaxed), 10);
/// ```
///
/// # Considerations
///
/// `compare_exchange` is a [compare-and-swap operation] and thus exhibits the usual downsides
/// of CAS operations. In particular, a load of the value followed by a successful
/// `compare_exchange` with the previous load *does not ensure* that other threads have not
/// changed the value in the interim! This is usually important when the *equality* check in
/// the `compare_exchange` is being used to check the *identity* of a value, but equality
/// does not necessarily imply identity. This is a particularly common case for pointers, as
/// a pointer holding the same address does not imply that the same object exists at that
/// address! In this case, `compare_exchange` can lead to the [ABA problem].
///
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
#[inline]
#[stable(feature = "extended_compare_and_swap", since = "1.10.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn compare_exchange(&self, current: usize, new: usize,
success: Ordering, failure: Ordering) -> Result<usize, usize> {
unsafe {
atomic_compare_exchange(self.as_ptr(), current, new, success,
failure)
}
}
/// Stores a value into the atomic integer if the current value is the same as
/// the `current` value.
///
#[doc = "Unlike [`AtomicUsize::compare_exchange`],"]
/// this function is allowed to spuriously fail even
/// when the comparison succeeds, which can result in more efficient code on some
/// platforms. The return value is a result indicating whether the new value was
/// written and containing the previous value.
///
/// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory
/// ordering of this operation. `success` describes the required ordering for the
/// read-modify-write operation that takes place if the comparison with `current` succeeds.
/// `failure` describes the required ordering for the load operation that takes place when
/// the comparison fails. Using [`Acquire`] as success ordering makes the store part
/// of this operation [`Relaxed`], and using [`Release`] makes the successful load
/// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`usize`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicUsize, Ordering};"]
///
#[doc = "let val = AtomicUsize::new(4);"]
///
/// let mut old = val.load(Ordering::Relaxed);
/// loop {
/// let new = old * 2;
/// match val.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) {
/// Ok(_) => break,
/// Err(x) => old = x,
/// }
/// }
/// ```
///
/// # Considerations
///
/// `compare_exchange` is a [compare-and-swap operation] and thus exhibits the usual downsides
/// of CAS operations. In particular, a load of the value followed by a successful
/// `compare_exchange` with the previous load *does not ensure* that other threads have not
/// changed the value in the interim. This is usually important when the *equality* check in
/// the `compare_exchange` is being used to check the *identity* of a value, but equality
/// does not necessarily imply identity. This is a particularly common case for pointers, as
/// a pointer holding the same address does not imply that the same object exists at that
/// address! In this case, `compare_exchange` can lead to the [ABA problem].
///
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
#[inline]
#[stable(feature = "extended_compare_and_swap", since = "1.10.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn compare_exchange_weak(&self, current: usize, new: usize,
success: Ordering, failure: Ordering) -> Result<usize, usize> {
unsafe {
atomic_compare_exchange_weak(self.as_ptr(), current, new, success,
failure)
}
}
/// Adds to the current value, returning the previous value.
///
/// This operation wraps around on overflow.
///
/// `fetch_add` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`usize`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicUsize, Ordering};"]
///
#[doc = "let foo = AtomicUsize::new(0);"]
/// assert_eq!(foo.fetch_add(10, Ordering::SeqCst), 0);
/// assert_eq!(foo.load(Ordering::SeqCst), 10);
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_add(&self, val: usize, order: Ordering) -> usize {
unsafe { atomic_add(self.as_ptr(), val, order) }
}
/// Subtracts from the current value, returning the previous value.
///
/// This operation wraps around on overflow.
///
/// `fetch_sub` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`usize`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicUsize, Ordering};"]
///
#[doc = "let foo = AtomicUsize::new(20);"]
/// assert_eq!(foo.fetch_sub(10, Ordering::SeqCst), 20);
/// assert_eq!(foo.load(Ordering::SeqCst), 10);
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_sub(&self, val: usize, order: Ordering) -> usize {
unsafe { atomic_sub(self.as_ptr(), val, order) }
}
/// Bitwise "and" with the current value.
///
/// Performs a bitwise "and" operation on the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_and` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`usize`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicUsize, Ordering};"]
///
#[doc = "let foo = AtomicUsize::new(0b101101);"]
/// assert_eq!(foo.fetch_and(0b110011, Ordering::SeqCst), 0b101101);
/// assert_eq!(foo.load(Ordering::SeqCst), 0b100001);
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_and(&self, val: usize, order: Ordering) -> usize {
unsafe { atomic_and(self.as_ptr(), val, order) }
}
/// Bitwise "nand" with the current value.
///
/// Performs a bitwise "nand" operation on the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_nand` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`usize`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicUsize, Ordering};"]
///
#[doc = "let foo = AtomicUsize::new(0x13);"]
/// assert_eq!(foo.fetch_nand(0x31, Ordering::SeqCst), 0x13);
/// assert_eq!(foo.load(Ordering::SeqCst), !(0x13 & 0x31));
/// ```
#[inline]
#[stable(feature = "atomic_nand", since = "1.27.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_nand(&self, val: usize, order: Ordering) -> usize {
unsafe { atomic_nand(self.as_ptr(), val, order) }
}
/// Bitwise "or" with the current value.
///
/// Performs a bitwise "or" operation on the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_or` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`usize`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicUsize, Ordering};"]
///
#[doc = "let foo = AtomicUsize::new(0b101101);"]
/// assert_eq!(foo.fetch_or(0b110011, Ordering::SeqCst), 0b101101);
/// assert_eq!(foo.load(Ordering::SeqCst), 0b111111);
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_or(&self, val: usize, order: Ordering) -> usize {
unsafe { atomic_or(self.as_ptr(), val, order) }
}
/// Bitwise "xor" with the current value.
///
/// Performs a bitwise "xor" operation on the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_xor` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`usize`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicUsize, Ordering};"]
///
#[doc = "let foo = AtomicUsize::new(0b101101);"]
/// assert_eq!(foo.fetch_xor(0b110011, Ordering::SeqCst), 0b101101);
/// assert_eq!(foo.load(Ordering::SeqCst), 0b011110);
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_xor(&self, val: usize, order: Ordering) -> usize {
unsafe { atomic_xor(self.as_ptr(), val, order) }
}
/// An alias for
#[doc = "[`AtomicUsize::try_update`]"]
/// .
#[inline]
#[stable(feature = "no_more_cas", since = "1.45.0")]
#[rustc_should_not_be_called_on_const_items]
#[deprecated(since = "1.99.0", note =
"renamed to `try_update` for consistency", suggestion = "try_update")]
pub fn fetch_update<F>(&self, set_order: Ordering, fetch_order: Ordering,
f: F) -> Result<usize, usize> where F: FnMut(usize) -> Option<usize> {
self.try_update(set_order, fetch_order, f)
}
/// Fetches the value, and applies a function to it that returns an optional
/// new value. Returns a `Result` of `Ok(previous_value)` if the function returned `Some(_)`, else
/// `Err(previous_value)`.
///
#[doc = "See also: [`update`](`AtomicUsize::update`)."]
///
/// Note: This may call the function multiple times if the value has been changed from other threads in
/// the meantime, as long as the function returns `Some(_)`, but the function will have been applied
/// only once to the stored value.
///
/// `try_update` takes two [`Ordering`] arguments to describe the memory ordering of this operation.
/// The first describes the required ordering for when the operation finally succeeds while the second
/// describes the required ordering for loads. These correspond to the success and failure orderings of
#[doc = "[`AtomicUsize::compare_exchange`]"]
/// respectively.
///
/// Using [`Acquire`] as success ordering makes the store part
/// of this operation [`Relaxed`], and using [`Release`] makes the final successful load
/// [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`usize`]."]
///
/// # Considerations
///
/// This method is not magic; it is not provided by the hardware, and does not act like a
/// critical section or mutex.
///
/// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
/// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem]
/// if this atomic integer is an index or more generally if knowledge of only the *bitwise value*
/// of the atomic is not in and of itself sufficient to ensure any required preconditions.
///
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
///
/// # Examples
///
#[doc = "```rust"]
#[doc = "use std::sync::atomic::{AtomicUsize, Ordering};"]
///
#[doc = "let x = AtomicUsize::new(7);"]
/// assert_eq!(x.try_update(Ordering::SeqCst, Ordering::SeqCst, |_| None), Err(7));
/// assert_eq!(x.try_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(x + 1)), Ok(7));
/// assert_eq!(x.try_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(x + 1)), Ok(8));
/// assert_eq!(x.load(Ordering::SeqCst), 9);
/// ```
#[inline]
#[stable(feature = "atomic_try_update", since = "1.95.0")]
#[rustc_should_not_be_called_on_const_items]
pub fn try_update(&self, set_order: Ordering, fetch_order: Ordering,
mut f: impl FnMut(usize) -> Option<usize>) -> Result<usize, usize> {
let mut prev = self.load(fetch_order);
while let Some(next) = f(prev) {
match self.compare_exchange_weak(prev, next, set_order,
fetch_order) {
x @ Ok(_) => return x,
Err(next_prev) => prev = next_prev,
}
}
Err(prev)
}
/// Fetches the value, and applies a function to it that returns a new value.
/// The new value is stored and the old value is returned.
///
#[doc = "See also: [`try_update`](`AtomicUsize::try_update`)."]
///
/// Note: This may call the function multiple times if the value has been changed from other threads in
/// the meantime, but the function will have been applied only once to the stored value.
///
/// `update` takes two [`Ordering`] arguments to describe the memory ordering of this operation.
/// The first describes the required ordering for when the operation finally succeeds while the second
/// describes the required ordering for loads. These correspond to the success and failure orderings of
#[doc = "[`AtomicUsize::compare_exchange`]"]
/// respectively.
///
/// Using [`Acquire`] as success ordering makes the store part
/// of this operation [`Relaxed`], and using [`Release`] makes the final successful load
/// [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`usize`]."]
///
/// # Considerations
///
/// [CAS operation]: https://en.wikipedia.org/wiki/Compare-and-swap
/// This method is not magic; it is not provided by the hardware, and does not act like a
/// critical section or mutex.
///
/// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to
/// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem]
/// if this atomic integer is an index or more generally if knowledge of only the *bitwise value*
/// of the atomic is not in and of itself sufficient to ensure any required preconditions.
///
/// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
/// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap
///
/// # Examples
///
#[doc = "```rust"]
#[doc = "use std::sync::atomic::{AtomicUsize, Ordering};"]
///
#[doc = "let x = AtomicUsize::new(7);"]
/// assert_eq!(x.update(Ordering::SeqCst, Ordering::SeqCst, |x| x + 1), 7);
/// assert_eq!(x.update(Ordering::SeqCst, Ordering::SeqCst, |x| x + 1), 8);
/// assert_eq!(x.load(Ordering::SeqCst), 9);
/// ```
#[inline]
#[stable(feature = "atomic_try_update", since = "1.95.0")]
#[rustc_should_not_be_called_on_const_items]
pub fn update(&self, set_order: Ordering, fetch_order: Ordering,
mut f: impl FnMut(usize) -> usize) -> usize {
let mut prev = self.load(fetch_order);
loop {
match self.compare_exchange_weak(prev, f(prev), set_order,
fetch_order) {
Ok(x) => break x,
Err(next_prev) => prev = next_prev,
}
}
}
/// Maximum with the current value.
///
/// Finds the maximum of the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_max` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`usize`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicUsize, Ordering};"]
///
#[doc = "let foo = AtomicUsize::new(23);"]
/// assert_eq!(foo.fetch_max(42, Ordering::SeqCst), 23);
/// assert_eq!(foo.load(Ordering::SeqCst), 42);
/// ```
///
/// If you want to obtain the maximum value in one step, you can use the following:
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicUsize, Ordering};"]
///
#[doc = "let foo = AtomicUsize::new(23);"]
/// let bar = 42;
/// let max_foo = foo.fetch_max(bar, Ordering::SeqCst).max(bar);
/// assert!(max_foo == 42);
/// ```
#[inline]
#[stable(feature = "atomic_min_max", since = "1.45.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_max(&self, val: usize, order: Ordering) -> usize {
unsafe { atomic_umax(self.as_ptr(), val, order) }
}
/// Minimum with the current value.
///
/// Finds the minimum of the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// `fetch_min` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation. All ordering modes are possible. Note that using
/// [`Acquire`] makes the store part of this operation [`Relaxed`], and
/// using [`Release`] makes the load part [`Relaxed`].
///
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = "[`usize`]."]
///
/// # Examples
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicUsize, Ordering};"]
///
#[doc = "let foo = AtomicUsize::new(23);"]
/// assert_eq!(foo.fetch_min(42, Ordering::Relaxed), 23);
/// assert_eq!(foo.load(Ordering::Relaxed), 23);
/// assert_eq!(foo.fetch_min(22, Ordering::Relaxed), 23);
/// assert_eq!(foo.load(Ordering::Relaxed), 22);
/// ```
///
/// If you want to obtain the minimum value in one step, you can use the following:
///
#[doc = "```"]
#[doc = "use std::sync::atomic::{AtomicUsize, Ordering};"]
///
#[doc = "let foo = AtomicUsize::new(23);"]
/// let bar = 12;
/// let min_foo = foo.fetch_min(bar, Ordering::SeqCst).min(bar);
/// assert_eq!(min_foo, 12);
/// ```
#[inline]
#[stable(feature = "atomic_min_max", since = "1.45.0")]
#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
#[rustc_should_not_be_called_on_const_items]
pub const fn fetch_min(&self, val: usize, order: Ordering) -> usize {
unsafe { atomic_umin(self.as_ptr(), val, order) }
}
/// Returns a mutable pointer to the underlying integer.
///
/// Doing non-atomic reads and writes on the resulting integer can be a data race.
/// This method is mostly useful for FFI, where the function signature may use
#[doc = "`*mut usize` instead of `&AtomicUsize`."]
///
/// Returning an `*mut` pointer from a shared reference to this atomic is safe because the
/// atomic types work with interior mutability. All modifications of an atomic change the value
/// through a shared reference, and can do so safely as long as they use atomic operations. Any
/// use of the returned raw pointer requires an `unsafe` block and still has to uphold the
/// requirements of the [memory model].
///
/// # Examples
///
/// ```ignore (extern-declaration)
/// # fn main() {
#[doc = "use std::sync::atomic::AtomicUsize;"]
///
/// extern "C" {
#[doc = " fn my_atomic_op(arg: *mut usize);"]
/// }
///
#[doc = "let atomic = AtomicUsize::new(1);"]
///
/// // SAFETY: Safe as long as `my_atomic_op` is atomic.
/// unsafe {
/// my_atomic_op(atomic.as_ptr());
/// }
/// # }
/// ```
///
/// [memory model]: self#memory-model-for-atomic-accesses
#[inline]
#[stable(feature = "atomic_as_ptr", since = "1.70.0")]
#[rustc_const_stable(feature = "atomic_as_ptr", since = "1.70.0")]
#[rustc_never_returns_null_ptr]
pub const fn as_ptr(&self) -> *mut usize { self.v.get().cast() }
}
/// An [`AtomicIsize`] initialized to `0`.
#[stable(feature = "rust1", since = "1.0.0")]
#[deprecated(since = "1.34.0", note = "the `new` function is now preferred",
suggestion = "AtomicIsize::new(0)",)]
#[expect(clippy :: declare_interior_mutable_const, reason =
"legacy atomic initializer")]
pub const ATOMIC_ISIZE_INIT: AtomicIsize = AtomicIsize::new(0);
/// An [`AtomicUsize`] initialized to `0`.
#[stable(feature = "rust1", since = "1.0.0")]
#[deprecated(since = "1.34.0", note = "the `new` function is now preferred",
suggestion = "AtomicUsize::new(0)",)]
#[expect(clippy :: declare_interior_mutable_const, reason =
"legacy atomic initializer")]
pub const ATOMIC_USIZE_INIT: AtomicUsize = AtomicUsize::new(0);atomic_int_ptr_sized! {
4279"16" 2
4280"32" 4
4281"64" 8
4282}42834284#[inline]
4285#[cfg(target_has_atomic)]
4286const fn strongest_failure_ordering(order: Ordering) -> Ordering {
4287match order {
4288Release => Relaxed,
4289Relaxed => Relaxed,
4290SeqCst => SeqCst,
4291Acquire => Acquire,
4292AcqRel => Acquire,
4293 }
4294}
42954296#[inline]
4297#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
4298#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
4299const unsafe fn atomic_store<T: Copy, const VOLATILE: bool>(dst: *mut T, val: T, order: Ordering) {
4300// SAFETY: the caller must uphold the safety contract for `atomic_store`.
4301unsafe {
4302match order {
4303Relaxed => intrinsics::atomic_store::<T, { AO::Relaxed }, VOLATILE>(dst, val),
4304Release => intrinsics::atomic_store::<T, { AO::Release }, VOLATILE>(dst, val),
4305SeqCst => intrinsics::atomic_store::<T, { AO::SeqCst }, VOLATILE>(dst, val),
4306Acquire => {
crate::panicking::panic_fmt(format_args!("there is no such thing as an acquire store"));
}panic!("there is no such thing as an acquire store"),
4307AcqRel => {
crate::panicking::panic_fmt(format_args!("there is no such thing as an acquire-release store"));
}panic!("there is no such thing as an acquire-release store"),
4308 }
4309 }
4310}
43114312#[inline]
4313#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
4314#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
4315const unsafe fn atomic_load<T: Copy, const VOLATILE: bool>(dst: *const T, order: Ordering) -> T {
4316// SAFETY: the caller must uphold the safety contract for `atomic_load`.
4317unsafe {
4318match order {
4319Relaxed => intrinsics::atomic_load::<T, { AO::Relaxed }, VOLATILE>(dst),
4320Acquire => intrinsics::atomic_load::<T, { AO::Acquire }, VOLATILE>(dst),
4321SeqCst => intrinsics::atomic_load::<T, { AO::SeqCst }, VOLATILE>(dst),
4322Release => {
crate::panicking::panic_fmt(format_args!("there is no such thing as a release load"));
}panic!("there is no such thing as a release load"),
4323AcqRel => {
crate::panicking::panic_fmt(format_args!("there is no such thing as an acquire-release load"));
}panic!("there is no such thing as an acquire-release load"),
4324 }
4325 }
4326}
43274328#[inline]
4329#[cfg(target_has_atomic)]
4330#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
4331#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
4332const unsafe fn atomic_swap<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
4333// SAFETY: the caller must uphold the safety contract for `atomic_swap`.
4334unsafe {
4335match order {
4336Relaxed => intrinsics::atomic_xchg::<T, { AO::Relaxed }>(dst, val),
4337Acquire => intrinsics::atomic_xchg::<T, { AO::Acquire }>(dst, val),
4338Release => intrinsics::atomic_xchg::<T, { AO::Release }>(dst, val),
4339AcqRel => intrinsics::atomic_xchg::<T, { AO::AcqRel }>(dst, val),
4340SeqCst => intrinsics::atomic_xchg::<T, { AO::SeqCst }>(dst, val),
4341 }
4342 }
4343}
43444345/// Returns the previous value (like __sync_fetch_and_add).
4346#[inline]
4347#[cfg(target_has_atomic)]
4348#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
4349#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
4350const unsafe fn atomic_add<T: Copy, U: Copy>(dst: *mut T, val: U, order: Ordering) -> T {
4351// SAFETY: the caller must uphold the safety contract for `atomic_add`.
4352unsafe {
4353match order {
4354Relaxed => intrinsics::atomic_xadd::<T, U, { AO::Relaxed }>(dst, val),
4355Acquire => intrinsics::atomic_xadd::<T, U, { AO::Acquire }>(dst, val),
4356Release => intrinsics::atomic_xadd::<T, U, { AO::Release }>(dst, val),
4357AcqRel => intrinsics::atomic_xadd::<T, U, { AO::AcqRel }>(dst, val),
4358SeqCst => intrinsics::atomic_xadd::<T, U, { AO::SeqCst }>(dst, val),
4359 }
4360 }
4361}
43624363/// Returns the previous value (like __sync_fetch_and_sub).
4364#[inline]
4365#[cfg(target_has_atomic)]
4366#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
4367#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
4368const unsafe fn atomic_sub<T: Copy, U: Copy>(dst: *mut T, val: U, order: Ordering) -> T {
4369// SAFETY: the caller must uphold the safety contract for `atomic_sub`.
4370unsafe {
4371match order {
4372Relaxed => intrinsics::atomic_xsub::<T, U, { AO::Relaxed }>(dst, val),
4373Acquire => intrinsics::atomic_xsub::<T, U, { AO::Acquire }>(dst, val),
4374Release => intrinsics::atomic_xsub::<T, U, { AO::Release }>(dst, val),
4375AcqRel => intrinsics::atomic_xsub::<T, U, { AO::AcqRel }>(dst, val),
4376SeqCst => intrinsics::atomic_xsub::<T, U, { AO::SeqCst }>(dst, val),
4377 }
4378 }
4379}
43804381/// Publicly exposed for stdarch; nobody else should use this.
4382#[inline]
4383#[cfg(target_has_atomic)]
4384#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
4385#[unstable(feature = "core_intrinsics", issue = "none")]
4386#[doc(hidden)]
4387#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
4388pub const unsafe fn atomic_compare_exchange<T: Copy>(
4389 dst: *mut T,
4390 old: T,
4391 new: T,
4392 success: Ordering,
4393 failure: Ordering,
4394) -> Result<T, T> {
4395// SAFETY: the caller must uphold the safety contract for `atomic_compare_exchange`.
4396let (val, ok) = unsafe {
4397match (success, failure) {
4398 (Relaxed, Relaxed) => {
4399 intrinsics::atomic_cxchg::<T, { AO::Relaxed }, { AO::Relaxed }>(dst, old, new)
4400 }
4401 (Relaxed, Acquire) => {
4402 intrinsics::atomic_cxchg::<T, { AO::Relaxed }, { AO::Acquire }>(dst, old, new)
4403 }
4404 (Relaxed, SeqCst) => {
4405 intrinsics::atomic_cxchg::<T, { AO::Relaxed }, { AO::SeqCst }>(dst, old, new)
4406 }
4407 (Acquire, Relaxed) => {
4408 intrinsics::atomic_cxchg::<T, { AO::Acquire }, { AO::Relaxed }>(dst, old, new)
4409 }
4410 (Acquire, Acquire) => {
4411 intrinsics::atomic_cxchg::<T, { AO::Acquire }, { AO::Acquire }>(dst, old, new)
4412 }
4413 (Acquire, SeqCst) => {
4414 intrinsics::atomic_cxchg::<T, { AO::Acquire }, { AO::SeqCst }>(dst, old, new)
4415 }
4416 (Release, Relaxed) => {
4417 intrinsics::atomic_cxchg::<T, { AO::Release }, { AO::Relaxed }>(dst, old, new)
4418 }
4419 (Release, Acquire) => {
4420 intrinsics::atomic_cxchg::<T, { AO::Release }, { AO::Acquire }>(dst, old, new)
4421 }
4422 (Release, SeqCst) => {
4423 intrinsics::atomic_cxchg::<T, { AO::Release }, { AO::SeqCst }>(dst, old, new)
4424 }
4425 (AcqRel, Relaxed) => {
4426 intrinsics::atomic_cxchg::<T, { AO::AcqRel }, { AO::Relaxed }>(dst, old, new)
4427 }
4428 (AcqRel, Acquire) => {
4429 intrinsics::atomic_cxchg::<T, { AO::AcqRel }, { AO::Acquire }>(dst, old, new)
4430 }
4431 (AcqRel, SeqCst) => {
4432 intrinsics::atomic_cxchg::<T, { AO::AcqRel }, { AO::SeqCst }>(dst, old, new)
4433 }
4434 (SeqCst, Relaxed) => {
4435 intrinsics::atomic_cxchg::<T, { AO::SeqCst }, { AO::Relaxed }>(dst, old, new)
4436 }
4437 (SeqCst, Acquire) => {
4438 intrinsics::atomic_cxchg::<T, { AO::SeqCst }, { AO::Acquire }>(dst, old, new)
4439 }
4440 (SeqCst, SeqCst) => {
4441 intrinsics::atomic_cxchg::<T, { AO::SeqCst }, { AO::SeqCst }>(dst, old, new)
4442 }
4443 (_, AcqRel) => {
crate::panicking::panic_fmt(format_args!("there is no such thing as an acquire-release failure ordering"));
}panic!("there is no such thing as an acquire-release failure ordering"),
4444 (_, Release) => {
crate::panicking::panic_fmt(format_args!("there is no such thing as a release failure ordering"));
}panic!("there is no such thing as a release failure ordering"),
4445 }
4446 };
4447if ok { Ok(val) } else { Err(val) }
4448}
44494450#[inline]
4451#[cfg(target_has_atomic)]
4452#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
4453#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
4454const unsafe fn atomic_compare_exchange_weak<T: Copy>(
4455 dst: *mut T,
4456 old: T,
4457 new: T,
4458 success: Ordering,
4459 failure: Ordering,
4460) -> Result<T, T> {
4461// SAFETY: the caller must uphold the safety contract for `atomic_compare_exchange_weak`.
4462let (val, ok) = unsafe {
4463match (success, failure) {
4464 (Relaxed, Relaxed) => {
4465 intrinsics::atomic_cxchgweak::<T, { AO::Relaxed }, { AO::Relaxed }>(dst, old, new)
4466 }
4467 (Relaxed, Acquire) => {
4468 intrinsics::atomic_cxchgweak::<T, { AO::Relaxed }, { AO::Acquire }>(dst, old, new)
4469 }
4470 (Relaxed, SeqCst) => {
4471 intrinsics::atomic_cxchgweak::<T, { AO::Relaxed }, { AO::SeqCst }>(dst, old, new)
4472 }
4473 (Acquire, Relaxed) => {
4474 intrinsics::atomic_cxchgweak::<T, { AO::Acquire }, { AO::Relaxed }>(dst, old, new)
4475 }
4476 (Acquire, Acquire) => {
4477 intrinsics::atomic_cxchgweak::<T, { AO::Acquire }, { AO::Acquire }>(dst, old, new)
4478 }
4479 (Acquire, SeqCst) => {
4480 intrinsics::atomic_cxchgweak::<T, { AO::Acquire }, { AO::SeqCst }>(dst, old, new)
4481 }
4482 (Release, Relaxed) => {
4483 intrinsics::atomic_cxchgweak::<T, { AO::Release }, { AO::Relaxed }>(dst, old, new)
4484 }
4485 (Release, Acquire) => {
4486 intrinsics::atomic_cxchgweak::<T, { AO::Release }, { AO::Acquire }>(dst, old, new)
4487 }
4488 (Release, SeqCst) => {
4489 intrinsics::atomic_cxchgweak::<T, { AO::Release }, { AO::SeqCst }>(dst, old, new)
4490 }
4491 (AcqRel, Relaxed) => {
4492 intrinsics::atomic_cxchgweak::<T, { AO::AcqRel }, { AO::Relaxed }>(dst, old, new)
4493 }
4494 (AcqRel, Acquire) => {
4495 intrinsics::atomic_cxchgweak::<T, { AO::AcqRel }, { AO::Acquire }>(dst, old, new)
4496 }
4497 (AcqRel, SeqCst) => {
4498 intrinsics::atomic_cxchgweak::<T, { AO::AcqRel }, { AO::SeqCst }>(dst, old, new)
4499 }
4500 (SeqCst, Relaxed) => {
4501 intrinsics::atomic_cxchgweak::<T, { AO::SeqCst }, { AO::Relaxed }>(dst, old, new)
4502 }
4503 (SeqCst, Acquire) => {
4504 intrinsics::atomic_cxchgweak::<T, { AO::SeqCst }, { AO::Acquire }>(dst, old, new)
4505 }
4506 (SeqCst, SeqCst) => {
4507 intrinsics::atomic_cxchgweak::<T, { AO::SeqCst }, { AO::SeqCst }>(dst, old, new)
4508 }
4509 (_, AcqRel) => {
crate::panicking::panic_fmt(format_args!("there is no such thing as an acquire-release failure ordering"));
}panic!("there is no such thing as an acquire-release failure ordering"),
4510 (_, Release) => {
crate::panicking::panic_fmt(format_args!("there is no such thing as a release failure ordering"));
}panic!("there is no such thing as a release failure ordering"),
4511 }
4512 };
4513if ok { Ok(val) } else { Err(val) }
4514}
45154516#[inline]
4517#[cfg(target_has_atomic)]
4518#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
4519#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
4520const unsafe fn atomic_and<T: Copy, U: Copy>(dst: *mut T, val: U, order: Ordering) -> T {
4521// SAFETY: the caller must uphold the safety contract for `atomic_and`
4522unsafe {
4523match order {
4524Relaxed => intrinsics::atomic_and::<T, U, { AO::Relaxed }>(dst, val),
4525Acquire => intrinsics::atomic_and::<T, U, { AO::Acquire }>(dst, val),
4526Release => intrinsics::atomic_and::<T, U, { AO::Release }>(dst, val),
4527AcqRel => intrinsics::atomic_and::<T, U, { AO::AcqRel }>(dst, val),
4528SeqCst => intrinsics::atomic_and::<T, U, { AO::SeqCst }>(dst, val),
4529 }
4530 }
4531}
45324533#[inline]
4534#[cfg(target_has_atomic)]
4535#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
4536#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
4537const unsafe fn atomic_nand<T: Copy, U: Copy>(dst: *mut T, val: U, order: Ordering) -> T {
4538// SAFETY: the caller must uphold the safety contract for `atomic_nand`
4539unsafe {
4540match order {
4541Relaxed => intrinsics::atomic_nand::<T, U, { AO::Relaxed }>(dst, val),
4542Acquire => intrinsics::atomic_nand::<T, U, { AO::Acquire }>(dst, val),
4543Release => intrinsics::atomic_nand::<T, U, { AO::Release }>(dst, val),
4544AcqRel => intrinsics::atomic_nand::<T, U, { AO::AcqRel }>(dst, val),
4545SeqCst => intrinsics::atomic_nand::<T, U, { AO::SeqCst }>(dst, val),
4546 }
4547 }
4548}
45494550#[inline]
4551#[cfg(target_has_atomic)]
4552#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
4553#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
4554const unsafe fn atomic_or<T: Copy, U: Copy>(dst: *mut T, val: U, order: Ordering) -> T {
4555// SAFETY: the caller must uphold the safety contract for `atomic_or`
4556unsafe {
4557match order {
4558SeqCst => intrinsics::atomic_or::<T, U, { AO::SeqCst }>(dst, val),
4559Acquire => intrinsics::atomic_or::<T, U, { AO::Acquire }>(dst, val),
4560Release => intrinsics::atomic_or::<T, U, { AO::Release }>(dst, val),
4561AcqRel => intrinsics::atomic_or::<T, U, { AO::AcqRel }>(dst, val),
4562Relaxed => intrinsics::atomic_or::<T, U, { AO::Relaxed }>(dst, val),
4563 }
4564 }
4565}
45664567#[inline]
4568#[cfg(target_has_atomic)]
4569#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
4570#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
4571const unsafe fn atomic_xor<T: Copy, U: Copy>(dst: *mut T, val: U, order: Ordering) -> T {
4572// SAFETY: the caller must uphold the safety contract for `atomic_xor`
4573unsafe {
4574match order {
4575SeqCst => intrinsics::atomic_xor::<T, U, { AO::SeqCst }>(dst, val),
4576Acquire => intrinsics::atomic_xor::<T, U, { AO::Acquire }>(dst, val),
4577Release => intrinsics::atomic_xor::<T, U, { AO::Release }>(dst, val),
4578AcqRel => intrinsics::atomic_xor::<T, U, { AO::AcqRel }>(dst, val),
4579Relaxed => intrinsics::atomic_xor::<T, U, { AO::Relaxed }>(dst, val),
4580 }
4581 }
4582}
45834584/// Updates `*dst` to the max value of `val` and the old value (signed comparison)
4585#[inline]
4586#[cfg(target_has_atomic)]
4587#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
4588#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
4589const unsafe fn atomic_max<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
4590// SAFETY: the caller must uphold the safety contract for `atomic_max`
4591unsafe {
4592match order {
4593Relaxed => intrinsics::atomic_max::<T, { AO::Relaxed }>(dst, val),
4594Acquire => intrinsics::atomic_max::<T, { AO::Acquire }>(dst, val),
4595Release => intrinsics::atomic_max::<T, { AO::Release }>(dst, val),
4596AcqRel => intrinsics::atomic_max::<T, { AO::AcqRel }>(dst, val),
4597SeqCst => intrinsics::atomic_max::<T, { AO::SeqCst }>(dst, val),
4598 }
4599 }
4600}
46014602/// Updates `*dst` to the min value of `val` and the old value (signed comparison)
4603#[inline]
4604#[cfg(target_has_atomic)]
4605#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
4606#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
4607const unsafe fn atomic_min<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
4608// SAFETY: the caller must uphold the safety contract for `atomic_min`
4609unsafe {
4610match order {
4611Relaxed => intrinsics::atomic_min::<T, { AO::Relaxed }>(dst, val),
4612Acquire => intrinsics::atomic_min::<T, { AO::Acquire }>(dst, val),
4613Release => intrinsics::atomic_min::<T, { AO::Release }>(dst, val),
4614AcqRel => intrinsics::atomic_min::<T, { AO::AcqRel }>(dst, val),
4615SeqCst => intrinsics::atomic_min::<T, { AO::SeqCst }>(dst, val),
4616 }
4617 }
4618}
46194620/// Updates `*dst` to the max value of `val` and the old value (unsigned comparison)
4621#[inline]
4622#[cfg(target_has_atomic)]
4623#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
4624#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
4625const unsafe fn atomic_umax<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
4626// SAFETY: the caller must uphold the safety contract for `atomic_umax`
4627unsafe {
4628match order {
4629Relaxed => intrinsics::atomic_umax::<T, { AO::Relaxed }>(dst, val),
4630Acquire => intrinsics::atomic_umax::<T, { AO::Acquire }>(dst, val),
4631Release => intrinsics::atomic_umax::<T, { AO::Release }>(dst, val),
4632AcqRel => intrinsics::atomic_umax::<T, { AO::AcqRel }>(dst, val),
4633SeqCst => intrinsics::atomic_umax::<T, { AO::SeqCst }>(dst, val),
4634 }
4635 }
4636}
46374638/// Updates `*dst` to the min value of `val` and the old value (unsigned comparison)
4639#[inline]
4640#[cfg(target_has_atomic)]
4641#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
4642#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
4643const unsafe fn atomic_umin<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
4644// SAFETY: the caller must uphold the safety contract for `atomic_umin`
4645unsafe {
4646match order {
4647Relaxed => intrinsics::atomic_umin::<T, { AO::Relaxed }>(dst, val),
4648Acquire => intrinsics::atomic_umin::<T, { AO::Acquire }>(dst, val),
4649Release => intrinsics::atomic_umin::<T, { AO::Release }>(dst, val),
4650AcqRel => intrinsics::atomic_umin::<T, { AO::AcqRel }>(dst, val),
4651SeqCst => intrinsics::atomic_umin::<T, { AO::SeqCst }>(dst, val),
4652 }
4653 }
4654}
46554656/// An atomic fence.
4657///
4658/// Fences create synchronization between themselves and atomic operations or fences in other
4659/// threads. It can be helpful to think of a fence as preventing the compiler and CPU from
4660/// reordering certain types of memory operations around it, but that is a simplified model which
4661/// fails to capture some of the nuances.
4662///
4663/// There are 3 different ways to use an atomic fence:
4664///
4665/// - atomic - fence synchronization: an atomic operation with (at least) [`Release`] ordering
4666/// semantics synchronizes with a fence with (at least) [`Acquire`] ordering semantics.
4667/// - fence - atomic synchronization: a fence with (at least) [`Release`] ordering semantics
4668/// synchronizes with an atomic operation with (at least) [`Acquire`] ordering semantics.
4669/// - fence - fence synchronization: a fence with (at least) [`Release`] ordering semantics
4670/// synchronizes with a fence with (at least) [`Acquire`] ordering semantics.
4671///
4672/// These 3 ways complement the regular, fence-less, atomic - atomic synchronization.
4673///
4674/// ## Atomic - Fence
4675///
4676/// An atomic operation on one thread will synchronize with a fence on another thread when:
4677///
4678/// - on thread 1:
4679/// - an atomic operation 'X' with (at least) [`Release`] ordering semantics on some atomic
4680/// object 'm',
4681///
4682/// - is paired on thread 2 with:
4683/// - an atomic read 'Y' with any order on 'm',
4684/// - followed by a fence 'B' with (at least) [`Acquire`] ordering semantics.
4685///
4686/// This provides a happens-before dependence between X and B.
4687///
4688/// ```text
4689/// Thread 1 Thread 2
4690///
4691/// m.store(3, Release); X ---------
4692/// |
4693/// |
4694/// -------------> Y if m.load(Relaxed) == 3 {
4695/// B fence(Acquire);
4696/// ...
4697/// }
4698/// ```
4699///
4700/// ## Fence - Atomic
4701///
4702/// A fence on one thread will synchronize with an atomic operation on another thread when:
4703///
4704/// - on thread:
4705/// - a fence 'A' with (at least) [`Release`] ordering semantics,
4706/// - followed by an atomic write 'X' with any ordering on some atomic object 'm',
4707///
4708/// - is paired on thread 2 with:
4709/// - an atomic operation 'Y' with (at least) [`Acquire`] ordering semantics.
4710///
4711/// This provides a happens-before dependence between A and Y.
4712///
4713/// ```text
4714/// Thread 1 Thread 2
4715///
4716/// fence(Release); A
4717/// m.store(3, Relaxed); X ---------
4718/// |
4719/// |
4720/// -------------> Y if m.load(Acquire) == 3 {
4721/// ...
4722/// }
4723/// ```
4724///
4725/// ## Fence - Fence
4726///
4727/// A fence on one thread will synchronize with a fence on another thread when:
4728///
4729/// - on thread 1:
4730/// - a fence 'A' which has (at least) [`Release`] ordering semantics,
4731/// - followed by an atomic write 'X' with any ordering on some atomic object 'm',
4732///
4733/// - is paired on thread 2 with:
4734/// - an atomic read 'Y' with any ordering on 'm',
4735/// - followed by a fence 'B' with (at least) [`Acquire`] ordering semantics.
4736///
4737/// This provides a happens-before dependence between A and B.
4738///
4739/// ```text
4740/// Thread 1 Thread 2
4741///
4742/// fence(Release); A --------------
4743/// m.store(3, Relaxed); X --------- |
4744/// | |
4745/// | |
4746/// -------------> Y if m.load(Relaxed) == 3 {
4747/// |-------> B fence(Acquire);
4748/// ...
4749/// }
4750/// ```
4751///
4752/// ## Mandatory Atomic
4753///
4754/// Note that in the examples above, it is crucial that the access to `m` are atomic. Fences cannot
4755/// be used to establish synchronization between non-atomic accesses in different threads. However,
4756/// thanks to the happens-before relationship, any non-atomic access that happen-before the atomic
4757/// operation or fence with (at least) [`Release`] ordering semantics are now also properly
4758/// synchronized with any non-atomic accesses that happen-after the atomic operation or fence with
4759/// (at least) [`Acquire`] ordering semantics.
4760///
4761/// ## Memory Ordering
4762///
4763/// A fence which has [`SeqCst`] ordering, in addition to having both [`Acquire`] and [`Release`]
4764/// semantics, participates in the global program order of the other [`SeqCst`] operations and/or
4765/// fences.
4766///
4767/// Accepts [`Acquire`], [`Release`], [`AcqRel`] and [`SeqCst`] orderings.
4768///
4769/// # Panics
4770///
4771/// Panics if `order` is [`Relaxed`].
4772///
4773/// # Examples
4774///
4775/// ```
4776/// use std::sync::atomic::AtomicBool;
4777/// use std::sync::atomic::fence;
4778/// use std::sync::atomic::Ordering;
4779///
4780/// // A mutual exclusion primitive based on spinlock.
4781/// pub struct Mutex {
4782/// flag: AtomicBool,
4783/// }
4784///
4785/// impl Mutex {
4786/// pub fn new() -> Mutex {
4787/// Mutex {
4788/// flag: AtomicBool::new(false),
4789/// }
4790/// }
4791///
4792/// pub fn lock(&self) {
4793/// // Wait until the old value is `false`.
4794/// while self
4795/// .flag
4796/// .compare_exchange_weak(false, true, Ordering::Relaxed, Ordering::Relaxed)
4797/// .is_err()
4798/// {}
4799/// // This fence synchronizes-with store in `unlock`.
4800/// fence(Ordering::Acquire);
4801/// }
4802///
4803/// pub fn unlock(&self) {
4804/// self.flag.store(false, Ordering::Release);
4805/// }
4806/// }
4807/// ```
4808#[inline]
4809#[stable(feature = "rust1", since = "1.0.0")]
4810#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
4811#[rustc_diagnostic_item = "fence"]
4812#[doc(alias = "atomic_thread_fence")]
4813#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
4814pub const fn fence(order: Ordering) {
4815// SAFETY: using an atomic fence is safe.
4816unsafe {
4817match order {
4818Acquire => intrinsics::atomic_fence::<{ AO::Acquire }>(),
4819Release => intrinsics::atomic_fence::<{ AO::Release }>(),
4820AcqRel => intrinsics::atomic_fence::<{ AO::AcqRel }>(),
4821SeqCst => intrinsics::atomic_fence::<{ AO::SeqCst }>(),
4822Relaxed => {
crate::panicking::panic_fmt(format_args!("there is no such thing as a relaxed fence"));
}panic!("there is no such thing as a relaxed fence"),
4823 }
4824 }
4825}
48264827/// An atomic fence for synchronization within a single thread.
4828///
4829/// Like [`fence`], this function establishes synchronization with other atomic operations and
4830/// fences. However, unlike [`fence`], `compiler_fence` only establishes synchronization with
4831/// operations *in the same thread*. This may at first sound rather useless, since code within a
4832/// thread is typically already totally ordered and does not need any further synchronization.
4833/// However, there are cases where code can run on the same thread without being synchronized:
4834/// - The most common case is that of a *signal handler*: a signal handler runs in the same thread
4835/// as the code it interrupted, but it is not synchronized with that code. `compiler_fence`
4836/// can be used to establish synchronization between a thread and its signal handler, the same way
4837/// that `fence` can be used to establish synchronization across threads.
4838/// - Similar situations can arise in embedded programming with interrupt handlers, or in custom
4839/// implementations of preemptive green threads. In general, `compiler_fence` can establish
4840/// synchronization with code that is guaranteed to run on the same hardware CPU.
4841///
4842/// See [`fence`] for how a fence can be used to achieve synchronization. Note that just like
4843/// [`fence`], synchronization still requires atomic operations to be used in both threads -- it is
4844/// not possible to perform synchronization entirely with fences and non-atomic operations.
4845///
4846/// `compiler_fence` does not emit any machine code. However, note that `compiler_fence` is also
4847/// *not* a "compiler barrier". It can be helpful to think of a `compiler_fence` as preventing the
4848/// compiler from reordering certain types of memory operations around it, but that is a simplified
4849/// model which fails to capture some of the nuances. The only actual guarantee made by
4850/// `compiler_fence` is establishing synchronization with signal handlers and similar kinds of code,
4851/// under the rules described in the [`fence`] documentation.
4852///
4853/// `compiler_fence` corresponds to [`atomic_signal_fence`] in C and C++.
4854///
4855/// [`atomic_signal_fence`]: https://en.cppreference.com/w/cpp/atomic/atomic_signal_fence
4856///
4857/// # Panics
4858///
4859/// Panics if `order` is [`Relaxed`].
4860///
4861/// # Examples
4862///
4863/// Without the two `compiler_fence` calls, the read of `IMPORTANT_VARIABLE` in `signal_handler`
4864/// is *undefined behavior* due to a data race, despite everything happening in a single thread.
4865/// This is because the signal handler is considered to run concurrently with its associated
4866/// thread, and explicit synchronization is required to pass data between a thread and its
4867/// signal handler. The code below uses two `compiler_fence` calls to establish the usual
4868/// release-acquire synchronization pattern (see [`fence`] for an image).
4869///
4870/// ```
4871/// use std::sync::atomic::AtomicBool;
4872/// use std::sync::atomic::Ordering;
4873/// use std::sync::atomic::compiler_fence;
4874///
4875/// static mut IMPORTANT_VARIABLE: usize = 0;
4876/// static IS_READY: AtomicBool = AtomicBool::new(false);
4877///
4878/// fn main() {
4879/// unsafe { IMPORTANT_VARIABLE = 42 };
4880/// // Marks earlier writes as being released with future relaxed stores.
4881/// compiler_fence(Ordering::Release);
4882/// IS_READY.store(true, Ordering::Relaxed);
4883/// }
4884///
4885/// fn signal_handler() {
4886/// if IS_READY.load(Ordering::Relaxed) {
4887/// // Acquires writes that were released with relaxed stores that we read from.
4888/// compiler_fence(Ordering::Acquire);
4889/// assert_eq!(unsafe { IMPORTANT_VARIABLE }, 42);
4890/// }
4891/// }
4892/// ```
4893#[inline]
4894#[stable(feature = "compiler_fences", since = "1.21.0")]
4895#[rustc_const_unstable(feature = "const_atomic", issue = "160078")]
4896#[rustc_diagnostic_item = "compiler_fence"]
4897#[doc(alias = "atomic_signal_fence")]
4898#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
4899pub const fn compiler_fence(order: Ordering) {
4900// SAFETY: using an atomic fence is safe.
4901unsafe {
4902match order {
4903Acquire => intrinsics::atomic_singlethreadfence::<{ AO::Acquire }>(),
4904Release => intrinsics::atomic_singlethreadfence::<{ AO::Release }>(),
4905AcqRel => intrinsics::atomic_singlethreadfence::<{ AO::AcqRel }>(),
4906SeqCst => intrinsics::atomic_singlethreadfence::<{ AO::SeqCst }>(),
4907Relaxed => {
crate::panicking::panic_fmt(format_args!("there is no such thing as a relaxed fence"));
}panic!("there is no such thing as a relaxed fence"),
4908 }
4909 }
4910}
49114912#[cfg(target_has_atomic_load_store = "8")]
4913#[stable(feature = "atomic_debug", since = "1.3.0")]
4914impl fmt::Debugfor AtomicBool {
4915fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
4916 fmt::Debug::fmt(&self.load(Ordering::Relaxed), f)
4917 }
4918}
49194920#[cfg(target_has_atomic_load_store = "ptr")]
4921#[stable(feature = "atomic_debug", since = "1.3.0")]
4922impl<T> fmt::Debugfor AtomicPtr<T> {
4923fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
4924 fmt::Debug::fmt(&self.load(Ordering::Relaxed), f)
4925 }
4926}
49274928#[cfg(target_has_atomic_load_store = "ptr")]
4929#[stable(feature = "atomic_pointer", since = "1.24.0")]
4930impl<T> fmt::Pointerfor AtomicPtr<T> {
4931fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
4932 fmt::Pointer::fmt(&self.load(Ordering::Relaxed), f)
4933 }
4934}
49354936/// Signals the processor that it is inside a busy-wait spin-loop ("spin lock").
4937///
4938/// This function is deprecated in favor of [`hint::spin_loop`].
4939///
4940/// [`hint::spin_loop`]: crate::hint::spin_loop
4941#[inline]
4942#[stable(feature = "spin_loop_hint", since = "1.24.0")]
4943#[deprecated(since = "1.51.0", note = "use hint::spin_loop instead")]
4944pub fn spin_loop_hint() {
4945spin_loop()
4946}