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 //! Each method takes an `Ordering` which represents the strength of
23 //! the memory barrier for that operation. These orderings are the
24 //! same as [LLVM atomic orderings][1]. For more information see the [nomicon][2].
26 //! [1]: http://llvm.org/docs/LangRef.html#memory-model-for-concurrent-operations
27 //! [2]: ../../../nomicon/atomics.html
29 //! Atomic variables are safe to share between threads (they implement `Sync`)
30 //! but they do not themselves provide the mechanism for sharing and follow the
31 //! [threading model](../../../std/thread/index.html#the-threading-model) of rust.
32 //! The most common way to share an atomic variable is to put it into an `Arc` (an
33 //! atomically-reference-counted shared pointer).
35 //! Most atomic types may be stored in static variables, initialized using
36 //! the provided static initializers like `ATOMIC_BOOL_INIT`. Atomic statics
37 //! are often used for lazy global initialization.
42 //! A simple spinlock:
45 //! use std::sync::Arc;
46 //! use std::sync::atomic::{AtomicUsize, Ordering};
50 //! let spinlock = Arc::new(AtomicUsize::new(1));
52 //! let spinlock_clone = spinlock.clone();
53 //! let thread = thread::spawn(move|| {
54 //! spinlock_clone.store(0, Ordering::SeqCst);
57 //! // Wait for the other thread to release the lock
58 //! while spinlock.load(Ordering::SeqCst) != 0 {}
60 //! if let Err(panic) = thread.join() {
61 //! println!("Thread had an error: {:?}", panic);
66 //! Keep a global count of live threads:
69 //! use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
71 //! static GLOBAL_THREAD_COUNT: AtomicUsize = ATOMIC_USIZE_INIT;
73 //! let old_thread_count = GLOBAL_THREAD_COUNT.fetch_add(1, Ordering::SeqCst);
74 //! println!("live threads: {}", old_thread_count + 1);
77 #![stable(feature = "rust1", since = "1.0.0")]
78 #![cfg_attr(not(target_has_atomic = "8"), allow(dead_code))]
79 #![cfg_attr(not(target_has_atomic = "8"), allow(unused_imports))]
81 use self::Ordering::*;
87 /// A boolean type which can be safely shared between threads.
89 /// This type has the same in-memory representation as a `bool`.
90 #[cfg(target_has_atomic = "8")]
91 #[stable(feature = "rust1", since = "1.0.0")]
92 pub struct AtomicBool {
96 #[cfg(target_has_atomic = "8")]
97 #[stable(feature = "rust1", since = "1.0.0")]
98 impl Default for AtomicBool {
99 /// Creates an `AtomicBool` initialized to `false`.
100 fn default() -> Self {
105 // Send is implicitly implemented for AtomicBool.
106 #[cfg(target_has_atomic = "8")]
107 #[stable(feature = "rust1", since = "1.0.0")]
108 unsafe impl Sync for AtomicBool {}
110 /// A raw pointer type which can be safely shared between threads.
112 /// This type has the same in-memory representation as a `*mut T`.
113 #[cfg(target_has_atomic = "ptr")]
114 #[stable(feature = "rust1", since = "1.0.0")]
115 pub struct AtomicPtr<T> {
116 p: UnsafeCell<*mut T>,
119 #[cfg(target_has_atomic = "ptr")]
120 #[stable(feature = "rust1", since = "1.0.0")]
121 impl<T> Default for AtomicPtr<T> {
122 /// Creates a null `AtomicPtr<T>`.
123 fn default() -> AtomicPtr<T> {
124 AtomicPtr::new(::ptr::null_mut())
128 #[cfg(target_has_atomic = "ptr")]
129 #[stable(feature = "rust1", since = "1.0.0")]
130 unsafe impl<T> Send for AtomicPtr<T> {}
131 #[cfg(target_has_atomic = "ptr")]
132 #[stable(feature = "rust1", since = "1.0.0")]
133 unsafe impl<T> Sync for AtomicPtr<T> {}
135 /// Atomic memory orderings
137 /// Memory orderings limit the ways that both the compiler and CPU may reorder
138 /// instructions around atomic operations. At its most restrictive,
139 /// "sequentially consistent" atomics allow neither reads nor writes
140 /// to be moved either before or after the atomic operation; on the other end
141 /// "relaxed" atomics allow all reorderings.
143 /// Rust's memory orderings are [the same as
144 /// LLVM's](http://llvm.org/docs/LangRef.html#memory-model-for-concurrent-operations).
146 /// For more information see the [nomicon][1].
147 /// [1]: ../../../nomicon/atomics.html
148 #[stable(feature = "rust1", since = "1.0.0")]
149 #[derive(Copy, Clone, Debug)]
151 /// No ordering constraints, only atomic operations. Corresponds to LLVM's
152 /// `Monotonic` ordering.
153 #[stable(feature = "rust1", since = "1.0.0")]
155 /// When coupled with a store, all previous writes become visible
156 /// to the other threads that perform a load with `Acquire` ordering
157 /// on the same value.
158 #[stable(feature = "rust1", since = "1.0.0")]
160 /// When coupled with a load, all subsequent loads will see data
161 /// written before a store with `Release` ordering on the same value
162 /// in other threads.
163 #[stable(feature = "rust1", since = "1.0.0")]
165 /// When coupled with a load, uses `Acquire` ordering, and with a store
166 /// `Release` ordering.
167 #[stable(feature = "rust1", since = "1.0.0")]
169 /// Like `AcqRel` with the additional guarantee that all threads see all
170 /// sequentially consistent operations in the same order.
171 #[stable(feature = "rust1", since = "1.0.0")]
173 // Prevent exhaustive matching to allow for future extension
175 #[unstable(feature = "future_atomic_orderings", issue = "0")]
179 /// An `AtomicBool` initialized to `false`.
180 #[cfg(target_has_atomic = "8")]
181 #[stable(feature = "rust1", since = "1.0.0")]
182 pub const ATOMIC_BOOL_INIT: AtomicBool = AtomicBool::new(false);
184 #[cfg(target_has_atomic = "8")]
186 /// Creates a new `AtomicBool`.
191 /// use std::sync::atomic::AtomicBool;
193 /// let atomic_true = AtomicBool::new(true);
194 /// let atomic_false = AtomicBool::new(false);
197 #[stable(feature = "rust1", since = "1.0.0")]
198 pub const fn new(v: bool) -> AtomicBool {
199 AtomicBool { v: UnsafeCell::new(v as u8) }
202 /// Returns a mutable reference to the underlying `bool`.
204 /// This is safe because the mutable reference guarantees that no other threads are
205 /// concurrently accessing the atomic data.
210 /// use std::sync::atomic::{AtomicBool, Ordering};
212 /// let mut some_bool = AtomicBool::new(true);
213 /// assert_eq!(*some_bool.get_mut(), true);
214 /// *some_bool.get_mut() = false;
215 /// assert_eq!(some_bool.load(Ordering::SeqCst), false);
218 #[stable(feature = "atomic_access", since = "1.15.0")]
219 pub fn get_mut(&mut self) -> &mut bool {
220 unsafe { &mut *(self.v.get() as *mut bool) }
223 /// Consumes the atomic and returns the contained value.
225 /// This is safe because passing `self` by value guarantees that no other threads are
226 /// concurrently accessing the atomic data.
231 /// use std::sync::atomic::AtomicBool;
233 /// let some_bool = AtomicBool::new(true);
234 /// assert_eq!(some_bool.into_inner(), true);
237 #[stable(feature = "atomic_access", since = "1.15.0")]
238 pub fn into_inner(self) -> bool {
239 unsafe { self.v.into_inner() != 0 }
242 /// Loads a value from the bool.
244 /// `load` takes an [`Ordering`] argument which describes the memory ordering
245 /// of this operation.
249 /// Panics if `order` is [`Release`] or [`AcqRel`].
251 /// [`Ordering`]: enum.Ordering.html
252 /// [`Release`]: enum.Ordering.html#variant.Release
253 /// [`AcqRel`]: enum.Ordering.html#variant.Release
258 /// use std::sync::atomic::{AtomicBool, Ordering};
260 /// let some_bool = AtomicBool::new(true);
262 /// assert_eq!(some_bool.load(Ordering::Relaxed), true);
265 #[stable(feature = "rust1", since = "1.0.0")]
266 pub fn load(&self, order: Ordering) -> bool {
267 unsafe { atomic_load(self.v.get(), order) != 0 }
270 /// Stores a value into the bool.
272 /// `store` takes an [`Ordering`] argument which describes the memory ordering
273 /// of this operation.
275 /// [`Ordering`]: enum.Ordering.html
280 /// use std::sync::atomic::{AtomicBool, Ordering};
282 /// let some_bool = AtomicBool::new(true);
284 /// some_bool.store(false, Ordering::Relaxed);
285 /// assert_eq!(some_bool.load(Ordering::Relaxed), false);
290 /// Panics if `order` is `Acquire` or `AcqRel`.
292 #[stable(feature = "rust1", since = "1.0.0")]
293 pub fn store(&self, val: bool, order: Ordering) {
295 atomic_store(self.v.get(), val as u8, order);
299 /// Stores a value into the bool, returning the old value.
301 /// `swap` takes an [`Ordering`] argument which describes the memory ordering
302 /// of this operation.
304 /// [`Ordering`]: enum.Ordering.html
309 /// use std::sync::atomic::{AtomicBool, Ordering};
311 /// let some_bool = AtomicBool::new(true);
313 /// assert_eq!(some_bool.swap(false, Ordering::Relaxed), true);
314 /// assert_eq!(some_bool.load(Ordering::Relaxed), false);
317 #[stable(feature = "rust1", since = "1.0.0")]
318 pub fn swap(&self, val: bool, order: Ordering) -> bool {
319 unsafe { atomic_swap(self.v.get(), val as u8, order) != 0 }
322 /// Stores a value into the `bool` if the current value is the same as the `current` value.
324 /// The return value is always the previous value. If it is equal to `current`, then the value
327 /// `compare_and_swap` also takes an [`Ordering`] argument which describes the memory
328 /// ordering of this operation.
330 /// [`Ordering`]: enum.Ordering.html
335 /// use std::sync::atomic::{AtomicBool, Ordering};
337 /// let some_bool = AtomicBool::new(true);
339 /// assert_eq!(some_bool.compare_and_swap(true, false, Ordering::Relaxed), true);
340 /// assert_eq!(some_bool.load(Ordering::Relaxed), false);
342 /// assert_eq!(some_bool.compare_and_swap(true, true, Ordering::Relaxed), false);
343 /// assert_eq!(some_bool.load(Ordering::Relaxed), false);
346 #[stable(feature = "rust1", since = "1.0.0")]
347 pub fn compare_and_swap(&self, current: bool, new: bool, order: Ordering) -> bool {
348 match self.compare_exchange(current, new, order, strongest_failure_ordering(order)) {
354 /// Stores a value into the `bool` if the current value is the same as the `current` value.
356 /// The return value is a result indicating whether the new value was written and containing
357 /// the previous value. On success this value is guaranteed to be equal to `current`.
359 /// `compare_exchange` takes two [`Ordering`] arguments to describe the memory
360 /// ordering of this operation. The first describes the required ordering if the
361 /// operation succeeds while the second describes the required ordering when the
362 /// operation fails. The failure ordering can't be [`Release`] or [`AcqRel`] and must
363 /// be equivalent or weaker than the success ordering.
365 /// [`Ordering`]: enum.Ordering.html
366 /// [`Release`]: enum.Ordering.html#variant.Release
367 /// [`AcqRel`]: enum.Ordering.html#variant.Release
372 /// use std::sync::atomic::{AtomicBool, Ordering};
374 /// let some_bool = AtomicBool::new(true);
376 /// assert_eq!(some_bool.compare_exchange(true,
378 /// Ordering::Acquire,
379 /// Ordering::Relaxed),
381 /// assert_eq!(some_bool.load(Ordering::Relaxed), false);
383 /// assert_eq!(some_bool.compare_exchange(true, true,
384 /// Ordering::SeqCst,
385 /// Ordering::Acquire),
387 /// assert_eq!(some_bool.load(Ordering::Relaxed), false);
390 #[stable(feature = "extended_compare_and_swap", since = "1.10.0")]
391 pub fn compare_exchange(&self,
396 -> Result<bool, bool> {
398 atomic_compare_exchange(self.v.get(), current as u8, new as u8, success, failure)
401 Err(x) => Err(x != 0),
405 /// Stores a value into the `bool` if the current value is the same as the `current` value.
407 /// Unlike `compare_exchange`, this function is allowed to spuriously fail even when the
408 /// comparison succeeds, which can result in more efficient code on some platforms. The
409 /// return value is a result indicating whether the new value was written and containing the
412 /// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory
413 /// ordering of this operation. The first describes the required ordering if the operation
414 /// succeeds while the second describes the required ordering when the operation fails. The
415 /// failure ordering can't be [`Release`] or [`AcqRel`] and must be equivalent or
416 /// weaker than the success ordering.
418 /// [`Ordering`]: enum.Ordering.html
419 /// [`Release`]: enum.Ordering.html#variant.Release
420 /// [`AcqRel`]: enum.Ordering.html#variant.Release
425 /// use std::sync::atomic::{AtomicBool, Ordering};
427 /// let val = AtomicBool::new(false);
430 /// let mut old = val.load(Ordering::Relaxed);
432 /// match val.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) {
434 /// Err(x) => old = x,
439 #[stable(feature = "extended_compare_and_swap", since = "1.10.0")]
440 pub fn compare_exchange_weak(&self,
445 -> Result<bool, bool> {
447 atomic_compare_exchange_weak(self.v.get(), current as u8, new as u8, success, failure)
450 Err(x) => Err(x != 0),
454 /// Logical "and" with a boolean value.
456 /// Performs a logical "and" operation on the current value and the argument `val`, and sets
457 /// the new value to the result.
459 /// Returns the previous value.
464 /// use std::sync::atomic::{AtomicBool, Ordering};
466 /// let foo = AtomicBool::new(true);
467 /// assert_eq!(foo.fetch_and(false, Ordering::SeqCst), true);
468 /// assert_eq!(foo.load(Ordering::SeqCst), false);
470 /// let foo = AtomicBool::new(true);
471 /// assert_eq!(foo.fetch_and(true, Ordering::SeqCst), true);
472 /// assert_eq!(foo.load(Ordering::SeqCst), true);
474 /// let foo = AtomicBool::new(false);
475 /// assert_eq!(foo.fetch_and(false, Ordering::SeqCst), false);
476 /// assert_eq!(foo.load(Ordering::SeqCst), false);
479 #[stable(feature = "rust1", since = "1.0.0")]
480 pub fn fetch_and(&self, val: bool, order: Ordering) -> bool {
481 unsafe { atomic_and(self.v.get(), val as u8, order) != 0 }
484 /// Logical "nand" with a boolean value.
486 /// Performs a logical "nand" operation on the current value and the argument `val`, and sets
487 /// the new value to the result.
489 /// Returns the previous value.
494 /// use std::sync::atomic::{AtomicBool, Ordering};
496 /// let foo = AtomicBool::new(true);
497 /// assert_eq!(foo.fetch_nand(false, Ordering::SeqCst), true);
498 /// assert_eq!(foo.load(Ordering::SeqCst), true);
500 /// let foo = AtomicBool::new(true);
501 /// assert_eq!(foo.fetch_nand(true, Ordering::SeqCst), true);
502 /// assert_eq!(foo.load(Ordering::SeqCst) as usize, 0);
503 /// assert_eq!(foo.load(Ordering::SeqCst), false);
505 /// let foo = AtomicBool::new(false);
506 /// assert_eq!(foo.fetch_nand(false, Ordering::SeqCst), false);
507 /// assert_eq!(foo.load(Ordering::SeqCst), true);
510 #[stable(feature = "rust1", since = "1.0.0")]
511 pub fn fetch_nand(&self, val: bool, order: Ordering) -> bool {
512 // We can't use atomic_nand here because it can result in a bool with
513 // an invalid value. This happens because the atomic operation is done
514 // with an 8-bit integer internally, which would set the upper 7 bits.
515 // So we just use a compare-exchange loop instead, which is what the
516 // intrinsic actually expands to anyways on many platforms.
517 let mut old = self.load(Relaxed);
519 let new = !(old && val);
520 match self.compare_exchange_weak(old, new, order, Relaxed) {
528 /// Logical "or" with a boolean value.
530 /// Performs a logical "or" operation on the current value and the argument `val`, and sets the
531 /// new value to the result.
533 /// Returns the previous value.
538 /// use std::sync::atomic::{AtomicBool, Ordering};
540 /// let foo = AtomicBool::new(true);
541 /// assert_eq!(foo.fetch_or(false, Ordering::SeqCst), true);
542 /// assert_eq!(foo.load(Ordering::SeqCst), true);
544 /// let foo = AtomicBool::new(true);
545 /// assert_eq!(foo.fetch_or(true, Ordering::SeqCst), true);
546 /// assert_eq!(foo.load(Ordering::SeqCst), true);
548 /// let foo = AtomicBool::new(false);
549 /// assert_eq!(foo.fetch_or(false, Ordering::SeqCst), false);
550 /// assert_eq!(foo.load(Ordering::SeqCst), false);
553 #[stable(feature = "rust1", since = "1.0.0")]
554 pub fn fetch_or(&self, val: bool, order: Ordering) -> bool {
555 unsafe { atomic_or(self.v.get(), val as u8, order) != 0 }
558 /// Logical "xor" with a boolean value.
560 /// Performs a logical "xor" operation on the current value and the argument `val`, and sets
561 /// the new value to the result.
563 /// Returns the previous value.
568 /// use std::sync::atomic::{AtomicBool, Ordering};
570 /// let foo = AtomicBool::new(true);
571 /// assert_eq!(foo.fetch_xor(false, Ordering::SeqCst), true);
572 /// assert_eq!(foo.load(Ordering::SeqCst), true);
574 /// let foo = AtomicBool::new(true);
575 /// assert_eq!(foo.fetch_xor(true, Ordering::SeqCst), true);
576 /// assert_eq!(foo.load(Ordering::SeqCst), false);
578 /// let foo = AtomicBool::new(false);
579 /// assert_eq!(foo.fetch_xor(false, Ordering::SeqCst), false);
580 /// assert_eq!(foo.load(Ordering::SeqCst), false);
583 #[stable(feature = "rust1", since = "1.0.0")]
584 pub fn fetch_xor(&self, val: bool, order: Ordering) -> bool {
585 unsafe { atomic_xor(self.v.get(), val as u8, order) != 0 }
589 #[cfg(target_has_atomic = "ptr")]
590 impl<T> AtomicPtr<T> {
591 /// Creates a new `AtomicPtr`.
596 /// use std::sync::atomic::AtomicPtr;
598 /// let ptr = &mut 5;
599 /// let atomic_ptr = AtomicPtr::new(ptr);
602 #[stable(feature = "rust1", since = "1.0.0")]
603 pub const fn new(p: *mut T) -> AtomicPtr<T> {
604 AtomicPtr { p: UnsafeCell::new(p) }
607 /// Returns a mutable reference to the underlying pointer.
609 /// This is safe because the mutable reference guarantees that no other threads are
610 /// concurrently accessing the atomic data.
615 /// use std::sync::atomic::{AtomicPtr, Ordering};
617 /// let mut atomic_ptr = AtomicPtr::new(&mut 10);
618 /// *atomic_ptr.get_mut() = &mut 5;
619 /// assert_eq!(unsafe { *atomic_ptr.load(Ordering::SeqCst) }, 5);
622 #[stable(feature = "atomic_access", since = "1.15.0")]
623 pub fn get_mut(&mut self) -> &mut *mut T {
624 unsafe { &mut *self.p.get() }
627 /// Consumes the atomic and returns the contained value.
629 /// This is safe because passing `self` by value guarantees that no other threads are
630 /// concurrently accessing the atomic data.
635 /// use std::sync::atomic::AtomicPtr;
637 /// let atomic_ptr = AtomicPtr::new(&mut 5);
638 /// assert_eq!(unsafe { *atomic_ptr.into_inner() }, 5);
641 #[stable(feature = "atomic_access", since = "1.15.0")]
642 pub fn into_inner(self) -> *mut T {
643 unsafe { self.p.into_inner() }
646 /// Loads a value from the pointer.
648 /// `load` takes an [`Ordering`] argument which describes the memory ordering
649 /// of this operation.
653 /// Panics if `order` is [`Release`] or [`AcqRel`].
655 /// [`Ordering`]: enum.Ordering.html
656 /// [`Release`]: enum.Ordering.html#variant.Release
657 /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
662 /// use std::sync::atomic::{AtomicPtr, Ordering};
664 /// let ptr = &mut 5;
665 /// let some_ptr = AtomicPtr::new(ptr);
667 /// let value = some_ptr.load(Ordering::Relaxed);
670 #[stable(feature = "rust1", since = "1.0.0")]
671 pub fn load(&self, order: Ordering) -> *mut T {
672 unsafe { atomic_load(self.p.get() as *mut usize, order) as *mut T }
675 /// Stores a value into the pointer.
677 /// `store` takes an [`Ordering`] argument which describes the memory ordering
678 /// of this operation.
680 /// [`Ordering`]: enum.Ordering.html
685 /// use std::sync::atomic::{AtomicPtr, Ordering};
687 /// let ptr = &mut 5;
688 /// let some_ptr = AtomicPtr::new(ptr);
690 /// let other_ptr = &mut 10;
692 /// some_ptr.store(other_ptr, Ordering::Relaxed);
697 /// Panics if `order` is `Acquire` or `AcqRel`.
699 #[stable(feature = "rust1", since = "1.0.0")]
700 pub fn store(&self, ptr: *mut T, order: Ordering) {
702 atomic_store(self.p.get() as *mut usize, ptr as usize, order);
706 /// Stores a value into the pointer, returning the old value.
708 /// `swap` takes an [`Ordering`] argument which describes the memory ordering
709 /// of this operation.
711 /// [`Ordering`]: enum.Ordering.html
716 /// use std::sync::atomic::{AtomicPtr, Ordering};
718 /// let ptr = &mut 5;
719 /// let some_ptr = AtomicPtr::new(ptr);
721 /// let other_ptr = &mut 10;
723 /// let value = some_ptr.swap(other_ptr, Ordering::Relaxed);
726 #[stable(feature = "rust1", since = "1.0.0")]
727 pub fn swap(&self, ptr: *mut T, order: Ordering) -> *mut T {
728 unsafe { atomic_swap(self.p.get() as *mut usize, ptr as usize, order) as *mut T }
731 /// Stores a value into the pointer if the current value is the same as the `current` value.
733 /// The return value is always the previous value. If it is equal to `current`, then the value
736 /// `compare_and_swap` also takes an [`Ordering`] argument which describes the memory
737 /// ordering of this operation.
739 /// [`Ordering`]: enum.Ordering.html
744 /// use std::sync::atomic::{AtomicPtr, Ordering};
746 /// let ptr = &mut 5;
747 /// let some_ptr = AtomicPtr::new(ptr);
749 /// let other_ptr = &mut 10;
750 /// let another_ptr = &mut 10;
752 /// let value = some_ptr.compare_and_swap(other_ptr, another_ptr, Ordering::Relaxed);
755 #[stable(feature = "rust1", since = "1.0.0")]
756 pub fn compare_and_swap(&self, current: *mut T, new: *mut T, order: Ordering) -> *mut T {
757 match self.compare_exchange(current, new, order, strongest_failure_ordering(order)) {
763 /// Stores a value into the pointer if the current value is the same as the `current` value.
765 /// The return value is a result indicating whether the new value was written and containing
766 /// the previous value. On success this value is guaranteed to be equal to `current`.
768 /// `compare_exchange` takes two [`Ordering`] arguments to describe the memory
769 /// ordering of this operation. The first describes the required ordering if
770 /// the operation succeeds while the second describes the required ordering when
771 /// the operation fails. The failure ordering can't be [`Release`] or [`AcqRel`]
772 /// and must be equivalent or weaker than the success ordering.
774 /// [`Ordering`]: enum.Ordering.html
775 /// [`Release`]: enum.Ordering.html#variant.Release
776 /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
781 /// use std::sync::atomic::{AtomicPtr, Ordering};
783 /// let ptr = &mut 5;
784 /// let some_ptr = AtomicPtr::new(ptr);
786 /// let other_ptr = &mut 10;
787 /// let another_ptr = &mut 10;
789 /// let value = some_ptr.compare_exchange(other_ptr, another_ptr,
790 /// Ordering::SeqCst, Ordering::Relaxed);
793 #[stable(feature = "extended_compare_and_swap", since = "1.10.0")]
794 pub fn compare_exchange(&self,
799 -> Result<*mut T, *mut T> {
801 let res = atomic_compare_exchange(self.p.get() as *mut usize,
807 Ok(x) => Ok(x as *mut T),
808 Err(x) => Err(x as *mut T),
813 /// Stores a value into the pointer if the current value is the same as the `current` value.
815 /// Unlike [`compare_exchange`], this function is allowed to spuriously fail even when the
816 /// comparison succeeds, which can result in more efficient code on some platforms. The
817 /// return value is a result indicating whether the new value was written and containing the
820 /// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory
821 /// ordering of this operation. The first describes the required ordering if the operation
822 /// succeeds while the second describes the required ordering when the operation fails. The
823 /// failure ordering can't be [`Release`] or [`AcqRel`] and must be equivalent or
824 /// weaker than the success ordering.
826 /// [`compare_exchange`]: #method.compare_exchange
827 /// [`Ordering`]: enum.Ordering.html
828 /// [`Release`]: enum.Ordering.html#variant.Release
829 /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
834 /// use std::sync::atomic::{AtomicPtr, Ordering};
836 /// let some_ptr = AtomicPtr::new(&mut 5);
838 /// let new = &mut 10;
839 /// let mut old = some_ptr.load(Ordering::Relaxed);
841 /// match some_ptr.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) {
843 /// Err(x) => old = x,
848 #[stable(feature = "extended_compare_and_swap", since = "1.10.0")]
849 pub fn compare_exchange_weak(&self,
854 -> Result<*mut T, *mut T> {
856 let res = atomic_compare_exchange_weak(self.p.get() as *mut usize,
862 Ok(x) => Ok(x as *mut T),
863 Err(x) => Err(x as *mut T),
869 macro_rules! atomic_int {
874 $int_type:ident $atomic_type:ident $atomic_init:ident) => {
875 /// An integer type which can be safely shared between threads.
877 /// This type has the same in-memory representation as the underlying integer type.
879 pub struct $atomic_type {
880 v: UnsafeCell<$int_type>,
883 /// An atomic integer initialized to `0`.
885 pub const $atomic_init: $atomic_type = $atomic_type::new(0);
888 impl Default for $atomic_type {
889 fn default() -> Self {
890 Self::new(Default::default())
895 impl fmt::Debug for $atomic_type {
896 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
897 f.debug_tuple(stringify!($atomic_type))
898 .field(&self.load(Ordering::SeqCst))
903 // Send is implicitly implemented.
905 unsafe impl Sync for $atomic_type {}
908 /// Creates a new atomic integer.
913 /// use std::sync::atomic::AtomicIsize;
915 /// let atomic_forty_two = AtomicIsize::new(42);
919 pub const fn new(v: $int_type) -> Self {
920 $atomic_type {v: UnsafeCell::new(v)}
923 /// Returns a mutable reference to the underlying integer.
925 /// This is safe because the mutable reference guarantees that no other threads are
926 /// concurrently accessing the atomic data.
931 /// use std::sync::atomic::{AtomicIsize, Ordering};
933 /// let mut some_isize = AtomicIsize::new(10);
934 /// assert_eq!(*some_isize.get_mut(), 10);
935 /// *some_isize.get_mut() = 5;
936 /// assert_eq!(some_isize.load(Ordering::SeqCst), 5);
940 pub fn get_mut(&mut self) -> &mut $int_type {
941 unsafe { &mut *self.v.get() }
944 /// Consumes the atomic and returns the contained value.
946 /// This is safe because passing `self` by value guarantees that no other threads are
947 /// concurrently accessing the atomic data.
952 /// use std::sync::atomic::AtomicIsize;
954 /// let some_isize = AtomicIsize::new(5);
955 /// assert_eq!(some_isize.into_inner(), 5);
959 pub fn into_inner(self) -> $int_type {
960 unsafe { self.v.into_inner() }
963 /// Loads a value from the atomic integer.
965 /// `load` takes an [`Ordering`] argument which describes the memory ordering of this
970 /// Panics if `order` is [`Release`] or [`AcqRel`].
972 /// [`Ordering`]: enum.Ordering.html
973 /// [`Release`]: enum.Ordering.html#variant.Release
974 /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
979 /// use std::sync::atomic::{AtomicIsize, Ordering};
981 /// let some_isize = AtomicIsize::new(5);
983 /// assert_eq!(some_isize.load(Ordering::Relaxed), 5);
987 pub fn load(&self, order: Ordering) -> $int_type {
988 unsafe { atomic_load(self.v.get(), order) }
991 /// Stores a value into the atomic integer.
993 /// `store` takes an [`Ordering`] argument which describes the memory ordering of this
996 /// [`Ordering`]: enum.Ordering.html
1001 /// use std::sync::atomic::{AtomicIsize, Ordering};
1003 /// let some_isize = AtomicIsize::new(5);
1005 /// some_isize.store(10, Ordering::Relaxed);
1006 /// assert_eq!(some_isize.load(Ordering::Relaxed), 10);
1011 /// Panics if `order` is `Acquire` or `AcqRel`.
1014 pub fn store(&self, val: $int_type, order: Ordering) {
1015 unsafe { atomic_store(self.v.get(), val, order); }
1018 /// Stores a value into the atomic integer, returning the old value.
1020 /// `swap` takes an [`Ordering`] argument which describes the memory ordering of this
1023 /// [`Ordering`]: enum.Ordering.html
1028 /// use std::sync::atomic::{AtomicIsize, Ordering};
1030 /// let some_isize = AtomicIsize::new(5);
1032 /// assert_eq!(some_isize.swap(10, Ordering::Relaxed), 5);
1036 pub fn swap(&self, val: $int_type, order: Ordering) -> $int_type {
1037 unsafe { atomic_swap(self.v.get(), val, order) }
1040 /// Stores a value into the atomic integer if the current value is the same as the
1041 /// `current` value.
1043 /// The return value is always the previous value. If it is equal to `current`, then the
1044 /// value was updated.
1046 /// `compare_and_swap` also takes an [`Ordering`] argument which describes the memory
1047 /// ordering of this operation.
1049 /// [`Ordering`]: enum.Ordering.html
1054 /// use std::sync::atomic::{AtomicIsize, Ordering};
1056 /// let some_isize = AtomicIsize::new(5);
1058 /// assert_eq!(some_isize.compare_and_swap(5, 10, Ordering::Relaxed), 5);
1059 /// assert_eq!(some_isize.load(Ordering::Relaxed), 10);
1061 /// assert_eq!(some_isize.compare_and_swap(6, 12, Ordering::Relaxed), 10);
1062 /// assert_eq!(some_isize.load(Ordering::Relaxed), 10);
1066 pub fn compare_and_swap(&self,
1069 order: Ordering) -> $int_type {
1070 match self.compare_exchange(current,
1073 strongest_failure_ordering(order)) {
1079 /// Stores a value into the atomic integer if the current value is the same as the
1080 /// `current` value.
1082 /// The return value is a result indicating whether the new value was written and
1083 /// containing the previous value. On success this value is guaranteed to be equal to
1086 /// `compare_exchange` takes two [`Ordering`] arguments to describe the memory
1087 /// ordering of this operation. The first describes the required ordering if
1088 /// the operation succeeds while the second describes the required ordering when
1089 /// the operation fails. The failure ordering can't be [`Release`] or [`AcqRel`] and
1090 /// must be equivalent or weaker than the success ordering.
1092 /// [`Ordering`]: enum.Ordering.html
1093 /// [`Release`]: enum.Ordering.html#variant.Release
1094 /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
1099 /// use std::sync::atomic::{AtomicIsize, Ordering};
1101 /// let some_isize = AtomicIsize::new(5);
1103 /// assert_eq!(some_isize.compare_exchange(5, 10,
1104 /// Ordering::Acquire,
1105 /// Ordering::Relaxed),
1107 /// assert_eq!(some_isize.load(Ordering::Relaxed), 10);
1109 /// assert_eq!(some_isize.compare_exchange(6, 12,
1110 /// Ordering::SeqCst,
1111 /// Ordering::Acquire),
1113 /// assert_eq!(some_isize.load(Ordering::Relaxed), 10);
1117 pub fn compare_exchange(&self,
1121 failure: Ordering) -> Result<$int_type, $int_type> {
1122 unsafe { atomic_compare_exchange(self.v.get(), current, new, success, failure) }
1125 /// Stores a value into the atomic integer if the current value is the same as the
1126 /// `current` value.
1128 /// Unlike [`compare_exchange`], this function is allowed to spuriously fail even
1129 /// when the comparison succeeds, which can result in more efficient code on some
1130 /// platforms. The return value is a result indicating whether the new value was
1131 /// written and containing the previous value.
1133 /// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory
1134 /// ordering of this operation. The first describes the required ordering if the
1135 /// operation succeeds while the second describes the required ordering when the
1136 /// operation fails. The failure ordering can't be [`Release`] or [`AcqRel`] and
1137 /// must be equivalent or weaker than the success ordering.
1139 /// [`compare_exchange`]: #method.compare_exchange
1140 /// [`Ordering`]: enum.Ordering.html
1141 /// [`Release`]: enum.Ordering.html#variant.Release
1142 /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
1147 /// use std::sync::atomic::{AtomicIsize, Ordering};
1149 /// let val = AtomicIsize::new(4);
1151 /// let mut old = val.load(Ordering::Relaxed);
1153 /// let new = old * 2;
1154 /// match val.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) {
1156 /// Err(x) => old = x,
1162 pub fn compare_exchange_weak(&self,
1166 failure: Ordering) -> Result<$int_type, $int_type> {
1168 atomic_compare_exchange_weak(self.v.get(), current, new, success, failure)
1172 /// Add to the current value, returning the previous value.
1177 /// use std::sync::atomic::{AtomicIsize, Ordering};
1179 /// let foo = AtomicIsize::new(0);
1180 /// assert_eq!(foo.fetch_add(10, Ordering::SeqCst), 0);
1181 /// assert_eq!(foo.load(Ordering::SeqCst), 10);
1185 pub fn fetch_add(&self, val: $int_type, order: Ordering) -> $int_type {
1186 unsafe { atomic_add(self.v.get(), val, order) }
1189 /// Subtract from the current value, returning the previous value.
1194 /// use std::sync::atomic::{AtomicIsize, Ordering};
1196 /// let foo = AtomicIsize::new(0);
1197 /// assert_eq!(foo.fetch_sub(10, Ordering::SeqCst), 0);
1198 /// assert_eq!(foo.load(Ordering::SeqCst), -10);
1202 pub fn fetch_sub(&self, val: $int_type, order: Ordering) -> $int_type {
1203 unsafe { atomic_sub(self.v.get(), val, order) }
1206 /// Bitwise and with the current value, returning the previous value.
1211 /// use std::sync::atomic::{AtomicIsize, Ordering};
1213 /// let foo = AtomicIsize::new(0b101101);
1214 /// assert_eq!(foo.fetch_and(0b110011, Ordering::SeqCst), 0b101101);
1215 /// assert_eq!(foo.load(Ordering::SeqCst), 0b100001);
1218 pub fn fetch_and(&self, val: $int_type, order: Ordering) -> $int_type {
1219 unsafe { atomic_and(self.v.get(), val, order) }
1222 /// Bitwise or with the current value, returning the previous value.
1227 /// use std::sync::atomic::{AtomicIsize, Ordering};
1229 /// let foo = AtomicIsize::new(0b101101);
1230 /// assert_eq!(foo.fetch_or(0b110011, Ordering::SeqCst), 0b101101);
1231 /// assert_eq!(foo.load(Ordering::SeqCst), 0b111111);
1234 pub fn fetch_or(&self, val: $int_type, order: Ordering) -> $int_type {
1235 unsafe { atomic_or(self.v.get(), val, order) }
1238 /// Bitwise xor with the current value, returning the previous value.
1243 /// use std::sync::atomic::{AtomicIsize, Ordering};
1245 /// let foo = AtomicIsize::new(0b101101);
1246 /// assert_eq!(foo.fetch_xor(0b110011, Ordering::SeqCst), 0b101101);
1247 /// assert_eq!(foo.load(Ordering::SeqCst), 0b011110);
1250 pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
1251 unsafe { atomic_xor(self.v.get(), val, order) }
1257 #[cfg(target_has_atomic = "8")]
1259 unstable(feature = "integer_atomics", issue = "32976"),
1260 unstable(feature = "integer_atomics", issue = "32976"),
1261 unstable(feature = "integer_atomics", issue = "32976"),
1262 unstable(feature = "integer_atomics", issue = "32976"),
1263 i8 AtomicI8 ATOMIC_I8_INIT
1265 #[cfg(target_has_atomic = "8")]
1267 unstable(feature = "integer_atomics", issue = "32976"),
1268 unstable(feature = "integer_atomics", issue = "32976"),
1269 unstable(feature = "integer_atomics", issue = "32976"),
1270 unstable(feature = "integer_atomics", issue = "32976"),
1271 u8 AtomicU8 ATOMIC_U8_INIT
1273 #[cfg(target_has_atomic = "16")]
1275 unstable(feature = "integer_atomics", issue = "32976"),
1276 unstable(feature = "integer_atomics", issue = "32976"),
1277 unstable(feature = "integer_atomics", issue = "32976"),
1278 unstable(feature = "integer_atomics", issue = "32976"),
1279 i16 AtomicI16 ATOMIC_I16_INIT
1281 #[cfg(target_has_atomic = "16")]
1283 unstable(feature = "integer_atomics", issue = "32976"),
1284 unstable(feature = "integer_atomics", issue = "32976"),
1285 unstable(feature = "integer_atomics", issue = "32976"),
1286 unstable(feature = "integer_atomics", issue = "32976"),
1287 u16 AtomicU16 ATOMIC_U16_INIT
1289 #[cfg(target_has_atomic = "32")]
1291 unstable(feature = "integer_atomics", issue = "32976"),
1292 unstable(feature = "integer_atomics", issue = "32976"),
1293 unstable(feature = "integer_atomics", issue = "32976"),
1294 unstable(feature = "integer_atomics", issue = "32976"),
1295 i32 AtomicI32 ATOMIC_I32_INIT
1297 #[cfg(target_has_atomic = "32")]
1299 unstable(feature = "integer_atomics", issue = "32976"),
1300 unstable(feature = "integer_atomics", issue = "32976"),
1301 unstable(feature = "integer_atomics", issue = "32976"),
1302 unstable(feature = "integer_atomics", issue = "32976"),
1303 u32 AtomicU32 ATOMIC_U32_INIT
1305 #[cfg(target_has_atomic = "64")]
1307 unstable(feature = "integer_atomics", issue = "32976"),
1308 unstable(feature = "integer_atomics", issue = "32976"),
1309 unstable(feature = "integer_atomics", issue = "32976"),
1310 unstable(feature = "integer_atomics", issue = "32976"),
1311 i64 AtomicI64 ATOMIC_I64_INIT
1313 #[cfg(target_has_atomic = "64")]
1315 unstable(feature = "integer_atomics", issue = "32976"),
1316 unstable(feature = "integer_atomics", issue = "32976"),
1317 unstable(feature = "integer_atomics", issue = "32976"),
1318 unstable(feature = "integer_atomics", issue = "32976"),
1319 u64 AtomicU64 ATOMIC_U64_INIT
1322 #[cfg(target_has_atomic = "128")]
1324 unstable(feature = "i128", issue = "35118"),
1325 unstable(feature = "i128", issue = "35118"),
1326 unstable(feature = "i128", issue = "35118"),
1327 unstable(feature = "i128", issue = "35118"),
1328 i128 AtomicI128 ATOMIC_I128_INIT
1331 #[cfg(target_has_atomic = "128")]
1333 unstable(feature = "i128", issue = "35118"),
1334 unstable(feature = "i128", issue = "35118"),
1335 unstable(feature = "i128", issue = "35118"),
1336 unstable(feature = "i128", issue = "35118"),
1337 u128 AtomicU128 ATOMIC_U128_INIT
1339 #[cfg(target_has_atomic = "ptr")]
1341 stable(feature = "rust1", since = "1.0.0"),
1342 stable(feature = "extended_compare_and_swap", since = "1.10.0"),
1343 stable(feature = "atomic_debug", since = "1.3.0"),
1344 stable(feature = "atomic_access", since = "1.15.0"),
1345 isize AtomicIsize ATOMIC_ISIZE_INIT
1347 #[cfg(target_has_atomic = "ptr")]
1349 stable(feature = "rust1", since = "1.0.0"),
1350 stable(feature = "extended_compare_and_swap", since = "1.10.0"),
1351 stable(feature = "atomic_debug", since = "1.3.0"),
1352 stable(feature = "atomic_access", since = "1.15.0"),
1353 usize AtomicUsize ATOMIC_USIZE_INIT
1357 fn strongest_failure_ordering(order: Ordering) -> Ordering {
1364 __Nonexhaustive => __Nonexhaustive,
1369 unsafe fn atomic_store<T>(dst: *mut T, val: T, order: Ordering) {
1371 Release => intrinsics::atomic_store_rel(dst, val),
1372 Relaxed => intrinsics::atomic_store_relaxed(dst, val),
1373 SeqCst => intrinsics::atomic_store(dst, val),
1374 Acquire => panic!("there is no such thing as an acquire store"),
1375 AcqRel => panic!("there is no such thing as an acquire/release store"),
1376 __Nonexhaustive => panic!("invalid memory ordering"),
1381 unsafe fn atomic_load<T>(dst: *const T, order: Ordering) -> T {
1383 Acquire => intrinsics::atomic_load_acq(dst),
1384 Relaxed => intrinsics::atomic_load_relaxed(dst),
1385 SeqCst => intrinsics::atomic_load(dst),
1386 Release => panic!("there is no such thing as a release load"),
1387 AcqRel => panic!("there is no such thing as an acquire/release load"),
1388 __Nonexhaustive => panic!("invalid memory ordering"),
1393 unsafe fn atomic_swap<T>(dst: *mut T, val: T, order: Ordering) -> T {
1395 Acquire => intrinsics::atomic_xchg_acq(dst, val),
1396 Release => intrinsics::atomic_xchg_rel(dst, val),
1397 AcqRel => intrinsics::atomic_xchg_acqrel(dst, val),
1398 Relaxed => intrinsics::atomic_xchg_relaxed(dst, val),
1399 SeqCst => intrinsics::atomic_xchg(dst, val),
1400 __Nonexhaustive => panic!("invalid memory ordering"),
1404 /// Returns the old value (like __sync_fetch_and_add).
1406 unsafe fn atomic_add<T>(dst: *mut T, val: T, order: Ordering) -> T {
1408 Acquire => intrinsics::atomic_xadd_acq(dst, val),
1409 Release => intrinsics::atomic_xadd_rel(dst, val),
1410 AcqRel => intrinsics::atomic_xadd_acqrel(dst, val),
1411 Relaxed => intrinsics::atomic_xadd_relaxed(dst, val),
1412 SeqCst => intrinsics::atomic_xadd(dst, val),
1413 __Nonexhaustive => panic!("invalid memory ordering"),
1417 /// Returns the old value (like __sync_fetch_and_sub).
1419 unsafe fn atomic_sub<T>(dst: *mut T, val: T, order: Ordering) -> T {
1421 Acquire => intrinsics::atomic_xsub_acq(dst, val),
1422 Release => intrinsics::atomic_xsub_rel(dst, val),
1423 AcqRel => intrinsics::atomic_xsub_acqrel(dst, val),
1424 Relaxed => intrinsics::atomic_xsub_relaxed(dst, val),
1425 SeqCst => intrinsics::atomic_xsub(dst, val),
1426 __Nonexhaustive => panic!("invalid memory ordering"),
1431 unsafe fn atomic_compare_exchange<T>(dst: *mut T,
1437 let (val, ok) = match (success, failure) {
1438 (Acquire, Acquire) => intrinsics::atomic_cxchg_acq(dst, old, new),
1439 (Release, Relaxed) => intrinsics::atomic_cxchg_rel(dst, old, new),
1440 (AcqRel, Acquire) => intrinsics::atomic_cxchg_acqrel(dst, old, new),
1441 (Relaxed, Relaxed) => intrinsics::atomic_cxchg_relaxed(dst, old, new),
1442 (SeqCst, SeqCst) => intrinsics::atomic_cxchg(dst, old, new),
1443 (Acquire, Relaxed) => intrinsics::atomic_cxchg_acq_failrelaxed(dst, old, new),
1444 (AcqRel, Relaxed) => intrinsics::atomic_cxchg_acqrel_failrelaxed(dst, old, new),
1445 (SeqCst, Relaxed) => intrinsics::atomic_cxchg_failrelaxed(dst, old, new),
1446 (SeqCst, Acquire) => intrinsics::atomic_cxchg_failacq(dst, old, new),
1447 (__Nonexhaustive, _) => panic!("invalid memory ordering"),
1448 (_, __Nonexhaustive) => panic!("invalid memory ordering"),
1449 (_, AcqRel) => panic!("there is no such thing as an acquire/release failure ordering"),
1450 (_, Release) => panic!("there is no such thing as a release failure ordering"),
1451 _ => panic!("a failure ordering can't be stronger than a success ordering"),
1453 if ok { Ok(val) } else { Err(val) }
1457 unsafe fn atomic_compare_exchange_weak<T>(dst: *mut T,
1463 let (val, ok) = match (success, failure) {
1464 (Acquire, Acquire) => intrinsics::atomic_cxchgweak_acq(dst, old, new),
1465 (Release, Relaxed) => intrinsics::atomic_cxchgweak_rel(dst, old, new),
1466 (AcqRel, Acquire) => intrinsics::atomic_cxchgweak_acqrel(dst, old, new),
1467 (Relaxed, Relaxed) => intrinsics::atomic_cxchgweak_relaxed(dst, old, new),
1468 (SeqCst, SeqCst) => intrinsics::atomic_cxchgweak(dst, old, new),
1469 (Acquire, Relaxed) => intrinsics::atomic_cxchgweak_acq_failrelaxed(dst, old, new),
1470 (AcqRel, Relaxed) => intrinsics::atomic_cxchgweak_acqrel_failrelaxed(dst, old, new),
1471 (SeqCst, Relaxed) => intrinsics::atomic_cxchgweak_failrelaxed(dst, old, new),
1472 (SeqCst, Acquire) => intrinsics::atomic_cxchgweak_failacq(dst, old, new),
1473 (__Nonexhaustive, _) => panic!("invalid memory ordering"),
1474 (_, __Nonexhaustive) => panic!("invalid memory ordering"),
1475 (_, AcqRel) => panic!("there is no such thing as an acquire/release failure ordering"),
1476 (_, Release) => panic!("there is no such thing as a release failure ordering"),
1477 _ => panic!("a failure ordering can't be stronger than a success ordering"),
1479 if ok { Ok(val) } else { Err(val) }
1483 unsafe fn atomic_and<T>(dst: *mut T, val: T, order: Ordering) -> T {
1485 Acquire => intrinsics::atomic_and_acq(dst, val),
1486 Release => intrinsics::atomic_and_rel(dst, val),
1487 AcqRel => intrinsics::atomic_and_acqrel(dst, val),
1488 Relaxed => intrinsics::atomic_and_relaxed(dst, val),
1489 SeqCst => intrinsics::atomic_and(dst, val),
1490 __Nonexhaustive => panic!("invalid memory ordering"),
1495 unsafe fn atomic_or<T>(dst: *mut T, val: T, order: Ordering) -> T {
1497 Acquire => intrinsics::atomic_or_acq(dst, val),
1498 Release => intrinsics::atomic_or_rel(dst, val),
1499 AcqRel => intrinsics::atomic_or_acqrel(dst, val),
1500 Relaxed => intrinsics::atomic_or_relaxed(dst, val),
1501 SeqCst => intrinsics::atomic_or(dst, val),
1502 __Nonexhaustive => panic!("invalid memory ordering"),
1507 unsafe fn atomic_xor<T>(dst: *mut T, val: T, order: Ordering) -> T {
1509 Acquire => intrinsics::atomic_xor_acq(dst, val),
1510 Release => intrinsics::atomic_xor_rel(dst, val),
1511 AcqRel => intrinsics::atomic_xor_acqrel(dst, val),
1512 Relaxed => intrinsics::atomic_xor_relaxed(dst, val),
1513 SeqCst => intrinsics::atomic_xor(dst, val),
1514 __Nonexhaustive => panic!("invalid memory ordering"),
1518 /// An atomic fence.
1520 /// A fence 'A' which has [`Release`] ordering semantics, synchronizes with a
1521 /// fence 'B' with (at least) [`Acquire`] semantics, if and only if there exists
1522 /// atomic operations X and Y, both operating on some atomic object 'M' such
1523 /// that A is sequenced before X, Y is synchronized before B and Y observes
1524 /// the change to M. This provides a happens-before dependence between A and B.
1526 /// Atomic operations with [`Release`] or [`Acquire`] semantics can also synchronize
1529 /// A fence which has [`SeqCst`] ordering, in addition to having both [`Acquire`]
1530 /// and [`Release`] semantics, participates in the global program order of the
1531 /// other [`SeqCst`] operations and/or fences.
1533 /// Accepts [`Acquire`], [`Release`], [`AcqRel`] and [`SeqCst`] orderings.
1537 /// Panics if `order` is [`Relaxed`].
1539 /// [`Ordering`]: enum.Ordering.html
1540 /// [`Acquire`]: enum.Ordering.html#variant.Acquire
1541 /// [`SeqCst`]: enum.Ordering.html#variant.SeqCst
1542 /// [`Release`]: enum.Ordering.html#variant.Release
1543 /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
1544 /// [`Relaxed`]: enum.Ordering.html#variant.Relaxed
1546 #[stable(feature = "rust1", since = "1.0.0")]
1547 pub fn fence(order: Ordering) {
1550 Acquire => intrinsics::atomic_fence_acq(),
1551 Release => intrinsics::atomic_fence_rel(),
1552 AcqRel => intrinsics::atomic_fence_acqrel(),
1553 SeqCst => intrinsics::atomic_fence(),
1554 Relaxed => panic!("there is no such thing as a relaxed fence"),
1555 __Nonexhaustive => panic!("invalid memory ordering"),
1561 #[cfg(target_has_atomic = "8")]
1562 #[stable(feature = "atomic_debug", since = "1.3.0")]
1563 impl fmt::Debug for AtomicBool {
1564 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1565 f.debug_tuple("AtomicBool").field(&self.load(Ordering::SeqCst)).finish()
1569 #[cfg(target_has_atomic = "ptr")]
1570 #[stable(feature = "atomic_debug", since = "1.3.0")]
1571 impl<T> fmt::Debug for AtomicPtr<T> {
1572 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1573 f.debug_tuple("AtomicPtr").field(&self.load(Ordering::SeqCst)).finish()