1 // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
13 //! Atomic types provide primitive shared-memory communication between
14 //! threads, and are the building blocks of other concurrent
17 //! This module defines atomic versions of a select number of primitive
18 //! types, including [`AtomicBool`], [`AtomicIsize`], and [`AtomicUsize`].
19 //! Atomic types present operations that, when used correctly, synchronize
20 //! updates between threads.
22 //! [`AtomicBool`]: struct.AtomicBool.html
23 //! [`AtomicIsize`]: struct.AtomicIsize.html
24 //! [`AtomicUsize`]: struct.AtomicUsize.html
26 //! Each method takes an [`Ordering`] which represents the strength of
27 //! the memory barrier for that operation. These orderings are the
28 //! same as [LLVM atomic orderings][1]. For more information see the [nomicon][2].
30 //! [`Ordering`]: enum.Ordering.html
32 //! [1]: http://llvm.org/docs/LangRef.html#memory-model-for-concurrent-operations
33 //! [2]: ../../../nomicon/atomics.html
35 //! Atomic variables are safe to share between threads (they implement [`Sync`])
36 //! but they do not themselves provide the mechanism for sharing and follow the
37 //! [threading model](../../../std/thread/index.html#the-threading-model) of rust.
38 //! The most common way to share an atomic variable is to put it into an [`Arc`][arc] (an
39 //! atomically-reference-counted shared pointer).
41 //! [`Sync`]: ../../marker/trait.Sync.html
42 //! [arc]: ../../../std/sync/struct.Arc.html
44 //! Most atomic types may be stored in static variables, initialized using
45 //! the provided static initializers like [`ATOMIC_BOOL_INIT`]. Atomic statics
46 //! are often used for lazy global initialization.
48 //! [`ATOMIC_BOOL_INIT`]: constant.ATOMIC_BOOL_INIT.html
52 //! A simple spinlock:
55 //! use std::sync::Arc;
56 //! use std::sync::atomic::{AtomicUsize, Ordering};
60 //! let spinlock = Arc::new(AtomicUsize::new(1));
62 //! let spinlock_clone = spinlock.clone();
63 //! let thread = thread::spawn(move|| {
64 //! spinlock_clone.store(0, Ordering::SeqCst);
67 //! // Wait for the other thread to release the lock
68 //! while spinlock.load(Ordering::SeqCst) != 0 {}
70 //! if let Err(panic) = thread.join() {
71 //! println!("Thread had an error: {:?}", panic);
76 //! Keep a global count of live threads:
79 //! use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
81 //! static GLOBAL_THREAD_COUNT: AtomicUsize = ATOMIC_USIZE_INIT;
83 //! let old_thread_count = GLOBAL_THREAD_COUNT.fetch_add(1, Ordering::SeqCst);
84 //! println!("live threads: {}", old_thread_count + 1);
87 #![stable(feature = "rust1", since = "1.0.0")]
88 #![cfg_attr(not(target_has_atomic = "8"), allow(dead_code))]
89 #![cfg_attr(not(target_has_atomic = "8"), allow(unused_imports))]
91 use self::Ordering::*;
97 /// A boolean type which can be safely shared between threads.
99 /// This type has the same in-memory representation as a `bool`.
100 #[cfg(target_has_atomic = "8")]
101 #[stable(feature = "rust1", since = "1.0.0")]
102 pub struct AtomicBool {
106 #[cfg(target_has_atomic = "8")]
107 #[stable(feature = "rust1", since = "1.0.0")]
108 impl Default for AtomicBool {
109 /// Creates an `AtomicBool` initialized to `false`.
110 fn default() -> Self {
115 // Send is implicitly implemented for AtomicBool.
116 #[cfg(target_has_atomic = "8")]
117 #[stable(feature = "rust1", since = "1.0.0")]
118 unsafe impl Sync for AtomicBool {}
120 /// A raw pointer type which can be safely shared between threads.
122 /// This type has the same in-memory representation as a `*mut T`.
123 #[cfg(target_has_atomic = "ptr")]
124 #[stable(feature = "rust1", since = "1.0.0")]
125 pub struct AtomicPtr<T> {
126 p: UnsafeCell<*mut T>,
129 #[cfg(target_has_atomic = "ptr")]
130 #[stable(feature = "rust1", since = "1.0.0")]
131 impl<T> Default for AtomicPtr<T> {
132 /// Creates a null `AtomicPtr<T>`.
133 fn default() -> AtomicPtr<T> {
134 AtomicPtr::new(::ptr::null_mut())
138 #[cfg(target_has_atomic = "ptr")]
139 #[stable(feature = "rust1", since = "1.0.0")]
140 unsafe impl<T> Send for AtomicPtr<T> {}
141 #[cfg(target_has_atomic = "ptr")]
142 #[stable(feature = "rust1", since = "1.0.0")]
143 unsafe impl<T> Sync for AtomicPtr<T> {}
145 /// Atomic memory orderings
147 /// Memory orderings limit the ways that both the compiler and CPU may reorder
148 /// instructions around atomic operations. At its most restrictive,
149 /// "sequentially consistent" atomics allow neither reads nor writes
150 /// to be moved either before or after the atomic operation; on the other end
151 /// "relaxed" atomics allow all reorderings.
153 /// Rust's memory orderings are [the same as
154 /// LLVM's](http://llvm.org/docs/LangRef.html#memory-model-for-concurrent-operations).
156 /// For more information see the [nomicon].
158 /// [nomicon]: ../../../nomicon/atomics.html
159 #[stable(feature = "rust1", since = "1.0.0")]
160 #[derive(Copy, Clone, Debug)]
162 /// No ordering constraints, only atomic operations.
164 /// Corresponds to LLVM's [`Monotonic`] ordering.
166 /// [`Monotonic`]: http://llvm.org/docs/Atomics.html#monotonic
167 #[stable(feature = "rust1", since = "1.0.0")]
169 /// When coupled with a store, all previous writes become visible
170 /// to the other threads that perform a load with [`Acquire`] ordering
171 /// on the same value.
173 /// [`Acquire`]: http://llvm.org/docs/Atomics.html#acquire
174 #[stable(feature = "rust1", since = "1.0.0")]
176 /// When coupled with a load, all subsequent loads will see data
177 /// written before a store with [`Release`] ordering on the same value
178 /// in other threads.
180 /// [`Release`]: http://llvm.org/docs/Atomics.html#release
181 #[stable(feature = "rust1", since = "1.0.0")]
183 /// When coupled with a load, uses [`Acquire`] ordering, and with a store
184 /// [`Release`] ordering.
186 /// [`Acquire`]: http://llvm.org/docs/Atomics.html#acquire
187 /// [`Release`]: http://llvm.org/docs/Atomics.html#release
188 #[stable(feature = "rust1", since = "1.0.0")]
190 /// Like `AcqRel` with the additional guarantee that all threads see all
191 /// sequentially consistent operations in the same order.
192 #[stable(feature = "rust1", since = "1.0.0")]
194 // Prevent exhaustive matching to allow for future extension
196 #[unstable(feature = "future_atomic_orderings", issue = "0")]
200 /// An [`AtomicBool`] initialized to `false`.
202 /// [`AtomicBool`]: struct.AtomicBool.html
203 #[cfg(target_has_atomic = "8")]
204 #[stable(feature = "rust1", since = "1.0.0")]
205 pub const ATOMIC_BOOL_INIT: AtomicBool = AtomicBool::new(false);
207 #[cfg(target_has_atomic = "8")]
209 /// Creates a new `AtomicBool`.
214 /// use std::sync::atomic::AtomicBool;
216 /// let atomic_true = AtomicBool::new(true);
217 /// let atomic_false = AtomicBool::new(false);
220 #[stable(feature = "rust1", since = "1.0.0")]
221 pub const fn new(v: bool) -> AtomicBool {
222 AtomicBool { v: UnsafeCell::new(v as u8) }
225 /// Returns a mutable reference to the underlying `bool`.
227 /// This is safe because the mutable reference guarantees that no other threads are
228 /// concurrently accessing the atomic data.
233 /// use std::sync::atomic::{AtomicBool, Ordering};
235 /// let mut some_bool = AtomicBool::new(true);
236 /// assert_eq!(*some_bool.get_mut(), true);
237 /// *some_bool.get_mut() = false;
238 /// assert_eq!(some_bool.load(Ordering::SeqCst), false);
241 #[stable(feature = "atomic_access", since = "1.15.0")]
242 pub fn get_mut(&mut self) -> &mut bool {
243 unsafe { &mut *(self.v.get() as *mut bool) }
246 /// Consumes the atomic and returns the contained value.
248 /// This is safe because passing `self` by value guarantees that no other threads are
249 /// concurrently accessing the atomic data.
254 /// use std::sync::atomic::AtomicBool;
256 /// let some_bool = AtomicBool::new(true);
257 /// assert_eq!(some_bool.into_inner(), true);
260 #[stable(feature = "atomic_access", since = "1.15.0")]
261 pub fn into_inner(self) -> bool {
262 unsafe { self.v.into_inner() != 0 }
265 /// Loads a value from the bool.
267 /// `load` takes an [`Ordering`] argument which describes the memory ordering
268 /// of this operation.
272 /// Panics if `order` is [`Release`] or [`AcqRel`].
274 /// [`Ordering`]: enum.Ordering.html
275 /// [`Release`]: enum.Ordering.html#variant.Release
276 /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
281 /// use std::sync::atomic::{AtomicBool, Ordering};
283 /// let some_bool = AtomicBool::new(true);
285 /// assert_eq!(some_bool.load(Ordering::Relaxed), true);
288 #[stable(feature = "rust1", since = "1.0.0")]
289 pub fn load(&self, order: Ordering) -> bool {
290 unsafe { atomic_load(self.v.get(), order) != 0 }
293 /// Stores a value into the bool.
295 /// `store` takes an [`Ordering`] argument which describes the memory ordering
296 /// of this operation.
298 /// [`Ordering`]: enum.Ordering.html
303 /// use std::sync::atomic::{AtomicBool, Ordering};
305 /// let some_bool = AtomicBool::new(true);
307 /// some_bool.store(false, Ordering::Relaxed);
308 /// assert_eq!(some_bool.load(Ordering::Relaxed), false);
313 /// Panics if `order` is [`Acquire`] or [`AcqRel`].
315 /// [`Acquire`]: enum.Ordering.html#variant.Acquire
316 /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
318 #[stable(feature = "rust1", since = "1.0.0")]
319 pub fn store(&self, val: bool, order: Ordering) {
321 atomic_store(self.v.get(), val as u8, order);
325 /// Stores a value into the bool, returning the previous value.
327 /// `swap` takes an [`Ordering`] argument which describes the memory ordering
328 /// 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.swap(false, Ordering::Relaxed), true);
340 /// assert_eq!(some_bool.load(Ordering::Relaxed), false);
343 #[stable(feature = "rust1", since = "1.0.0")]
344 pub fn swap(&self, val: bool, order: Ordering) -> bool {
345 unsafe { atomic_swap(self.v.get(), val as u8, order) != 0 }
348 /// Stores a value into the `bool` if the current value is the same as the `current` value.
350 /// The return value is always the previous value. If it is equal to `current`, then the value
353 /// `compare_and_swap` also takes an [`Ordering`] argument which describes the memory
354 /// ordering of this operation.
356 /// [`Ordering`]: enum.Ordering.html
361 /// use std::sync::atomic::{AtomicBool, Ordering};
363 /// let some_bool = AtomicBool::new(true);
365 /// assert_eq!(some_bool.compare_and_swap(true, false, Ordering::Relaxed), true);
366 /// assert_eq!(some_bool.load(Ordering::Relaxed), false);
368 /// assert_eq!(some_bool.compare_and_swap(true, true, Ordering::Relaxed), false);
369 /// assert_eq!(some_bool.load(Ordering::Relaxed), false);
372 #[stable(feature = "rust1", since = "1.0.0")]
373 pub fn compare_and_swap(&self, current: bool, new: bool, order: Ordering) -> bool {
374 match self.compare_exchange(current, new, order, strongest_failure_ordering(order)) {
380 /// Stores a value into the `bool` if the current value is the same as the `current` value.
382 /// The return value is a result indicating whether the new value was written and containing
383 /// the previous value. On success this value is guaranteed to be equal to `current`.
385 /// `compare_exchange` takes two [`Ordering`] arguments to describe the memory
386 /// ordering of this operation. The first describes the required ordering if the
387 /// operation succeeds while the second describes the required ordering when the
388 /// operation fails. The failure ordering can't be [`Release`] or [`AcqRel`] and must
389 /// be equivalent or weaker than the success ordering.
391 /// [`Ordering`]: enum.Ordering.html
392 /// [`Release`]: enum.Ordering.html#variant.Release
393 /// [`AcqRel`]: enum.Ordering.html#variant.Release
398 /// use std::sync::atomic::{AtomicBool, Ordering};
400 /// let some_bool = AtomicBool::new(true);
402 /// assert_eq!(some_bool.compare_exchange(true,
404 /// Ordering::Acquire,
405 /// Ordering::Relaxed),
407 /// assert_eq!(some_bool.load(Ordering::Relaxed), false);
409 /// assert_eq!(some_bool.compare_exchange(true, true,
410 /// Ordering::SeqCst,
411 /// Ordering::Acquire),
413 /// assert_eq!(some_bool.load(Ordering::Relaxed), false);
416 #[stable(feature = "extended_compare_and_swap", since = "1.10.0")]
417 pub fn compare_exchange(&self,
422 -> Result<bool, bool> {
424 atomic_compare_exchange(self.v.get(), current as u8, new as u8, success, failure)
427 Err(x) => Err(x != 0),
431 /// Stores a value into the `bool` if the current value is the same as the `current` value.
433 /// Unlike [`compare_exchange`], this function is allowed to spuriously fail even when the
434 /// comparison succeeds, which can result in more efficient code on some platforms. The
435 /// return value is a result indicating whether the new value was written and containing the
438 /// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory
439 /// ordering of this operation. The first describes the required ordering if the operation
440 /// succeeds while the second describes the required ordering when the operation fails. The
441 /// failure ordering can't be [`Release`] or [`AcqRel`] and must be equivalent or
442 /// weaker than the success ordering.
444 /// [`compare_exchange`]: #method.compare_exchange
445 /// [`Ordering`]: enum.Ordering.html
446 /// [`Release`]: enum.Ordering.html#variant.Release
447 /// [`AcqRel`]: enum.Ordering.html#variant.Release
452 /// use std::sync::atomic::{AtomicBool, Ordering};
454 /// let val = AtomicBool::new(false);
457 /// let mut old = val.load(Ordering::Relaxed);
459 /// match val.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) {
461 /// Err(x) => old = x,
466 #[stable(feature = "extended_compare_and_swap", since = "1.10.0")]
467 pub fn compare_exchange_weak(&self,
472 -> Result<bool, bool> {
474 atomic_compare_exchange_weak(self.v.get(), current as u8, new as u8, success, failure)
477 Err(x) => Err(x != 0),
481 /// Logical "and" with a boolean value.
483 /// Performs a logical "and" operation on the current value and the argument `val`, and sets
484 /// the new value to the result.
486 /// Returns the previous value.
491 /// use std::sync::atomic::{AtomicBool, Ordering};
493 /// let foo = AtomicBool::new(true);
494 /// assert_eq!(foo.fetch_and(false, Ordering::SeqCst), true);
495 /// assert_eq!(foo.load(Ordering::SeqCst), false);
497 /// let foo = AtomicBool::new(true);
498 /// assert_eq!(foo.fetch_and(true, Ordering::SeqCst), true);
499 /// assert_eq!(foo.load(Ordering::SeqCst), true);
501 /// let foo = AtomicBool::new(false);
502 /// assert_eq!(foo.fetch_and(false, Ordering::SeqCst), false);
503 /// assert_eq!(foo.load(Ordering::SeqCst), false);
506 #[stable(feature = "rust1", since = "1.0.0")]
507 pub fn fetch_and(&self, val: bool, order: Ordering) -> bool {
508 unsafe { atomic_and(self.v.get(), val as u8, order) != 0 }
511 /// Logical "nand" with a boolean value.
513 /// Performs a logical "nand" operation on the current value and the argument `val`, and sets
514 /// the new value to the result.
516 /// Returns the previous value.
521 /// use std::sync::atomic::{AtomicBool, Ordering};
523 /// let foo = AtomicBool::new(true);
524 /// assert_eq!(foo.fetch_nand(false, Ordering::SeqCst), true);
525 /// assert_eq!(foo.load(Ordering::SeqCst), true);
527 /// let foo = AtomicBool::new(true);
528 /// assert_eq!(foo.fetch_nand(true, Ordering::SeqCst), true);
529 /// assert_eq!(foo.load(Ordering::SeqCst) as usize, 0);
530 /// assert_eq!(foo.load(Ordering::SeqCst), false);
532 /// let foo = AtomicBool::new(false);
533 /// assert_eq!(foo.fetch_nand(false, Ordering::SeqCst), false);
534 /// assert_eq!(foo.load(Ordering::SeqCst), true);
537 #[stable(feature = "rust1", since = "1.0.0")]
538 pub fn fetch_nand(&self, val: bool, order: Ordering) -> bool {
539 // We can't use atomic_nand here because it can result in a bool with
540 // an invalid value. This happens because the atomic operation is done
541 // with an 8-bit integer internally, which would set the upper 7 bits.
542 // So we just use a compare-exchange loop instead, which is what the
543 // intrinsic actually expands to anyways on many platforms.
544 let mut old = self.load(Relaxed);
546 let new = !(old && val);
547 match self.compare_exchange_weak(old, new, order, Relaxed) {
555 /// Logical "or" with a boolean value.
557 /// Performs a logical "or" operation on the current value and the argument `val`, and sets the
558 /// new value to the result.
560 /// Returns the previous value.
565 /// use std::sync::atomic::{AtomicBool, Ordering};
567 /// let foo = AtomicBool::new(true);
568 /// assert_eq!(foo.fetch_or(false, Ordering::SeqCst), true);
569 /// assert_eq!(foo.load(Ordering::SeqCst), true);
571 /// let foo = AtomicBool::new(true);
572 /// assert_eq!(foo.fetch_or(true, Ordering::SeqCst), true);
573 /// assert_eq!(foo.load(Ordering::SeqCst), true);
575 /// let foo = AtomicBool::new(false);
576 /// assert_eq!(foo.fetch_or(false, Ordering::SeqCst), false);
577 /// assert_eq!(foo.load(Ordering::SeqCst), false);
580 #[stable(feature = "rust1", since = "1.0.0")]
581 pub fn fetch_or(&self, val: bool, order: Ordering) -> bool {
582 unsafe { atomic_or(self.v.get(), val as u8, order) != 0 }
585 /// Logical "xor" with a boolean value.
587 /// Performs a logical "xor" operation on the current value and the argument `val`, and sets
588 /// the new value to the result.
590 /// Returns the previous value.
595 /// use std::sync::atomic::{AtomicBool, Ordering};
597 /// let foo = AtomicBool::new(true);
598 /// assert_eq!(foo.fetch_xor(false, Ordering::SeqCst), true);
599 /// assert_eq!(foo.load(Ordering::SeqCst), true);
601 /// let foo = AtomicBool::new(true);
602 /// assert_eq!(foo.fetch_xor(true, Ordering::SeqCst), true);
603 /// assert_eq!(foo.load(Ordering::SeqCst), false);
605 /// let foo = AtomicBool::new(false);
606 /// assert_eq!(foo.fetch_xor(false, Ordering::SeqCst), false);
607 /// assert_eq!(foo.load(Ordering::SeqCst), false);
610 #[stable(feature = "rust1", since = "1.0.0")]
611 pub fn fetch_xor(&self, val: bool, order: Ordering) -> bool {
612 unsafe { atomic_xor(self.v.get(), val as u8, order) != 0 }
616 #[cfg(target_has_atomic = "ptr")]
617 impl<T> AtomicPtr<T> {
618 /// Creates a new `AtomicPtr`.
623 /// use std::sync::atomic::AtomicPtr;
625 /// let ptr = &mut 5;
626 /// let atomic_ptr = AtomicPtr::new(ptr);
629 #[stable(feature = "rust1", since = "1.0.0")]
630 pub const fn new(p: *mut T) -> AtomicPtr<T> {
631 AtomicPtr { p: UnsafeCell::new(p) }
634 /// Returns a mutable reference to the underlying pointer.
636 /// This is safe because the mutable reference guarantees that no other threads are
637 /// concurrently accessing the atomic data.
642 /// use std::sync::atomic::{AtomicPtr, Ordering};
644 /// let mut atomic_ptr = AtomicPtr::new(&mut 10);
645 /// *atomic_ptr.get_mut() = &mut 5;
646 /// assert_eq!(unsafe { *atomic_ptr.load(Ordering::SeqCst) }, 5);
649 #[stable(feature = "atomic_access", since = "1.15.0")]
650 pub fn get_mut(&mut self) -> &mut *mut T {
651 unsafe { &mut *self.p.get() }
654 /// Consumes the atomic and returns the contained value.
656 /// This is safe because passing `self` by value guarantees that no other threads are
657 /// concurrently accessing the atomic data.
662 /// use std::sync::atomic::AtomicPtr;
664 /// let atomic_ptr = AtomicPtr::new(&mut 5);
665 /// assert_eq!(unsafe { *atomic_ptr.into_inner() }, 5);
668 #[stable(feature = "atomic_access", since = "1.15.0")]
669 pub fn into_inner(self) -> *mut T {
670 unsafe { self.p.into_inner() }
673 /// Loads a value from the pointer.
675 /// `load` takes an [`Ordering`] argument which describes the memory ordering
676 /// of this operation.
680 /// Panics if `order` is [`Release`] or [`AcqRel`].
682 /// [`Ordering`]: enum.Ordering.html
683 /// [`Release`]: enum.Ordering.html#variant.Release
684 /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
689 /// use std::sync::atomic::{AtomicPtr, Ordering};
691 /// let ptr = &mut 5;
692 /// let some_ptr = AtomicPtr::new(ptr);
694 /// let value = some_ptr.load(Ordering::Relaxed);
697 #[stable(feature = "rust1", since = "1.0.0")]
698 pub fn load(&self, order: Ordering) -> *mut T {
699 unsafe { atomic_load(self.p.get() as *mut usize, order) as *mut T }
702 /// Stores a value into the pointer.
704 /// `store` takes an [`Ordering`] argument which describes the memory ordering
705 /// of this operation.
707 /// [`Ordering`]: enum.Ordering.html
712 /// use std::sync::atomic::{AtomicPtr, Ordering};
714 /// let ptr = &mut 5;
715 /// let some_ptr = AtomicPtr::new(ptr);
717 /// let other_ptr = &mut 10;
719 /// some_ptr.store(other_ptr, Ordering::Relaxed);
724 /// Panics if `order` is [`Acquire`] or [`AcqRel`].
726 /// [`Acquire`]: enum.Ordering.html#variant.Acquire
727 /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
729 #[stable(feature = "rust1", since = "1.0.0")]
730 pub fn store(&self, ptr: *mut T, order: Ordering) {
732 atomic_store(self.p.get() as *mut usize, ptr as usize, order);
736 /// Stores a value into the pointer, returning the previous value.
738 /// `swap` takes an [`Ordering`] argument which describes the memory ordering
739 /// of this operation.
741 /// [`Ordering`]: enum.Ordering.html
746 /// use std::sync::atomic::{AtomicPtr, Ordering};
748 /// let ptr = &mut 5;
749 /// let some_ptr = AtomicPtr::new(ptr);
751 /// let other_ptr = &mut 10;
753 /// let value = some_ptr.swap(other_ptr, Ordering::Relaxed);
756 #[stable(feature = "rust1", since = "1.0.0")]
757 pub fn swap(&self, ptr: *mut T, order: Ordering) -> *mut T {
758 unsafe { atomic_swap(self.p.get() as *mut usize, ptr as usize, order) as *mut T }
761 /// Stores a value into the pointer if the current value is the same as the `current` value.
763 /// The return value is always the previous value. If it is equal to `current`, then the value
766 /// `compare_and_swap` also takes an [`Ordering`] argument which describes the memory
767 /// ordering of this operation.
769 /// [`Ordering`]: enum.Ordering.html
774 /// use std::sync::atomic::{AtomicPtr, Ordering};
776 /// let ptr = &mut 5;
777 /// let some_ptr = AtomicPtr::new(ptr);
779 /// let other_ptr = &mut 10;
780 /// let another_ptr = &mut 10;
782 /// let value = some_ptr.compare_and_swap(other_ptr, another_ptr, Ordering::Relaxed);
785 #[stable(feature = "rust1", since = "1.0.0")]
786 pub fn compare_and_swap(&self, current: *mut T, new: *mut T, order: Ordering) -> *mut T {
787 match self.compare_exchange(current, new, order, strongest_failure_ordering(order)) {
793 /// Stores a value into the pointer if the current value is the same as the `current` value.
795 /// The return value is a result indicating whether the new value was written and containing
796 /// the previous value. On success this value is guaranteed to be equal to `current`.
798 /// `compare_exchange` takes two [`Ordering`] arguments to describe the memory
799 /// ordering of this operation. The first describes the required ordering if
800 /// the operation succeeds while the second describes the required ordering when
801 /// the operation fails. The failure ordering can't be [`Release`] or [`AcqRel`]
802 /// and must be equivalent or weaker than the success ordering.
804 /// [`Ordering`]: enum.Ordering.html
805 /// [`Release`]: enum.Ordering.html#variant.Release
806 /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
811 /// use std::sync::atomic::{AtomicPtr, Ordering};
813 /// let ptr = &mut 5;
814 /// let some_ptr = AtomicPtr::new(ptr);
816 /// let other_ptr = &mut 10;
817 /// let another_ptr = &mut 10;
819 /// let value = some_ptr.compare_exchange(other_ptr, another_ptr,
820 /// Ordering::SeqCst, Ordering::Relaxed);
823 #[stable(feature = "extended_compare_and_swap", since = "1.10.0")]
824 pub fn compare_exchange(&self,
829 -> Result<*mut T, *mut T> {
831 let res = atomic_compare_exchange(self.p.get() as *mut usize,
837 Ok(x) => Ok(x as *mut T),
838 Err(x) => Err(x as *mut T),
843 /// Stores a value into the pointer if the current value is the same as the `current` value.
845 /// Unlike [`compare_exchange`], this function is allowed to spuriously fail even when the
846 /// comparison succeeds, which can result in more efficient code on some platforms. The
847 /// return value is a result indicating whether the new value was written and containing the
850 /// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory
851 /// ordering of this operation. The first describes the required ordering if the operation
852 /// succeeds while the second describes the required ordering when the operation fails. The
853 /// failure ordering can't be [`Release`] or [`AcqRel`] and must be equivalent or
854 /// weaker than the success ordering.
856 /// [`compare_exchange`]: #method.compare_exchange
857 /// [`Ordering`]: enum.Ordering.html
858 /// [`Release`]: enum.Ordering.html#variant.Release
859 /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
864 /// use std::sync::atomic::{AtomicPtr, Ordering};
866 /// let some_ptr = AtomicPtr::new(&mut 5);
868 /// let new = &mut 10;
869 /// let mut old = some_ptr.load(Ordering::Relaxed);
871 /// match some_ptr.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) {
873 /// Err(x) => old = x,
878 #[stable(feature = "extended_compare_and_swap", since = "1.10.0")]
879 pub fn compare_exchange_weak(&self,
884 -> Result<*mut T, *mut T> {
886 let res = atomic_compare_exchange_weak(self.p.get() as *mut usize,
892 Ok(x) => Ok(x as *mut T),
893 Err(x) => Err(x as *mut T),
899 macro_rules! atomic_int {
904 $int_type:ident $atomic_type:ident $atomic_init:ident) => {
905 /// An integer type which can be safely shared between threads.
907 /// This type has the same in-memory representation as the underlying integer type.
909 pub struct $atomic_type {
910 v: UnsafeCell<$int_type>,
913 /// An atomic integer initialized to `0`.
915 pub const $atomic_init: $atomic_type = $atomic_type::new(0);
918 impl Default for $atomic_type {
919 fn default() -> Self {
920 Self::new(Default::default())
925 impl fmt::Debug for $atomic_type {
926 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
927 f.debug_tuple(stringify!($atomic_type))
928 .field(&self.load(Ordering::SeqCst))
933 // Send is implicitly implemented.
935 unsafe impl Sync for $atomic_type {}
938 /// Creates a new atomic integer.
943 /// use std::sync::atomic::AtomicIsize;
945 /// let atomic_forty_two = AtomicIsize::new(42);
949 pub const fn new(v: $int_type) -> Self {
950 $atomic_type {v: UnsafeCell::new(v)}
953 /// Returns a mutable reference to the underlying integer.
955 /// This is safe because the mutable reference guarantees that no other threads are
956 /// concurrently accessing the atomic data.
961 /// use std::sync::atomic::{AtomicIsize, Ordering};
963 /// let mut some_isize = AtomicIsize::new(10);
964 /// assert_eq!(*some_isize.get_mut(), 10);
965 /// *some_isize.get_mut() = 5;
966 /// assert_eq!(some_isize.load(Ordering::SeqCst), 5);
970 pub fn get_mut(&mut self) -> &mut $int_type {
971 unsafe { &mut *self.v.get() }
974 /// Consumes the atomic and returns the contained value.
976 /// This is safe because passing `self` by value guarantees that no other threads are
977 /// concurrently accessing the atomic data.
982 /// use std::sync::atomic::AtomicIsize;
984 /// let some_isize = AtomicIsize::new(5);
985 /// assert_eq!(some_isize.into_inner(), 5);
989 pub fn into_inner(self) -> $int_type {
990 unsafe { self.v.into_inner() }
993 /// Loads a value from the atomic integer.
995 /// `load` takes an [`Ordering`] argument which describes the memory ordering of this
1000 /// Panics if `order` is [`Release`] or [`AcqRel`].
1002 /// [`Ordering`]: enum.Ordering.html
1003 /// [`Release`]: enum.Ordering.html#variant.Release
1004 /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
1009 /// use std::sync::atomic::{AtomicIsize, Ordering};
1011 /// let some_isize = AtomicIsize::new(5);
1013 /// assert_eq!(some_isize.load(Ordering::Relaxed), 5);
1017 pub fn load(&self, order: Ordering) -> $int_type {
1018 unsafe { atomic_load(self.v.get(), order) }
1021 /// Stores a value into the atomic integer.
1023 /// `store` takes an [`Ordering`] argument which describes the memory ordering of this
1026 /// [`Ordering`]: enum.Ordering.html
1031 /// use std::sync::atomic::{AtomicIsize, Ordering};
1033 /// let some_isize = AtomicIsize::new(5);
1035 /// some_isize.store(10, Ordering::Relaxed);
1036 /// assert_eq!(some_isize.load(Ordering::Relaxed), 10);
1041 /// Panics if `order` is [`Acquire`] or [`AcqRel`].
1043 /// [`Acquire`]: enum.Ordering.html#variant.Acquire
1044 /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
1047 pub fn store(&self, val: $int_type, order: Ordering) {
1048 unsafe { atomic_store(self.v.get(), val, order); }
1051 /// Stores a value into the atomic integer, returning the previous value.
1053 /// `swap` takes an [`Ordering`] argument which describes the memory ordering of this
1056 /// [`Ordering`]: enum.Ordering.html
1061 /// use std::sync::atomic::{AtomicIsize, Ordering};
1063 /// let some_isize = AtomicIsize::new(5);
1065 /// assert_eq!(some_isize.swap(10, Ordering::Relaxed), 5);
1069 pub fn swap(&self, val: $int_type, order: Ordering) -> $int_type {
1070 unsafe { atomic_swap(self.v.get(), val, order) }
1073 /// Stores a value into the atomic integer if the current value is the same as the
1074 /// `current` value.
1076 /// The return value is always the previous value. If it is equal to `current`, then the
1077 /// value was updated.
1079 /// `compare_and_swap` also takes an [`Ordering`] argument which describes the memory
1080 /// ordering of this operation.
1082 /// [`Ordering`]: enum.Ordering.html
1087 /// use std::sync::atomic::{AtomicIsize, Ordering};
1089 /// let some_isize = AtomicIsize::new(5);
1091 /// assert_eq!(some_isize.compare_and_swap(5, 10, Ordering::Relaxed), 5);
1092 /// assert_eq!(some_isize.load(Ordering::Relaxed), 10);
1094 /// assert_eq!(some_isize.compare_and_swap(6, 12, Ordering::Relaxed), 10);
1095 /// assert_eq!(some_isize.load(Ordering::Relaxed), 10);
1099 pub fn compare_and_swap(&self,
1102 order: Ordering) -> $int_type {
1103 match self.compare_exchange(current,
1106 strongest_failure_ordering(order)) {
1112 /// Stores a value into the atomic integer if the current value is the same as the
1113 /// `current` value.
1115 /// The return value is a result indicating whether the new value was written and
1116 /// containing the previous value. On success this value is guaranteed to be equal to
1119 /// `compare_exchange` takes two [`Ordering`] arguments to describe the memory
1120 /// ordering of this operation. The first describes the required ordering if
1121 /// the operation succeeds while the second describes the required ordering when
1122 /// the operation fails. The failure ordering can't be [`Release`] or [`AcqRel`] and
1123 /// must be equivalent or weaker than the success ordering.
1125 /// [`Ordering`]: enum.Ordering.html
1126 /// [`Release`]: enum.Ordering.html#variant.Release
1127 /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
1132 /// use std::sync::atomic::{AtomicIsize, Ordering};
1134 /// let some_isize = AtomicIsize::new(5);
1136 /// assert_eq!(some_isize.compare_exchange(5, 10,
1137 /// Ordering::Acquire,
1138 /// Ordering::Relaxed),
1140 /// assert_eq!(some_isize.load(Ordering::Relaxed), 10);
1142 /// assert_eq!(some_isize.compare_exchange(6, 12,
1143 /// Ordering::SeqCst,
1144 /// Ordering::Acquire),
1146 /// assert_eq!(some_isize.load(Ordering::Relaxed), 10);
1150 pub fn compare_exchange(&self,
1154 failure: Ordering) -> Result<$int_type, $int_type> {
1155 unsafe { atomic_compare_exchange(self.v.get(), current, new, success, failure) }
1158 /// Stores a value into the atomic integer if the current value is the same as the
1159 /// `current` value.
1161 /// Unlike [`compare_exchange`], this function is allowed to spuriously fail even
1162 /// when the comparison succeeds, which can result in more efficient code on some
1163 /// platforms. The return value is a result indicating whether the new value was
1164 /// written and containing the previous value.
1166 /// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory
1167 /// ordering of this operation. The first describes the required ordering if the
1168 /// operation succeeds while the second describes the required ordering when the
1169 /// operation fails. The failure ordering can't be [`Release`] or [`AcqRel`] and
1170 /// must be equivalent or weaker than the success ordering.
1172 /// [`compare_exchange`]: #method.compare_exchange
1173 /// [`Ordering`]: enum.Ordering.html
1174 /// [`Release`]: enum.Ordering.html#variant.Release
1175 /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
1180 /// use std::sync::atomic::{AtomicIsize, Ordering};
1182 /// let val = AtomicIsize::new(4);
1184 /// let mut old = val.load(Ordering::Relaxed);
1186 /// let new = old * 2;
1187 /// match val.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) {
1189 /// Err(x) => old = x,
1195 pub fn compare_exchange_weak(&self,
1199 failure: Ordering) -> Result<$int_type, $int_type> {
1201 atomic_compare_exchange_weak(self.v.get(), current, new, success, failure)
1205 /// Adds to the current value, returning the previous value.
1207 /// This operation wraps around on overflow.
1212 /// use std::sync::atomic::{AtomicIsize, Ordering};
1214 /// let foo = AtomicIsize::new(0);
1215 /// assert_eq!(foo.fetch_add(10, Ordering::SeqCst), 0);
1216 /// assert_eq!(foo.load(Ordering::SeqCst), 10);
1220 pub fn fetch_add(&self, val: $int_type, order: Ordering) -> $int_type {
1221 unsafe { atomic_add(self.v.get(), val, order) }
1224 /// Subtracts from the current value, returning the previous value.
1226 /// This operation wraps around on overflow.
1231 /// use std::sync::atomic::{AtomicIsize, Ordering};
1233 /// let foo = AtomicIsize::new(0);
1234 /// assert_eq!(foo.fetch_sub(10, Ordering::SeqCst), 0);
1235 /// assert_eq!(foo.load(Ordering::SeqCst), -10);
1239 pub fn fetch_sub(&self, val: $int_type, order: Ordering) -> $int_type {
1240 unsafe { atomic_sub(self.v.get(), val, order) }
1243 /// Bitwise "and" with the current value.
1245 /// Performs a bitwise "and" operation on the current value and the argument `val`, and
1246 /// sets the new value to the result.
1248 /// Returns the previous value.
1253 /// use std::sync::atomic::{AtomicIsize, Ordering};
1255 /// let foo = AtomicIsize::new(0b101101);
1256 /// assert_eq!(foo.fetch_and(0b110011, Ordering::SeqCst), 0b101101);
1257 /// assert_eq!(foo.load(Ordering::SeqCst), 0b100001);
1260 pub fn fetch_and(&self, val: $int_type, order: Ordering) -> $int_type {
1261 unsafe { atomic_and(self.v.get(), val, order) }
1264 /// Bitwise "or" with the current value.
1266 /// Performs a bitwise "or" operation on the current value and the argument `val`, and
1267 /// sets the new value to the result.
1269 /// Returns the previous value.
1274 /// use std::sync::atomic::{AtomicIsize, Ordering};
1276 /// let foo = AtomicIsize::new(0b101101);
1277 /// assert_eq!(foo.fetch_or(0b110011, Ordering::SeqCst), 0b101101);
1278 /// assert_eq!(foo.load(Ordering::SeqCst), 0b111111);
1281 pub fn fetch_or(&self, val: $int_type, order: Ordering) -> $int_type {
1282 unsafe { atomic_or(self.v.get(), val, order) }
1285 /// Bitwise "xor" with the current value.
1287 /// Performs a bitwise "xor" operation on the current value and the argument `val`, and
1288 /// sets the new value to the result.
1290 /// Returns the previous value.
1295 /// use std::sync::atomic::{AtomicIsize, Ordering};
1297 /// let foo = AtomicIsize::new(0b101101);
1298 /// assert_eq!(foo.fetch_xor(0b110011, Ordering::SeqCst), 0b101101);
1299 /// assert_eq!(foo.load(Ordering::SeqCst), 0b011110);
1302 pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
1303 unsafe { atomic_xor(self.v.get(), val, order) }
1309 #[cfg(target_has_atomic = "8")]
1311 unstable(feature = "integer_atomics", issue = "32976"),
1312 unstable(feature = "integer_atomics", issue = "32976"),
1313 unstable(feature = "integer_atomics", issue = "32976"),
1314 unstable(feature = "integer_atomics", issue = "32976"),
1315 i8 AtomicI8 ATOMIC_I8_INIT
1317 #[cfg(target_has_atomic = "8")]
1319 unstable(feature = "integer_atomics", issue = "32976"),
1320 unstable(feature = "integer_atomics", issue = "32976"),
1321 unstable(feature = "integer_atomics", issue = "32976"),
1322 unstable(feature = "integer_atomics", issue = "32976"),
1323 u8 AtomicU8 ATOMIC_U8_INIT
1325 #[cfg(target_has_atomic = "16")]
1327 unstable(feature = "integer_atomics", issue = "32976"),
1328 unstable(feature = "integer_atomics", issue = "32976"),
1329 unstable(feature = "integer_atomics", issue = "32976"),
1330 unstable(feature = "integer_atomics", issue = "32976"),
1331 i16 AtomicI16 ATOMIC_I16_INIT
1333 #[cfg(target_has_atomic = "16")]
1335 unstable(feature = "integer_atomics", issue = "32976"),
1336 unstable(feature = "integer_atomics", issue = "32976"),
1337 unstable(feature = "integer_atomics", issue = "32976"),
1338 unstable(feature = "integer_atomics", issue = "32976"),
1339 u16 AtomicU16 ATOMIC_U16_INIT
1341 #[cfg(target_has_atomic = "32")]
1343 unstable(feature = "integer_atomics", issue = "32976"),
1344 unstable(feature = "integer_atomics", issue = "32976"),
1345 unstable(feature = "integer_atomics", issue = "32976"),
1346 unstable(feature = "integer_atomics", issue = "32976"),
1347 i32 AtomicI32 ATOMIC_I32_INIT
1349 #[cfg(target_has_atomic = "32")]
1351 unstable(feature = "integer_atomics", issue = "32976"),
1352 unstable(feature = "integer_atomics", issue = "32976"),
1353 unstable(feature = "integer_atomics", issue = "32976"),
1354 unstable(feature = "integer_atomics", issue = "32976"),
1355 u32 AtomicU32 ATOMIC_U32_INIT
1357 #[cfg(target_has_atomic = "64")]
1359 unstable(feature = "integer_atomics", issue = "32976"),
1360 unstable(feature = "integer_atomics", issue = "32976"),
1361 unstable(feature = "integer_atomics", issue = "32976"),
1362 unstable(feature = "integer_atomics", issue = "32976"),
1363 i64 AtomicI64 ATOMIC_I64_INIT
1365 #[cfg(target_has_atomic = "64")]
1367 unstable(feature = "integer_atomics", issue = "32976"),
1368 unstable(feature = "integer_atomics", issue = "32976"),
1369 unstable(feature = "integer_atomics", issue = "32976"),
1370 unstable(feature = "integer_atomics", issue = "32976"),
1371 u64 AtomicU64 ATOMIC_U64_INIT
1373 #[cfg(target_has_atomic = "ptr")]
1375 stable(feature = "rust1", since = "1.0.0"),
1376 stable(feature = "extended_compare_and_swap", since = "1.10.0"),
1377 stable(feature = "atomic_debug", since = "1.3.0"),
1378 stable(feature = "atomic_access", since = "1.15.0"),
1379 isize AtomicIsize ATOMIC_ISIZE_INIT
1381 #[cfg(target_has_atomic = "ptr")]
1383 stable(feature = "rust1", since = "1.0.0"),
1384 stable(feature = "extended_compare_and_swap", since = "1.10.0"),
1385 stable(feature = "atomic_debug", since = "1.3.0"),
1386 stable(feature = "atomic_access", since = "1.15.0"),
1387 usize AtomicUsize ATOMIC_USIZE_INIT
1391 fn strongest_failure_ordering(order: Ordering) -> Ordering {
1398 __Nonexhaustive => __Nonexhaustive,
1403 unsafe fn atomic_store<T>(dst: *mut T, val: T, order: Ordering) {
1405 Release => intrinsics::atomic_store_rel(dst, val),
1406 Relaxed => intrinsics::atomic_store_relaxed(dst, val),
1407 SeqCst => intrinsics::atomic_store(dst, val),
1408 Acquire => panic!("there is no such thing as an acquire store"),
1409 AcqRel => panic!("there is no such thing as an acquire/release store"),
1410 __Nonexhaustive => panic!("invalid memory ordering"),
1415 unsafe fn atomic_load<T>(dst: *const T, order: Ordering) -> T {
1417 Acquire => intrinsics::atomic_load_acq(dst),
1418 Relaxed => intrinsics::atomic_load_relaxed(dst),
1419 SeqCst => intrinsics::atomic_load(dst),
1420 Release => panic!("there is no such thing as a release load"),
1421 AcqRel => panic!("there is no such thing as an acquire/release load"),
1422 __Nonexhaustive => panic!("invalid memory ordering"),
1427 unsafe fn atomic_swap<T>(dst: *mut T, val: T, order: Ordering) -> T {
1429 Acquire => intrinsics::atomic_xchg_acq(dst, val),
1430 Release => intrinsics::atomic_xchg_rel(dst, val),
1431 AcqRel => intrinsics::atomic_xchg_acqrel(dst, val),
1432 Relaxed => intrinsics::atomic_xchg_relaxed(dst, val),
1433 SeqCst => intrinsics::atomic_xchg(dst, val),
1434 __Nonexhaustive => panic!("invalid memory ordering"),
1438 /// Returns the previous value (like __sync_fetch_and_add).
1440 unsafe fn atomic_add<T>(dst: *mut T, val: T, order: Ordering) -> T {
1442 Acquire => intrinsics::atomic_xadd_acq(dst, val),
1443 Release => intrinsics::atomic_xadd_rel(dst, val),
1444 AcqRel => intrinsics::atomic_xadd_acqrel(dst, val),
1445 Relaxed => intrinsics::atomic_xadd_relaxed(dst, val),
1446 SeqCst => intrinsics::atomic_xadd(dst, val),
1447 __Nonexhaustive => panic!("invalid memory ordering"),
1451 /// Returns the previous value (like __sync_fetch_and_sub).
1453 unsafe fn atomic_sub<T>(dst: *mut T, val: T, order: Ordering) -> T {
1455 Acquire => intrinsics::atomic_xsub_acq(dst, val),
1456 Release => intrinsics::atomic_xsub_rel(dst, val),
1457 AcqRel => intrinsics::atomic_xsub_acqrel(dst, val),
1458 Relaxed => intrinsics::atomic_xsub_relaxed(dst, val),
1459 SeqCst => intrinsics::atomic_xsub(dst, val),
1460 __Nonexhaustive => panic!("invalid memory ordering"),
1465 unsafe fn atomic_compare_exchange<T>(dst: *mut T,
1471 let (val, ok) = match (success, failure) {
1472 (Acquire, Acquire) => intrinsics::atomic_cxchg_acq(dst, old, new),
1473 (Release, Relaxed) => intrinsics::atomic_cxchg_rel(dst, old, new),
1474 (AcqRel, Acquire) => intrinsics::atomic_cxchg_acqrel(dst, old, new),
1475 (Relaxed, Relaxed) => intrinsics::atomic_cxchg_relaxed(dst, old, new),
1476 (SeqCst, SeqCst) => intrinsics::atomic_cxchg(dst, old, new),
1477 (Acquire, Relaxed) => intrinsics::atomic_cxchg_acq_failrelaxed(dst, old, new),
1478 (AcqRel, Relaxed) => intrinsics::atomic_cxchg_acqrel_failrelaxed(dst, old, new),
1479 (SeqCst, Relaxed) => intrinsics::atomic_cxchg_failrelaxed(dst, old, new),
1480 (SeqCst, Acquire) => intrinsics::atomic_cxchg_failacq(dst, old, new),
1481 (__Nonexhaustive, _) => panic!("invalid memory ordering"),
1482 (_, __Nonexhaustive) => panic!("invalid memory ordering"),
1483 (_, AcqRel) => panic!("there is no such thing as an acquire/release failure ordering"),
1484 (_, Release) => panic!("there is no such thing as a release failure ordering"),
1485 _ => panic!("a failure ordering can't be stronger than a success ordering"),
1487 if ok { Ok(val) } else { Err(val) }
1491 unsafe fn atomic_compare_exchange_weak<T>(dst: *mut T,
1497 let (val, ok) = match (success, failure) {
1498 (Acquire, Acquire) => intrinsics::atomic_cxchgweak_acq(dst, old, new),
1499 (Release, Relaxed) => intrinsics::atomic_cxchgweak_rel(dst, old, new),
1500 (AcqRel, Acquire) => intrinsics::atomic_cxchgweak_acqrel(dst, old, new),
1501 (Relaxed, Relaxed) => intrinsics::atomic_cxchgweak_relaxed(dst, old, new),
1502 (SeqCst, SeqCst) => intrinsics::atomic_cxchgweak(dst, old, new),
1503 (Acquire, Relaxed) => intrinsics::atomic_cxchgweak_acq_failrelaxed(dst, old, new),
1504 (AcqRel, Relaxed) => intrinsics::atomic_cxchgweak_acqrel_failrelaxed(dst, old, new),
1505 (SeqCst, Relaxed) => intrinsics::atomic_cxchgweak_failrelaxed(dst, old, new),
1506 (SeqCst, Acquire) => intrinsics::atomic_cxchgweak_failacq(dst, old, new),
1507 (__Nonexhaustive, _) => panic!("invalid memory ordering"),
1508 (_, __Nonexhaustive) => panic!("invalid memory ordering"),
1509 (_, AcqRel) => panic!("there is no such thing as an acquire/release failure ordering"),
1510 (_, Release) => panic!("there is no such thing as a release failure ordering"),
1511 _ => panic!("a failure ordering can't be stronger than a success ordering"),
1513 if ok { Ok(val) } else { Err(val) }
1517 unsafe fn atomic_and<T>(dst: *mut T, val: T, order: Ordering) -> T {
1519 Acquire => intrinsics::atomic_and_acq(dst, val),
1520 Release => intrinsics::atomic_and_rel(dst, val),
1521 AcqRel => intrinsics::atomic_and_acqrel(dst, val),
1522 Relaxed => intrinsics::atomic_and_relaxed(dst, val),
1523 SeqCst => intrinsics::atomic_and(dst, val),
1524 __Nonexhaustive => panic!("invalid memory ordering"),
1529 unsafe fn atomic_or<T>(dst: *mut T, val: T, order: Ordering) -> T {
1531 Acquire => intrinsics::atomic_or_acq(dst, val),
1532 Release => intrinsics::atomic_or_rel(dst, val),
1533 AcqRel => intrinsics::atomic_or_acqrel(dst, val),
1534 Relaxed => intrinsics::atomic_or_relaxed(dst, val),
1535 SeqCst => intrinsics::atomic_or(dst, val),
1536 __Nonexhaustive => panic!("invalid memory ordering"),
1541 unsafe fn atomic_xor<T>(dst: *mut T, val: T, order: Ordering) -> T {
1543 Acquire => intrinsics::atomic_xor_acq(dst, val),
1544 Release => intrinsics::atomic_xor_rel(dst, val),
1545 AcqRel => intrinsics::atomic_xor_acqrel(dst, val),
1546 Relaxed => intrinsics::atomic_xor_relaxed(dst, val),
1547 SeqCst => intrinsics::atomic_xor(dst, val),
1548 __Nonexhaustive => panic!("invalid memory ordering"),
1552 /// An atomic fence.
1554 /// A fence 'A' which has [`Release`] ordering semantics, synchronizes with a
1555 /// fence 'B' with (at least) [`Acquire`] semantics, if and only if there exists
1556 /// atomic operations X and Y, both operating on some atomic object 'M' such
1557 /// that A is sequenced before X, Y is synchronized before B and Y observes
1558 /// the change to M. This provides a happens-before dependence between A and B.
1560 /// Atomic operations with [`Release`] or [`Acquire`] semantics can also synchronize
1563 /// A fence which has [`SeqCst`] ordering, in addition to having both [`Acquire`]
1564 /// and [`Release`] semantics, participates in the global program order of the
1565 /// other [`SeqCst`] operations and/or fences.
1567 /// Accepts [`Acquire`], [`Release`], [`AcqRel`] and [`SeqCst`] orderings.
1571 /// Panics if `order` is [`Relaxed`].
1573 /// [`Ordering`]: enum.Ordering.html
1574 /// [`Acquire`]: enum.Ordering.html#variant.Acquire
1575 /// [`SeqCst`]: enum.Ordering.html#variant.SeqCst
1576 /// [`Release`]: enum.Ordering.html#variant.Release
1577 /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
1578 /// [`Relaxed`]: enum.Ordering.html#variant.Relaxed
1580 #[stable(feature = "rust1", since = "1.0.0")]
1581 pub fn fence(order: Ordering) {
1584 Acquire => intrinsics::atomic_fence_acq(),
1585 Release => intrinsics::atomic_fence_rel(),
1586 AcqRel => intrinsics::atomic_fence_acqrel(),
1587 SeqCst => intrinsics::atomic_fence(),
1588 Relaxed => panic!("there is no such thing as a relaxed fence"),
1589 __Nonexhaustive => panic!("invalid memory ordering"),
1595 #[cfg(target_has_atomic = "8")]
1596 #[stable(feature = "atomic_debug", since = "1.3.0")]
1597 impl fmt::Debug for AtomicBool {
1598 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1599 f.debug_tuple("AtomicBool").field(&self.load(Ordering::SeqCst)).finish()
1603 #[cfg(target_has_atomic = "ptr")]
1604 #[stable(feature = "atomic_debug", since = "1.3.0")]
1605 impl<T> fmt::Debug for AtomicPtr<T> {
1606 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1607 f.debug_tuple("AtomicPtr").field(&self.load(Ordering::SeqCst)).finish()