1 // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
13 //! Atomic types provide primitive shared-memory communication between
14 //! threads, and are the building blocks of other concurrent
17 //! This module defines atomic versions of a select number of primitive
18 //! types, including [`AtomicBool`], [`AtomicIsize`], and [`AtomicUsize`].
19 //! Atomic types present operations that, when used correctly, synchronize
20 //! updates between threads.
22 //! [`AtomicBool`]: struct.AtomicBool.html
23 //! [`AtomicIsize`]: struct.AtomicIsize.html
24 //! [`AtomicUsize`]: struct.AtomicUsize.html
26 //! Each method takes an [`Ordering`] which represents the strength of
27 //! the memory barrier for that operation. These orderings are the
28 //! same as [LLVM atomic orderings][1]. For more information see the [nomicon][2].
30 //! [`Ordering`]: enum.Ordering.html
32 //! [1]: http://llvm.org/docs/LangRef.html#memory-model-for-concurrent-operations
33 //! [2]: ../../../nomicon/atomics.html
35 //! Atomic variables are safe to share between threads (they implement [`Sync`])
36 //! but they do not themselves provide the mechanism for sharing and follow the
37 //! [threading model](../../../std/thread/index.html#the-threading-model) of rust.
38 //! The most common way to share an atomic variable is to put it into an [`Arc`][arc] (an
39 //! atomically-reference-counted shared pointer).
41 //! [`Sync`]: ../../marker/trait.Sync.html
42 //! [arc]: ../../../std/sync/struct.Arc.html
44 //! Most atomic types may be stored in static variables, initialized using
45 //! the provided static initializers like [`ATOMIC_BOOL_INIT`]. Atomic statics
46 //! are often used for lazy global initialization.
48 //! [`ATOMIC_BOOL_INIT`]: constant.ATOMIC_BOOL_INIT.html
52 //! A simple spinlock:
55 //! use std::sync::Arc;
56 //! use std::sync::atomic::{AtomicUsize, Ordering};
60 //! let spinlock = Arc::new(AtomicUsize::new(1));
62 //! let spinlock_clone = spinlock.clone();
63 //! let thread = thread::spawn(move|| {
64 //! spinlock_clone.store(0, Ordering::SeqCst);
67 //! // Wait for the other thread to release the lock
68 //! while spinlock.load(Ordering::SeqCst) != 0 {}
70 //! if let Err(panic) = thread.join() {
71 //! println!("Thread had an error: {:?}", panic);
76 //! Keep a global count of live threads:
79 //! use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
81 //! static GLOBAL_THREAD_COUNT: AtomicUsize = ATOMIC_USIZE_INIT;
83 //! let old_thread_count = GLOBAL_THREAD_COUNT.fetch_add(1, Ordering::SeqCst);
84 //! println!("live threads: {}", old_thread_count + 1);
87 #![stable(feature = "rust1", since = "1.0.0")]
88 #![cfg_attr(not(target_has_atomic = "8"), allow(dead_code))]
89 #![cfg_attr(not(target_has_atomic = "8"), allow(unused_imports))]
91 use self::Ordering::*;
97 /// Save power or switch hyperthreads in a busy-wait spin-loop.
99 /// This function is deliberately more primitive than
100 /// `std::thread::yield_now` and does not directly yield to the
101 /// system's scheduler. In some cases it might be useful to use a
102 /// combination of both functions. Careful benchmarking is advised.
104 /// On some platforms this function may not do anything at all.
106 #[stable(feature = "spin_loop_hint", since = "1.24.0")]
107 pub fn spin_loop_hint() {
108 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
110 asm!("pause" ::: "memory" : "volatile");
113 #[cfg(target_arch = "aarch64")]
115 asm!("yield" ::: "memory" : "volatile");
119 /// A boolean type which can be safely shared between threads.
121 /// This type has the same in-memory representation as a [`bool`].
123 /// [`bool`]: ../../../std/primitive.bool.html
124 #[cfg(target_has_atomic = "8")]
125 #[stable(feature = "rust1", since = "1.0.0")]
126 pub struct AtomicBool {
130 #[cfg(target_has_atomic = "8")]
131 #[stable(feature = "rust1", since = "1.0.0")]
132 impl Default for AtomicBool {
133 /// Creates an `AtomicBool` initialized to `false`.
134 fn default() -> Self {
139 // Send is implicitly implemented for AtomicBool.
140 #[cfg(target_has_atomic = "8")]
141 #[stable(feature = "rust1", since = "1.0.0")]
142 unsafe impl Sync for AtomicBool {}
144 /// A raw pointer type which can be safely shared between threads.
146 /// This type has the same in-memory representation as a `*mut T`.
147 #[cfg(target_has_atomic = "ptr")]
148 #[stable(feature = "rust1", since = "1.0.0")]
149 pub struct AtomicPtr<T> {
150 p: UnsafeCell<*mut T>,
153 #[cfg(target_has_atomic = "ptr")]
154 #[stable(feature = "rust1", since = "1.0.0")]
155 impl<T> Default for AtomicPtr<T> {
156 /// Creates a null `AtomicPtr<T>`.
157 fn default() -> AtomicPtr<T> {
158 AtomicPtr::new(::ptr::null_mut())
162 #[cfg(target_has_atomic = "ptr")]
163 #[stable(feature = "rust1", since = "1.0.0")]
164 unsafe impl<T> Send for AtomicPtr<T> {}
165 #[cfg(target_has_atomic = "ptr")]
166 #[stable(feature = "rust1", since = "1.0.0")]
167 unsafe impl<T> Sync for AtomicPtr<T> {}
169 /// Atomic memory orderings
171 /// Memory orderings limit the ways that both the compiler and CPU may reorder
172 /// instructions around atomic operations. At its most restrictive,
173 /// "sequentially consistent" atomics allow neither reads nor writes
174 /// to be moved either before or after the atomic operation; on the other end
175 /// "relaxed" atomics allow all reorderings.
177 /// Rust's memory orderings are [the same as
178 /// LLVM's](http://llvm.org/docs/LangRef.html#memory-model-for-concurrent-operations).
180 /// For more information see the [nomicon].
182 /// [nomicon]: ../../../nomicon/atomics.html
183 #[stable(feature = "rust1", since = "1.0.0")]
184 #[derive(Copy, Clone, Debug)]
186 /// No ordering constraints, only atomic operations.
188 /// Corresponds to LLVM's [`Monotonic`] ordering.
190 /// [`Monotonic`]: http://llvm.org/docs/Atomics.html#monotonic
191 #[stable(feature = "rust1", since = "1.0.0")]
193 /// When coupled with a store, all previous writes become visible
194 /// to the other threads that perform a load with [`Acquire`] ordering
195 /// on the same value.
197 /// [`Acquire`]: http://llvm.org/docs/Atomics.html#acquire
198 #[stable(feature = "rust1", since = "1.0.0")]
200 /// When coupled with a load, all subsequent loads will see data
201 /// written before a store with [`Release`] ordering on the same value
202 /// in other threads.
204 /// [`Release`]: http://llvm.org/docs/Atomics.html#release
205 #[stable(feature = "rust1", since = "1.0.0")]
207 /// When coupled with a load, uses [`Acquire`] ordering, and with a store
208 /// [`Release`] ordering.
210 /// [`Acquire`]: http://llvm.org/docs/Atomics.html#acquire
211 /// [`Release`]: http://llvm.org/docs/Atomics.html#release
212 #[stable(feature = "rust1", since = "1.0.0")]
214 /// Like `AcqRel` with the additional guarantee that all threads see all
215 /// sequentially consistent operations in the same order.
216 #[stable(feature = "rust1", since = "1.0.0")]
218 // Prevent exhaustive matching to allow for future extension
220 #[unstable(feature = "future_atomic_orderings", issue = "0")]
224 /// An [`AtomicBool`] initialized to `false`.
226 /// [`AtomicBool`]: struct.AtomicBool.html
227 #[cfg(target_has_atomic = "8")]
228 #[stable(feature = "rust1", since = "1.0.0")]
229 pub const ATOMIC_BOOL_INIT: AtomicBool = AtomicBool::new(false);
231 #[cfg(target_has_atomic = "8")]
233 /// Creates a new `AtomicBool`.
238 /// use std::sync::atomic::AtomicBool;
240 /// let atomic_true = AtomicBool::new(true);
241 /// let atomic_false = AtomicBool::new(false);
244 #[stable(feature = "rust1", since = "1.0.0")]
245 pub const fn new(v: bool) -> AtomicBool {
246 AtomicBool { v: UnsafeCell::new(v as u8) }
249 /// Returns a mutable reference to the underlying [`bool`].
251 /// This is safe because the mutable reference guarantees that no other threads are
252 /// concurrently accessing the atomic data.
254 /// [`bool`]: ../../../std/primitive.bool.html
259 /// use std::sync::atomic::{AtomicBool, Ordering};
261 /// let mut some_bool = AtomicBool::new(true);
262 /// assert_eq!(*some_bool.get_mut(), true);
263 /// *some_bool.get_mut() = false;
264 /// assert_eq!(some_bool.load(Ordering::SeqCst), false);
267 #[stable(feature = "atomic_access", since = "1.15.0")]
268 pub fn get_mut(&mut self) -> &mut bool {
269 unsafe { &mut *(self.v.get() as *mut bool) }
272 /// Consumes the atomic and returns the contained value.
274 /// This is safe because passing `self` by value guarantees that no other threads are
275 /// concurrently accessing the atomic data.
280 /// use std::sync::atomic::AtomicBool;
282 /// let some_bool = AtomicBool::new(true);
283 /// assert_eq!(some_bool.into_inner(), true);
286 #[stable(feature = "atomic_access", since = "1.15.0")]
287 pub fn into_inner(self) -> bool {
288 unsafe { self.v.into_inner() != 0 }
291 /// Loads a value from the bool.
293 /// `load` takes an [`Ordering`] argument which describes the memory ordering
294 /// of this operation.
298 /// Panics if `order` is [`Release`] or [`AcqRel`].
300 /// [`Ordering`]: enum.Ordering.html
301 /// [`Release`]: enum.Ordering.html#variant.Release
302 /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
307 /// use std::sync::atomic::{AtomicBool, Ordering};
309 /// let some_bool = AtomicBool::new(true);
311 /// assert_eq!(some_bool.load(Ordering::Relaxed), true);
314 #[stable(feature = "rust1", since = "1.0.0")]
315 pub fn load(&self, order: Ordering) -> bool {
316 unsafe { atomic_load(self.v.get(), order) != 0 }
319 /// Stores a value into the bool.
321 /// `store` takes an [`Ordering`] argument which describes the memory ordering
322 /// of this operation.
324 /// [`Ordering`]: enum.Ordering.html
329 /// use std::sync::atomic::{AtomicBool, Ordering};
331 /// let some_bool = AtomicBool::new(true);
333 /// some_bool.store(false, Ordering::Relaxed);
334 /// assert_eq!(some_bool.load(Ordering::Relaxed), false);
339 /// Panics if `order` is [`Acquire`] or [`AcqRel`].
341 /// [`Acquire`]: enum.Ordering.html#variant.Acquire
342 /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
344 #[stable(feature = "rust1", since = "1.0.0")]
345 pub fn store(&self, val: bool, order: Ordering) {
347 atomic_store(self.v.get(), val as u8, order);
351 /// Stores a value into the bool, returning the previous value.
353 /// `swap` takes an [`Ordering`] argument which describes the memory ordering
354 /// of this operation.
356 /// [`Ordering`]: enum.Ordering.html
361 /// use std::sync::atomic::{AtomicBool, Ordering};
363 /// let some_bool = AtomicBool::new(true);
365 /// assert_eq!(some_bool.swap(false, Ordering::Relaxed), true);
366 /// assert_eq!(some_bool.load(Ordering::Relaxed), false);
369 #[stable(feature = "rust1", since = "1.0.0")]
370 pub fn swap(&self, val: bool, order: Ordering) -> bool {
371 unsafe { atomic_swap(self.v.get(), val as u8, order) != 0 }
374 /// Stores a value into the [`bool`] if the current value is the same as the `current` value.
376 /// The return value is always the previous value. If it is equal to `current`, then the value
379 /// `compare_and_swap` also takes an [`Ordering`] argument which describes the memory
380 /// ordering of this operation.
382 /// [`Ordering`]: enum.Ordering.html
383 /// [`bool`]: ../../../std/primitive.bool.html
388 /// use std::sync::atomic::{AtomicBool, Ordering};
390 /// let some_bool = AtomicBool::new(true);
392 /// assert_eq!(some_bool.compare_and_swap(true, false, Ordering::Relaxed), true);
393 /// assert_eq!(some_bool.load(Ordering::Relaxed), false);
395 /// assert_eq!(some_bool.compare_and_swap(true, true, Ordering::Relaxed), false);
396 /// assert_eq!(some_bool.load(Ordering::Relaxed), false);
399 #[stable(feature = "rust1", since = "1.0.0")]
400 pub fn compare_and_swap(&self, current: bool, new: bool, order: Ordering) -> bool {
401 match self.compare_exchange(current, new, order, strongest_failure_ordering(order)) {
407 /// Stores a value into the [`bool`] if the current value is the same as the `current` value.
409 /// The return value is a result indicating whether the new value was written and containing
410 /// the previous value. On success this value is guaranteed to be equal to `current`.
412 /// `compare_exchange` takes two [`Ordering`] arguments to describe the memory
413 /// ordering of this operation. The first describes the required ordering if the
414 /// operation succeeds while the second describes the required ordering when the
415 /// operation fails. The failure ordering can't be [`Release`] or [`AcqRel`] and must
416 /// be equivalent or weaker than the success ordering.
418 /// [`bool`]: ../../../std/primitive.bool.html
419 /// [`Ordering`]: enum.Ordering.html
420 /// [`Release`]: enum.Ordering.html#variant.Release
421 /// [`AcqRel`]: enum.Ordering.html#variant.Release
426 /// use std::sync::atomic::{AtomicBool, Ordering};
428 /// let some_bool = AtomicBool::new(true);
430 /// assert_eq!(some_bool.compare_exchange(true,
432 /// Ordering::Acquire,
433 /// Ordering::Relaxed),
435 /// assert_eq!(some_bool.load(Ordering::Relaxed), false);
437 /// assert_eq!(some_bool.compare_exchange(true, true,
438 /// Ordering::SeqCst,
439 /// Ordering::Acquire),
441 /// assert_eq!(some_bool.load(Ordering::Relaxed), false);
444 #[stable(feature = "extended_compare_and_swap", since = "1.10.0")]
445 pub fn compare_exchange(&self,
450 -> Result<bool, bool> {
452 atomic_compare_exchange(self.v.get(), current as u8, new as u8, success, failure)
455 Err(x) => Err(x != 0),
459 /// Stores a value into the [`bool`] if the current value is the same as the `current` value.
461 /// Unlike [`compare_exchange`], this function is allowed to spuriously fail even when the
462 /// comparison succeeds, which can result in more efficient code on some platforms. The
463 /// return value is a result indicating whether the new value was written and containing the
466 /// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory
467 /// ordering of this operation. The first describes the required ordering if the operation
468 /// succeeds while the second describes the required ordering when the operation fails. The
469 /// failure ordering can't be [`Release`] or [`AcqRel`] and must be equivalent or
470 /// weaker than the success ordering.
472 /// [`bool`]: ../../../std/primitive.bool.html
473 /// [`compare_exchange`]: #method.compare_exchange
474 /// [`Ordering`]: enum.Ordering.html
475 /// [`Release`]: enum.Ordering.html#variant.Release
476 /// [`AcqRel`]: enum.Ordering.html#variant.Release
481 /// use std::sync::atomic::{AtomicBool, Ordering};
483 /// let val = AtomicBool::new(false);
486 /// let mut old = val.load(Ordering::Relaxed);
488 /// match val.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) {
490 /// Err(x) => old = x,
495 #[stable(feature = "extended_compare_and_swap", since = "1.10.0")]
496 pub fn compare_exchange_weak(&self,
501 -> Result<bool, bool> {
503 atomic_compare_exchange_weak(self.v.get(), current as u8, new as u8, success, failure)
506 Err(x) => Err(x != 0),
510 /// Logical "and" with a boolean value.
512 /// Performs a logical "and" operation on the current value and the argument `val`, and sets
513 /// the new value to the result.
515 /// Returns the previous value.
520 /// use std::sync::atomic::{AtomicBool, Ordering};
522 /// let foo = AtomicBool::new(true);
523 /// assert_eq!(foo.fetch_and(false, Ordering::SeqCst), true);
524 /// assert_eq!(foo.load(Ordering::SeqCst), false);
526 /// let foo = AtomicBool::new(true);
527 /// assert_eq!(foo.fetch_and(true, Ordering::SeqCst), true);
528 /// assert_eq!(foo.load(Ordering::SeqCst), true);
530 /// let foo = AtomicBool::new(false);
531 /// assert_eq!(foo.fetch_and(false, Ordering::SeqCst), false);
532 /// assert_eq!(foo.load(Ordering::SeqCst), false);
535 #[stable(feature = "rust1", since = "1.0.0")]
536 pub fn fetch_and(&self, val: bool, order: Ordering) -> bool {
537 unsafe { atomic_and(self.v.get(), val as u8, order) != 0 }
540 /// Logical "nand" with a boolean value.
542 /// Performs a logical "nand" operation on the current value and the argument `val`, and sets
543 /// the new value to the result.
545 /// Returns the previous value.
550 /// use std::sync::atomic::{AtomicBool, Ordering};
552 /// let foo = AtomicBool::new(true);
553 /// assert_eq!(foo.fetch_nand(false, Ordering::SeqCst), true);
554 /// assert_eq!(foo.load(Ordering::SeqCst), true);
556 /// let foo = AtomicBool::new(true);
557 /// assert_eq!(foo.fetch_nand(true, Ordering::SeqCst), true);
558 /// assert_eq!(foo.load(Ordering::SeqCst) as usize, 0);
559 /// assert_eq!(foo.load(Ordering::SeqCst), false);
561 /// let foo = AtomicBool::new(false);
562 /// assert_eq!(foo.fetch_nand(false, Ordering::SeqCst), false);
563 /// assert_eq!(foo.load(Ordering::SeqCst), true);
566 #[stable(feature = "rust1", since = "1.0.0")]
567 pub fn fetch_nand(&self, val: bool, order: Ordering) -> bool {
568 // We can't use atomic_nand here because it can result in a bool with
569 // an invalid value. This happens because the atomic operation is done
570 // with an 8-bit integer internally, which would set the upper 7 bits.
571 // So we just use fetch_xor or swap instead.
574 // We must invert the bool.
575 self.fetch_xor(true, order)
577 // !(x & false) == true
578 // We must set the bool to true.
579 self.swap(true, order)
583 /// Logical "or" with a boolean value.
585 /// Performs a logical "or" operation on the current value and the argument `val`, and sets the
586 /// new value to the result.
588 /// Returns the previous value.
593 /// use std::sync::atomic::{AtomicBool, Ordering};
595 /// let foo = AtomicBool::new(true);
596 /// assert_eq!(foo.fetch_or(false, Ordering::SeqCst), true);
597 /// assert_eq!(foo.load(Ordering::SeqCst), true);
599 /// let foo = AtomicBool::new(true);
600 /// assert_eq!(foo.fetch_or(true, Ordering::SeqCst), true);
601 /// assert_eq!(foo.load(Ordering::SeqCst), true);
603 /// let foo = AtomicBool::new(false);
604 /// assert_eq!(foo.fetch_or(false, Ordering::SeqCst), false);
605 /// assert_eq!(foo.load(Ordering::SeqCst), false);
608 #[stable(feature = "rust1", since = "1.0.0")]
609 pub fn fetch_or(&self, val: bool, order: Ordering) -> bool {
610 unsafe { atomic_or(self.v.get(), val as u8, order) != 0 }
613 /// Logical "xor" with a boolean value.
615 /// Performs a logical "xor" operation on the current value and the argument `val`, and sets
616 /// the new value to the result.
618 /// Returns the previous value.
623 /// use std::sync::atomic::{AtomicBool, Ordering};
625 /// let foo = AtomicBool::new(true);
626 /// assert_eq!(foo.fetch_xor(false, Ordering::SeqCst), true);
627 /// assert_eq!(foo.load(Ordering::SeqCst), true);
629 /// let foo = AtomicBool::new(true);
630 /// assert_eq!(foo.fetch_xor(true, Ordering::SeqCst), true);
631 /// assert_eq!(foo.load(Ordering::SeqCst), false);
633 /// let foo = AtomicBool::new(false);
634 /// assert_eq!(foo.fetch_xor(false, Ordering::SeqCst), false);
635 /// assert_eq!(foo.load(Ordering::SeqCst), false);
638 #[stable(feature = "rust1", since = "1.0.0")]
639 pub fn fetch_xor(&self, val: bool, order: Ordering) -> bool {
640 unsafe { atomic_xor(self.v.get(), val as u8, order) != 0 }
644 #[cfg(target_has_atomic = "ptr")]
645 impl<T> AtomicPtr<T> {
646 /// Creates a new `AtomicPtr`.
651 /// use std::sync::atomic::AtomicPtr;
653 /// let ptr = &mut 5;
654 /// let atomic_ptr = AtomicPtr::new(ptr);
657 #[stable(feature = "rust1", since = "1.0.0")]
658 pub const fn new(p: *mut T) -> AtomicPtr<T> {
659 AtomicPtr { p: UnsafeCell::new(p) }
662 /// Returns a mutable reference to the underlying pointer.
664 /// This is safe because the mutable reference guarantees that no other threads are
665 /// concurrently accessing the atomic data.
670 /// use std::sync::atomic::{AtomicPtr, Ordering};
672 /// let mut atomic_ptr = AtomicPtr::new(&mut 10);
673 /// *atomic_ptr.get_mut() = &mut 5;
674 /// assert_eq!(unsafe { *atomic_ptr.load(Ordering::SeqCst) }, 5);
677 #[stable(feature = "atomic_access", since = "1.15.0")]
678 pub fn get_mut(&mut self) -> &mut *mut T {
679 unsafe { &mut *self.p.get() }
682 /// Consumes the atomic and returns the contained value.
684 /// This is safe because passing `self` by value guarantees that no other threads are
685 /// concurrently accessing the atomic data.
690 /// use std::sync::atomic::AtomicPtr;
692 /// let atomic_ptr = AtomicPtr::new(&mut 5);
693 /// assert_eq!(unsafe { *atomic_ptr.into_inner() }, 5);
696 #[stable(feature = "atomic_access", since = "1.15.0")]
697 pub fn into_inner(self) -> *mut T {
698 unsafe { self.p.into_inner() }
701 /// Loads a value from the pointer.
703 /// `load` takes an [`Ordering`] argument which describes the memory ordering
704 /// of this operation.
708 /// Panics if `order` is [`Release`] or [`AcqRel`].
710 /// [`Ordering`]: enum.Ordering.html
711 /// [`Release`]: enum.Ordering.html#variant.Release
712 /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
717 /// use std::sync::atomic::{AtomicPtr, Ordering};
719 /// let ptr = &mut 5;
720 /// let some_ptr = AtomicPtr::new(ptr);
722 /// let value = some_ptr.load(Ordering::Relaxed);
725 #[stable(feature = "rust1", since = "1.0.0")]
726 pub fn load(&self, order: Ordering) -> *mut T {
727 unsafe { atomic_load(self.p.get() as *mut usize, order) as *mut T }
730 /// Stores a value into the pointer.
732 /// `store` takes an [`Ordering`] argument which describes the memory ordering
733 /// of this operation.
735 /// [`Ordering`]: enum.Ordering.html
740 /// use std::sync::atomic::{AtomicPtr, Ordering};
742 /// let ptr = &mut 5;
743 /// let some_ptr = AtomicPtr::new(ptr);
745 /// let other_ptr = &mut 10;
747 /// some_ptr.store(other_ptr, Ordering::Relaxed);
752 /// Panics if `order` is [`Acquire`] or [`AcqRel`].
754 /// [`Acquire`]: enum.Ordering.html#variant.Acquire
755 /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
757 #[stable(feature = "rust1", since = "1.0.0")]
758 pub fn store(&self, ptr: *mut T, order: Ordering) {
760 atomic_store(self.p.get() as *mut usize, ptr as usize, order);
764 /// Stores a value into the pointer, returning the previous value.
766 /// `swap` takes an [`Ordering`] argument which describes the memory ordering
767 /// of this operation.
769 /// [`Ordering`]: enum.Ordering.html
774 /// use std::sync::atomic::{AtomicPtr, Ordering};
776 /// let ptr = &mut 5;
777 /// let some_ptr = AtomicPtr::new(ptr);
779 /// let other_ptr = &mut 10;
781 /// let value = some_ptr.swap(other_ptr, Ordering::Relaxed);
784 #[stable(feature = "rust1", since = "1.0.0")]
785 pub fn swap(&self, ptr: *mut T, order: Ordering) -> *mut T {
786 unsafe { atomic_swap(self.p.get() as *mut usize, ptr as usize, order) as *mut T }
789 /// Stores a value into the pointer if the current value is the same as the `current` value.
791 /// The return value is always the previous value. If it is equal to `current`, then the value
794 /// `compare_and_swap` also takes an [`Ordering`] argument which describes the memory
795 /// ordering of this operation.
797 /// [`Ordering`]: enum.Ordering.html
802 /// use std::sync::atomic::{AtomicPtr, Ordering};
804 /// let ptr = &mut 5;
805 /// let some_ptr = AtomicPtr::new(ptr);
807 /// let other_ptr = &mut 10;
808 /// let another_ptr = &mut 10;
810 /// let value = some_ptr.compare_and_swap(other_ptr, another_ptr, Ordering::Relaxed);
813 #[stable(feature = "rust1", since = "1.0.0")]
814 pub fn compare_and_swap(&self, current: *mut T, new: *mut T, order: Ordering) -> *mut T {
815 match self.compare_exchange(current, new, order, strongest_failure_ordering(order)) {
821 /// Stores a value into the pointer if the current value is the same as the `current` value.
823 /// The return value is a result indicating whether the new value was written and containing
824 /// the previous value. On success this value is guaranteed to be equal to `current`.
826 /// `compare_exchange` takes two [`Ordering`] arguments to describe the memory
827 /// ordering of this operation. The first describes the required ordering if
828 /// the operation succeeds while the second describes the required ordering when
829 /// the operation fails. The failure ordering can't be [`Release`] or [`AcqRel`]
830 /// and must be equivalent or weaker than the success ordering.
832 /// [`Ordering`]: enum.Ordering.html
833 /// [`Release`]: enum.Ordering.html#variant.Release
834 /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
839 /// use std::sync::atomic::{AtomicPtr, Ordering};
841 /// let ptr = &mut 5;
842 /// let some_ptr = AtomicPtr::new(ptr);
844 /// let other_ptr = &mut 10;
845 /// let another_ptr = &mut 10;
847 /// let value = some_ptr.compare_exchange(other_ptr, another_ptr,
848 /// Ordering::SeqCst, Ordering::Relaxed);
851 #[stable(feature = "extended_compare_and_swap", since = "1.10.0")]
852 pub fn compare_exchange(&self,
857 -> Result<*mut T, *mut T> {
859 let res = atomic_compare_exchange(self.p.get() as *mut usize,
865 Ok(x) => Ok(x as *mut T),
866 Err(x) => Err(x as *mut T),
871 /// Stores a value into the pointer if the current value is the same as the `current` value.
873 /// Unlike [`compare_exchange`], this function is allowed to spuriously fail even when the
874 /// comparison succeeds, which can result in more efficient code on some platforms. The
875 /// return value is a result indicating whether the new value was written and containing the
878 /// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory
879 /// ordering of this operation. The first describes the required ordering if the operation
880 /// succeeds while the second describes the required ordering when the operation fails. The
881 /// failure ordering can't be [`Release`] or [`AcqRel`] and must be equivalent or
882 /// weaker than the success ordering.
884 /// [`compare_exchange`]: #method.compare_exchange
885 /// [`Ordering`]: enum.Ordering.html
886 /// [`Release`]: enum.Ordering.html#variant.Release
887 /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
892 /// use std::sync::atomic::{AtomicPtr, Ordering};
894 /// let some_ptr = AtomicPtr::new(&mut 5);
896 /// let new = &mut 10;
897 /// let mut old = some_ptr.load(Ordering::Relaxed);
899 /// match some_ptr.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) {
901 /// Err(x) => old = x,
906 #[stable(feature = "extended_compare_and_swap", since = "1.10.0")]
907 pub fn compare_exchange_weak(&self,
912 -> Result<*mut T, *mut T> {
914 let res = atomic_compare_exchange_weak(self.p.get() as *mut usize,
920 Ok(x) => Ok(x as *mut T),
921 Err(x) => Err(x as *mut T),
927 #[cfg(target_has_atomic = "8")]
928 #[stable(feature = "atomic_bool_from", since = "1.24.0")]
929 impl From<bool> for AtomicBool {
931 fn from(b: bool) -> Self { Self::new(b) }
934 #[cfg(target_has_atomic = "ptr")]
935 #[stable(feature = "atomic_from", since = "1.23.0")]
936 impl<T> From<*mut T> for AtomicPtr<T> {
938 fn from(p: *mut T) -> Self { Self::new(p) }
941 #[cfg(target_has_atomic = "ptr")]
942 macro_rules! atomic_int {
948 $s_int_type:expr, $int_ref:expr,
949 $int_type:ident $atomic_type:ident $atomic_init:ident) => {
950 /// An integer type which can be safely shared between threads.
952 /// This type has the same in-memory representation as the underlying
957 /// ). For more about the differences between atomic types and
958 /// non-atomic types, please see the [module-level documentation].
960 /// Please note that examples are shared between atomic variants of
961 /// primitive integer types, so it's normal that they are all
962 /// demonstrating [`AtomicIsize`].
964 /// [module-level documentation]: index.html
965 /// [`AtomicIsize`]: struct.AtomicIsize.html
967 pub struct $atomic_type {
968 v: UnsafeCell<$int_type>,
971 /// An atomic integer initialized to `0`.
973 pub const $atomic_init: $atomic_type = $atomic_type::new(0);
976 impl Default for $atomic_type {
977 fn default() -> Self {
978 Self::new(Default::default())
983 impl From<$int_type> for $atomic_type {
985 fn from(v: $int_type) -> Self { Self::new(v) }
989 impl fmt::Debug for $atomic_type {
990 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
991 f.debug_tuple(stringify!($atomic_type))
992 .field(&self.load(Ordering::SeqCst))
997 // Send is implicitly implemented.
999 unsafe impl Sync for $atomic_type {}
1002 /// Creates a new atomic integer.
1007 /// use std::sync::atomic::AtomicIsize;
1009 /// let atomic_forty_two = AtomicIsize::new(42);
1013 pub const fn new(v: $int_type) -> Self {
1014 $atomic_type {v: UnsafeCell::new(v)}
1017 /// Returns a mutable reference to the underlying integer.
1019 /// This is safe because the mutable reference guarantees that no other threads are
1020 /// concurrently accessing the atomic data.
1025 /// use std::sync::atomic::{AtomicIsize, Ordering};
1027 /// let mut some_isize = AtomicIsize::new(10);
1028 /// assert_eq!(*some_isize.get_mut(), 10);
1029 /// *some_isize.get_mut() = 5;
1030 /// assert_eq!(some_isize.load(Ordering::SeqCst), 5);
1034 pub fn get_mut(&mut self) -> &mut $int_type {
1035 unsafe { &mut *self.v.get() }
1038 /// Consumes the atomic and returns the contained value.
1040 /// This is safe because passing `self` by value guarantees that no other threads are
1041 /// concurrently accessing the atomic data.
1046 /// use std::sync::atomic::AtomicIsize;
1048 /// let some_isize = AtomicIsize::new(5);
1049 /// assert_eq!(some_isize.into_inner(), 5);
1053 pub fn into_inner(self) -> $int_type {
1054 unsafe { self.v.into_inner() }
1057 /// Loads a value from the atomic integer.
1059 /// `load` takes an [`Ordering`] argument which describes the memory ordering of this
1064 /// Panics if `order` is [`Release`] or [`AcqRel`].
1066 /// [`Ordering`]: enum.Ordering.html
1067 /// [`Release`]: enum.Ordering.html#variant.Release
1068 /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
1073 /// use std::sync::atomic::{AtomicIsize, Ordering};
1075 /// let some_isize = AtomicIsize::new(5);
1077 /// assert_eq!(some_isize.load(Ordering::Relaxed), 5);
1081 pub fn load(&self, order: Ordering) -> $int_type {
1082 unsafe { atomic_load(self.v.get(), order) }
1085 /// Stores a value into the atomic integer.
1087 /// `store` takes an [`Ordering`] argument which describes the memory ordering of this
1090 /// [`Ordering`]: enum.Ordering.html
1095 /// use std::sync::atomic::{AtomicIsize, Ordering};
1097 /// let some_isize = AtomicIsize::new(5);
1099 /// some_isize.store(10, Ordering::Relaxed);
1100 /// assert_eq!(some_isize.load(Ordering::Relaxed), 10);
1105 /// Panics if `order` is [`Acquire`] or [`AcqRel`].
1107 /// [`Acquire`]: enum.Ordering.html#variant.Acquire
1108 /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
1111 pub fn store(&self, val: $int_type, order: Ordering) {
1112 unsafe { atomic_store(self.v.get(), val, order); }
1115 /// Stores a value into the atomic integer, returning the previous value.
1117 /// `swap` takes an [`Ordering`] argument which describes the memory ordering of this
1120 /// [`Ordering`]: enum.Ordering.html
1125 /// use std::sync::atomic::{AtomicIsize, Ordering};
1127 /// let some_isize = AtomicIsize::new(5);
1129 /// assert_eq!(some_isize.swap(10, Ordering::Relaxed), 5);
1133 pub fn swap(&self, val: $int_type, order: Ordering) -> $int_type {
1134 unsafe { atomic_swap(self.v.get(), val, order) }
1137 /// Stores a value into the atomic integer if the current value is the same as the
1138 /// `current` value.
1140 /// The return value is always the previous value. If it is equal to `current`, then the
1141 /// value was updated.
1143 /// `compare_and_swap` also takes an [`Ordering`] argument which describes the memory
1144 /// ordering of this operation.
1146 /// [`Ordering`]: enum.Ordering.html
1151 /// use std::sync::atomic::{AtomicIsize, Ordering};
1153 /// let some_isize = AtomicIsize::new(5);
1155 /// assert_eq!(some_isize.compare_and_swap(5, 10, Ordering::Relaxed), 5);
1156 /// assert_eq!(some_isize.load(Ordering::Relaxed), 10);
1158 /// assert_eq!(some_isize.compare_and_swap(6, 12, Ordering::Relaxed), 10);
1159 /// assert_eq!(some_isize.load(Ordering::Relaxed), 10);
1163 pub fn compare_and_swap(&self,
1166 order: Ordering) -> $int_type {
1167 match self.compare_exchange(current,
1170 strongest_failure_ordering(order)) {
1176 /// Stores a value into the atomic integer if the current value is the same as the
1177 /// `current` value.
1179 /// The return value is a result indicating whether the new value was written and
1180 /// containing the previous value. On success this value is guaranteed to be equal to
1183 /// `compare_exchange` takes two [`Ordering`] arguments to describe the memory
1184 /// ordering of this operation. The first describes the required ordering if
1185 /// the operation succeeds while the second describes the required ordering when
1186 /// the operation fails. The failure ordering can't be [`Release`] or [`AcqRel`] and
1187 /// must be equivalent or weaker than the success ordering.
1189 /// [`Ordering`]: enum.Ordering.html
1190 /// [`Release`]: enum.Ordering.html#variant.Release
1191 /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
1196 /// use std::sync::atomic::{AtomicIsize, Ordering};
1198 /// let some_isize = AtomicIsize::new(5);
1200 /// assert_eq!(some_isize.compare_exchange(5, 10,
1201 /// Ordering::Acquire,
1202 /// Ordering::Relaxed),
1204 /// assert_eq!(some_isize.load(Ordering::Relaxed), 10);
1206 /// assert_eq!(some_isize.compare_exchange(6, 12,
1207 /// Ordering::SeqCst,
1208 /// Ordering::Acquire),
1210 /// assert_eq!(some_isize.load(Ordering::Relaxed), 10);
1214 pub fn compare_exchange(&self,
1218 failure: Ordering) -> Result<$int_type, $int_type> {
1219 unsafe { atomic_compare_exchange(self.v.get(), current, new, success, failure) }
1222 /// Stores a value into the atomic integer if the current value is the same as the
1223 /// `current` value.
1225 /// Unlike [`compare_exchange`], this function is allowed to spuriously fail even
1226 /// when the comparison succeeds, which can result in more efficient code on some
1227 /// platforms. The return value is a result indicating whether the new value was
1228 /// written and containing the previous value.
1230 /// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory
1231 /// ordering of this operation. The first describes the required ordering if the
1232 /// operation succeeds while the second describes the required ordering when the
1233 /// operation fails. The failure ordering can't be [`Release`] or [`AcqRel`] and
1234 /// must be equivalent or weaker than the success ordering.
1236 /// [`compare_exchange`]: #method.compare_exchange
1237 /// [`Ordering`]: enum.Ordering.html
1238 /// [`Release`]: enum.Ordering.html#variant.Release
1239 /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
1244 /// use std::sync::atomic::{AtomicIsize, Ordering};
1246 /// let val = AtomicIsize::new(4);
1248 /// let mut old = val.load(Ordering::Relaxed);
1250 /// let new = old * 2;
1251 /// match val.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) {
1253 /// Err(x) => old = x,
1259 pub fn compare_exchange_weak(&self,
1263 failure: Ordering) -> Result<$int_type, $int_type> {
1265 atomic_compare_exchange_weak(self.v.get(), current, new, success, failure)
1269 /// Adds to the current value, returning the previous value.
1271 /// This operation wraps around on overflow.
1276 /// use std::sync::atomic::{AtomicIsize, Ordering};
1278 /// let foo = AtomicIsize::new(0);
1279 /// assert_eq!(foo.fetch_add(10, Ordering::SeqCst), 0);
1280 /// assert_eq!(foo.load(Ordering::SeqCst), 10);
1284 pub fn fetch_add(&self, val: $int_type, order: Ordering) -> $int_type {
1285 unsafe { atomic_add(self.v.get(), val, order) }
1288 /// Subtracts from the current value, returning the previous value.
1290 /// This operation wraps around on overflow.
1295 /// use std::sync::atomic::{AtomicIsize, Ordering};
1297 /// let foo = AtomicIsize::new(0);
1298 /// assert_eq!(foo.fetch_sub(10, Ordering::SeqCst), 0);
1299 /// assert_eq!(foo.load(Ordering::SeqCst), -10);
1303 pub fn fetch_sub(&self, val: $int_type, order: Ordering) -> $int_type {
1304 unsafe { atomic_sub(self.v.get(), val, order) }
1307 /// Bitwise "and" with the current value.
1309 /// Performs a bitwise "and" operation on the current value and the argument `val`, and
1310 /// sets the new value to the result.
1312 /// Returns the previous value.
1317 /// use std::sync::atomic::{AtomicIsize, Ordering};
1319 /// let foo = AtomicIsize::new(0b101101);
1320 /// assert_eq!(foo.fetch_and(0b110011, Ordering::SeqCst), 0b101101);
1321 /// assert_eq!(foo.load(Ordering::SeqCst), 0b100001);
1324 pub fn fetch_and(&self, val: $int_type, order: Ordering) -> $int_type {
1325 unsafe { atomic_and(self.v.get(), val, order) }
1328 /// Bitwise "or" with the current value.
1330 /// Performs a bitwise "or" operation on the current value and the argument `val`, and
1331 /// sets the new value to the result.
1333 /// Returns the previous value.
1338 /// use std::sync::atomic::{AtomicIsize, Ordering};
1340 /// let foo = AtomicIsize::new(0b101101);
1341 /// assert_eq!(foo.fetch_or(0b110011, Ordering::SeqCst), 0b101101);
1342 /// assert_eq!(foo.load(Ordering::SeqCst), 0b111111);
1345 pub fn fetch_or(&self, val: $int_type, order: Ordering) -> $int_type {
1346 unsafe { atomic_or(self.v.get(), val, order) }
1349 /// Bitwise "xor" with the current value.
1351 /// Performs a bitwise "xor" operation on the current value and the argument `val`, and
1352 /// sets the new value to the result.
1354 /// Returns the previous value.
1359 /// use std::sync::atomic::{AtomicIsize, Ordering};
1361 /// let foo = AtomicIsize::new(0b101101);
1362 /// assert_eq!(foo.fetch_xor(0b110011, Ordering::SeqCst), 0b101101);
1363 /// assert_eq!(foo.load(Ordering::SeqCst), 0b011110);
1366 pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
1367 unsafe { atomic_xor(self.v.get(), val, order) }
1373 #[cfg(target_has_atomic = "8")]
1375 unstable(feature = "integer_atomics", issue = "32976"),
1376 unstable(feature = "integer_atomics", issue = "32976"),
1377 unstable(feature = "integer_atomics", issue = "32976"),
1378 unstable(feature = "integer_atomics", issue = "32976"),
1379 unstable(feature = "integer_atomics", issue = "32976"),
1380 "i8", "../../../std/primitive.i8.html",
1381 i8 AtomicI8 ATOMIC_I8_INIT
1383 #[cfg(target_has_atomic = "8")]
1385 unstable(feature = "integer_atomics", issue = "32976"),
1386 unstable(feature = "integer_atomics", issue = "32976"),
1387 unstable(feature = "integer_atomics", issue = "32976"),
1388 unstable(feature = "integer_atomics", issue = "32976"),
1389 unstable(feature = "integer_atomics", issue = "32976"),
1390 "u8", "../../../std/primitive.u8.html",
1391 u8 AtomicU8 ATOMIC_U8_INIT
1393 #[cfg(target_has_atomic = "16")]
1395 unstable(feature = "integer_atomics", issue = "32976"),
1396 unstable(feature = "integer_atomics", issue = "32976"),
1397 unstable(feature = "integer_atomics", issue = "32976"),
1398 unstable(feature = "integer_atomics", issue = "32976"),
1399 unstable(feature = "integer_atomics", issue = "32976"),
1400 "i16", "../../../std/primitive.i16.html",
1401 i16 AtomicI16 ATOMIC_I16_INIT
1403 #[cfg(target_has_atomic = "16")]
1405 unstable(feature = "integer_atomics", issue = "32976"),
1406 unstable(feature = "integer_atomics", issue = "32976"),
1407 unstable(feature = "integer_atomics", issue = "32976"),
1408 unstable(feature = "integer_atomics", issue = "32976"),
1409 unstable(feature = "integer_atomics", issue = "32976"),
1410 "u16", "../../../std/primitive.u16.html",
1411 u16 AtomicU16 ATOMIC_U16_INIT
1413 #[cfg(target_has_atomic = "32")]
1415 unstable(feature = "integer_atomics", issue = "32976"),
1416 unstable(feature = "integer_atomics", issue = "32976"),
1417 unstable(feature = "integer_atomics", issue = "32976"),
1418 unstable(feature = "integer_atomics", issue = "32976"),
1419 unstable(feature = "integer_atomics", issue = "32976"),
1420 "i32", "../../../std/primitive.i32.html",
1421 i32 AtomicI32 ATOMIC_I32_INIT
1423 #[cfg(target_has_atomic = "32")]
1425 unstable(feature = "integer_atomics", issue = "32976"),
1426 unstable(feature = "integer_atomics", issue = "32976"),
1427 unstable(feature = "integer_atomics", issue = "32976"),
1428 unstable(feature = "integer_atomics", issue = "32976"),
1429 unstable(feature = "integer_atomics", issue = "32976"),
1430 "u32", "../../../std/primitive.u32.html",
1431 u32 AtomicU32 ATOMIC_U32_INIT
1433 #[cfg(target_has_atomic = "64")]
1435 unstable(feature = "integer_atomics", issue = "32976"),
1436 unstable(feature = "integer_atomics", issue = "32976"),
1437 unstable(feature = "integer_atomics", issue = "32976"),
1438 unstable(feature = "integer_atomics", issue = "32976"),
1439 unstable(feature = "integer_atomics", issue = "32976"),
1440 "i64", "../../../std/primitive.i64.html",
1441 i64 AtomicI64 ATOMIC_I64_INIT
1443 #[cfg(target_has_atomic = "64")]
1445 unstable(feature = "integer_atomics", issue = "32976"),
1446 unstable(feature = "integer_atomics", issue = "32976"),
1447 unstable(feature = "integer_atomics", issue = "32976"),
1448 unstable(feature = "integer_atomics", issue = "32976"),
1449 unstable(feature = "integer_atomics", issue = "32976"),
1450 "u64", "../../../std/primitive.u64.html",
1451 u64 AtomicU64 ATOMIC_U64_INIT
1453 #[cfg(target_has_atomic = "ptr")]
1455 stable(feature = "rust1", since = "1.0.0"),
1456 stable(feature = "extended_compare_and_swap", since = "1.10.0"),
1457 stable(feature = "atomic_debug", since = "1.3.0"),
1458 stable(feature = "atomic_access", since = "1.15.0"),
1459 stable(feature = "atomic_from", since = "1.23.0"),
1460 "isize", "../../../std/primitive.isize.html",
1461 isize AtomicIsize ATOMIC_ISIZE_INIT
1463 #[cfg(target_has_atomic = "ptr")]
1465 stable(feature = "rust1", since = "1.0.0"),
1466 stable(feature = "extended_compare_and_swap", since = "1.10.0"),
1467 stable(feature = "atomic_debug", since = "1.3.0"),
1468 stable(feature = "atomic_access", since = "1.15.0"),
1469 stable(feature = "atomic_from", since = "1.23.0"),
1470 "usize", "../../../std/primitive.usize.html",
1471 usize AtomicUsize ATOMIC_USIZE_INIT
1475 fn strongest_failure_ordering(order: Ordering) -> Ordering {
1482 __Nonexhaustive => __Nonexhaustive,
1487 unsafe fn atomic_store<T>(dst: *mut T, val: T, order: Ordering) {
1489 Release => intrinsics::atomic_store_rel(dst, val),
1490 Relaxed => intrinsics::atomic_store_relaxed(dst, val),
1491 SeqCst => intrinsics::atomic_store(dst, val),
1492 Acquire => panic!("there is no such thing as an acquire store"),
1493 AcqRel => panic!("there is no such thing as an acquire/release store"),
1494 __Nonexhaustive => panic!("invalid memory ordering"),
1499 unsafe fn atomic_load<T>(dst: *const T, order: Ordering) -> T {
1501 Acquire => intrinsics::atomic_load_acq(dst),
1502 Relaxed => intrinsics::atomic_load_relaxed(dst),
1503 SeqCst => intrinsics::atomic_load(dst),
1504 Release => panic!("there is no such thing as a release load"),
1505 AcqRel => panic!("there is no such thing as an acquire/release load"),
1506 __Nonexhaustive => panic!("invalid memory ordering"),
1511 unsafe fn atomic_swap<T>(dst: *mut T, val: T, order: Ordering) -> T {
1513 Acquire => intrinsics::atomic_xchg_acq(dst, val),
1514 Release => intrinsics::atomic_xchg_rel(dst, val),
1515 AcqRel => intrinsics::atomic_xchg_acqrel(dst, val),
1516 Relaxed => intrinsics::atomic_xchg_relaxed(dst, val),
1517 SeqCst => intrinsics::atomic_xchg(dst, val),
1518 __Nonexhaustive => panic!("invalid memory ordering"),
1522 /// Returns the previous value (like __sync_fetch_and_add).
1524 unsafe fn atomic_add<T>(dst: *mut T, val: T, order: Ordering) -> T {
1526 Acquire => intrinsics::atomic_xadd_acq(dst, val),
1527 Release => intrinsics::atomic_xadd_rel(dst, val),
1528 AcqRel => intrinsics::atomic_xadd_acqrel(dst, val),
1529 Relaxed => intrinsics::atomic_xadd_relaxed(dst, val),
1530 SeqCst => intrinsics::atomic_xadd(dst, val),
1531 __Nonexhaustive => panic!("invalid memory ordering"),
1535 /// Returns the previous value (like __sync_fetch_and_sub).
1537 unsafe fn atomic_sub<T>(dst: *mut T, val: T, order: Ordering) -> T {
1539 Acquire => intrinsics::atomic_xsub_acq(dst, val),
1540 Release => intrinsics::atomic_xsub_rel(dst, val),
1541 AcqRel => intrinsics::atomic_xsub_acqrel(dst, val),
1542 Relaxed => intrinsics::atomic_xsub_relaxed(dst, val),
1543 SeqCst => intrinsics::atomic_xsub(dst, val),
1544 __Nonexhaustive => panic!("invalid memory ordering"),
1549 unsafe fn atomic_compare_exchange<T>(dst: *mut T,
1555 let (val, ok) = match (success, failure) {
1556 (Acquire, Acquire) => intrinsics::atomic_cxchg_acq(dst, old, new),
1557 (Release, Relaxed) => intrinsics::atomic_cxchg_rel(dst, old, new),
1558 (AcqRel, Acquire) => intrinsics::atomic_cxchg_acqrel(dst, old, new),
1559 (Relaxed, Relaxed) => intrinsics::atomic_cxchg_relaxed(dst, old, new),
1560 (SeqCst, SeqCst) => intrinsics::atomic_cxchg(dst, old, new),
1561 (Acquire, Relaxed) => intrinsics::atomic_cxchg_acq_failrelaxed(dst, old, new),
1562 (AcqRel, Relaxed) => intrinsics::atomic_cxchg_acqrel_failrelaxed(dst, old, new),
1563 (SeqCst, Relaxed) => intrinsics::atomic_cxchg_failrelaxed(dst, old, new),
1564 (SeqCst, Acquire) => intrinsics::atomic_cxchg_failacq(dst, old, new),
1565 (__Nonexhaustive, _) => panic!("invalid memory ordering"),
1566 (_, __Nonexhaustive) => panic!("invalid memory ordering"),
1567 (_, AcqRel) => panic!("there is no such thing as an acquire/release failure ordering"),
1568 (_, Release) => panic!("there is no such thing as a release failure ordering"),
1569 _ => panic!("a failure ordering can't be stronger than a success ordering"),
1571 if ok { Ok(val) } else { Err(val) }
1575 unsafe fn atomic_compare_exchange_weak<T>(dst: *mut T,
1581 let (val, ok) = match (success, failure) {
1582 (Acquire, Acquire) => intrinsics::atomic_cxchgweak_acq(dst, old, new),
1583 (Release, Relaxed) => intrinsics::atomic_cxchgweak_rel(dst, old, new),
1584 (AcqRel, Acquire) => intrinsics::atomic_cxchgweak_acqrel(dst, old, new),
1585 (Relaxed, Relaxed) => intrinsics::atomic_cxchgweak_relaxed(dst, old, new),
1586 (SeqCst, SeqCst) => intrinsics::atomic_cxchgweak(dst, old, new),
1587 (Acquire, Relaxed) => intrinsics::atomic_cxchgweak_acq_failrelaxed(dst, old, new),
1588 (AcqRel, Relaxed) => intrinsics::atomic_cxchgweak_acqrel_failrelaxed(dst, old, new),
1589 (SeqCst, Relaxed) => intrinsics::atomic_cxchgweak_failrelaxed(dst, old, new),
1590 (SeqCst, Acquire) => intrinsics::atomic_cxchgweak_failacq(dst, old, new),
1591 (__Nonexhaustive, _) => panic!("invalid memory ordering"),
1592 (_, __Nonexhaustive) => panic!("invalid memory ordering"),
1593 (_, AcqRel) => panic!("there is no such thing as an acquire/release failure ordering"),
1594 (_, Release) => panic!("there is no such thing as a release failure ordering"),
1595 _ => panic!("a failure ordering can't be stronger than a success ordering"),
1597 if ok { Ok(val) } else { Err(val) }
1601 unsafe fn atomic_and<T>(dst: *mut T, val: T, order: Ordering) -> T {
1603 Acquire => intrinsics::atomic_and_acq(dst, val),
1604 Release => intrinsics::atomic_and_rel(dst, val),
1605 AcqRel => intrinsics::atomic_and_acqrel(dst, val),
1606 Relaxed => intrinsics::atomic_and_relaxed(dst, val),
1607 SeqCst => intrinsics::atomic_and(dst, val),
1608 __Nonexhaustive => panic!("invalid memory ordering"),
1613 unsafe fn atomic_or<T>(dst: *mut T, val: T, order: Ordering) -> T {
1615 Acquire => intrinsics::atomic_or_acq(dst, val),
1616 Release => intrinsics::atomic_or_rel(dst, val),
1617 AcqRel => intrinsics::atomic_or_acqrel(dst, val),
1618 Relaxed => intrinsics::atomic_or_relaxed(dst, val),
1619 SeqCst => intrinsics::atomic_or(dst, val),
1620 __Nonexhaustive => panic!("invalid memory ordering"),
1625 unsafe fn atomic_xor<T>(dst: *mut T, val: T, order: Ordering) -> T {
1627 Acquire => intrinsics::atomic_xor_acq(dst, val),
1628 Release => intrinsics::atomic_xor_rel(dst, val),
1629 AcqRel => intrinsics::atomic_xor_acqrel(dst, val),
1630 Relaxed => intrinsics::atomic_xor_relaxed(dst, val),
1631 SeqCst => intrinsics::atomic_xor(dst, val),
1632 __Nonexhaustive => panic!("invalid memory ordering"),
1636 /// An atomic fence.
1638 /// Depending on the specified order, a fence prevents the compiler and CPU from
1639 /// reordering certain types of memory operations around it.
1640 /// That creates synchronizes-with relationships between it and atomic operations
1641 /// or fences in other threads.
1643 /// A fence 'A' which has (at least) [`Release`] ordering semantics, synchronizes
1644 /// with a fence 'B' with (at least) [`Acquire`] semantics, if and only if there
1645 /// exist operations X and Y, both operating on some atomic object 'M' such
1646 /// that A is sequenced before X, Y is synchronized before B and Y observes
1647 /// the change to M. This provides a happens-before dependence between A and B.
1650 /// Thread 1 Thread 2
1652 /// fence(Release); A --------------
1653 /// x.store(3, Relaxed); X --------- |
1656 /// -------------> Y if x.load(Relaxed) == 3 {
1657 /// |-------> B fence(Acquire);
1662 /// Atomic operations with [`Release`] or [`Acquire`] semantics can also synchronize
1665 /// A fence which has [`SeqCst`] ordering, in addition to having both [`Acquire`]
1666 /// and [`Release`] semantics, participates in the global program order of the
1667 /// other [`SeqCst`] operations and/or fences.
1669 /// Accepts [`Acquire`], [`Release`], [`AcqRel`] and [`SeqCst`] orderings.
1673 /// Panics if `order` is [`Relaxed`].
1678 /// use std::sync::atomic::AtomicBool;
1679 /// use std::sync::atomic::fence;
1680 /// use std::sync::atomic::Ordering;
1682 /// // A mutual exclusion primitive based on spinlock.
1683 /// pub struct Mutex {
1684 /// flag: AtomicBool,
1688 /// pub fn new() -> Mutex {
1690 /// flag: AtomicBool::new(false),
1694 /// pub fn lock(&self) {
1695 /// while !self.flag.compare_and_swap(false, true, Ordering::Relaxed) {}
1696 /// // This fence synchronizes-with store in `unlock`.
1697 /// fence(Ordering::Acquire);
1700 /// pub fn unlock(&self) {
1701 /// self.flag.store(false, Ordering::Release);
1706 /// [`Ordering`]: enum.Ordering.html
1707 /// [`Acquire`]: enum.Ordering.html#variant.Acquire
1708 /// [`SeqCst`]: enum.Ordering.html#variant.SeqCst
1709 /// [`Release`]: enum.Ordering.html#variant.Release
1710 /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
1711 /// [`Relaxed`]: enum.Ordering.html#variant.Relaxed
1713 #[stable(feature = "rust1", since = "1.0.0")]
1714 pub fn fence(order: Ordering) {
1717 Acquire => intrinsics::atomic_fence_acq(),
1718 Release => intrinsics::atomic_fence_rel(),
1719 AcqRel => intrinsics::atomic_fence_acqrel(),
1720 SeqCst => intrinsics::atomic_fence(),
1721 Relaxed => panic!("there is no such thing as a relaxed fence"),
1722 __Nonexhaustive => panic!("invalid memory ordering"),
1728 /// A compiler memory fence.
1730 /// `compiler_fence` does not emit any machine code, but restricts the kinds
1731 /// of memory re-ordering the compiler is allowed to do. Specifically, depending on
1732 /// the given [`Ordering`] semantics, the compiler may be disallowed from moving reads
1733 /// or writes from before or after the call to the other side of the call to
1734 /// `compiler_fence`. Note that it does **not** prevent the *hardware*
1735 /// from doing such re-ordering. This is not a problem in a single-threaded,
1736 /// execution context, but when other threads may modify memory at the same
1737 /// time, stronger synchronization primitives such as [`fence`] are required.
1739 /// The re-ordering prevented by the different ordering semantics are:
1741 /// - with [`SeqCst`], no re-ordering of reads and writes across this point is allowed.
1742 /// - with [`Release`], preceding reads and writes cannot be moved past subsequent writes.
1743 /// - with [`Acquire`], subsequent reads and writes cannot be moved ahead of preceding reads.
1744 /// - with [`AcqRel`], both of the above rules are enforced.
1746 /// `compiler_fence` is generally only useful for preventing a thread from
1747 /// racing *with itself*. That is, if a given thread is executing one piece
1748 /// of code, and is then interrupted, and starts executing code elsewhere
1749 /// (while still in the same thread, and conceptually still on the same
1750 /// core). In traditional programs, this can only occur when a signal
1751 /// handler is registered. In more low-level code, such situations can also
1752 /// arise when handling interrupts, when implementing green threads with
1753 /// pre-emption, etc. Curious readers are encouraged to read the Linux kernel's
1754 /// discussion of [memory barriers].
1758 /// Panics if `order` is [`Relaxed`].
1762 /// Without `compiler_fence`, the `assert_eq!` in following code
1763 /// is *not* guaranteed to succeed, despite everything happening in a single thread.
1764 /// To see why, remember that the compiler is free to swap the stores to
1765 /// `IMPORTANT_VARIABLE` and `IS_READ` since they are both
1766 /// `Ordering::Relaxed`. If it does, and the signal handler is invoked right
1767 /// after `IS_READY` is updated, then the signal handler will see
1768 /// `IS_READY=1`, but `IMPORTANT_VARIABLE=0`.
1769 /// Using a `compiler_fence` remedies this situation.
1772 /// use std::sync::atomic::{AtomicBool, AtomicUsize};
1773 /// use std::sync::atomic::{ATOMIC_BOOL_INIT, ATOMIC_USIZE_INIT};
1774 /// use std::sync::atomic::Ordering;
1775 /// use std::sync::atomic::compiler_fence;
1777 /// static IMPORTANT_VARIABLE: AtomicUsize = ATOMIC_USIZE_INIT;
1778 /// static IS_READY: AtomicBool = ATOMIC_BOOL_INIT;
1781 /// IMPORTANT_VARIABLE.store(42, Ordering::Relaxed);
1782 /// // prevent earlier writes from being moved beyond this point
1783 /// compiler_fence(Ordering::Release);
1784 /// IS_READY.store(true, Ordering::Relaxed);
1787 /// fn signal_handler() {
1788 /// if IS_READY.load(Ordering::Relaxed) {
1789 /// assert_eq!(IMPORTANT_VARIABLE.load(Ordering::Relaxed), 42);
1794 /// [`fence`]: fn.fence.html
1795 /// [`Ordering`]: enum.Ordering.html
1796 /// [`Acquire`]: enum.Ordering.html#variant.Acquire
1797 /// [`SeqCst`]: enum.Ordering.html#variant.SeqCst
1798 /// [`Release`]: enum.Ordering.html#variant.Release
1799 /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
1800 /// [`Relaxed`]: enum.Ordering.html#variant.Relaxed
1801 /// [memory barriers]: https://www.kernel.org/doc/Documentation/memory-barriers.txt
1803 #[stable(feature = "compiler_fences", since = "1.21.0")]
1804 pub fn compiler_fence(order: Ordering) {
1807 Acquire => intrinsics::atomic_singlethreadfence_acq(),
1808 Release => intrinsics::atomic_singlethreadfence_rel(),
1809 AcqRel => intrinsics::atomic_singlethreadfence_acqrel(),
1810 SeqCst => intrinsics::atomic_singlethreadfence(),
1811 Relaxed => panic!("there is no such thing as a relaxed compiler fence"),
1812 __Nonexhaustive => panic!("invalid memory ordering"),
1818 #[cfg(target_has_atomic = "8")]
1819 #[stable(feature = "atomic_debug", since = "1.3.0")]
1820 impl fmt::Debug for AtomicBool {
1821 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1822 f.debug_tuple("AtomicBool").field(&self.load(Ordering::SeqCst)).finish()
1826 #[cfg(target_has_atomic = "ptr")]
1827 #[stable(feature = "atomic_debug", since = "1.3.0")]
1828 impl<T> fmt::Debug for AtomicPtr<T> {
1829 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1830 f.debug_tuple("AtomicPtr").field(&self.load(Ordering::SeqCst)).finish()
1834 #[cfg(target_has_atomic = "ptr")]
1835 #[stable(feature = "atomic_pointer", since = "1.24.0")]
1836 impl<T> fmt::Pointer for AtomicPtr<T> {
1837 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1838 fmt::Pointer::fmt(&self.load(Ordering::SeqCst), f)