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 previous 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 previous 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 previous 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 /// Adds to the current value, returning the previous value.
1174 /// This operation wraps around on overflow.
1179 /// use std::sync::atomic::{AtomicIsize, Ordering};
1181 /// let foo = AtomicIsize::new(0);
1182 /// assert_eq!(foo.fetch_add(10, Ordering::SeqCst), 0);
1183 /// assert_eq!(foo.load(Ordering::SeqCst), 10);
1187 pub fn fetch_add(&self, val: $int_type, order: Ordering) -> $int_type {
1188 unsafe { atomic_add(self.v.get(), val, order) }
1191 /// Subtracts from the current value, returning the previous value.
1193 /// This operation wraps around on overflow.
1198 /// use std::sync::atomic::{AtomicIsize, Ordering};
1200 /// let foo = AtomicIsize::new(0);
1201 /// assert_eq!(foo.fetch_sub(10, Ordering::SeqCst), 0);
1202 /// assert_eq!(foo.load(Ordering::SeqCst), -10);
1206 pub fn fetch_sub(&self, val: $int_type, order: Ordering) -> $int_type {
1207 unsafe { atomic_sub(self.v.get(), val, order) }
1210 /// Bitwise "and" with the current value.
1212 /// Performs a bitwise "and" operation on the current value and the argument `val`, and
1213 /// sets the new value to the result.
1215 /// Returns the previous value.
1220 /// use std::sync::atomic::{AtomicIsize, Ordering};
1222 /// let foo = AtomicIsize::new(0b101101);
1223 /// assert_eq!(foo.fetch_and(0b110011, Ordering::SeqCst), 0b101101);
1224 /// assert_eq!(foo.load(Ordering::SeqCst), 0b100001);
1227 pub fn fetch_and(&self, val: $int_type, order: Ordering) -> $int_type {
1228 unsafe { atomic_and(self.v.get(), val, order) }
1231 /// Bitwise "or" with the current value.
1233 /// Performs a bitwise "or" operation on the current value and the argument `val`, and
1234 /// sets the new value to the result.
1236 /// Returns the previous value.
1241 /// use std::sync::atomic::{AtomicIsize, Ordering};
1243 /// let foo = AtomicIsize::new(0b101101);
1244 /// assert_eq!(foo.fetch_or(0b110011, Ordering::SeqCst), 0b101101);
1245 /// assert_eq!(foo.load(Ordering::SeqCst), 0b111111);
1248 pub fn fetch_or(&self, val: $int_type, order: Ordering) -> $int_type {
1249 unsafe { atomic_or(self.v.get(), val, order) }
1252 /// Bitwise "xor" with the current value.
1254 /// Performs a bitwise "xor" operation on the current value and the argument `val`, and
1255 /// sets the new value to the result.
1257 /// Returns the previous value.
1262 /// use std::sync::atomic::{AtomicIsize, Ordering};
1264 /// let foo = AtomicIsize::new(0b101101);
1265 /// assert_eq!(foo.fetch_xor(0b110011, Ordering::SeqCst), 0b101101);
1266 /// assert_eq!(foo.load(Ordering::SeqCst), 0b011110);
1269 pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
1270 unsafe { atomic_xor(self.v.get(), val, order) }
1276 #[cfg(target_has_atomic = "8")]
1278 unstable(feature = "integer_atomics", issue = "32976"),
1279 unstable(feature = "integer_atomics", issue = "32976"),
1280 unstable(feature = "integer_atomics", issue = "32976"),
1281 unstable(feature = "integer_atomics", issue = "32976"),
1282 i8 AtomicI8 ATOMIC_I8_INIT
1284 #[cfg(target_has_atomic = "8")]
1286 unstable(feature = "integer_atomics", issue = "32976"),
1287 unstable(feature = "integer_atomics", issue = "32976"),
1288 unstable(feature = "integer_atomics", issue = "32976"),
1289 unstable(feature = "integer_atomics", issue = "32976"),
1290 u8 AtomicU8 ATOMIC_U8_INIT
1292 #[cfg(target_has_atomic = "16")]
1294 unstable(feature = "integer_atomics", issue = "32976"),
1295 unstable(feature = "integer_atomics", issue = "32976"),
1296 unstable(feature = "integer_atomics", issue = "32976"),
1297 unstable(feature = "integer_atomics", issue = "32976"),
1298 i16 AtomicI16 ATOMIC_I16_INIT
1300 #[cfg(target_has_atomic = "16")]
1302 unstable(feature = "integer_atomics", issue = "32976"),
1303 unstable(feature = "integer_atomics", issue = "32976"),
1304 unstable(feature = "integer_atomics", issue = "32976"),
1305 unstable(feature = "integer_atomics", issue = "32976"),
1306 u16 AtomicU16 ATOMIC_U16_INIT
1308 #[cfg(target_has_atomic = "32")]
1310 unstable(feature = "integer_atomics", issue = "32976"),
1311 unstable(feature = "integer_atomics", issue = "32976"),
1312 unstable(feature = "integer_atomics", issue = "32976"),
1313 unstable(feature = "integer_atomics", issue = "32976"),
1314 i32 AtomicI32 ATOMIC_I32_INIT
1316 #[cfg(target_has_atomic = "32")]
1318 unstable(feature = "integer_atomics", issue = "32976"),
1319 unstable(feature = "integer_atomics", issue = "32976"),
1320 unstable(feature = "integer_atomics", issue = "32976"),
1321 unstable(feature = "integer_atomics", issue = "32976"),
1322 u32 AtomicU32 ATOMIC_U32_INIT
1324 #[cfg(target_has_atomic = "64")]
1326 unstable(feature = "integer_atomics", issue = "32976"),
1327 unstable(feature = "integer_atomics", issue = "32976"),
1328 unstable(feature = "integer_atomics", issue = "32976"),
1329 unstable(feature = "integer_atomics", issue = "32976"),
1330 i64 AtomicI64 ATOMIC_I64_INIT
1332 #[cfg(target_has_atomic = "64")]
1334 unstable(feature = "integer_atomics", issue = "32976"),
1335 unstable(feature = "integer_atomics", issue = "32976"),
1336 unstable(feature = "integer_atomics", issue = "32976"),
1337 unstable(feature = "integer_atomics", issue = "32976"),
1338 u64 AtomicU64 ATOMIC_U64_INIT
1340 #[cfg(target_has_atomic = "ptr")]
1342 stable(feature = "rust1", since = "1.0.0"),
1343 stable(feature = "extended_compare_and_swap", since = "1.10.0"),
1344 stable(feature = "atomic_debug", since = "1.3.0"),
1345 stable(feature = "atomic_access", since = "1.15.0"),
1346 isize AtomicIsize ATOMIC_ISIZE_INIT
1348 #[cfg(target_has_atomic = "ptr")]
1350 stable(feature = "rust1", since = "1.0.0"),
1351 stable(feature = "extended_compare_and_swap", since = "1.10.0"),
1352 stable(feature = "atomic_debug", since = "1.3.0"),
1353 stable(feature = "atomic_access", since = "1.15.0"),
1354 usize AtomicUsize ATOMIC_USIZE_INIT
1358 fn strongest_failure_ordering(order: Ordering) -> Ordering {
1365 __Nonexhaustive => __Nonexhaustive,
1370 unsafe fn atomic_store<T>(dst: *mut T, val: T, order: Ordering) {
1372 Release => intrinsics::atomic_store_rel(dst, val),
1373 Relaxed => intrinsics::atomic_store_relaxed(dst, val),
1374 SeqCst => intrinsics::atomic_store(dst, val),
1375 Acquire => panic!("there is no such thing as an acquire store"),
1376 AcqRel => panic!("there is no such thing as an acquire/release store"),
1377 __Nonexhaustive => panic!("invalid memory ordering"),
1382 unsafe fn atomic_load<T>(dst: *const T, order: Ordering) -> T {
1384 Acquire => intrinsics::atomic_load_acq(dst),
1385 Relaxed => intrinsics::atomic_load_relaxed(dst),
1386 SeqCst => intrinsics::atomic_load(dst),
1387 Release => panic!("there is no such thing as a release load"),
1388 AcqRel => panic!("there is no such thing as an acquire/release load"),
1389 __Nonexhaustive => panic!("invalid memory ordering"),
1394 unsafe fn atomic_swap<T>(dst: *mut T, val: T, order: Ordering) -> T {
1396 Acquire => intrinsics::atomic_xchg_acq(dst, val),
1397 Release => intrinsics::atomic_xchg_rel(dst, val),
1398 AcqRel => intrinsics::atomic_xchg_acqrel(dst, val),
1399 Relaxed => intrinsics::atomic_xchg_relaxed(dst, val),
1400 SeqCst => intrinsics::atomic_xchg(dst, val),
1401 __Nonexhaustive => panic!("invalid memory ordering"),
1405 /// Returns the previous value (like __sync_fetch_and_add).
1407 unsafe fn atomic_add<T>(dst: *mut T, val: T, order: Ordering) -> T {
1409 Acquire => intrinsics::atomic_xadd_acq(dst, val),
1410 Release => intrinsics::atomic_xadd_rel(dst, val),
1411 AcqRel => intrinsics::atomic_xadd_acqrel(dst, val),
1412 Relaxed => intrinsics::atomic_xadd_relaxed(dst, val),
1413 SeqCst => intrinsics::atomic_xadd(dst, val),
1414 __Nonexhaustive => panic!("invalid memory ordering"),
1418 /// Returns the previous value (like __sync_fetch_and_sub).
1420 unsafe fn atomic_sub<T>(dst: *mut T, val: T, order: Ordering) -> T {
1422 Acquire => intrinsics::atomic_xsub_acq(dst, val),
1423 Release => intrinsics::atomic_xsub_rel(dst, val),
1424 AcqRel => intrinsics::atomic_xsub_acqrel(dst, val),
1425 Relaxed => intrinsics::atomic_xsub_relaxed(dst, val),
1426 SeqCst => intrinsics::atomic_xsub(dst, val),
1427 __Nonexhaustive => panic!("invalid memory ordering"),
1432 unsafe fn atomic_compare_exchange<T>(dst: *mut T,
1438 let (val, ok) = match (success, failure) {
1439 (Acquire, Acquire) => intrinsics::atomic_cxchg_acq(dst, old, new),
1440 (Release, Relaxed) => intrinsics::atomic_cxchg_rel(dst, old, new),
1441 (AcqRel, Acquire) => intrinsics::atomic_cxchg_acqrel(dst, old, new),
1442 (Relaxed, Relaxed) => intrinsics::atomic_cxchg_relaxed(dst, old, new),
1443 (SeqCst, SeqCst) => intrinsics::atomic_cxchg(dst, old, new),
1444 (Acquire, Relaxed) => intrinsics::atomic_cxchg_acq_failrelaxed(dst, old, new),
1445 (AcqRel, Relaxed) => intrinsics::atomic_cxchg_acqrel_failrelaxed(dst, old, new),
1446 (SeqCst, Relaxed) => intrinsics::atomic_cxchg_failrelaxed(dst, old, new),
1447 (SeqCst, Acquire) => intrinsics::atomic_cxchg_failacq(dst, old, new),
1448 (__Nonexhaustive, _) => panic!("invalid memory ordering"),
1449 (_, __Nonexhaustive) => panic!("invalid memory ordering"),
1450 (_, AcqRel) => panic!("there is no such thing as an acquire/release failure ordering"),
1451 (_, Release) => panic!("there is no such thing as a release failure ordering"),
1452 _ => panic!("a failure ordering can't be stronger than a success ordering"),
1454 if ok { Ok(val) } else { Err(val) }
1458 unsafe fn atomic_compare_exchange_weak<T>(dst: *mut T,
1464 let (val, ok) = match (success, failure) {
1465 (Acquire, Acquire) => intrinsics::atomic_cxchgweak_acq(dst, old, new),
1466 (Release, Relaxed) => intrinsics::atomic_cxchgweak_rel(dst, old, new),
1467 (AcqRel, Acquire) => intrinsics::atomic_cxchgweak_acqrel(dst, old, new),
1468 (Relaxed, Relaxed) => intrinsics::atomic_cxchgweak_relaxed(dst, old, new),
1469 (SeqCst, SeqCst) => intrinsics::atomic_cxchgweak(dst, old, new),
1470 (Acquire, Relaxed) => intrinsics::atomic_cxchgweak_acq_failrelaxed(dst, old, new),
1471 (AcqRel, Relaxed) => intrinsics::atomic_cxchgweak_acqrel_failrelaxed(dst, old, new),
1472 (SeqCst, Relaxed) => intrinsics::atomic_cxchgweak_failrelaxed(dst, old, new),
1473 (SeqCst, Acquire) => intrinsics::atomic_cxchgweak_failacq(dst, old, new),
1474 (__Nonexhaustive, _) => panic!("invalid memory ordering"),
1475 (_, __Nonexhaustive) => panic!("invalid memory ordering"),
1476 (_, AcqRel) => panic!("there is no such thing as an acquire/release failure ordering"),
1477 (_, Release) => panic!("there is no such thing as a release failure ordering"),
1478 _ => panic!("a failure ordering can't be stronger than a success ordering"),
1480 if ok { Ok(val) } else { Err(val) }
1484 unsafe fn atomic_and<T>(dst: *mut T, val: T, order: Ordering) -> T {
1486 Acquire => intrinsics::atomic_and_acq(dst, val),
1487 Release => intrinsics::atomic_and_rel(dst, val),
1488 AcqRel => intrinsics::atomic_and_acqrel(dst, val),
1489 Relaxed => intrinsics::atomic_and_relaxed(dst, val),
1490 SeqCst => intrinsics::atomic_and(dst, val),
1491 __Nonexhaustive => panic!("invalid memory ordering"),
1496 unsafe fn atomic_or<T>(dst: *mut T, val: T, order: Ordering) -> T {
1498 Acquire => intrinsics::atomic_or_acq(dst, val),
1499 Release => intrinsics::atomic_or_rel(dst, val),
1500 AcqRel => intrinsics::atomic_or_acqrel(dst, val),
1501 Relaxed => intrinsics::atomic_or_relaxed(dst, val),
1502 SeqCst => intrinsics::atomic_or(dst, val),
1503 __Nonexhaustive => panic!("invalid memory ordering"),
1508 unsafe fn atomic_xor<T>(dst: *mut T, val: T, order: Ordering) -> T {
1510 Acquire => intrinsics::atomic_xor_acq(dst, val),
1511 Release => intrinsics::atomic_xor_rel(dst, val),
1512 AcqRel => intrinsics::atomic_xor_acqrel(dst, val),
1513 Relaxed => intrinsics::atomic_xor_relaxed(dst, val),
1514 SeqCst => intrinsics::atomic_xor(dst, val),
1515 __Nonexhaustive => panic!("invalid memory ordering"),
1519 /// An atomic fence.
1521 /// A fence 'A' which has [`Release`] ordering semantics, synchronizes with a
1522 /// fence 'B' with (at least) [`Acquire`] semantics, if and only if there exists
1523 /// atomic operations X and Y, both operating on some atomic object 'M' such
1524 /// that A is sequenced before X, Y is synchronized before B and Y observes
1525 /// the change to M. This provides a happens-before dependence between A and B.
1527 /// Atomic operations with [`Release`] or [`Acquire`] semantics can also synchronize
1530 /// A fence which has [`SeqCst`] ordering, in addition to having both [`Acquire`]
1531 /// and [`Release`] semantics, participates in the global program order of the
1532 /// other [`SeqCst`] operations and/or fences.
1534 /// Accepts [`Acquire`], [`Release`], [`AcqRel`] and [`SeqCst`] orderings.
1538 /// Panics if `order` is [`Relaxed`].
1540 /// [`Ordering`]: enum.Ordering.html
1541 /// [`Acquire`]: enum.Ordering.html#variant.Acquire
1542 /// [`SeqCst`]: enum.Ordering.html#variant.SeqCst
1543 /// [`Release`]: enum.Ordering.html#variant.Release
1544 /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
1545 /// [`Relaxed`]: enum.Ordering.html#variant.Relaxed
1547 #[stable(feature = "rust1", since = "1.0.0")]
1548 pub fn fence(order: Ordering) {
1551 Acquire => intrinsics::atomic_fence_acq(),
1552 Release => intrinsics::atomic_fence_rel(),
1553 AcqRel => intrinsics::atomic_fence_acqrel(),
1554 SeqCst => intrinsics::atomic_fence(),
1555 Relaxed => panic!("there is no such thing as a relaxed fence"),
1556 __Nonexhaustive => panic!("invalid memory ordering"),
1562 #[cfg(target_has_atomic = "8")]
1563 #[stable(feature = "atomic_debug", since = "1.3.0")]
1564 impl fmt::Debug for AtomicBool {
1565 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1566 f.debug_tuple("AtomicBool").field(&self.load(Ordering::SeqCst)).finish()
1570 #[cfg(target_has_atomic = "ptr")]
1571 #[stable(feature = "atomic_debug", since = "1.3.0")]
1572 impl<T> fmt::Debug for AtomicPtr<T> {
1573 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1574 f.debug_tuple("AtomicPtr").field(&self.load(Ordering::SeqCst)).finish()