[atomics] # 32 Concurrency support library [[thread]](./#thread) ## 32.5 Atomic operations [atomics] ### [32.5.1](#general) General [[atomics.general]](atomics.general) [1](#general-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L2388) Subclause [atomics] describes components for fine-grained atomic access[.](#general-1.sentence-1) This access is provided via operations on atomic objects[.](#general-1.sentence-2) ### [32.5.2](#syn) Header synopsis [[atomics.syn]](atomics.syn) [🔗](#header:%3catomic%3e) namespace std {// [[atomics.order]](#order "32.5.4 Order and consistency"), order and consistencyenum class memory_order : *unspecified*; // freestandinginline constexpr memory_order memory_order_relaxed = memory_order::relaxed; // freestandinginline constexpr memory_order memory_order_acquire = memory_order::acquire; // freestandinginline constexpr memory_order memory_order_release = memory_order::release; // freestandinginline constexpr memory_order memory_order_acq_rel = memory_order::acq_rel; // freestandinginline constexpr memory_order memory_order_seq_cst = memory_order::seq_cst; // freestanding}// [[atomics.lockfree]](#lockfree "32.5.5 Lock-free property"), lock-free property#define ATOMIC_BOOL_LOCK_FREE *unspecified* // freestanding#define ATOMIC_CHAR_LOCK_FREE *unspecified* // freestanding#define ATOMIC_CHAR8_T_LOCK_FREE *unspecified* // freestanding#define ATOMIC_CHAR16_T_LOCK_FREE *unspecified* // freestanding#define ATOMIC_CHAR32_T_LOCK_FREE *unspecified* // freestanding#define ATOMIC_WCHAR_T_LOCK_FREE *unspecified* // freestanding#define ATOMIC_SHORT_LOCK_FREE *unspecified* // freestanding#define ATOMIC_INT_LOCK_FREE *unspecified* // freestanding#define ATOMIC_LONG_LOCK_FREE *unspecified* // freestanding#define ATOMIC_LLONG_LOCK_FREE *unspecified* // freestanding#define ATOMIC_POINTER_LOCK_FREE *unspecified* // freestandingnamespace std {// [[atomics.ref.generic]](#ref.generic "32.5.7 Class template atomic_­ref"), class template atomic_reftemplate struct atomic_ref; // freestanding// [[atomics.types.generic]](#types.generic "32.5.8 Class template atomic"), class template atomictemplate struct atomic; // freestanding// [[atomics.types.pointer]](#types.pointer "32.5.8.5 Partial specialization for pointers"), partial specialization for pointerstemplate struct atomic; // freestanding// [[atomics.nonmembers]](#nonmembers "32.5.9 Non-member functions"), non-member functionstemplatebool atomic_is_lock_free(const volatile atomic*) noexcept; // freestandingtemplatebool atomic_is_lock_free(const atomic*) noexcept; // freestandingtemplatevoid atomic_store(volatile atomic*, // freestandingtypename atomic::value_type) noexcept; templateconstexpr void atomic_store(atomic*, // freestandingtypename atomic::value_type) noexcept; templatevoid atomic_store_explicit(volatile atomic*, // freestandingtypename atomic::value_type, memory_order) noexcept; templateconstexpr void atomic_store_explicit(atomic*, // freestandingtypename atomic::value_type, memory_order) noexcept; template T atomic_load(const volatile atomic*) noexcept; // freestandingtemplateconstexpr T atomic_load(const atomic*) noexcept; // freestandingtemplate T atomic_load_explicit(const volatile atomic*, memory_order) noexcept; // freestandingtemplateconstexpr T atomic_load_explicit(const atomic*, memory_order) noexcept; // freestandingtemplate T atomic_exchange(volatile atomic*, // freestandingtypename atomic::value_type) noexcept; templateconstexpr T atomic_exchange(atomic*, // freestandingtypename atomic::value_type) noexcept; template T atomic_exchange_explicit(volatile atomic*, // freestandingtypename atomic::value_type, memory_order) noexcept; templateconstexpr T atomic_exchange_explicit(atomic*, // freestandingtypename atomic::value_type, memory_order) noexcept; templatebool atomic_compare_exchange_weak(volatile atomic*, // freestandingtypename atomic::value_type*, typename atomic::value_type) noexcept; templateconstexpr bool atomic_compare_exchange_weak(atomic*, // freestandingtypename atomic::value_type*, typename atomic::value_type) noexcept; templatebool atomic_compare_exchange_strong(volatile atomic*, // freestandingtypename atomic::value_type*, typename atomic::value_type) noexcept; templateconstexpr bool atomic_compare_exchange_strong(atomic*, // freestandingtypename atomic::value_type*, typename atomic::value_type) noexcept; templatebool atomic_compare_exchange_weak_explicit(volatile atomic*, // freestandingtypename atomic::value_type*, typename atomic::value_type, memory_order, memory_order) noexcept; templateconstexpr bool atomic_compare_exchange_weak_explicit(atomic*, // freestandingtypename atomic::value_type*, typename atomic::value_type, memory_order, memory_order) noexcept; templatebool atomic_compare_exchange_strong_explicit(volatile atomic*, // freestandingtypename atomic::value_type*, typename atomic::value_type, memory_order, memory_order) noexcept; templateconstexpr bool atomic_compare_exchange_strong_explicit(atomic*, // freestandingtypename atomic::value_type*, typename atomic::value_type, memory_order, memory_order) noexcept; template T atomic_fetch_add(volatile atomic*, // freestandingtypename atomic::difference_type) noexcept; templateconstexpr T atomic_fetch_add(atomic*, // freestandingtypename atomic::difference_type) noexcept; template T atomic_fetch_add_explicit(volatile atomic*, // freestandingtypename atomic::difference_type, memory_order) noexcept; templateconstexpr T atomic_fetch_add_explicit(atomic*, // freestandingtypename atomic::difference_type, memory_order) noexcept; template T atomic_fetch_sub(volatile atomic*, // freestandingtypename atomic::difference_type) noexcept; templateconstexpr T atomic_fetch_sub(atomic*, // freestandingtypename atomic::difference_type) noexcept; template T atomic_fetch_sub_explicit(volatile atomic*, // freestandingtypename atomic::difference_type, memory_order) noexcept; templateconstexpr T atomic_fetch_sub_explicit(atomic*, // freestandingtypename atomic::difference_type, memory_order) noexcept; template T atomic_fetch_and(volatile atomic*, // freestandingtypename atomic::value_type) noexcept; templateconstexpr T atomic_fetch_and(atomic*, // freestandingtypename atomic::value_type) noexcept; template T atomic_fetch_and_explicit(volatile atomic*, // freestandingtypename atomic::value_type, memory_order) noexcept; templateconstexpr T atomic_fetch_and_explicit(atomic*, // freestandingtypename atomic::value_type, memory_order) noexcept; template T atomic_fetch_or(volatile atomic*, // freestandingtypename atomic::value_type) noexcept; templateconstexpr T atomic_fetch_or(atomic*, // freestandingtypename atomic::value_type) noexcept; template T atomic_fetch_or_explicit(volatile atomic*, // freestandingtypename atomic::value_type, memory_order) noexcept; templateconstexpr T atomic_fetch_or_explicit(atomic*, // freestandingtypename atomic::value_type, memory_order) noexcept; template T atomic_fetch_xor(volatile atomic*, // freestandingtypename atomic::value_type) noexcept; templateconstexpr T atomic_fetch_xor(atomic*, // freestandingtypename atomic::value_type) noexcept; template T atomic_fetch_xor_explicit(volatile atomic*, // freestandingtypename atomic::value_type, memory_order) noexcept; templateconstexpr T atomic_fetch_xor_explicit(atomic*, // freestandingtypename atomic::value_type, memory_order) noexcept; template T atomic_fetch_max(volatile atomic*, // freestandingtypename atomic::value_type) noexcept; templateconstexpr T atomic_fetch_max(atomic*, // freestandingtypename atomic::value_type) noexcept; template T atomic_fetch_max_explicit(volatile atomic*, // freestandingtypename atomic::value_type, memory_order) noexcept; templateconstexpr T atomic_fetch_max_explicit(atomic*, // freestandingtypename atomic::value_type, memory_order) noexcept; template T atomic_fetch_min(volatile atomic*, // freestandingtypename atomic::value_type) noexcept; templateconstexpr T atomic_fetch_min(atomic*, // freestandingtypename atomic::value_type) noexcept; template T atomic_fetch_min_explicit(volatile atomic*, // freestandingtypename atomic::value_type, memory_order) noexcept; templateconstexpr T atomic_fetch_min_explicit(atomic*, // freestandingtypename atomic::value_type, memory_order) noexcept; templatevoid atomic_store_add(volatile atomic*, // freestandingtypename atomic::difference_type) noexcept; templateconstexpr void atomic_store_add(atomic*, // freestandingtypename atomic::difference_type) noexcept; templatevoid atomic_store_add_explicit(volatile atomic*, // freestandingtypename atomic::difference_type, memory_order) noexcept; templateconstexpr void atomic_store_add_explicit(atomic*, // freestandingtypename atomic::difference_type, memory_order) noexcept; templatevoid atomic_store_sub(volatile atomic*, // freestandingtypename atomic::difference_type) noexcept; templateconstexpr void atomic_store_sub(atomic*, // freestandingtypename atomic::difference_type) noexcept; templatevoid atomic_store_sub_explicit(volatile atomic*, // freestandingtypename atomic::difference_type, memory_order) noexcept; templateconstexpr void atomic_store_sub_explicit(atomic*, // freestandingtypename atomic::difference_type, memory_order) noexcept; templatevoid atomic_store_and(volatile atomic*, // freestandingtypename atomic::value_type) noexcept; templateconstexpr void atomic_store_and(atomic*, // freestandingtypename atomic::value_type) noexcept; templatevoid atomic_store_and_explicit(volatile atomic*, // freestandingtypename atomic::value_type, memory_order) noexcept; templateconstexpr void atomic_store_and_explicit(atomic*, // freestandingtypename atomic::value_type, memory_order) noexcept; templatevoid atomic_store_or(volatile atomic*, // freestandingtypename atomic::value_type) noexcept; templateconstexpr void atomic_store_or(atomic*, // freestandingtypename atomic::value_type) noexcept; templatevoid atomic_store_or_explicit(volatile atomic*, // freestandingtypename atomic::value_type, memory_order) noexcept; templateconstexpr void atomic_store_or_explicit(atomic*, // freestandingtypename atomic::value_type, memory_order) noexcept; templatevoid atomic_store_xor(volatile atomic*, // freestandingtypename atomic::value_type) noexcept; templateconstexpr void atomic_store_xor(atomic*, // freestandingtypename atomic::value_type) noexcept; templatevoid atomic_store_xor_explicit(volatile atomic*, // freestandingtypename atomic::value_type, memory_order) noexcept; templateconstexpr void atomic_store_xor_explicit(atomic*, // freestandingtypename atomic::value_type, memory_order) noexcept; templatevoid atomic_store_max(volatile atomic*, // freestandingtypename atomic::value_type) noexcept; templateconstexpr void atomic_store_max(atomic*, // freestandingtypename atomic::value_type) noexcept; templatevoid atomic_store_max_explicit(volatile atomic*, // freestandingtypename atomic::value_type, memory_order) noexcept; templateconstexpr void atomic_store_max_explicit(atomic*, // freestandingtypename atomic::value_type, memory_order) noexcept; templatevoid atomic_store_min(volatile atomic*, // freestandingtypename atomic::value_type) noexcept; templateconstexpr void atomic_store_min(atomic*, // freestandingtypename atomic::value_type) noexcept; templatevoid atomic_store_min_explicit(volatile atomic*, // freestandingtypename atomic::value_type, memory_order) noexcept; templateconstexpr void atomic_store_min_explicit(atomic*, // freestandingtypename atomic::value_type, memory_order) noexcept; templatevoid atomic_wait(const volatile atomic*, // freestandingtypename atomic::value_type) noexcept; templateconstexpr void atomic_wait(const atomic*, // freestandingtypename atomic::value_type) noexcept; templatevoid atomic_wait_explicit(const volatile atomic*, // freestandingtypename atomic::value_type, memory_order) noexcept; templateconstexpr void atomic_wait_explicit(const atomic*, // freestandingtypename atomic::value_type, memory_order) noexcept; templatevoid atomic_notify_one(volatile atomic*) noexcept; // freestandingtemplateconstexpr void atomic_notify_one(atomic*) noexcept; // freestandingtemplatevoid atomic_notify_all(volatile atomic*) noexcept; // freestandingtemplateconstexpr void atomic_notify_all(atomic*) noexcept; // freestanding// [[atomics.alias]](#alias "32.5.3 Type aliases"), type aliasesusing atomic_bool = atomic; // freestandingusing atomic_char = atomic; // freestandingusing atomic_schar = atomic; // freestandingusing atomic_uchar = atomic; // freestandingusing atomic_short = atomic; // freestandingusing atomic_ushort = atomic; // freestandingusing atomic_int = atomic; // freestandingusing atomic_uint = atomic; // freestandingusing atomic_long = atomic; // freestandingusing atomic_ulong = atomic; // freestandingusing atomic_llong = atomic; // freestandingusing atomic_ullong = atomic; // freestandingusing atomic_char8_t = atomic; // freestandingusing atomic_char16_t = atomic; // freestandingusing atomic_char32_t = atomic; // freestandingusing atomic_wchar_t = atomic; // freestandingusing atomic_int8_t = atomic; // freestandingusing atomic_uint8_t = atomic; // freestandingusing atomic_int16_t = atomic; // freestandingusing atomic_uint16_t = atomic; // freestandingusing atomic_int32_t = atomic; // freestandingusing atomic_uint32_t = atomic; // freestandingusing atomic_int64_t = atomic; // freestandingusing atomic_uint64_t = atomic; // freestandingusing atomic_int_least8_t = atomic; // freestandingusing atomic_uint_least8_t = atomic; // freestandingusing atomic_int_least16_t = atomic; // freestandingusing atomic_uint_least16_t = atomic; // freestandingusing atomic_int_least32_t = atomic; // freestandingusing atomic_uint_least32_t = atomic; // freestandingusing atomic_int_least64_t = atomic; // freestandingusing atomic_uint_least64_t = atomic; // freestandingusing atomic_int_fast8_t = atomic; // freestandingusing atomic_uint_fast8_t = atomic; // freestandingusing atomic_int_fast16_t = atomic; // freestandingusing atomic_uint_fast16_t = atomic; // freestandingusing atomic_int_fast32_t = atomic; // freestandingusing atomic_uint_fast32_t = atomic; // freestandingusing atomic_int_fast64_t = atomic; // freestandingusing atomic_uint_fast64_t = atomic; // freestandingusing atomic_intptr_t = atomic; // freestandingusing atomic_uintptr_t = atomic; // freestandingusing atomic_size_t = atomic; // freestandingusing atomic_ptrdiff_t = atomic; // freestandingusing atomic_intmax_t = atomic; // freestandingusing atomic_uintmax_t = atomic; // freestandingusing atomic_signed_lock_free = *see below*; using atomic_unsigned_lock_free = *see below*; // [[atomics.flag]](#flag "32.5.10 Flag type and operations"), flag type and operationsstruct atomic_flag; // freestandingbool atomic_flag_test(const volatile atomic_flag*) noexcept; // freestandingconstexpr bool atomic_flag_test(const atomic_flag*) noexcept; // freestandingbool atomic_flag_test_explicit(const volatile atomic_flag*, // freestanding memory_order) noexcept; constexpr bool atomic_flag_test_explicit(const atomic_flag*, // freestanding memory_order) noexcept; bool atomic_flag_test_and_set(volatile atomic_flag*) noexcept; // freestandingconstexpr bool atomic_flag_test_and_set(atomic_flag*) noexcept; // freestandingbool atomic_flag_test_and_set_explicit(volatile atomic_flag*, // freestanding memory_order) noexcept; constexpr bool atomic_flag_test_and_set_explicit(atomic_flag*, // freestanding memory_order) noexcept; void atomic_flag_clear(volatile atomic_flag*) noexcept; // freestandingconstexpr void atomic_flag_clear(atomic_flag*) noexcept; // freestandingvoid atomic_flag_clear_explicit(volatile atomic_flag*, memory_order) noexcept; // freestandingconstexpr void atomic_flag_clear_explicit(atomic_flag*, memory_order) noexcept; // freestandingvoid atomic_flag_wait(const volatile atomic_flag*, bool) noexcept; // freestandingconstexpr void atomic_flag_wait(const atomic_flag*, bool) noexcept; // freestandingvoid atomic_flag_wait_explicit(const volatile atomic_flag*, // freestandingbool, memory_order) noexcept; constexpr void atomic_flag_wait_explicit(const atomic_flag*, // freestandingbool, memory_order) noexcept; void atomic_flag_notify_one(volatile atomic_flag*) noexcept; // freestandingconstexpr void atomic_flag_notify_one(atomic_flag*) noexcept; // freestandingvoid atomic_flag_notify_all(volatile atomic_flag*) noexcept; // freestandingconstexpr void atomic_flag_notify_all(atomic_flag*) noexcept; // freestanding#define ATOMIC_FLAG_INIT *see below* // freestanding// [[atomics.fences]](#fences "32.5.11 Fences"), fencesextern "C" constexpr void atomic_thread_fence(memory_order) noexcept; // freestandingextern "C" constexpr void atomic_signal_fence(memory_order) noexcept; // freestanding} ### [32.5.3](#alias) Type aliases [[atomics.alias]](atomics.alias) [1](#alias-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L2857) The type aliases atomic_intN_t, atomic_uintN_t,atomic_intptr_t, and atomic_uintptr_t are defined if and only ifintN_t, uintN_t,intptr_t, and uintptr_t are defined, respectively[.](#alias-1.sentence-1) [2](#alias-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L2865) The type aliasesatomic_signed_lock_free and atomic_unsigned_lock_free name specializations of atomic whose template arguments are integral types, respectively signed and unsigned, and whose is_always_lock_free property is true[.](#alias-2.sentence-1) [*Note [1](#alias-note-1)*: These aliases are optional in freestanding implementations ([[compliance]](compliance "16.4.2.5 Freestanding implementations"))[.](#alias-2.sentence-2) — *end note*] Implementations should choose for these aliases the integral specializations of atomic for which the atomic waiting and notifying operations ([[atomics.wait]](#wait "32.5.6 Waiting and notifying")) are most efficient[.](#alias-2.sentence-3) ### [32.5.4](#order) Order and consistency [[atomics.order]](atomics.order) namespace std {enum class memory_order : *unspecified* { relaxed = 0, acquire = 2, release = 3, acq_rel = 4, seq_cst = 5};} [1](#order-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L2903) The enumeration memory_order specifies the detailed regular (non-atomic) memory synchronization order as defined in[[intro.multithread]](intro.multithread "6.10.2 Multi-threaded executions and data races") and may provide for operation ordering[.](#order-1.sentence-1) Its enumerated values and their meanings are as follows: - [(1.1)](#order-1.1) memory_order​::​relaxed: no operation orders memory[.](#order-1.1.sentence-1) - [(1.2)](#order-1.2) memory_order​::​release, memory_order​::​acq_rel, andmemory_order​::​seq_cst: a store operation performs a release operation on the affected memory location[.](#order-1.2.sentence-1) - [(1.3)](#order-1.3) memory_order​::​acquire, memory_order​::​acq_rel, andmemory_order​::​seq_cst: a load operation performs an acquire operation on the affected memory location[.](#order-1.3.sentence-1) [*Note [1](#order-note-1)*: Atomic operations specifying memory_order​::​relaxed are relaxed with respect to memory ordering[.](#order-1.sentence-3) Implementations must still guarantee that any given atomic access to a particular atomic object be indivisible with respect to all other atomic accesses to that object[.](#order-1.sentence-4) — *end note*] [2](#order-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L2928) An atomic operation A that performs a release operation on an atomic object M synchronizes with an atomic operation B that performs an acquire operation on M and takes its value from any side effect in the release sequence headed by A[.](#order-2.sentence-1) [3](#order-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L2934) An atomic operation A on some atomic object M is[*coherence-ordered before*](#def:coherence-ordered_before "32.5.4 Order and consistency [atomics.order]") another atomic operation B on M if - [(3.1)](#order-3.1) A is a modification, andB reads the value stored by A, or - [(3.2)](#order-3.2) A precedes B in the modification order of M, or - [(3.3)](#order-3.3) A and B are not the same atomic read-modify-write operation, and there exists an atomic modification X of M such that A reads the value stored by X andX precedes B in the modification order of M, or - [(3.4)](#order-3.4) there exists an atomic modification X of M such that A is coherence-ordered before X andX is coherence-ordered before B[.](#order-3.sentence-1) [4](#order-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L2954) There is a single total order S on all memory_order​::​seq_cst operations, including fences, that satisfies the following constraints[.](#order-4.sentence-1) First, if A and B arememory_order​::​seq_cst operations andA strongly happens before B, then A precedes B in S[.](#order-4.sentence-2) Second, for every pair of atomic operations A andB on an object M, where A is coherence-ordered before B, the following four conditions are required to be satisfied by S: - [(4.1)](#order-4.1) if A and B are bothmemory_order​::​seq_cst operations, then A precedes B in S; and - [(4.2)](#order-4.2) if A is a memory_order​::​seq_cst operation andB happens before a memory_order​::​seq_cst fence Y, then A precedes Y in S; and - [(4.3)](#order-4.3) if a memory_order​::​seq_cst fence X happens before A andB is a memory_order​::​seq_cst operation, then X precedes B in S; and - [(4.4)](#order-4.4) if a memory_order​::​seq_cst fence X happens before A andB happens before a memory_order​::​seq_cst fence Y, then X precedes Y in S[.](#order-4.sentence-3) [5](#order-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L2985) [*Note [2](#order-note-2)*: This definition ensures that S is consistent with the modification order of any atomic object M[.](#order-5.sentence-1) It also ensures that a memory_order​::​seq_cst load A of M gets its value either from the last modification of M that precedes A in S or from some non-memory_order​::​seq_cst modification of M that does not happen before any modification of M that precedes A in S[.](#order-5.sentence-2) — *end note*] [6](#order-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L2998) [*Note [3](#order-note-3)*: We do not require that S be consistent with “happens before” ([[intro.races]](intro.races "6.10.2.2 Data races"))[.](#order-6.sentence-1) This allows more efficient implementation of memory_order​::​acquire and memory_order​::​release on some machine architectures[.](#order-6.sentence-2) It can produce surprising results when these are mixed with memory_order​::​seq_cst accesses[.](#order-6.sentence-3) — *end note*] [7](#order-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3009) [*Note [4](#order-note-4)*: memory_order​::​seq_cst ensures sequential consistency only for a program that is free of data races and uses exclusively memory_order​::​seq_cst atomic operations[.](#order-7.sentence-1) Any use of weaker ordering will invalidate this guarantee unless extreme care is used[.](#order-7.sentence-2) In many cases, memory_order​::​seq_cst atomic operations are reorderable with respect to other atomic operations performed by the same thread[.](#order-7.sentence-3) — *end note*] [8](#order-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3020) Implementations should ensure that no “out-of-thin-air” values are computed that circularly depend on their own computation[.](#order-8.sentence-1) [*Note [5](#order-note-5)*: For example, with x and y initially zero,// Thread 1: r1 = y.load(memory_order::relaxed); x.store(r1, memory_order::relaxed); // Thread 2: r2 = x.load(memory_order::relaxed); y.store(r2, memory_order::relaxed); this recommendation discourages producing r1 == r2 == 42, since the store of 42 to y is only possible if the store to x stores 42, which circularly depends on the store to y storing 42[.](#order-8.sentence-3) Note that without this restriction, such an execution is possible[.](#order-8.sentence-4) — *end note*] [9](#order-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3043) [*Note [6](#order-note-6)*: The recommendation similarly disallows r1 == r2 == 42 in the following example, with x and y again initially zero: // Thread 1: r1 = x.load(memory_order::relaxed);if (r1 == 42) y.store(42, memory_order::relaxed); // Thread 2: r2 = y.load(memory_order::relaxed);if (r2 == 42) x.store(42, memory_order::relaxed); — *end note*] [10](#order-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3061) Atomic read-modify-write operations shall always read the last value (in the modification order) written before the write associated with the read-modify-write operation[.](#order-10.sentence-1) [11](#order-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3066) An [*atomic modify-write operation*](#def:modify-write_operation,atomic "32.5.4 Order and consistency [atomics.order]") is an atomic read-modify-write operation with weaker synchronization requirements as specified in [[atomics.fences]](#fences "32.5.11 Fences")[.](#order-11.sentence-1) [*Note [7](#order-note-7)*: The intent is for atomic modify-write operations to be implemented using mechanisms that are not ordered, in hardware, by the implementation of acquire fences[.](#order-11.sentence-2) No other semantic or hardware property (e.g., that the mechanism is a far atomic operation) is implied[.](#order-11.sentence-3) — *end note*] [12](#order-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3078) *Recommended practice*: The implementation should make atomic stores visible to atomic loads, and atomic loads should observe atomic stores, within a reasonable amount of time[.](#order-12.sentence-1) ### [32.5.5](#lockfree) Lock-free property [[atomics.lockfree]](atomics.lockfree) [🔗](#:values_of_various_ATOMIC_..._LOCK_FREE_macros) #define ATOMIC_BOOL_LOCK_FREE *unspecified*#define ATOMIC_CHAR_LOCK_FREE *unspecified*#define ATOMIC_CHAR8_T_LOCK_FREE *unspecified*#define ATOMIC_CHAR16_T_LOCK_FREE *unspecified*#define ATOMIC_CHAR32_T_LOCK_FREE *unspecified*#define ATOMIC_WCHAR_T_LOCK_FREE *unspecified*#define ATOMIC_SHORT_LOCK_FREE *unspecified*#define ATOMIC_INT_LOCK_FREE *unspecified*#define ATOMIC_LONG_LOCK_FREE *unspecified*#define ATOMIC_LLONG_LOCK_FREE *unspecified*#define ATOMIC_POINTER_LOCK_FREE *unspecified* [1](#lockfree-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3101) The ATOMIC_..._LOCK_FREE macros indicate the lock-free property of the corresponding atomic types, with the signed and unsigned variants grouped together[.](#lockfree-1.sentence-1) The properties also apply to the corresponding (partial) specializations of theatomic template[.](#lockfree-1.sentence-2) A value of 0 indicates that the types are never lock-free[.](#lockfree-1.sentence-3) A value of 1 indicates that the types are sometimes lock-free[.](#lockfree-1.sentence-4) A value of 2 indicates that the types are always lock-free[.](#lockfree-1.sentence-5) [2](#lockfree-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3109) On a hosted implementation ([[compliance]](compliance "16.4.2.5 Freestanding implementations")), at least one signed integral specialization of the atomic template, along with the specialization for the corresponding unsigned type ([[basic.fundamental]](basic.fundamental "6.9.2 Fundamental types")), is always lock-free[.](#lockfree-2.sentence-1) [3](#lockfree-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3116) The functions atomic​::​is_lock_free andatomic_is_lock_free ([[atomics.types.operations]](#types.operations "32.5.8.2 Operations on atomic types")) indicate whether the object is lock-free[.](#lockfree-3.sentence-1) In any given program execution, the result of the lock-free query is the same for all atomic objects of the same type[.](#lockfree-3.sentence-2) [4](#lockfree-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3123) Atomic operations that are not lock-free are considered to potentially block ([[intro.progress]](intro.progress "6.10.2.3 Forward progress"))[.](#lockfree-4.sentence-1) [5](#lockfree-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3127) *Recommended practice*: Operations that are lock-free should also be address-free[.](#lockfree-5.sentence-1)[294](#footnote-294 "That is, atomic operations on the same memory location via two different addresses will communicate atomically.") The implementation of these operations should not depend on any per-process state[.](#lockfree-5.sentence-2) [*Note [1](#lockfree-note-1)*: This restriction enables communication by memory that is mapped into a process more than once and by memory that is shared between two processes[.](#lockfree-5.sentence-3) — *end note*] [294)](#footnote-294)[294)](#footnoteref-294) That is, atomic operations on the same memory location via two different addresses will communicate atomically[.](#footnote-294.sentence-1) ### [32.5.6](#wait) Waiting and notifying [[atomics.wait]](atomics.wait) [1](#wait-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3144) [*Atomic waiting operations*](#def:atomic,waiting_operation "32.5.6 Waiting and notifying [atomics.wait]") and [*atomic notifying operations*](#def:atomic,notifying_operation "32.5.6 Waiting and notifying [atomics.wait]") provide a mechanism to wait for the value of an atomic object to change more efficiently than can be achieved with polling[.](#wait-1.sentence-1) An atomic waiting operation may block until it is unblocked by an atomic notifying operation, according to each function's effects[.](#wait-1.sentence-2) [*Note [1](#wait-note-1)*: Programs are not guaranteed to observe transient atomic values, an issue known as the A-B-A problem, resulting in continued blocking if a condition is only temporarily met[.](#wait-1.sentence-3) — *end note*] [2](#wait-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3157) [*Note [2](#wait-note-2)*: The following functions are atomic waiting operations: - [(2.1)](#wait-2.1) atomic​::​wait, - [(2.2)](#wait-2.2) atomic_flag​::​wait, - [(2.3)](#wait-2.3) atomic_wait and atomic_wait_explicit, - [(2.4)](#wait-2.4) atomic_flag_wait and atomic_flag_wait_explicit, and - [(2.5)](#wait-2.5) atomic_ref​::​wait[.](#wait-2.sentence-1) — *end note*] [3](#wait-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3169) [*Note [3](#wait-note-3)*: The following functions are atomic notifying operations: - [(3.1)](#wait-3.1) atomic​::​notify_one and atomic​::​notify_all, - [(3.2)](#wait-3.2) atomic_flag​::​notify_one and atomic_flag​::​notify_all, - [(3.3)](#wait-3.3) atomic_notify_one and atomic_notify_all, - [(3.4)](#wait-3.4) atomic_flag_notify_one and atomic_flag_notify_all, and - [(3.5)](#wait-3.5) atomic_ref​::​notify_one and atomic_ref​::​notify_all[.](#wait-3.sentence-1) — *end note*] [4](#wait-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3182) A call to an atomic waiting operation on an atomic object M is [*eligible to be unblocked*](#def:eligible_to_be_unblocked "32.5.6 Waiting and notifying [atomics.wait]") by a call to an atomic notifying operation on M if there exist side effects X and Y on M such that: - [(4.1)](#wait-4.1) the atomic waiting operation has blocked after observing the result of X, - [(4.2)](#wait-4.2) X precedes Y in the modification order of M, and - [(4.3)](#wait-4.3) Y happens before the call to the atomic notifying operation[.](#wait-4.sentence-1) ### [32.5.7](#ref.generic) Class template atomic_ref [[atomics.ref.generic]](atomics.ref.generic) #### [32.5.7.1](#ref.generic.general) General [[atomics.ref.generic.general]](atomics.ref.generic.general) [🔗](#lib:atomic_ref) namespace std {template struct atomic_ref {private: T* ptr; // *exposition only*public:using value_type = remove_cv_t; static constexpr size_t required_alignment = *implementation-defined*; static constexpr bool is_always_lock_free = *implementation-defined*; bool is_lock_free() const noexcept; constexpr explicit atomic_ref(T&); constexpr atomic_ref(const atomic_ref&) noexcept; atomic_ref& operator=(const atomic_ref&) = delete; constexpr void store(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr value_type operator=(value_type) const noexcept; constexpr value_type load(memory_order = memory_order::seq_cst) const noexcept; constexpr operator value_type() const noexcept; constexpr value_type exchange(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr bool compare_exchange_weak(value_type&, value_type, memory_order, memory_order) const noexcept; constexpr bool compare_exchange_strong(value_type&, value_type, memory_order, memory_order) const noexcept; constexpr bool compare_exchange_weak(value_type&, value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr bool compare_exchange_strong(value_type&, value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr void wait(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr void notify_one() const noexcept; constexpr void notify_all() const noexcept; constexpr T* address() const noexcept; };} [1](#ref.generic.general-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3240) An atomic_ref object applies atomic operations ([[atomics.general]](#general "32.5.1 General")) to the object referenced by *ptr such that, for the lifetime ([[basic.life]](basic.life "6.8.4 Lifetime")) of the atomic_ref object, the object referenced by *ptr is an atomic object ([[intro.races]](intro.races "6.10.2.2 Data races"))[.](#ref.generic.general-1.sentence-1) [2](#ref.generic.general-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3246) The program is ill-formed if is_trivially_copyable_v is false[.](#ref.generic.general-2.sentence-1) [3](#ref.generic.general-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3249) The lifetime ([[basic.life]](basic.life "6.8.4 Lifetime")) of an object referenced by *ptr shall exceed the lifetime of all atomic_refs that reference the object[.](#ref.generic.general-3.sentence-1) While any atomic_ref instances exist that reference the *ptr object, all accesses to that object shall exclusively occur through those atomic_ref instances[.](#ref.generic.general-3.sentence-2) No subobject of the object referenced by atomic_ref shall be concurrently referenced by any other atomic_ref object[.](#ref.generic.general-3.sentence-3) [4](#ref.generic.general-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3259) Atomic operations applied to an object through a referencing atomic_ref are atomic with respect to atomic operations applied through any other atomic_ref referencing the same object[.](#ref.generic.general-4.sentence-1) [*Note [1](#ref.generic.general-note-1)*: Atomic operations or the atomic_ref constructor can acquire a shared resource, such as a lock associated with the referenced object, to enable atomic operations to be applied to the referenced object[.](#ref.generic.general-4.sentence-2) — *end note*] [5](#ref.generic.general-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3270) The program is ill-formed if is_always_lock_free is false andis_volatile_v is true[.](#ref.generic.general-5.sentence-1) #### [32.5.7.2](#ref.ops) Operations [[atomics.ref.ops]](atomics.ref.ops) [🔗](#lib:required_alignment,atomic_ref) `static constexpr size_t required_alignment; ` [1](#ref.ops-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3286) The alignment required for an object to be referenced by an atomic reference, which is at least alignof(T)[.](#ref.ops-1.sentence-1) [2](#ref.ops-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3290) [*Note [1](#ref.ops-note-1)*: Hardware could require an object referenced by an atomic_ref to have stricter alignment ([[basic.align]](basic.align "6.8.3 Alignment")) than other objects of type T[.](#ref.ops-2.sentence-1) Further, whether operations on an atomic_ref are lock-free could depend on the alignment of the referenced object[.](#ref.ops-2.sentence-2) For example, lock-free operations on std​::​complex could be supported only if aligned to 2*alignof(double)[.](#ref.ops-2.sentence-3) — *end note*] [🔗](#lib:is_always_lock_free,atomic_ref) `static constexpr bool is_always_lock_free; ` [3](#ref.ops-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3312) The static data member is_always_lock_free is true if the atomic_ref type's operations are always lock-free, and false otherwise[.](#ref.ops-3.sentence-1) [🔗](#lib:is_lock_free,atomic_ref) `bool is_lock_free() const noexcept; ` [4](#ref.ops-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3327) *Returns*: true if operations on all objects of the type atomic_ref are lock-free,false otherwise[.](#ref.ops-4.sentence-1) [🔗](#lib:atomic_ref,constructor) `constexpr atomic_ref(T& obj); ` [5](#ref.ops-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3343) *Preconditions*: The referenced object is aligned to required_alignment[.](#ref.ops-5.sentence-1) [6](#ref.ops-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3347) *Postconditions*: *this references obj[.](#ref.ops-6.sentence-1) [7](#ref.ops-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3351) *Throws*: Nothing[.](#ref.ops-7.sentence-1) [🔗](#lib:atomic_ref,constructor_) `constexpr atomic_ref(const atomic_ref& ref) noexcept; ` [8](#ref.ops-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3365) *Postconditions*: *this references the object referenced by ref[.](#ref.ops-8.sentence-1) [🔗](#lib:store,atomic_ref) `constexpr void store(value_type desired, memory_order order = memory_order::seq_cst) const noexcept; ` [9](#ref.ops-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3380) *Constraints*: is_const_v is false[.](#ref.ops-9.sentence-1) [10](#ref.ops-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3384) *Preconditions*: order ismemory_order​::​relaxed,memory_order​::​release, ormemory_order​::​seq_cst[.](#ref.ops-10.sentence-1) [11](#ref.ops-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3391) *Effects*: Atomically replaces the value referenced by *ptr with the value of desired[.](#ref.ops-11.sentence-1) Memory is affected according to the value of order[.](#ref.ops-11.sentence-2) [🔗](#lib:operator=,atomic_ref) `constexpr value_type operator=(value_type desired) const noexcept; ` [12](#ref.ops-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3407) *Constraints*: is_const_v is false[.](#ref.ops-12.sentence-1) [13](#ref.ops-13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3411) *Effects*: Equivalent to:store(desired);return desired; [🔗](#lib:load,atomic_ref) `constexpr value_type load(memory_order order = memory_order::seq_cst) const noexcept; ` [14](#ref.ops-14) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3429) *Preconditions*: order ismemory_order​::​relaxed,memory_order​::​acquire, ormemory_order​::​seq_cst[.](#ref.ops-14.sentence-1) [15](#ref.ops-15) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3436) *Effects*: Memory is affected according to the value of order[.](#ref.ops-15.sentence-1) [16](#ref.ops-16) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3440) *Returns*: Atomically returns the value referenced by *ptr[.](#ref.ops-16.sentence-1) [🔗](#lib:operator_type,atomic_ref) `constexpr operator value_type() const noexcept; ` [17](#ref.ops-17) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3454) *Effects*: Equivalent to: return load(); [🔗](#lib:exchange,atomic_ref) `constexpr value_type exchange(value_type desired, memory_order order = memory_order::seq_cst) const noexcept; ` [18](#ref.ops-18) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3469) *Constraints*: is_const_v is false[.](#ref.ops-18.sentence-1) [19](#ref.ops-19) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3473) *Effects*: Atomically replaces the value referenced by *ptr with desired[.](#ref.ops-19.sentence-1) Memory is affected according to the value of order[.](#ref.ops-19.sentence-2) This operation is an atomic read-modify-write operation ([[intro.multithread]](intro.multithread "6.10.2 Multi-threaded executions and data races"))[.](#ref.ops-19.sentence-3) [20](#ref.ops-20) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3480) *Returns*: Atomically returns the value referenced by *ptr immediately before the effects[.](#ref.ops-20.sentence-1) [🔗](#lib:compare_exchange_weak,atomic_ref) `constexpr bool compare_exchange_weak(value_type& expected, value_type desired, memory_order success, memory_order failure) const noexcept; constexpr bool compare_exchange_strong(value_type& expected, value_type desired, memory_order success, memory_order failure) const noexcept; constexpr bool compare_exchange_weak(value_type& expected, value_type desired, memory_order order = memory_order::seq_cst) const noexcept; constexpr bool compare_exchange_strong(value_type& expected, value_type desired, memory_order order = memory_order::seq_cst) const noexcept; ` [21](#ref.ops-21) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3509) *Constraints*: is_const_v is false[.](#ref.ops-21.sentence-1) [22](#ref.ops-22) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3513) *Preconditions*: failure ismemory_order​::​relaxed,memory_order​::​acquire, ormemory_order​::​seq_cst[.](#ref.ops-22.sentence-1) [23](#ref.ops-23) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3520) *Effects*: Retrieves the value in expected[.](#ref.ops-23.sentence-1) It then atomically compares the value representation of the value referenced by *ptr for equality with that previously retrieved from expected, and if true, replaces the value referenced by *ptr with that in desired[.](#ref.ops-23.sentence-2) If and only if the comparison is true, memory is affected according to the value of success, and if the comparison is false, memory is affected according to the value of failure[.](#ref.ops-23.sentence-3) When only one memory_order argument is supplied, the value of success is order, and the value of failure is order except that a value of memory_order​::​acq_rel shall be replaced by the value memory_order​::​acquire and a value of memory_order​::​release shall be replaced by the value memory_order​::​relaxed[.](#ref.ops-23.sentence-4) If and only if the comparison is false then, after the atomic operation, the value in expected is replaced by the value read from the value referenced by *ptr during the atomic comparison[.](#ref.ops-23.sentence-5) If the operation returns true, these operations are atomic read-modify-write operations ([[intro.races]](intro.races "6.10.2.2 Data races")) on the value referenced by *ptr[.](#ref.ops-23.sentence-6) Otherwise, these operations are atomic load operations on that memory[.](#ref.ops-23.sentence-7) [24](#ref.ops-24) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3549) *Returns*: The result of the comparison[.](#ref.ops-24.sentence-1) [25](#ref.ops-25) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3553) *Remarks*: A weak compare-and-exchange operation may fail spuriously[.](#ref.ops-25.sentence-1) That is, even when the contents of memory referred to by expected and ptr are equal, it may return false and store back to expected the same memory contents that were originally there[.](#ref.ops-25.sentence-2) [*Note [2](#ref.ops-note-2)*: This spurious failure enables implementation of compare-and-exchange on a broader class of machines, e.g., load-locked store-conditional machines[.](#ref.ops-25.sentence-3) A consequence of spurious failure is that nearly all uses of weak compare-and-exchange will be in a loop[.](#ref.ops-25.sentence-4) When a compare-and-exchange is in a loop, the weak version will yield better performance on some platforms[.](#ref.ops-25.sentence-5) When a weak compare-and-exchange would require a loop and a strong one would not, the strong one is preferable[.](#ref.ops-25.sentence-6) — *end note*] [🔗](#lib:wait,atomic_ref%3cT%3e) `constexpr void wait(value_type old, memory_order order = memory_order::seq_cst) const noexcept; ` [26](#ref.ops-26) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3579) *Preconditions*: order ismemory_order​::​relaxed,memory_order​::​acquire, ormemory_order​::​seq_cst[.](#ref.ops-26.sentence-1) [27](#ref.ops-27) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3586) *Effects*: Repeatedly performs the following steps, in order: - [(27.1)](#ref.ops-27.1) Evaluates load(order) and compares its value representation for equality against that of old[.](#ref.ops-27.1.sentence-1) - [(27.2)](#ref.ops-27.2) If they compare unequal, returns[.](#ref.ops-27.2.sentence-1) - [(27.3)](#ref.ops-27.3) Blocks until it is unblocked by an atomic notifying operation or is unblocked spuriously[.](#ref.ops-27.3.sentence-1) [28](#ref.ops-28) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3600) *Remarks*: This function is an atomic waiting operation ([[atomics.wait]](#wait "32.5.6 Waiting and notifying")) on atomic object *ptr[.](#ref.ops-28.sentence-1) [🔗](#lib:notify_one,atomic_ref%3cT%3e) `constexpr void notify_one() const noexcept; ` [29](#ref.ops-29) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3612) *Constraints*: is_const_v is false[.](#ref.ops-29.sentence-1) [30](#ref.ops-30) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3616) *Effects*: Unblocks the execution of at least one atomic waiting operation on *ptr that is eligible to be unblocked ([[atomics.wait]](#wait "32.5.6 Waiting and notifying")) by this call, if any such atomic waiting operations exist[.](#ref.ops-30.sentence-1) [31](#ref.ops-31) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3622) *Remarks*: This function is an atomic notifying operation ([[atomics.wait]](#wait "32.5.6 Waiting and notifying")) on atomic object *ptr[.](#ref.ops-31.sentence-1) [🔗](#lib:notify_all,atomic_ref%3cT%3e) `constexpr void notify_all() const noexcept; ` [32](#ref.ops-32) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3634) *Constraints*: is_const_v is false[.](#ref.ops-32.sentence-1) [33](#ref.ops-33) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3638) *Effects*: Unblocks the execution of all atomic waiting operations on *ptr that are eligible to be unblocked ([[atomics.wait]](#wait "32.5.6 Waiting and notifying")) by this call[.](#ref.ops-33.sentence-1) [34](#ref.ops-34) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3643) *Remarks*: This function is an atomic notifying operation ([[atomics.wait]](#wait "32.5.6 Waiting and notifying")) on atomic object *ptr[.](#ref.ops-34.sentence-1) [🔗](#lib:address,atomic_ref%3cT%3e) `constexpr T* address() const noexcept; ` [35](#ref.ops-35) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3655) *Returns*: ptr[.](#ref.ops-35.sentence-1) #### [32.5.7.3](#ref.int) Specializations for integral types [[atomics.ref.int]](atomics.ref.int) [1](#ref.int-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3662) There are specializations of the atomic_ref class template for all integral types except cv bool[.](#ref.int-1.sentence-1) For each such type *integral-type*, the specialization atomic_ref<*integral-type*> provides additional atomic operations appropriate to integral types[.](#ref.int-1.sentence-2) [*Note [1](#ref.int-note-1)*: The specialization atomic_ref uses the primary template ([[atomics.ref.generic]](#ref.generic "32.5.7 Class template atomic_­ref"))[.](#ref.int-1.sentence-3) — *end note*] [2](#ref.int-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3674) The program is ill-formed if is_always_lock_free is false andis_volatile_v<*integral-type*> is true[.](#ref.int-2.sentence-1) namespace std {template<> struct atomic_ref<*integral-type*> {private:*integral-type** ptr; // *exposition only*public:using value_type = remove_cv_t<*integral-type*>; using difference_type = value_type; static constexpr size_t required_alignment = *implementation-defined*; static constexpr bool is_always_lock_free = *implementation-defined*; bool is_lock_free() const noexcept; constexpr explicit atomic_ref(*integral-type*&); constexpr atomic_ref(const atomic_ref&) noexcept; atomic_ref& operator=(const atomic_ref&) = delete; constexpr void store(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr value_type operator=(value_type) const noexcept; constexpr value_type load(memory_order = memory_order::seq_cst) const noexcept; constexpr operator value_type() const noexcept; constexpr value_type exchange(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr bool compare_exchange_weak(value_type&, value_type, memory_order, memory_order) const noexcept; constexpr bool compare_exchange_strong(value_type&, value_type, memory_order, memory_order) const noexcept; constexpr bool compare_exchange_weak(value_type&, value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr bool compare_exchange_strong(value_type&, value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_add(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_sub(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_and(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_or(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_xor(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_max(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_min(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr void store_add(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr void store_sub(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr void store_and(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr void store_or(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr void store_xor(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr void store_max(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr void store_min(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr value_type operator++(int) const noexcept; constexpr value_type operator--(int) const noexcept; constexpr value_type operator++() const noexcept; constexpr value_type operator--() const noexcept; constexpr value_type operator+=(value_type) const noexcept; constexpr value_type operator-=(value_type) const noexcept; constexpr value_type operator&=(value_type) const noexcept; constexpr value_type operator|=(value_type) const noexcept; constexpr value_type operator^=(value_type) const noexcept; constexpr void wait(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr void notify_one() const noexcept; constexpr void notify_all() const noexcept; constexpr *integral-type** address() const noexcept; };} [3](#ref.int-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3761) Descriptions are provided below only for members that differ from the primary template[.](#ref.int-3.sentence-1) [4](#ref.int-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3765) The following operations perform arithmetic computations[.](#ref.int-4.sentence-1) The correspondence among key, operator, and computation is specified in Table [155](#tab:atomic.types.int.comp "Table 155: Atomic arithmetic computations")[.](#ref.int-4.sentence-2) [🔗](#lib:fetch_add,atomic_ref%3cintegral-type%3e) `constexpr value_type fetch_key(value_type operand, memory_order order = memory_order::seq_cst) const noexcept; ` [5](#ref.int-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3783) *Constraints*: is_const_v<*integral-type*> is false[.](#ref.int-5.sentence-1) [6](#ref.int-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3787) *Effects*: Atomically replaces the value referenced by *ptr with the result of the computation applied to the value referenced by *ptr and the given operand[.](#ref.int-6.sentence-1) Memory is affected according to the value of order[.](#ref.int-6.sentence-2) These operations are atomic read-modify-write operations ([[intro.races]](intro.races "6.10.2.2 Data races"))[.](#ref.int-6.sentence-3) [7](#ref.int-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3795) *Returns*: Atomically, the value referenced by *ptr immediately before the effects[.](#ref.int-7.sentence-1) [8](#ref.int-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3800) *Remarks*: Except for fetch_max and fetch_min, for signed integer types the result is as if the object value and parameters were converted to their corresponding unsigned types, the computation performed on those types, and the result converted back to the signed type[.](#ref.int-8.sentence-1) [*Note [2](#ref.int-note-2)*: There are no undefined results arising from the computation[.](#ref.int-8.sentence-2) — *end note*] [9](#ref.int-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3812) For fetch_max and fetch_min, the maximum and minimum computation is performed as if by max and min algorithms ([[alg.min.max]](alg.min.max "26.8.9 Minimum and maximum")), respectively, with the object value and the first parameter as the arguments[.](#ref.int-9.sentence-1) [🔗](#lib:store_add,atomic_ref%3cintegral-type%3e) `constexpr void store_key(value_type operand, memory_order order = memory_order::seq_cst) const noexcept; ` [10](#ref.int-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3831) *Preconditions*: order is memory_order​::​relaxed,memory_order​::​release, ormemory_order​::​seq_cst[.](#ref.int-10.sentence-1) [11](#ref.int-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3837) *Effects*: Atomically replaces the value referenced by *ptr with the result of the computation applied to the value referenced by *ptr and the given operand[.](#ref.int-11.sentence-1) Memory is affected according to the value of order[.](#ref.int-11.sentence-2) These operations are atomic modify-write operations ([[atomics.order]](#order "32.5.4 Order and consistency"))[.](#ref.int-11.sentence-3) [12](#ref.int-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3845) *Remarks*: Except for store_max and store_min, for signed integer types, the result is as if *ptr and parameters were converted to their corresponding unsigned types, the computation performed on those types, and the result converted back to the signed type[.](#ref.int-12.sentence-1) [*Note [3](#ref.int-note-3)*: There are no undefined results arising from the computation[.](#ref.int-12.sentence-2) — *end note*] For store_max and store_min, the maximum and minimum computation is performed as if by max and min algorithms ([[alg.min.max]](alg.min.max "26.8.9 Minimum and maximum")), respectively, with *ptr and the first parameter as the arguments[.](#ref.int-12.sentence-3) [🔗](#lib:operator+=,atomic_ref%3cintegral-type%3e) `constexpr value_type operator op=(value_type operand) const noexcept; ` [13](#ref.int-13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3872) *Constraints*: is_const_v<*integral-type*> is false[.](#ref.int-13.sentence-1) [14](#ref.int-14) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3876) *Effects*: Equivalent to:return fetch_*key*(operand) *op* operand; #### [32.5.7.4](#ref.float) Specializations for floating-point types [[atomics.ref.float]](atomics.ref.float) [1](#ref.float-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3884) There are specializations of the atomic_ref class template for all floating-point types[.](#ref.float-1.sentence-1) For each such type *floating-point-type*, the specialization atomic_ref<*floating-point-type*> provides additional atomic operations appropriate to floating-point types[.](#ref.float-1.sentence-2) [2](#ref.float-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3892) The program is ill-formed if is_always_lock_free is false andis_volatile_v<*floating-point-type*> is true[.](#ref.float-2.sentence-1) namespace std {template<> struct atomic_ref<*floating-point-type*> {private:*floating-point-type** ptr; // *exposition only*public:using value_type = remove_cv_t<*floating-point-type*>; using difference_type = value_type; static constexpr size_t required_alignment = *implementation-defined*; static constexpr bool is_always_lock_free = *implementation-defined*; bool is_lock_free() const noexcept; constexpr explicit atomic_ref(*floating-point-type*&); constexpr atomic_ref(const atomic_ref&) noexcept; atomic_ref& operator=(const atomic_ref&) = delete; constexpr void store(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr value_type operator=(value_type) const noexcept; constexpr value_type load(memory_order = memory_order::seq_cst) const noexcept; constexpr operator value_type() const noexcept; constexpr value_type exchange(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr bool compare_exchange_weak(value_type&, value_type, memory_order, memory_order) const noexcept; constexpr bool compare_exchange_strong(value_type&, value_type, memory_order, memory_order) const noexcept; constexpr bool compare_exchange_weak(value_type&, value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr bool compare_exchange_strong(value_type&, value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_add(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_sub(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_max(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_min(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_fmaximum(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_fminimum(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_fmaximum_num(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_fminimum_num(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr void store_add(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr void store_sub(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr void store_max(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr void store_min(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr void store_fmaximum(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr void store_fminimum(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr void store_fmaximum_num(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr void store_fminimum_num(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr value_type operator+=(value_type) const noexcept; constexpr value_type operator-=(value_type) const noexcept; constexpr void wait(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr void notify_one() const noexcept; constexpr void notify_all() const noexcept; constexpr *floating-point-type** address() const noexcept; };} [3](#ref.float-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3975) Descriptions are provided below only for members that differ from the primary template[.](#ref.float-3.sentence-1) [4](#ref.float-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3979) The following operations perform arithmetic computations[.](#ref.float-4.sentence-1) The correspondence among key, operator, and computation is specified in Table [155](#tab:atomic.types.int.comp "Table 155: Atomic arithmetic computations"), except for the keysmax,min,fmaximum,fminimum,fmaximum_num, andfminimum_num, which are specified below[.](#ref.float-4.sentence-2) [🔗](#lib:fetch_add,atomic_ref%3cfloating-point-type%3e) `constexpr value_type fetch_key(value_type operand, memory_order order = memory_order::seq_cst) const noexcept; ` [5](#ref.float-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4006) *Constraints*: is_const_v<*floating-point-type*> is false[.](#ref.float-5.sentence-1) [6](#ref.float-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4010) *Effects*: Atomically replaces the value referenced by *ptr with the result of the computation applied to the value referenced by *ptr and the given operand[.](#ref.float-6.sentence-1) Memory is affected according to the value of order[.](#ref.float-6.sentence-2) These operations are atomic read-modify-write operations ([[intro.races]](intro.races "6.10.2.2 Data races"))[.](#ref.float-6.sentence-3) [7](#ref.float-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4018) *Returns*: Atomically, the value referenced by *ptr immediately before the effects[.](#ref.float-7.sentence-1) [8](#ref.float-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4023) *Remarks*: If the result is not a representable value for its type ([[expr.pre]](expr.pre "7.1 Preamble")), the result is unspecified, but the operations otherwise have no undefined behavior[.](#ref.float-8.sentence-1) Atomic arithmetic operations on *floating-point-type* should conform to the std​::​numeric_limits traits associated with the floating-point type ([[limits.syn]](limits.syn "17.3.3 Header synopsis"))[.](#ref.float-8.sentence-2) The floating-point environment ([[cfenv]](cfenv "29.3 The floating-point environment")) for atomic arithmetic operations on *floating-​point-type* may be different than the calling thread's floating-point environment[.](#ref.float-8.sentence-3) [9](#ref.float-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4035) - [(9.1)](#ref.float-9.1) For fetch_fmaximum and fetch_fminimum, the maximum and minimum computation is performed as if by fmaximum and fminimum, respectively, with *ptr and the first parameter as the arguments[.](#ref.float-9.1.sentence-1) - [(9.2)](#ref.float-9.2) For fetch_fmaximum_num and fetch_fminimum_num, the maximum and minimum computation is performed as if by fmaximum_num and fminimum_num, respectively, with *ptr and the first parameter as the arguments[.](#ref.float-9.2.sentence-1) - [(9.3)](#ref.float-9.3) For fetch_max and fetch_min, the maximum and minimum computation is performed as if by fmaximum_num and fminimum_num, respectively, with *ptr and the first parameter as the arguments, except that: * [(9.3.1)](#ref.float-9.3.1) If both arguments are NaN, an unspecified NaN value is stored at *ptr[.](#ref.float-9.3.1.sentence-1) * [(9.3.2)](#ref.float-9.3.2) If exactly one argument is a NaN, either the other argument or an unspecified NaN value is stored at *ptr; it is unspecified which[.](#ref.float-9.3.2.sentence-1) * [(9.3.3)](#ref.float-9.3.3) If the arguments are differently signed zeros, which of these values is stored at *ptr is unspecified[.](#ref.float-9.3.3.sentence-1) [10](#ref.float-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4065) *Recommended practice*: The implementation of fetch_max and fetch_min should treat negative zero as smaller than positive zero[.](#ref.float-10.sentence-1) [🔗](#lib:store_add,atomic_ref%3cfloating-point-type%3e) `constexpr void store_key(value_type operand, memory_order order = memory_order::seq_cst) const noexcept; ` [11](#ref.float-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4085) *Preconditions*: order is memory_order​::​relaxed,memory_order​::​release, ormemory_order​::​seq_cst[.](#ref.float-11.sentence-1) [12](#ref.float-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4091) *Effects*: Atomically replaces the value referenced by *ptr with the result of the computation applied to the value referenced by *ptr and the given operand[.](#ref.float-12.sentence-1) Memory is affected according to the value of order[.](#ref.float-12.sentence-2) These operations are atomic modify-write operations ([[atomics.order]](#order "32.5.4 Order and consistency"))[.](#ref.float-12.sentence-3) [13](#ref.float-13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4099) *Remarks*: If the result is not a representable value for its type ([[expr.pre]](expr.pre "7.1 Preamble")), the result is unspecified, but the operations otherwise have no undefined behavior[.](#ref.float-13.sentence-1) Atomic arithmetic operations on *floating-point-type* should conform to the numeric_limits<*floating-point-type*> traits associated with the floating-point type ([[limits.syn]](limits.syn "17.3.3 Header synopsis"))[.](#ref.float-13.sentence-2) The floating-point environment ([[cfenv]](cfenv "29.3 The floating-point environment")) for atomic arithmetic operations on *floating-point-type* may be different than the calling thread's floating-point environment[.](#ref.float-13.sentence-3) The arithmetic rules of floating-point atomic modify-write operations may be different from operations on floating-point types or atomic floating-point types[.](#ref.float-13.sentence-4) [*Note [1](#ref.float-note-1)*: Tree reductions are permitted for atomic modify-write operations[.](#ref.float-13.sentence-5) — *end note*] [14](#ref.float-14) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4117) - [(14.1)](#ref.float-14.1) For store_fmaximum and store_fminimum, the maximum and minimum computation is performed as if by fmaximum and fminimum, respectively, with *ptr and the first parameter as the arguments[.](#ref.float-14.1.sentence-1) - [(14.2)](#ref.float-14.2) For store_fmaximum_num and store_fminimum_num, the maximum and minimum computation is performed as if by fmaximum_num and fminimum_num, respectively, with *ptr and the first parameter as the arguments[.](#ref.float-14.2.sentence-1) - [(14.3)](#ref.float-14.3) For store_max and store_min, the maximum and minimum computation is performed as if by fmaximum_num and fminimum_num, respectively, with *ptr and the first parameter as the arguments, except that: * [(14.3.1)](#ref.float-14.3.1) If both arguments are NaN, an unspecified NaN value is stored at *ptr[.](#ref.float-14.3.1.sentence-1) * [(14.3.2)](#ref.float-14.3.2) If exactly one argument is a NaN, either the other argument or an unspecified NaN value is stored at *ptr, it is unspecified which[.](#ref.float-14.3.2.sentence-1) * [(14.3.3)](#ref.float-14.3.3) If the arguments are differently signed zeros, which of these values is stored at *ptr is unspecified[.](#ref.float-14.3.3.sentence-1) [15](#ref.float-15) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4147) *Recommended practice*: The implementation of store_max and store_min should treat negative zero as smaller than positive zero[.](#ref.float-15.sentence-1) [🔗](#lib:operator+=,atomic_ref%3cfloating-point-type%3e) `constexpr value_type operator op=(value_type operand) const noexcept; ` [16](#ref.float-16) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4160) *Constraints*: is_const_v<*floating-point-type*> is false[.](#ref.float-16.sentence-1) [17](#ref.float-17) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4164) *Effects*: Equivalent to:return fetch_*key*(operand) *op* operand; #### [32.5.7.5](#ref.pointer) Specialization for pointers [[atomics.ref.pointer]](atomics.ref.pointer) [1](#ref.pointer-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4173) There are specializations of the atomic_ref class template for all pointer-to-object types[.](#ref.pointer-1.sentence-1) For each such type *pointer-type*, the specialization atomic_ref<*pointer-type*> provides additional atomic operations appropriate to pointer types[.](#ref.pointer-1.sentence-2) [2](#ref.pointer-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4180) The program is ill-formed if is_always_lock_free is false andis_volatile_v<*pointer-type*> is true[.](#ref.pointer-2.sentence-1) namespace std {template<> struct atomic_ref<*pointer-type*> {private:*pointer-type** ptr; // *exposition only*public:using value_type = remove_cv_t<*pointer-type*>; using difference_type = ptrdiff_t; static constexpr size_t required_alignment = *implementation-defined*; static constexpr bool is_always_lock_free = *implementation-defined*; bool is_lock_free() const noexcept; constexpr explicit atomic_ref(*pointer-type*&); constexpr atomic_ref(const atomic_ref&) noexcept; atomic_ref& operator=(const atomic_ref&) = delete; constexpr void store(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr value_type operator=(value_type) const noexcept; constexpr value_type load(memory_order = memory_order::seq_cst) const noexcept; constexpr operator value_type() const noexcept; constexpr value_type exchange(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr bool compare_exchange_weak(value_type&, value_type, memory_order, memory_order) const noexcept; constexpr bool compare_exchange_strong(value_type&, value_type, memory_order, memory_order) const noexcept; constexpr bool compare_exchange_weak(value_type&, value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr bool compare_exchange_strong(value_type&, value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_add(difference_type, memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_sub(difference_type, memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_max(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_min(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr void store_add(difference_type, memory_order = memory_order::seq_cst) const noexcept; constexpr void store_sub(difference_type, memory_order = memory_order::seq_cst) const noexcept; constexpr void store_max(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr void store_min(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr value_type operator++(int) const noexcept; constexpr value_type operator--(int) const noexcept; constexpr value_type operator++() const noexcept; constexpr value_type operator--() const noexcept; constexpr value_type operator+=(difference_type) const noexcept; constexpr value_type operator-=(difference_type) const noexcept; constexpr void wait(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr void notify_one() const noexcept; constexpr void notify_all() const noexcept; constexpr *pointer-type** address() const noexcept; };} [3](#ref.pointer-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4252) Descriptions are provided below only for members that differ from the primary template[.](#ref.pointer-3.sentence-1) [4](#ref.pointer-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4256) The following operations perform arithmetic computations[.](#ref.pointer-4.sentence-1) The correspondence among key, operator, and computation is specified in Table [156](#tab:atomic.types.pointer.comp "Table 156: Atomic pointer computations")[.](#ref.pointer-4.sentence-2) [🔗](#lib:fetch_add,atomic_ref%3cpointer-type%3e) `constexpr value_type fetch_key(difference_type operand, memory_order order = memory_order::seq_cst) const noexcept; ` [5](#ref.pointer-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4271) *Constraints*: is_const_v<*pointer-type*> is false[.](#ref.pointer-5.sentence-1) [6](#ref.pointer-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4275) *Mandates*: remove_pointer_t<*pointer-type*> is a complete object type[.](#ref.pointer-6.sentence-1) [7](#ref.pointer-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4279) *Effects*: Atomically replaces the value referenced by *ptr with the result of the computation applied to the value referenced by *ptr and the given operand[.](#ref.pointer-7.sentence-1) Memory is affected according to the value of order[.](#ref.pointer-7.sentence-2) These operations are atomic read-modify-write operations ([[intro.races]](intro.races "6.10.2.2 Data races"))[.](#ref.pointer-7.sentence-3) [8](#ref.pointer-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4287) *Returns*: Atomically, the value referenced by *ptr immediately before the effects[.](#ref.pointer-8.sentence-1) [9](#ref.pointer-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4292) *Remarks*: The result may be an undefined address, but the operations otherwise have no undefined behavior[.](#ref.pointer-9.sentence-1) [10](#ref.pointer-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4297) For fetch_max and fetch_min, the maximum and minimum computation is performed as if by max and min algorithms ([[alg.min.max]](alg.min.max "26.8.9 Minimum and maximum")), respectively, with the object value and the first parameter as the arguments[.](#ref.pointer-10.sentence-1) [*Note [1](#ref.pointer-note-1)*: If the pointers point to different complete objects (or subobjects thereof), the < operator does not establish a strict weak ordering (Table [29](utility.arg.requirements#tab:cpp17.lessthancomparable "Table 29: Cpp17LessThanComparable requirements"), [[expr.rel]](expr.rel "7.6.9 Relational operators"))[.](#ref.pointer-10.sentence-2) — *end note*] [🔗](#lib:store_add,atomic_ref%3cpointer-type%3e) `constexpr void store_key(see above operand, memory_order order = memory_order::seq_cst) const noexcept; ` [11](#ref.pointer-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4320) *Mandates*: T is a complete object type[.](#ref.pointer-11.sentence-1) [12](#ref.pointer-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4324) *Preconditions*: order is memory_order​::​relaxed,memory_order​::​release, ormemory_order​::​seq_cst[.](#ref.pointer-12.sentence-1) [13](#ref.pointer-13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4330) *Effects*: Atomically replaces the value referenced by *ptr with the result of the computation applied to the value referenced by *ptr and the given operand[.](#ref.pointer-13.sentence-1) Memory is affected according to the value of order[.](#ref.pointer-13.sentence-2) These operations are atomic modify-write operations ([[atomics.order]](#order "32.5.4 Order and consistency"))[.](#ref.pointer-13.sentence-3) [14](#ref.pointer-14) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4338) *Remarks*: The result may be an undefined address, but the operations otherwise have no undefined behavior[.](#ref.pointer-14.sentence-1) For store_max and store_min, the maximum and minimum computation is performed as if by max and min algorithms ([[alg.min.max]](alg.min.max "26.8.9 Minimum and maximum")), respectively, with *ptr and the first parameter as the arguments[.](#ref.pointer-14.sentence-2) [*Note [2](#ref.pointer-note-2)*: If the pointers point to different complete objects (or subobjects thereof), the < operator does not establish a strict weak ordering (Table [29](utility.arg.requirements#tab:cpp17.lessthancomparable "Table 29: Cpp17LessThanComparable requirements"), [[expr.rel]](expr.rel "7.6.9 Relational operators"))[.](#ref.pointer-14.sentence-3) — *end note*] [🔗](#lib:operator+=,atomic_ref%3cpointer-type%3e) `constexpr value_type operator op=(difference_type operand) const noexcept; ` [15](#ref.pointer-15) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4360) *Constraints*: is_const_v<*pointer-type*> is false[.](#ref.pointer-15.sentence-1) [16](#ref.pointer-16) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4364) *Effects*: Equivalent to:return fetch_*key*(operand) *op* operand; #### [32.5.7.6](#ref.memop) Member operators common to integers and pointers to objects [[atomics.ref.memop]](atomics.ref.memop) [1](#ref.memop-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4373) Let *referred-type* be *pointer-type* for the specializations in [[atomics.ref.pointer]](#ref.pointer "32.5.7.5 Specialization for pointers") and be *integral-type* for the specializations in [[atomics.ref.int]](#ref.int "32.5.7.3 Specializations for integral types")[.](#ref.memop-1.sentence-1) [🔗](#lib:operator++,atomic_ref%3cpointer-type%3e) `constexpr value_type operator++(int) const noexcept; ` [2](#ref.memop-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4388) *Constraints*: is_const_v<*referred-type*> is false[.](#ref.memop-2.sentence-1) [3](#ref.memop-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4392) *Effects*: Equivalent to: return fetch_add(1); [🔗](#lib:operator--,atomic_ref%3cpointer-type%3e) `constexpr value_type operator--(int) const noexcept; ` [4](#ref.memop-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4404) *Constraints*: is_const_v<*referred-type*> is false[.](#ref.memop-4.sentence-1) [5](#ref.memop-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4408) *Effects*: Equivalent to: return fetch_sub(1); [🔗](#lib:operator++,atomic_ref%3cpointer-type%3e_) `constexpr value_type operator++() const noexcept; ` [6](#ref.memop-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4420) *Constraints*: is_const_v<*referred-type*> is false[.](#ref.memop-6.sentence-1) [7](#ref.memop-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4424) *Effects*: Equivalent to: return fetch_add(1) + 1; [🔗](#lib:operator--,atomic_ref%3cpointer-type%3e_) `constexpr value_type operator--() const noexcept; ` [8](#ref.memop-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4436) *Constraints*: is_const_v<*referred-type*> is false[.](#ref.memop-8.sentence-1) [9](#ref.memop-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4440) *Effects*: Equivalent to: return fetch_sub(1) - 1; ### [32.5.8](#types.generic) Class template atomic [[atomics.types.generic]](atomics.types.generic) #### [32.5.8.1](#types.generic.general) General [[atomics.types.generic.general]](atomics.types.generic.general) [🔗](#lib:atomic) namespace std {template struct atomic {using value_type = T; static constexpr bool is_always_lock_free = *implementation-defined*; bool is_lock_free() const volatile noexcept; bool is_lock_free() const noexcept; // [[atomics.types.operations]](#types.operations "32.5.8.2 Operations on atomic types"), operations on atomic typesconstexpr atomic() noexcept(is_nothrow_default_constructible_v); constexpr atomic(T) noexcept; atomic(const atomic&) = delete; atomic& operator=(const atomic&) = delete; atomic& operator=(const atomic&) volatile = delete; T load(memory_order = memory_order::seq_cst) const volatile noexcept; constexpr T load(memory_order = memory_order::seq_cst) const noexcept; operator T() const volatile noexcept; constexpr operator T() const noexcept; void store(T, memory_order = memory_order::seq_cst) volatile noexcept; constexpr void store(T, memory_order = memory_order::seq_cst) noexcept; T operator=(T) volatile noexcept; constexpr T operator=(T) noexcept; T exchange(T, memory_order = memory_order::seq_cst) volatile noexcept; constexpr T exchange(T, memory_order = memory_order::seq_cst) noexcept; bool compare_exchange_weak(T&, T, memory_order, memory_order) volatile noexcept; constexpr bool compare_exchange_weak(T&, T, memory_order, memory_order) noexcept; bool compare_exchange_strong(T&, T, memory_order, memory_order) volatile noexcept; constexpr bool compare_exchange_strong(T&, T, memory_order, memory_order) noexcept; bool compare_exchange_weak(T&, T, memory_order = memory_order::seq_cst) volatile noexcept; constexpr bool compare_exchange_weak(T&, T, memory_order = memory_order::seq_cst) noexcept; bool compare_exchange_strong(T&, T, memory_order = memory_order::seq_cst) volatile noexcept; constexpr bool compare_exchange_strong(T&, T, memory_order = memory_order::seq_cst) noexcept; void wait(T, memory_order = memory_order::seq_cst) const volatile noexcept; constexpr void wait(T, memory_order = memory_order::seq_cst) const noexcept; void notify_one() volatile noexcept; constexpr void notify_one() noexcept; void notify_all() volatile noexcept; constexpr void notify_all() noexcept; };} [1](#types.generic.general-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4498) The template argument for T shall meet the[*Cpp17CopyConstructible*](utility.arg.requirements#:Cpp17CopyConstructible "16.4.4.2 Template argument requirements [utility.arg.requirements]") and [*Cpp17CopyAssignable*](utility.arg.requirements#:Cpp17CopyAssignable "16.4.4.2 Template argument requirements [utility.arg.requirements]") requirements[.](#types.generic.general-1.sentence-1) The program is ill-formed if any of - [(1.1)](#types.generic.general-1.1) is_trivially_copyable_v, - [(1.2)](#types.generic.general-1.2) is_copy_constructible_v, - [(1.3)](#types.generic.general-1.3) is_move_constructible_v, - [(1.4)](#types.generic.general-1.4) is_copy_assignable_v, - [(1.5)](#types.generic.general-1.5) is_move_assignable_v, or - [(1.6)](#types.generic.general-1.6) same_as>, is false[.](#types.generic.general-1.sentence-2) [*Note [1](#types.generic.general-note-1)*: Type arguments that are not also statically initializable can be difficult to use[.](#types.generic.general-1.sentence-3) — *end note*] [2](#types.generic.general-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4516) The specialization atomic is a standard-layout struct[.](#types.generic.general-2.sentence-1) It has a trivial destructor[.](#types.generic.general-2.sentence-2) [3](#types.generic.general-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4520) [*Note [2](#types.generic.general-note-2)*: The representation of an atomic specialization need not have the same size and alignment requirement as its corresponding argument type[.](#types.generic.general-3.sentence-1) — *end note*] #### [32.5.8.2](#types.operations) Operations on atomic types [[atomics.types.operations]](atomics.types.operations) [🔗](#lib:atomic,constructor) `constexpr atomic() noexcept(is_nothrow_default_constructible_v); ` [1](#types.operations-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4538) *Constraints*: is_default_constructible_v is true[.](#types.operations-1.sentence-1) [2](#types.operations-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4542) *Effects*: Initializes the atomic object with the value of T()[.](#types.operations-2.sentence-1) Initialization is not an atomic operation ([[intro.multithread]](intro.multithread "6.10.2 Multi-threaded executions and data races"))[.](#types.operations-2.sentence-2) [🔗](#lib:atomic,constructor_) `constexpr atomic(T desired) noexcept; ` [3](#types.operations-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4557) *Effects*: Initializes the object with the value desired[.](#types.operations-3.sentence-1) Initialization is not an atomic operation ([[intro.multithread]](intro.multithread "6.10.2 Multi-threaded executions and data races"))[.](#types.operations-3.sentence-2) [*Note [1](#types.operations-note-1)*: It is possible to have an access to an atomic object A race with its construction, for example by communicating the address of the just-constructed object A to another thread viamemory_order​::​relaxed operations on a suitable atomic pointer variable, and then immediately accessing A in the receiving thread[.](#types.operations-3.sentence-3) This results in undefined behavior[.](#types.operations-3.sentence-4) — *end note*] [🔗](#lib:is_always_lock_free,atomic) `static constexpr bool is_always_lock_free = implementation-defined; ` [4](#types.operations-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4582) The static data member is_always_lock_free is true if the atomic type's operations are always lock-free, and false otherwise[.](#types.operations-4.sentence-1) [*Note [2](#types.operations-note-2)*: The value of is_always_lock_free is consistent with the value of the corresponding ATOMIC_..._LOCK_FREE macro, if defined[.](#types.operations-4.sentence-2) — *end note*] [🔗](#lib:atomic_is_lock_free) `bool is_lock_free() const volatile noexcept; bool is_lock_free() const noexcept; ` [5](#types.operations-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4604) *Returns*: true if the object's operations are lock-free, false otherwise[.](#types.operations-5.sentence-1) [*Note [3](#types.operations-note-3)*: The return value of the is_lock_free member function is consistent with the value of is_always_lock_free for the same type[.](#types.operations-5.sentence-2) — *end note*] [🔗](#lib:atomic_store) `void store(T desired, memory_order order = memory_order::seq_cst) volatile noexcept; constexpr void store(T desired, memory_order order = memory_order::seq_cst) noexcept; ` [6](#types.operations-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4625) *Constraints*: For the volatile overload of this function,is_always_lock_free is true[.](#types.operations-6.sentence-1) [7](#types.operations-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4630) *Preconditions*: order ismemory_order​::​relaxed,memory_order​::​release, ormemory_order​::​seq_cst[.](#types.operations-7.sentence-1) [8](#types.operations-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4637) *Effects*: Atomically replaces the value pointed to by this with the value of desired[.](#types.operations-8.sentence-1) Memory is affected according to the value oforder[.](#types.operations-8.sentence-2) [🔗](#lib:operator=,atomic) `T operator=(T desired) volatile noexcept; constexpr T operator=(T desired) noexcept; ` [9](#types.operations-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4654) *Constraints*: For the volatile overload of this function,is_always_lock_free is true[.](#types.operations-9.sentence-1) [10](#types.operations-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4659) *Effects*: Equivalent to store(desired)[.](#types.operations-10.sentence-1) [11](#types.operations-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4663) *Returns*: desired[.](#types.operations-11.sentence-1) [🔗](#lib:atomic_load) `T load(memory_order order = memory_order::seq_cst) const volatile noexcept; constexpr T load(memory_order order = memory_order::seq_cst) const noexcept; ` [12](#types.operations-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4680) *Constraints*: For the volatile overload of this function,is_always_lock_free is true[.](#types.operations-12.sentence-1) [13](#types.operations-13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4685) *Preconditions*: order ismemory_order​::​relaxed,memory_order​::​acquire, ormemory_order​::​seq_cst[.](#types.operations-13.sentence-1) [14](#types.operations-14) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4692) *Effects*: Memory is affected according to the value of order[.](#types.operations-14.sentence-1) [15](#types.operations-15) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4696) *Returns*: Atomically returns the value pointed to by this[.](#types.operations-15.sentence-1) [🔗](#lib:operator_type,atomic) `operator T() const volatile noexcept; constexpr operator T() const noexcept; ` [16](#types.operations-16) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4711) *Constraints*: For the volatile overload of this function,is_always_lock_free is true[.](#types.operations-16.sentence-1) [17](#types.operations-17) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4716) *Effects*: Equivalent to: return load(); [🔗](#lib:atomic_exchange) `T exchange(T desired, memory_order order = memory_order::seq_cst) volatile noexcept; constexpr T exchange(T desired, memory_order order = memory_order::seq_cst) noexcept; ` [18](#types.operations-18) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4734) *Constraints*: For the volatile overload of this function,is_always_lock_free is true[.](#types.operations-18.sentence-1) [19](#types.operations-19) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4739) *Effects*: Atomically replaces the value pointed to by this with desired[.](#types.operations-19.sentence-1) Memory is affected according to the value of order[.](#types.operations-19.sentence-2) These operations are atomic read-modify-write operations ([[intro.multithread]](intro.multithread "6.10.2 Multi-threaded executions and data races"))[.](#types.operations-19.sentence-3) [20](#types.operations-20) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4746) *Returns*: Atomically returns the value pointed to by this immediately before the effects[.](#types.operations-20.sentence-1) [🔗](#lib:atomic_compare_exchange_weak) `bool compare_exchange_weak(T& expected, T desired, memory_order success, memory_order failure) volatile noexcept; constexpr bool compare_exchange_weak(T& expected, T desired, memory_order success, memory_order failure) noexcept; bool compare_exchange_strong(T& expected, T desired, memory_order success, memory_order failure) volatile noexcept; constexpr bool compare_exchange_strong(T& expected, T desired, memory_order success, memory_order failure) noexcept; bool compare_exchange_weak(T& expected, T desired, memory_order order = memory_order::seq_cst) volatile noexcept; constexpr bool compare_exchange_weak(T& expected, T desired, memory_order order = memory_order::seq_cst) noexcept; bool compare_exchange_strong(T& expected, T desired, memory_order order = memory_order::seq_cst) volatile noexcept; constexpr bool compare_exchange_strong(T& expected, T desired, memory_order order = memory_order::seq_cst) noexcept; ` [21](#types.operations-21) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4783) *Constraints*: For the volatile overload of this function,is_always_lock_free is true[.](#types.operations-21.sentence-1) [22](#types.operations-22) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4788) *Preconditions*: failure ismemory_order​::​relaxed,memory_order​::​acquire, ormemory_order​::​seq_cst[.](#types.operations-22.sentence-1) [23](#types.operations-23) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4795) *Effects*: Retrieves the value in expected[.](#types.operations-23.sentence-1) It then atomically compares the value representation of the value pointed to by this for equality with that previously retrieved from expected, and if true, replaces the value pointed to by this with that in desired[.](#types.operations-23.sentence-2) If and only if the comparison is true, memory is affected according to the value of success, and if the comparison is false, memory is affected according to the value of failure[.](#types.operations-23.sentence-3) When only one memory_order argument is supplied, the value of success is order, and the value offailure is order except that a value of memory_order​::​acq_rel shall be replaced by the value memory_order​::​acquire and a value ofmemory_order​::​release shall be replaced by the valuememory_order​::​relaxed[.](#types.operations-23.sentence-4) If and only if the comparison is false then, after the atomic operation, the value in expected is replaced by the value pointed to by this during the atomic comparison[.](#types.operations-23.sentence-5) If the operation returns true, these operations are atomic read-modify-write operations ([[intro.multithread]](intro.multithread "6.10.2 Multi-threaded executions and data races")) on the memory pointed to by this[.](#types.operations-23.sentence-6) Otherwise, these operations are atomic load operations on that memory[.](#types.operations-23.sentence-7) [24](#types.operations-24) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4819) *Returns*: The result of the comparison[.](#types.operations-24.sentence-1) [25](#types.operations-25) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4823) [*Note [4](#types.operations-note-4)*: For example, the effect ofcompare_exchange_strong on objects without padding bits ([[basic.types.general]](basic.types.general#term.padding.bits "6.9.1 General")) isif (memcmp(this, &expected, sizeof(*this)) == 0) memcpy(this, &desired, sizeof(*this));else memcpy(&expected, this, sizeof(*this)); — *end note*] [*Example [1](#types.operations-example-1)*: The expected use of the compare-and-exchange operations is as follows[.](#types.operations-25.sentence-2) The compare-and-exchange operations will update expected when another iteration of the loop is needed[.](#types.operations-25.sentence-3) expected = current.load();do { desired = function(expected);} while (!current.compare_exchange_weak(expected, desired)); — *end example*] [*Example [2](#types.operations-example-2)*: Because the expected value is updated only on failure, code releasing the memory containing the expected value on success will work[.](#types.operations-25.sentence-4) For example, list head insertion will act atomically and would not introduce a data race in the following code:do { p->next = head; // make new list node point to the current head} while (!head.compare_exchange_weak(p->next, p)); // try to insert — *end example*] [26](#types.operations-26) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4858) Implementations should ensure that weak compare-and-exchange operations do not consistently return false unless either the atomic object has value different from expected or there are concurrent modifications to the atomic object[.](#types.operations-26.sentence-1) [27](#types.operations-27) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4864) *Remarks*: A weak compare-and-exchange operation may fail spuriously[.](#types.operations-27.sentence-1) That is, even when the contents of memory referred to by expected and this are equal, it may return false and store back to expected the same memory contents that were originally there[.](#types.operations-27.sentence-2) [*Note [5](#types.operations-note-5)*: This spurious failure enables implementation of compare-and-exchange on a broader class of machines, e.g., load-locked store-conditional machines[.](#types.operations-27.sentence-3) A consequence of spurious failure is that nearly all uses of weak compare-and-exchange will be in a loop[.](#types.operations-27.sentence-4) When a compare-and-exchange is in a loop, the weak version will yield better performance on some platforms[.](#types.operations-27.sentence-5) When a weak compare-and-exchange would require a loop and a strong one would not, the strong one is preferable[.](#types.operations-27.sentence-6) — *end note*] [28](#types.operations-28) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4881) [*Note [6](#types.operations-note-6)*: Under cases where the memcpy and memcmp semantics of the compare-and-exchange operations apply, the comparisons can fail for values that compare equal withoperator== if the value representation has trap bits or alternate representations of the same value[.](#types.operations-28.sentence-1) Notably, on implementations conforming to ISO/IEC 60559, floating-point -0.0 and +0.0 will not compare equal with memcmp but will compare equal with operator==, and NaNs with the same payload will compare equal with memcmp but will not compare equal with operator==[.](#types.operations-28.sentence-2) — *end note*] [*Note [7](#types.operations-note-7)*: Because compare-and-exchange acts on an object's value representation, padding bits that never participate in the object's value representation are ignored[.](#types.operations-28.sentence-3) As a consequence, the following code is guaranteed to avoid spurious failure:struct padded {char clank = 0x42; // Padding here.unsigned biff = 0xC0DEFEFE;}; atomic pad = {}; bool zap() { padded expected, desired{0, 0}; return pad.compare_exchange_strong(expected, desired);} — *end note*] [*Note [8](#types.operations-note-8)*: For a union with bits that participate in the value representation of some members but not others, compare-and-exchange might always fail[.](#types.operations-28.sentence-5) This is because such padding bits have an indeterminate value when they do not participate in the value representation of the active member[.](#types.operations-28.sentence-6) As a consequence, the following code is not guaranteed to ever succeed:union pony {double celestia = 0.; short luna; // padded}; atomic princesses = {}; bool party(pony desired) { pony expected; return princesses.compare_exchange_strong(expected, desired);} — *end note*] [🔗](#lib:wait,atomic) `void wait(T old, memory_order order = memory_order::seq_cst) const volatile noexcept; constexpr void wait(T old, memory_order order = memory_order::seq_cst) const noexcept; ` [29](#types.operations-29) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4942) *Preconditions*: order ismemory_order​::​relaxed,memory_order​::​acquire, ormemory_order​::​seq_cst[.](#types.operations-29.sentence-1) [30](#types.operations-30) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4949) *Effects*: Repeatedly performs the following steps, in order: - [(30.1)](#types.operations-30.1) Evaluates load(order) and compares its value representation for equality against that of old[.](#types.operations-30.1.sentence-1) - [(30.2)](#types.operations-30.2) If they compare unequal, returns[.](#types.operations-30.2.sentence-1) - [(30.3)](#types.operations-30.3) Blocks until it is unblocked by an atomic notifying operation or is unblocked spuriously[.](#types.operations-30.3.sentence-1) [31](#types.operations-31) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4963) *Remarks*: This function is an atomic waiting operation ([[atomics.wait]](#wait "32.5.6 Waiting and notifying"))[.](#types.operations-31.sentence-1) [🔗](#lib:notify_one,atomic) `void notify_one() volatile noexcept; constexpr void notify_one() noexcept; ` [32](#types.operations-32) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4978) *Effects*: Unblocks the execution of at least one atomic waiting operation that is eligible to be unblocked ([[atomics.wait]](#wait "32.5.6 Waiting and notifying")) by this call, if any such atomic waiting operations exist[.](#types.operations-32.sentence-1) [33](#types.operations-33) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4984) *Remarks*: This function is an atomic notifying operation ([[atomics.wait]](#wait "32.5.6 Waiting and notifying"))[.](#types.operations-33.sentence-1) [🔗](#lib:notify_all,atomic) `void notify_all() volatile noexcept; constexpr void notify_all() noexcept; ` [34](#types.operations-34) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4999) *Effects*: Unblocks the execution of all atomic waiting operations that are eligible to be unblocked ([[atomics.wait]](#wait "32.5.6 Waiting and notifying")) by this call[.](#types.operations-34.sentence-1) [35](#types.operations-35) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L5004) *Remarks*: This function is an atomic notifying operation ([[atomics.wait]](#wait "32.5.6 Waiting and notifying"))[.](#types.operations-35.sentence-1) #### [32.5.8.3](#types.int) Specializations for integers [[atomics.types.int]](atomics.types.int) [1](#types.int-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L5012) There are specializations of the atomic class template for the integral typeschar,signed char,unsigned char,short,unsigned short,int,unsigned int,long,unsigned long,long long,unsigned long long,char8_t,char16_t,char32_t,wchar_t, and any other types needed by the typedefs in the header [](cstdint.syn#header:%3ccstdint%3e "17.4.1 Header synopsis [cstdint.syn]")[.](#types.int-1.sentence-1) For each such type *integral-type*, the specializationatomic<*integral-type*> provides additional atomic operations appropriate to integral types[.](#types.int-1.sentence-2) [*Note [1](#types.int-note-1)*: The specialization atomic uses the primary template ([[atomics.types.generic]](#types.generic "32.5.8 Class template atomic"))[.](#types.int-1.sentence-3) — *end note*] namespace std {template<> struct atomic<*integral-type*> {using value_type = *integral-type*; using difference_type = value_type; static constexpr bool is_always_lock_free = *implementation-defined*; bool is_lock_free() const volatile noexcept; bool is_lock_free() const noexcept; constexpr atomic() noexcept; constexpr atomic(*integral-type*) noexcept; atomic(const atomic&) = delete; atomic& operator=(const atomic&) = delete; atomic& operator=(const atomic&) volatile = delete; void store(*integral-type*, memory_order = memory_order::seq_cst) volatile noexcept; constexpr void store(*integral-type*, memory_order = memory_order::seq_cst) noexcept; *integral-type* operator=(*integral-type*) volatile noexcept; constexpr *integral-type* operator=(*integral-type*) noexcept; *integral-type* load(memory_order = memory_order::seq_cst) const volatile noexcept; constexpr *integral-type* load(memory_order = memory_order::seq_cst) const noexcept; operator *integral-type*() const volatile noexcept; constexpr operator *integral-type*() const noexcept; *integral-type* exchange(*integral-type*, memory_order = memory_order::seq_cst) volatile noexcept; constexpr *integral-type* exchange(*integral-type*, memory_order = memory_order::seq_cst) noexcept; bool compare_exchange_weak(*integral-type*&, *integral-type*, memory_order, memory_order) volatile noexcept; constexpr bool compare_exchange_weak(*integral-type*&, *integral-type*, memory_order, memory_order) noexcept; bool compare_exchange_strong(*integral-type*&, *integral-type*, memory_order, memory_order) volatile noexcept; constexpr bool compare_exchange_strong(*integral-type*&, *integral-type*, memory_order, memory_order) noexcept; bool compare_exchange_weak(*integral-type*&, *integral-type*, memory_order = memory_order::seq_cst) volatile noexcept; constexpr bool compare_exchange_weak(*integral-type*&, *integral-type*, memory_order = memory_order::seq_cst) noexcept; bool compare_exchange_strong(*integral-type*&, *integral-type*, memory_order = memory_order::seq_cst) volatile noexcept; constexpr bool compare_exchange_strong(*integral-type*&, *integral-type*, memory_order = memory_order::seq_cst) noexcept; *integral-type* fetch_add(*integral-type*, memory_order = memory_order::seq_cst) volatile noexcept; constexpr *integral-type* fetch_add(*integral-type*, memory_order = memory_order::seq_cst) noexcept; *integral-type* fetch_sub(*integral-type*, memory_order = memory_order::seq_cst) volatile noexcept; constexpr *integral-type* fetch_sub(*integral-type*, memory_order = memory_order::seq_cst) noexcept; *integral-type* fetch_and(*integral-type*, memory_order = memory_order::seq_cst) volatile noexcept; constexpr *integral-type* fetch_and(*integral-type*, memory_order = memory_order::seq_cst) noexcept; *integral-type* fetch_or(*integral-type*, memory_order = memory_order::seq_cst) volatile noexcept; constexpr *integral-type* fetch_or(*integral-type*, memory_order = memory_order::seq_cst) noexcept; *integral-type* fetch_xor(*integral-type*, memory_order = memory_order::seq_cst) volatile noexcept; constexpr *integral-type* fetch_xor(*integral-type*, memory_order = memory_order::seq_cst) noexcept; *integral-type* fetch_max(*integral-type*, memory_order = memory_order::seq_cst) volatile noexcept; constexpr *integral-type* fetch_max(*integral-type*, memory_order = memory_order::seq_cst) noexcept; *integral-type* fetch_min(*integral-type*, memory_order = memory_order::seq_cst) volatile noexcept; constexpr *integral-type* fetch_min(*integral-type*, memory_order = memory_order::seq_cst) noexcept; void store_add(*integral-type*, memory_order = memory_order::seq_cst) volatile noexcept; constexpr void store_add(*integral-type*, memory_order = memory_order::seq_cst) noexcept; void store_sub(*integral-type*, memory_order = memory_order::seq_cst) volatile noexcept; constexpr void store_sub(*integral-type*, memory_order = memory_order::seq_cst) noexcept; void store_and(*integral-type*, memory_order = memory_order::seq_cst) volatile noexcept; constexpr void store_and(*integral-type*, memory_order = memory_order::seq_cst) noexcept; void store_or(*integral-type*, memory_order = memory_order::seq_cst) volatile noexcept; constexpr void store_or(*integral-type*, memory_order = memory_order::seq_cst) noexcept; void store_xor(*integral-type*, memory_order = memory_order::seq_cst) volatile noexcept; constexpr void store_xor(*integral-type*, memory_order = memory_order::seq_cst) noexcept; void store_max(*integral-type*, memory_order = memory_order::seq_cst) volatile noexcept; constexpr void store_max(*integral-type*, memory_order = memory_order::seq_cst) noexcept; void store_min(*integral-type*, memory_order = memory_order::seq_cst) volatile noexcept; constexpr void store_min(*integral-type*, memory_order = memory_order::seq_cst) noexcept; *integral-type* operator++(int) volatile noexcept; constexpr *integral-type* operator++(int) noexcept; *integral-type* operator--(int) volatile noexcept; constexpr *integral-type* operator--(int) noexcept; *integral-type* operator++() volatile noexcept; constexpr *integral-type* operator++() noexcept; *integral-type* operator--() volatile noexcept; constexpr *integral-type* operator--() noexcept; *integral-type* operator+=(*integral-type*) volatile noexcept; constexpr *integral-type* operator+=(*integral-type*) noexcept; *integral-type* operator-=(*integral-type*) volatile noexcept; constexpr *integral-type* operator-=(*integral-type*) noexcept; *integral-type* operator&=(*integral-type*) volatile noexcept; constexpr *integral-type* operator&=(*integral-type*) noexcept; *integral-type* operator|=(*integral-type*) volatile noexcept; constexpr *integral-type* operator|=(*integral-type*) noexcept; *integral-type* operator^=(*integral-type*) volatile noexcept; constexpr *integral-type* operator^=(*integral-type*) noexcept; void wait(*integral-type*, memory_order = memory_order::seq_cst) const volatile noexcept; constexpr void wait(*integral-type*, memory_order = memory_order::seq_cst) const noexcept; void notify_one() volatile noexcept; constexpr void notify_one() noexcept; void notify_all() volatile noexcept; constexpr void notify_all() noexcept; };} [2](#types.int-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L5171) The atomic integral specializations are standard-layout structs[.](#types.int-2.sentence-1) They each have a trivial destructor[.](#types.int-2.sentence-2) [3](#types.int-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L5177) Descriptions are provided below only for members that differ from the primary template[.](#types.int-3.sentence-1) [4](#types.int-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L5180) The following operations perform arithmetic computations[.](#types.int-4.sentence-1) The correspondence among key, operator, and computation is specified in Table [155](#tab:atomic.types.int.comp "Table 155: Atomic arithmetic computations")[.](#types.int-4.sentence-2) Table [155](#tab:atomic.types.int.comp) — Atomic arithmetic computations [[tab:atomic.types.int.comp]](./tab:atomic.types.int.comp) | [🔗](#tab:atomic.types.int.comp-row-1)
***key*** | **Op** | **Computation** | ***key*** | **Op** | **Computation** | | --- | --- | --- | --- | --- | --- | | [🔗](#tab:atomic.types.int.comp-row-2)
add | + | addition | and | & | bitwise and | | [🔗](#tab:atomic.types.int.comp-row-3)
sub | - | subtraction | or | | | bitwise inclusive or | | [🔗](#tab:atomic.types.int.comp-row-4)
max | | maximum | xor | ^ | bitwise exclusive or | | [🔗](#tab:atomic.types.int.comp-row-5)
min | | minimum | | | | [🔗](#lib:atomic_fetch_add) `integral-type fetch_key(integral-type operand, memory_order order = memory_order::seq_cst) volatile noexcept; constexpr integral-type fetch_key(integral-type operand, memory_order order = memory_order::seq_cst) noexcept; ` [5](#types.int-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L5246) *Constraints*: For the volatile overload of this function,is_always_lock_free is true[.](#types.int-5.sentence-1) [6](#types.int-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L5251) *Effects*: Atomically replaces the value pointed to bythis with the result of the computation applied to the value pointed to by this and the given operand[.](#types.int-6.sentence-1) Memory is affected according to the value of order[.](#types.int-6.sentence-2) These operations are atomic read-modify-write operations ([[intro.multithread]](intro.multithread "6.10.2 Multi-threaded executions and data races"))[.](#types.int-6.sentence-3) [7](#types.int-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L5259) *Returns*: Atomically, the value pointed to by this immediately before the effects[.](#types.int-7.sentence-1) [8](#types.int-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L5263) *Remarks*: Except for fetch_max and fetch_min, for signed integer types the result is as if the object value and parameters were converted to their corresponding unsigned types, the computation performed on those types, and the result converted back to the signed type[.](#types.int-8.sentence-1) [*Note [2](#types.int-note-2)*: There are no undefined results arising from the computation[.](#types.int-8.sentence-2) — *end note*] [9](#types.int-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L5275) For fetch_max and fetch_min, the maximum and minimum computation is performed as if by max and min algorithms ([[alg.min.max]](alg.min.max "26.8.9 Minimum and maximum")), respectively, with the object value and the first parameter as the arguments[.](#types.int-9.sentence-1) [🔗](#lib:atomic_store_add) `void store_key(integral-type operand, memory_order order = memory_order::seq_cst) volatile noexcept; constexpr void store_key(integral-type operand, memory_order order = memory_order::seq_cst) noexcept; ` [10](#types.int-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L5308) *Constraints*: For the volatile overload of this function,is_always_lock_free is true[.](#types.int-10.sentence-1) [11](#types.int-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L5313) *Preconditions*: order ismemory_order​::​relaxed,memory_order​::​release, ormemory_order​::​seq_cst[.](#types.int-11.sentence-1) [12](#types.int-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L5320) *Effects*: Atomically replaces the value pointed to by this with the result of the computation applied to the value pointed to by this and the given operand[.](#types.int-12.sentence-1) Memory is affected according to the value of order[.](#types.int-12.sentence-2) These operations are atomic modify-write operations ([[atomics.order]](#order "32.5.4 Order and consistency"))[.](#types.int-12.sentence-3) [13](#types.int-13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L5328) *Remarks*: Except for store_max and store_min, for signed integer types, the result is as if the value pointed to by this and parameters were converted to their corresponding unsigned types, the computation performed on those types, and the result converted back to the signed type[.](#types.int-13.sentence-1) [*Note [3](#types.int-note-3)*: There are no undefined results arising from the computation[.](#types.int-13.sentence-2) — *end note*] For store_max and store_min, the maximum and minimum computation is performed as if by max and min algorithms ([[alg.min.max]](alg.min.max "26.8.9 Minimum and maximum")), respectively, with the value pointed to by this and the first parameter as the arguments[.](#types.int-13.sentence-3) [🔗](#lib:operator+=,atomic%3cT*%3e) `integral-type operator op=(integral-type operand) volatile noexcept; constexpr integral-type operator op=(integral-type operand) noexcept; ` [14](#types.int-14) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L5358) *Constraints*: For the volatile overload of this function,is_always_lock_free is true[.](#types.int-14.sentence-1) [15](#types.int-15) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L5363) *Effects*: Equivalent to: return fetch_*key*(operand) *op* operand; #### [32.5.8.4](#types.float) Specializations for floating-point types [[atomics.types.float]](atomics.types.float) [1](#types.float-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L5371) There are specializations of the atomic class template for all cv-unqualified floating-point types[.](#types.float-1.sentence-1) For each such type *floating-point-type*, the specialization atomic<*floating-point-type*> provides additional atomic operations appropriate to floating-point types[.](#types.float-1.sentence-2) namespace std {template<> struct atomic<*floating-point-type*> {using value_type = *floating-point-type*; using difference_type = value_type; static constexpr bool is_always_lock_free = *implementation-defined*; bool is_lock_free() const volatile noexcept; bool is_lock_free() const noexcept; constexpr atomic() noexcept; constexpr atomic(*floating-point-type*) noexcept; atomic(const atomic&) = delete; atomic& operator=(const atomic&) = delete; atomic& operator=(const atomic&) volatile = delete; void store(*floating-point-type*, memory_order = memory_order::seq_cst) volatile noexcept; constexpr void store(*floating-point-type*, memory_order = memory_order::seq_cst) noexcept; *floating-point-type* operator=(*floating-point-type*) volatile noexcept; constexpr *floating-point-type* operator=(*floating-point-type*) noexcept; *floating-point-type* load(memory_order = memory_order::seq_cst) volatile noexcept; constexpr *floating-point-type* load(memory_order = memory_order::seq_cst) noexcept; operator *floating-point-type*() volatile noexcept; constexpr operator *floating-point-type*() noexcept; *floating-point-type* exchange(*floating-point-type*, memory_order = memory_order::seq_cst) volatile noexcept; constexpr *floating-point-type* exchange(*floating-point-type*, memory_order = memory_order::seq_cst) noexcept; bool compare_exchange_weak(*floating-point-type*&, *floating-point-type*, memory_order, memory_order) volatile noexcept; constexpr bool compare_exchange_weak(*floating-point-type*&, *floating-point-type*, memory_order, memory_order) noexcept; bool compare_exchange_strong(*floating-point-type*&, *floating-point-type*, memory_order, memory_order) volatile noexcept; constexpr bool compare_exchange_strong(*floating-point-type*&, *floating-point-type*, memory_order, memory_order) noexcept; bool compare_exchange_weak(*floating-point-type*&, *floating-point-type*, memory_order = memory_order::seq_cst) volatile noexcept; constexpr bool compare_exchange_weak(*floating-point-type*&, *floating-point-type*, memory_order = memory_order::seq_cst) noexcept; bool compare_exchange_strong(*floating-point-type*&, *floating-point-type*, memory_order = memory_order::seq_cst) volatile noexcept; constexpr bool compare_exchange_strong(*floating-point-type*&, *floating-point-type*, memory_order = memory_order::seq_cst) noexcept; *floating-point-type* fetch_add(*floating-point-type*, memory_order = memory_order::seq_cst) volatile noexcept; constexpr *floating-point-type* fetch_add(*floating-point-type*, memory_order = memory_order::seq_cst) noexcept; *floating-point-type* fetch_sub(*floating-point-type*, memory_order = memory_order::seq_cst) volatile noexcept; constexpr *floating-point-type* fetch_sub(*floating-point-type*, memory_order = memory_order::seq_cst) noexcept; *floating-point-type* fetch_max(*floating-point-type*, memory_order = memory_order::seq_cst) volatile noexcept; constexpr *floating-point-type* fetch_max(*floating-point-type*, memory_order = memory_order::seq_cst) noexcept; *floating-point-type* fetch_min(*floating-point-type*, memory_order = memory_order::seq_cst) volatile noexcept; constexpr *floating-poin-type*t fetch_min(*floating-point-type*, memory_order = memory_order::seq_cst) noexcept; *floating-point-type* fetch_fmaximum(*floating-point-type*, memory_order = memory_order::seq_cst) volatile noexcept; constexpr *floating-point-type* fetch_fmaximum(*floating-point-type*, memory_order = memory_order::seq_cst) noexcept; *floating-point-type* fetch_fminimum(*floating-point-type*, memory_order = memory_order::seq_cst) volatile noexcept; constexpr *floating-point-type* fetch_fminimum(*floating-point-type*, memory_order = memory_order::seq_cst) noexcept; *floating-point-type* fetch_fmaximum_num(*floating-point-type*, memory_order = memory_order::seq_cst) volatile noexcept; constexpr *floating-point-type* fetch_fmaximum_num(*floating-point-type*, memory_order = memory_order::seq_cst) noexcept; *floating-point-type* fetch_fminimum_num(*floating-point-type*, memory_order = memory_order::seq_cst) volatile noexcept; constexpr *floating-point-type* fetch_fminimum_num(*floating-point-type*, memory_order = memory_order::seq_cst) noexcept; void store_add(*floating-point-type*, memory_order = memory_order::seq_cst) volatile noexcept; constexpr void store_add(*floating-point-type*, memory_order = memory_order::seq_cst) noexcept; void store_sub(*floating-point-type*, memory_order = memory_order::seq_cst) volatile noexcept; constexpr void store_sub(*floating-point-type*, memory_order = memory_order::seq_cst) noexcept; void store_max(*floating-point-type*, memory_order = memory_order::seq_cst) volatile noexcept; constexpr void store_max(*floating-point-type*, memory_order = memory_order::seq_cst) noexcept; void store_min(*floating-point-type*, memory_order = memory_order::seq_cst) volatile noexcept; constexpr void store_min(*floating-point-type*, memory_order = memory_order::seq_cst) noexcept; void store_fmaximum(*floating-point-type*, memory_order = memory_order::seq_cst) volatile noexcept; constexpr void store_fmaximum(*floating-point-type*, memory_order = memory_order::seq_cst) noexcept; void store_fminimum(*floating-point-type*, memory_order = memory_order::seq_cst) volatile noexcept; constexpr void store_fminimum(*floating-point-type*, memory_order = memory_order::seq_cst) noexcept; void store_fmaximum_num(*floating-point-type*, memory_order = memory_order::seq_cst) volatile noexcept; constexpr void store_fmaximum_num(*floating-point-type*, memory_order = memory_order::seq_cst) noexcept; void store_fminimum_num(*floating-point-type*, memory_order = memory_order::seq_cst) volatile noexcept; constexpr void store_fminimum_num(*floating-point-type*, memory_order = memory_order::seq_cst) noexcept; *floating-point-type* operator+=(*floating-point-type*) volatile noexcept; constexpr *floating-point-type* operator+=(*floating-point-type*) noexcept; *floating-point-type* operator-=(*floating-point-type*) volatile noexcept; constexpr *floating-point-type* operator-=(*floating-point-type*) noexcept; void wait(*floating-point-type*, memory_order = memory_order::seq_cst) const volatile noexcept; constexpr void wait(*floating-point-type*, memory_order = memory_order::seq_cst) const noexcept; void notify_one() volatile noexcept; constexpr void notify_one() noexcept; void notify_all() volatile noexcept; constexpr void notify_all() noexcept; };} [2](#types.float-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L5506) The atomic floating-point specializations are standard-layout structs[.](#types.float-2.sentence-1) They each have a trivial destructor[.](#types.float-2.sentence-2) [3](#types.float-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L5512) Descriptions are provided below only for members that differ from the primary template[.](#types.float-3.sentence-1) [4](#types.float-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L5515) The following operations perform arithmetic addition and subtraction computations[.](#types.float-4.sentence-1) The correspondence among key, operator, and computation is specified in Table [155](#tab:atomic.types.int.comp "Table 155: Atomic arithmetic computations"), except for the keysmax,min,fmaximum,fminimum,fmaximum_num, andfminimum_num, which are specified below[.](#types.float-4.sentence-2) [🔗](#lib:atomic_fetch_add_) `floating-point-type fetch_key(floating-point-type operand, memory_order order = memory_order::seq_cst) volatile noexcept; constexpr floating-point-type fetch_key(floating-point-type operand, memory_order order = memory_order::seq_cst) noexcept; ` [5](#types.float-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L5548) *Constraints*: For the volatile overload of this function,is_always_lock_free is true[.](#types.float-5.sentence-1) [6](#types.float-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L5553) *Effects*: Atomically replaces the value pointed to by this with the result of the computation applied to the value pointed to by this and the given operand[.](#types.float-6.sentence-1) Memory is affected according to the value of order[.](#types.float-6.sentence-2) These operations are atomic read-modify-write operations ([[intro.multithread]](intro.multithread "6.10.2 Multi-threaded executions and data races"))[.](#types.float-6.sentence-3) [7](#types.float-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L5561) *Returns*: Atomically, the value pointed to by this immediately before the effects[.](#types.float-7.sentence-1) [8](#types.float-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L5565) *Remarks*: If the result is not a representable value for its type ([[expr.pre]](expr.pre "7.1 Preamble")) the result is unspecified, but the operations otherwise have no undefined behavior[.](#types.float-8.sentence-1) Atomic arithmetic operations on *floating-point-type* should conform to the std​::​numeric_limits<*floating-point-type*> traits associated with the floating-point type ([[limits.syn]](limits.syn "17.3.3 Header synopsis"))[.](#types.float-8.sentence-2) The floating-point environment ([[cfenv]](cfenv "29.3 The floating-point environment")) for atomic arithmetic operations on *floating-point-type* may be different than the calling thread's floating-point environment[.](#types.float-8.sentence-3) [9](#types.float-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L5576) - [(9.1)](#types.float-9.1) For fetch_fmaximum and fetch_fminimum, the maximum and minimum computation is performed as if by fmaximum and fminimum, respectively, with the value pointed to by this and the first parameter as the arguments[.](#types.float-9.1.sentence-1) - [(9.2)](#types.float-9.2) For fetch_fmaximum_num and fetch_fminimum_num, the maximum and minimum computation is performed as if by fmaximum_num and fminimum_num, respectively, with the value pointed to by this and the first parameter as the arguments[.](#types.float-9.2.sentence-1) - [(9.3)](#types.float-9.3) For fetch_max and fetch_min, the maximum and minimum computation is performed as if by fmaximum_num and fminimum_num, respectively, with the value pointed to by this and the first parameter as the arguments, except that: * [(9.3.1)](#types.float-9.3.1) If both arguments are NaN, an unspecified NaN value replaces the value pointed to by this[.](#types.float-9.3.1.sentence-1) * [(9.3.2)](#types.float-9.3.2) If exactly one argument is a NaN, either the other argument or an unspecified NaN value replaces the value pointed to by this; it is unspecified which[.](#types.float-9.3.2.sentence-1) * [(9.3.3)](#types.float-9.3.3) If the arguments are differently signed zeros, which of these values replaces the value pointed to by this is unspecified[.](#types.float-9.3.3.sentence-1) [10](#types.float-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L5610) *Recommended practice*: The implementation of fetch_max and fetch_min should treat negative zero as smaller than positive zero[.](#types.float-10.sentence-1) [🔗](#lib:store_max,atomic%3cfloating-point-type%3e) `void store_key(floating-point-type operand, memory_order order = memory_order::seq_cst) volatile noexcept; constexpr void store_key(floating-point-type operand, memory_order order = memory_order::seq_cst) noexcept; ` [11](#types.float-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L5630) *Constraints*: For the volatile overload of this function,is_always_lock_free is true[.](#types.float-11.sentence-1) [12](#types.float-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L5635) *Preconditions*: order ismemory_order​::​relaxed,memory_order​::​release, ormemory_order​::​seq_cst[.](#types.float-12.sentence-1) [13](#types.float-13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L5642) *Effects*: Atomically replaces the value pointed to by this with the result of the computation applied to the value pointed to by this and the given operand[.](#types.float-13.sentence-1) Memory is affected according to the value of order[.](#types.float-13.sentence-2) These operations are atomic modify-write operations ([[atomics.order]](#order "32.5.4 Order and consistency"))[.](#types.float-13.sentence-3) [14](#types.float-14) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L5650) *Remarks*: If the result is not a representable value for its type ([[expr.pre]](expr.pre "7.1 Preamble")) the result is unspecified, but the operations otherwise have no undefined behavior[.](#types.float-14.sentence-1) Atomic arithmetic operations on *floating-point-type* should conform to the numeric_limits<*floating-point-type*> traits associated with the floating-point type ([[limits.syn]](limits.syn "17.3.3 Header synopsis"))[.](#types.float-14.sentence-2) The floating-point environment ([[cfenv]](cfenv "29.3 The floating-point environment")) for atomic arithmetic operations on *floating-point-type* may be different than the calling thread's floating-point environment[.](#types.float-14.sentence-3) The arithmetic rules of floating-point atomic modify-write operations may be different from operations on floating-point types or atomic floating-point types[.](#types.float-14.sentence-4) [*Note [1](#types.float-note-1)*: Tree reductions are permitted for atomic modify-write operations[.](#types.float-14.sentence-5) — *end note*] [15](#types.float-15) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L5668) - [(15.1)](#types.float-15.1) For store_fmaximum and store_fminimum, the maximum and minimum computation is performed as if by fmaximum and fminimum, respectively, with the value pointed to by this and the first parameter as the arguments[.](#types.float-15.1.sentence-1) - [(15.2)](#types.float-15.2) For store_fmaximum_num and store_fminimum_num, the maximum and minimum computation is performed as if by fmaximum_num and fminimum_num, respectively, with the value pointed to by this and the first parameter as the arguments[.](#types.float-15.2.sentence-1) - [(15.3)](#types.float-15.3) For store_max and store_min, the maximum and minimum computation is performed as if by fmaximum_num and fminimum_num, respectively, with the value pointed to by this and the first parameter as the arguments, except that: * [(15.3.1)](#types.float-15.3.1) If both arguments are NaN, an unspecified NaN value replaces the value pointed to by this[.](#types.float-15.3.1.sentence-1) * [(15.3.2)](#types.float-15.3.2) If exactly one argument is a NaN, either the other argument or an unspecified NaN value replaces the value pointed to by this; it is unspecified which[.](#types.float-15.3.2.sentence-1) * [(15.3.3)](#types.float-15.3.3) If the arguments are differently signed zeros, which of these values replaces the value pointed to by this is unspecified[.](#types.float-15.3.3.sentence-1) [16](#types.float-16) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L5703) *Recommended practice*: The implementation of store_max and store_min should treat negative zero as smaller than positive zero[.](#types.float-16.sentence-1) [🔗](#lib:operator+=,atomic%3cT*%3e_) `floating-point-type operator op=(floating-point-type operand) volatile noexcept; constexpr floating-point-type operator op=(floating-point-type operand) noexcept; ` [17](#types.float-17) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L5719) *Constraints*: For the volatile overload of this function,is_always_lock_free is true[.](#types.float-17.sentence-1) [18](#types.float-18) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L5724) *Effects*: Equivalent to: return fetch_*key*(operand) *op* operand; [19](#types.float-19) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L5728) *Remarks*: If the result is not a representable value for its type ([[expr.pre]](expr.pre "7.1 Preamble")) the result is unspecified, but the operations otherwise have no undefined behavior[.](#types.float-19.sentence-1) Atomic arithmetic operations on *floating-point-type* should conform to the std​::​numeric_limits<*floating-point-type*> traits associated with the floating-point type ([[limits.syn]](limits.syn "17.3.3 Header synopsis"))[.](#types.float-19.sentence-2) The floating-point environment ([[cfenv]](cfenv "29.3 The floating-point environment")) for atomic arithmetic operations on *floating-point-type* may be different than the calling thread's floating-point environment[.](#types.float-19.sentence-3) #### [32.5.8.5](#types.pointer) Partial specialization for pointers [[atomics.types.pointer]](atomics.types.pointer) namespace std {template struct atomic {using value_type = T*; using difference_type = ptrdiff_t; static constexpr bool is_always_lock_free = *implementation-defined*; bool is_lock_free() const volatile noexcept; bool is_lock_free() const noexcept; constexpr atomic() noexcept; constexpr atomic(T*) noexcept; atomic(const atomic&) = delete; atomic& operator=(const atomic&) = delete; atomic& operator=(const atomic&) volatile = delete; void store(T*, memory_order = memory_order::seq_cst) volatile noexcept; constexpr void store(T*, memory_order = memory_order::seq_cst) noexcept; T* operator=(T*) volatile noexcept; constexpr T* operator=(T*) noexcept; T* load(memory_order = memory_order::seq_cst) const volatile noexcept; constexpr T* load(memory_order = memory_order::seq_cst) const noexcept; operator T*() const volatile noexcept; constexpr operator T*() const noexcept; T* exchange(T*, memory_order = memory_order::seq_cst) volatile noexcept; constexpr T* exchange(T*, memory_order = memory_order::seq_cst) noexcept; bool compare_exchange_weak(T*&, T*, memory_order, memory_order) volatile noexcept; constexpr bool compare_exchange_weak(T*&, T*, memory_order, memory_order) noexcept; bool compare_exchange_strong(T*&, T*, memory_order, memory_order) volatile noexcept; constexpr bool compare_exchange_strong(T*&, T*, memory_order, memory_order) noexcept; bool compare_exchange_weak(T*&, T*, memory_order = memory_order::seq_cst) volatile noexcept; constexpr bool compare_exchange_weak(T*&, T*, memory_order = memory_order::seq_cst) noexcept; bool compare_exchange_strong(T*&, T*, memory_order = memory_order::seq_cst) volatile noexcept; constexpr bool compare_exchange_strong(T*&, T*, memory_order = memory_order::seq_cst) noexcept; T* fetch_add(ptrdiff_t, memory_order = memory_order::seq_cst) volatile noexcept; constexpr T* fetch_add(ptrdiff_t, memory_order = memory_order::seq_cst) noexcept; T* fetch_sub(ptrdiff_t, memory_order = memory_order::seq_cst) volatile noexcept; constexpr T* fetch_sub(ptrdiff_t, memory_order = memory_order::seq_cst) noexcept; T* fetch_max(T*, memory_order = memory_order::seq_cst) volatile noexcept; constexpr T* fetch_max(T*, memory_order = memory_order::seq_cst) noexcept; T* fetch_min(T*, memory_order = memory_order::seq_cst) volatile noexcept; constexpr T* fetch_min(T*, memory_order = memory_order::seq_cst) noexcept; void store_add(ptrdiff_t, memory_order = memory_order::seq_cst) volatile noexcept; constexpr void store_add(ptrdiff_t, memory_order = memory_order::seq_cst) noexcept; void store_sub(ptrdiff_t, memory_order = memory_order::seq_cst) volatile noexcept; constexpr void store_sub(ptrdiff_t, memory_order = memory_order::seq_cst) noexcept; void store_max(T*, memory_order = memory_order::seq_cst) volatile noexcept; constexpr void store_max(T*, memory_order = memory_order::seq_cst) noexcept; void store_min(T*, memory_order = memory_order::seq_cst) volatile noexcept; constexpr void store_min(T*, memory_order = memory_order::seq_cst) noexcept; T* operator++(int) volatile noexcept; constexpr T* operator++(int) noexcept; T* operator--(int) volatile noexcept; constexpr T* operator--(int) noexcept; T* operator++() volatile noexcept; constexpr T* operator++() noexcept; T* operator--() volatile noexcept; constexpr T* operator--() noexcept; T* operator+=(ptrdiff_t) volatile noexcept; constexpr T* operator+=(ptrdiff_t) noexcept; T* operator-=(ptrdiff_t) volatile noexcept; constexpr T* operator-=(ptrdiff_t) noexcept; void wait(T*, memory_order = memory_order::seq_cst) const volatile noexcept; constexpr void wait(T*, memory_order = memory_order::seq_cst) const noexcept; void notify_one() volatile noexcept; constexpr void notify_one() noexcept; void notify_all() volatile noexcept; constexpr void notify_all() noexcept; };} [1](#types.pointer-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L5825) There is a partial specialization of the atomic class template for pointers[.](#types.pointer-1.sentence-1) Specializations of this partial specialization are standard-layout structs[.](#types.pointer-1.sentence-2) They each have a trivial destructor[.](#types.pointer-1.sentence-3) [2](#types.pointer-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L5830) Descriptions are provided below only for members that differ from the primary template[.](#types.pointer-2.sentence-1) [3](#types.pointer-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L5833) The following operations perform pointer arithmetic[.](#types.pointer-3.sentence-1) The correspondence among key, operator, and computation is specified in Table [156](#tab:atomic.types.pointer.comp "Table 156: Atomic pointer computations")[.](#types.pointer-3.sentence-2) Table [156](#tab:atomic.types.pointer.comp) — Atomic pointer computations [[tab:atomic.types.pointer.comp]](./tab:atomic.types.pointer.comp) | [🔗](#tab:atomic.types.pointer.comp-row-1)
***key*** | **Op** | **Computation** | ***key*** | **Op** | **Computation** | | --- | --- | --- | --- | --- | --- | | [🔗](#tab:atomic.types.pointer.comp-row-2)
add | + | addition | sub | - | subtraction | | [🔗](#tab:atomic.types.pointer.comp-row-3)
max | | maximum | min | | minimum | [🔗](#lib:atomic_fetch_add__) `T* fetch_key(ptrdiff_t operand, memory_order order = memory_order::seq_cst) volatile noexcept; constexpr T* fetch_key(ptrdiff_t operand, memory_order order = memory_order::seq_cst) noexcept; ` [4](#types.pointer-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L5879) *Constraints*: For the volatile overload of this function,is_always_lock_free is true[.](#types.pointer-4.sentence-1) [5](#types.pointer-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L5884) *Mandates*: T is a complete object type[.](#types.pointer-5.sentence-1) [*Note [1](#types.pointer-note-1)*: Pointer arithmetic on void* or function pointers is ill-formed[.](#types.pointer-5.sentence-2) — *end note*] [6](#types.pointer-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L5891) *Effects*: Atomically replaces the value pointed to bythis with the result of the computation applied to the value pointed to by this and the given operand[.](#types.pointer-6.sentence-1) Memory is affected according to the value of order[.](#types.pointer-6.sentence-2) These operations are atomic read-modify-write operations ([[intro.multithread]](intro.multithread "6.10.2 Multi-threaded executions and data races"))[.](#types.pointer-6.sentence-3) [7](#types.pointer-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L5899) *Returns*: Atomically, the value pointed to by this immediately before the effects[.](#types.pointer-7.sentence-1) [8](#types.pointer-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L5903) *Remarks*: The result may be an undefined address, but the operations otherwise have no undefined behavior[.](#types.pointer-8.sentence-1) [9](#types.pointer-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L5908) For fetch_max and fetch_min, the maximum and minimum computation is performed as if by max and min algorithms ([[alg.min.max]](alg.min.max "26.8.9 Minimum and maximum")), respectively, with the object value and the first parameter as the arguments[.](#types.pointer-9.sentence-1) [*Note [2](#types.pointer-note-2)*: If the pointers point to different complete objects (or subobjects thereof), the < operator does not establish a strict weak ordering (Table [29](utility.arg.requirements#tab:cpp17.lessthancomparable "Table 29: Cpp17LessThanComparable requirements"), [[expr.rel]](expr.rel "7.6.9 Relational operators"))[.](#types.pointer-9.sentence-2) — *end note*] [🔗](#lib:atomic_store_add_) `void store_key(see above operand, memory_order order = memory_order::seq_cst) volatile noexcept; constexpr void store_key(see above operand, memory_order order = memory_order::seq_cst) noexcept; ` [10](#types.pointer-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L5939) *Constraints*: For the volatile overload of this function,is_always_lock_free is true[.](#types.pointer-10.sentence-1) [11](#types.pointer-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L5944) *Mandates*: T is a complete object type[.](#types.pointer-11.sentence-1) [*Note [3](#types.pointer-note-3)*: Pointer arithmetic on void* or function pointers is ill-formed[.](#types.pointer-11.sentence-2) — *end note*] [12](#types.pointer-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L5951) *Effects*: Atomically replaces the value pointed to by this with the result of the computation applied to the value pointed to by this and the given operand[.](#types.pointer-12.sentence-1) Memory is affected according to the value of order[.](#types.pointer-12.sentence-2) These operations are atomic modify-write operations ([[atomics.order]](#order "32.5.4 Order and consistency"))[.](#types.pointer-12.sentence-3) [13](#types.pointer-13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L5959) *Remarks*: The result may be an undefined address, but the operations otherwise have no undefined behavior[.](#types.pointer-13.sentence-1) For store_max and store_min, the maximum and minimum computation is performed as if by max and min algorithms ([[alg.min.max]](alg.min.max "26.8.9 Minimum and maximum")), respectively, with the value pointed to by this and the first parameter as the arguments[.](#types.pointer-13.sentence-2) [*Note [4](#types.pointer-note-4)*: If the pointers point to different complete objects (or subobjects thereof), the < operator does not establish a strict weak ordering (Table [29](utility.arg.requirements#tab:cpp17.lessthancomparable "Table 29: Cpp17LessThanComparable requirements"), [[expr.rel]](expr.rel "7.6.9 Relational operators"))[.](#types.pointer-13.sentence-3) — *end note*] [🔗](#lib:operator+=,atomic%3cT*%3e__) `T* operator op=(ptrdiff_t operand) volatile noexcept; constexpr T* operator op=(ptrdiff_t operand) noexcept; ` [14](#types.pointer-14) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L5983) *Constraints*: For the volatile overload of this function,is_always_lock_free is true[.](#types.pointer-14.sentence-1) [15](#types.pointer-15) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L5988) *Effects*: Equivalent to: return fetch_*key*(operand) *op* operand; #### [32.5.8.6](#types.memop) Member operators common to integers and pointers to objects [[atomics.types.memop]](atomics.types.memop) [🔗](#lib:operator++,atomic%3cT*%3e) `value_type operator++(int) volatile noexcept; constexpr value_type operator++(int) noexcept; ` [1](#types.memop-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6003) *Constraints*: For the volatile overload of this function,is_always_lock_free is true[.](#types.memop-1.sentence-1) [2](#types.memop-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6008) *Effects*: Equivalent to: return fetch_add(1); [🔗](#lib:operator--,atomic%3cT*%3e) `value_type operator--(int) volatile noexcept; constexpr value_type operator--(int) noexcept; ` [3](#types.memop-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6021) *Constraints*: For the volatile overload of this function,is_always_lock_free is true[.](#types.memop-3.sentence-1) [4](#types.memop-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6026) *Effects*: Equivalent to: return fetch_sub(1); [🔗](#lib:operator++,atomic%3cT*%3e_) `value_type operator++() volatile noexcept; constexpr value_type operator++() noexcept; ` [5](#types.memop-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6039) *Constraints*: For the volatile overload of this function,is_always_lock_free is true[.](#types.memop-5.sentence-1) [6](#types.memop-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6044) *Effects*: Equivalent to: return fetch_add(1) + 1; [🔗](#lib:operator--,atomic%3cT*%3e_) `value_type operator--() volatile noexcept; constexpr value_type operator--() noexcept; ` [7](#types.memop-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6057) *Constraints*: For the volatile overload of this function,is_always_lock_free is true[.](#types.memop-7.sentence-1) [8](#types.memop-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6062) *Effects*: Equivalent to: return fetch_sub(1) - 1; #### [32.5.8.7](#util.smartptr.atomic) Partial specializations for smart pointers [[util.smartptr.atomic]](util.smartptr.atomic) #### [32.5.8.7.1](#util.smartptr.atomic.general) General [[util.smartptr.atomic.general]](util.smartptr.atomic.general) [1](#util.smartptr.atomic.general-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6072) The library provides partial specializations of the atomic template for shared-ownership smart pointers ([[util.sharedptr]](util.sharedptr "20.3.2 Shared-ownership pointers"))[.](#util.smartptr.atomic.general-1.sentence-1) [*Note [1](#util.smartptr.atomic.general-note-1)*: The partial specializations are declared in header [](memory.syn#header:%3cmemory%3e "20.2.2 Header synopsis [memory.syn]")[.](#util.smartptr.atomic.general-1.sentence-2) — *end note*] The behavior of all operations is as specified in [[atomics.types.generic]](#types.generic "32.5.8 Class template atomic"), unless specified otherwise[.](#util.smartptr.atomic.general-1.sentence-3) The template parameter T of these partial specializations may be an incomplete type[.](#util.smartptr.atomic.general-1.sentence-4) [2](#util.smartptr.atomic.general-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6083) All changes to an atomic smart pointer in [[util.smartptr.atomic]](#util.smartptr.atomic "32.5.8.7 Partial specializations for smart pointers"), and all associated use_count increments, are guaranteed to be performed atomically[.](#util.smartptr.atomic.general-2.sentence-1) Associated use_count decrements are sequenced after the atomic operation, but are not required to be part of it[.](#util.smartptr.atomic.general-2.sentence-2) Any associated deletion and deallocation are sequenced after the atomic update step and are not part of the atomic operation[.](#util.smartptr.atomic.general-2.sentence-3) [*Note [2](#util.smartptr.atomic.general-note-2)*: If the atomic operation uses locks, locks acquired by the implementation will be held when any use_count adjustments are performed, and will not be held when any destruction or deallocation resulting from this is performed[.](#util.smartptr.atomic.general-2.sentence-4) — *end note*] [3](#util.smartptr.atomic.general-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6101) [*Example [1](#util.smartptr.atomic.general-example-1)*: template class atomic_list {struct node { T t; shared_ptr next; }; atomic> head; public: shared_ptr find(T t) const {auto p = head.load(); while (p && p->t != t) p = p->next; return p; }void push_front(T t) {auto p = make_shared(); p->t = t; p->next = head; while (!head.compare_exchange_weak(p->next, p)) {}}}; — *end example*] #### [32.5.8.7.2](#util.smartptr.atomic.shared) Partial specialization for shared_ptr [[util.smartptr.atomic.shared]](util.smartptr.atomic.shared) [🔗](#lib:atomic%3cshared_ptr%3cT%3e%3e) namespace std {template struct atomic> {using value_type = shared_ptr; static constexpr bool is_always_lock_free = *implementation-defined*; bool is_lock_free() const noexcept; constexpr atomic() noexcept; constexpr atomic(nullptr_t) noexcept : atomic() { }constexpr atomic(shared_ptr desired) noexcept; atomic(const atomic&) = delete; void operator=(const atomic&) = delete; constexpr shared_ptr load(memory_order order = memory_order::seq_cst) const noexcept; constexpr operator shared_ptr() const noexcept; constexpr void store(shared_ptr desired, memory_order order = memory_order::seq_cst) noexcept; constexpr void operator=(shared_ptr desired) noexcept; constexpr void operator=(nullptr_t) noexcept; constexpr shared_ptr exchange(shared_ptr desired, memory_order order = memory_order::seq_cst) noexcept; constexpr bool compare_exchange_weak(shared_ptr& expected, shared_ptr desired, memory_order success, memory_order failure) noexcept; constexpr bool compare_exchange_strong(shared_ptr& expected, shared_ptr desired, memory_order success, memory_order failure) noexcept; constexpr bool compare_exchange_weak(shared_ptr& expected, shared_ptr desired, memory_order order = memory_order::seq_cst) noexcept; constexpr bool compare_exchange_strong(shared_ptr& expected, shared_ptr desired, memory_order order = memory_order::seq_cst) noexcept; constexpr void wait(shared_ptr old, memory_order order = memory_order::seq_cst) const noexcept; constexpr void notify_one() noexcept; constexpr void notify_all() noexcept; private: shared_ptr p; // *exposition only*};} [🔗](#lib:atomic%3cshared_ptr%3cT%3e%3e,constructor) `constexpr atomic() noexcept; ` [1](#util.smartptr.atomic.shared-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6181) *Effects*: Value-initializes p[.](#util.smartptr.atomic.shared-1.sentence-1) [🔗](#lib:atomic%3cshared_ptr%3cT%3e%3e,constructor_) `constexpr atomic(shared_ptr desired) noexcept; ` [2](#util.smartptr.atomic.shared-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6192) *Effects*: Initializes the object with the value desired[.](#util.smartptr.atomic.shared-2.sentence-1) Initialization is not an atomic operation ([[intro.multithread]](intro.multithread "6.10.2 Multi-threaded executions and data races"))[.](#util.smartptr.atomic.shared-2.sentence-2) [*Note [1](#util.smartptr.atomic.shared-note-1)*: It is possible to have an access to an atomic object A race with its construction, for example, by communicating the address of the just-constructed object A to another thread via memory_order​::​relaxed operations on a suitable atomic pointer variable, and then immediately accessing A in the receiving thread[.](#util.smartptr.atomic.shared-2.sentence-3) This results in undefined behavior[.](#util.smartptr.atomic.shared-2.sentence-4) — *end note*] [🔗](#lib:store,atomic%3cshared_ptr%3cT%3e%3e) `constexpr void store(shared_ptr desired, memory_order order = memory_order::seq_cst) noexcept; ` [3](#util.smartptr.atomic.shared-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6214) *Preconditions*: order ismemory_order​::​relaxed,memory_order​::​release, ormemory_order​::​seq_cst[.](#util.smartptr.atomic.shared-3.sentence-1) [4](#util.smartptr.atomic.shared-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6221) *Effects*: Atomically replaces the value pointed to by this with the value of desired as if by p.swap(desired)[.](#util.smartptr.atomic.shared-4.sentence-1) Memory is affected according to the value of order[.](#util.smartptr.atomic.shared-4.sentence-2) [🔗](#lib:operator=,atomic%3cshared_ptr%3cT%3e%3e) `constexpr void operator=(shared_ptr desired) noexcept; ` [5](#util.smartptr.atomic.shared-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6234) *Effects*: Equivalent to store(desired)[.](#util.smartptr.atomic.shared-5.sentence-1) [🔗](#lib:operator=,atomic%3cshared_ptr%3cT%3e%3e_) `constexpr void operator=(nullptr_t) noexcept; ` [6](#util.smartptr.atomic.shared-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6245) *Effects*: Equivalent to store(nullptr)[.](#util.smartptr.atomic.shared-6.sentence-1) [🔗](#lib:load,atomic%3cshared_ptr%3cT%3e%3e) `constexpr shared_ptr load(memory_order order = memory_order::seq_cst) const noexcept; ` [7](#util.smartptr.atomic.shared-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6256) *Preconditions*: order ismemory_order​::​relaxed,memory_order​::​acquire, ormemory_order​::​seq_cst[.](#util.smartptr.atomic.shared-7.sentence-1) [8](#util.smartptr.atomic.shared-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6263) *Effects*: Memory is affected according to the value of order[.](#util.smartptr.atomic.shared-8.sentence-1) [9](#util.smartptr.atomic.shared-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6267) *Returns*: Atomically returns p[.](#util.smartptr.atomic.shared-9.sentence-1) [🔗](#lib:operator_shared_ptr%3cT%3e,atomic%3cshared_ptr%3cT%3e%3e) `constexpr operator shared_ptr() const noexcept; ` [10](#util.smartptr.atomic.shared-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6278) *Effects*: Equivalent to: return load(); [🔗](#lib:exchange,atomic%3cshared_ptr%3cT%3e%3e) `constexpr shared_ptr exchange(shared_ptr desired, memory_order order = memory_order::seq_cst) noexcept; ` [11](#util.smartptr.atomic.shared-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6290) *Effects*: Atomically replaces p with desired as if by p.swap(desired)[.](#util.smartptr.atomic.shared-11.sentence-1) Memory is affected according to the value of order[.](#util.smartptr.atomic.shared-11.sentence-2) This is an atomic read-modify-write operation ([[intro.races]](intro.races "6.10.2.2 Data races"))[.](#util.smartptr.atomic.shared-11.sentence-3) [12](#util.smartptr.atomic.shared-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6297) *Returns*: Atomically returns the value of p immediately before the effects[.](#util.smartptr.atomic.shared-12.sentence-1) [🔗](#lib:compare_exchange_weak,atomic%3cshared_ptr%3cT%3e%3e) `constexpr bool compare_exchange_weak(shared_ptr& expected, shared_ptr desired, memory_order success, memory_order failure) noexcept; constexpr bool compare_exchange_strong(shared_ptr& expected, shared_ptr desired, memory_order success, memory_order failure) noexcept; ` [13](#util.smartptr.atomic.shared-13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6312) *Preconditions*: failure ismemory_order​::​relaxed,memory_order​::​acquire, ormemory_order​::​seq_cst[.](#util.smartptr.atomic.shared-13.sentence-1) [14](#util.smartptr.atomic.shared-14) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6319) *Effects*: If p is equivalent to expected, assigns desired to p and has synchronization semantics corresponding to the value of success, otherwise assigns p to expected and has synchronization semantics corresponding to the value of failure[.](#util.smartptr.atomic.shared-14.sentence-1) [15](#util.smartptr.atomic.shared-15) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6327) *Returns*: true if p was equivalent to expected,false otherwise[.](#util.smartptr.atomic.shared-15.sentence-1) [16](#util.smartptr.atomic.shared-16) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6332) *Remarks*: Two shared_ptr objects are equivalent if they store the same pointer value and either share ownership or are both empty[.](#util.smartptr.atomic.shared-16.sentence-1) The weak form may fail spuriously[.](#util.smartptr.atomic.shared-16.sentence-2) See [[atomics.types.operations]](#types.operations "32.5.8.2 Operations on atomic types")[.](#util.smartptr.atomic.shared-16.sentence-3) [17](#util.smartptr.atomic.shared-17) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6339) If the operation returns true,expected is not accessed after the atomic update and the operation is an atomic read-modify-write operation ([[intro.multithread]](intro.multithread "6.10.2 Multi-threaded executions and data races")) on the memory pointed to by this[.](#util.smartptr.atomic.shared-17.sentence-1) Otherwise, the operation is an atomic load operation on that memory, andexpected is updated with the existing value read from the atomic object in the attempted atomic update[.](#util.smartptr.atomic.shared-17.sentence-2) The use_count update corresponding to the write to expected is part of the atomic operation[.](#util.smartptr.atomic.shared-17.sentence-3) The write to expected itself is not required to be part of the atomic operation[.](#util.smartptr.atomic.shared-17.sentence-4) [🔗](#lib:compare_exchange_weak,atomic%3cshared_ptr%3cT%3e%3e_) `constexpr bool compare_exchange_weak(shared_ptr& expected, shared_ptr desired, memory_order order = memory_order::seq_cst) noexcept; ` [18](#util.smartptr.atomic.shared-18) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6360) *Effects*: Equivalent to:return compare_exchange_weak(expected, desired, order, fail_order); where fail_order is the same as order except that a value of memory_order​::​acq_rel shall be replaced by the value memory_order​::​acquire and a value of memory_order​::​release shall be replaced by the value memory_order​::​relaxed[.](#util.smartptr.atomic.shared-18.sentence-1) [🔗](#lib:compare_exchange_strong,atomic%3cshared_ptr%3cT%3e%3e_) `constexpr bool compare_exchange_strong(shared_ptr& expected, shared_ptr desired, memory_order order = memory_order::seq_cst) noexcept; ` [19](#util.smartptr.atomic.shared-19) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6380) *Effects*: Equivalent to:return compare_exchange_strong(expected, desired, order, fail_order); where fail_order is the same as order except that a value of memory_order​::​acq_rel shall be replaced by the value memory_order​::​acquire and a value of memory_order​::​release shall be replaced by the value memory_order​::​relaxed[.](#util.smartptr.atomic.shared-19.sentence-1) [🔗](#lib:wait,atomic%3cshared_ptr%3cT%3e%3e) `constexpr void wait(shared_ptr old, memory_order order = memory_order::seq_cst) const noexcept; ` [20](#util.smartptr.atomic.shared-20) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6399) *Preconditions*: order ismemory_order​::​relaxed,memory_order​::​acquire, ormemory_order​::​seq_cst[.](#util.smartptr.atomic.shared-20.sentence-1) [21](#util.smartptr.atomic.shared-21) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6406) *Effects*: Repeatedly performs the following steps, in order: - [(21.1)](#util.smartptr.atomic.shared-21.1) Evaluates load(order) and compares it to old[.](#util.smartptr.atomic.shared-21.1.sentence-1) - [(21.2)](#util.smartptr.atomic.shared-21.2) If the two are not equivalent, returns[.](#util.smartptr.atomic.shared-21.2.sentence-1) - [(21.3)](#util.smartptr.atomic.shared-21.3) Blocks until it is unblocked by an atomic notifying operation or is unblocked spuriously[.](#util.smartptr.atomic.shared-21.3.sentence-1) [22](#util.smartptr.atomic.shared-22) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6419) *Remarks*: Two shared_ptr objects are equivalent if they store the same pointer and either share ownership or are both empty[.](#util.smartptr.atomic.shared-22.sentence-1) This function is an atomic waiting operation ([[atomics.wait]](#wait "32.5.6 Waiting and notifying"))[.](#util.smartptr.atomic.shared-22.sentence-2) [🔗](#lib:notify_one,atomic%3cshared_ptr%3cT%3e%3e) `constexpr void notify_one() noexcept; ` [23](#util.smartptr.atomic.shared-23) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6432) *Effects*: Unblocks the execution of at least one atomic waiting operation that is eligible to be unblocked ([[atomics.wait]](#wait "32.5.6 Waiting and notifying")) by this call, if any such atomic waiting operations exist[.](#util.smartptr.atomic.shared-23.sentence-1) [24](#util.smartptr.atomic.shared-24) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6438) *Remarks*: This function is an atomic notifying operation ([[atomics.wait]](#wait "32.5.6 Waiting and notifying"))[.](#util.smartptr.atomic.shared-24.sentence-1) [🔗](#lib:notify_all,atomic%3cshared_ptr%3cT%3e%3e) `constexpr void notify_all() noexcept; ` [25](#util.smartptr.atomic.shared-25) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6449) *Effects*: Unblocks the execution of all atomic waiting operations that are eligible to be unblocked ([[atomics.wait]](#wait "32.5.6 Waiting and notifying")) by this call[.](#util.smartptr.atomic.shared-25.sentence-1) [26](#util.smartptr.atomic.shared-26) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6454) *Remarks*: This function is an atomic notifying operation ([[atomics.wait]](#wait "32.5.6 Waiting and notifying"))[.](#util.smartptr.atomic.shared-26.sentence-1) #### [32.5.8.7.3](#util.smartptr.atomic.weak) Partial specialization for weak_ptr [[util.smartptr.atomic.weak]](util.smartptr.atomic.weak) [🔗](#lib:atomic%3cweak_ptr%3cT%3e%3e) namespace std {template struct atomic> {using value_type = weak_ptr; static constexpr bool is_always_lock_free = *implementation-defined*; bool is_lock_free() const noexcept; constexpr atomic() noexcept; constexpr atomic(weak_ptr desired) noexcept; atomic(const atomic&) = delete; void operator=(const atomic&) = delete; constexpr weak_ptr load(memory_order order = memory_order::seq_cst) const noexcept; constexpr operator weak_ptr() const noexcept; constexpr void store(weak_ptr desired, memory_order order = memory_order::seq_cst) noexcept; constexpr void operator=(weak_ptr desired) noexcept; constexpr weak_ptr exchange(weak_ptr desired, memory_order order = memory_order::seq_cst) noexcept; constexpr bool compare_exchange_weak(weak_ptr& expected, weak_ptr desired, memory_order success, memory_order failure) noexcept; constexpr bool compare_exchange_strong(weak_ptr& expected, weak_ptr desired, memory_order success, memory_order failure) noexcept; constexpr bool compare_exchange_weak(weak_ptr& expected, weak_ptr desired, memory_order order = memory_order::seq_cst) noexcept; constexpr bool compare_exchange_strong(weak_ptr& expected, weak_ptr desired, memory_order order = memory_order::seq_cst) noexcept; constexpr void wait(weak_ptr old, memory_order order = memory_order::seq_cst) const noexcept; constexpr void notify_one() noexcept; constexpr void notify_all() noexcept; private: weak_ptr p; // *exposition only*};} [🔗](#lib:atomic%3cweak_ptr%3cT%3e%3e,constructor) `constexpr atomic() noexcept; ` [1](#util.smartptr.atomic.weak-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6509) *Effects*: Value-initializes p[.](#util.smartptr.atomic.weak-1.sentence-1) [🔗](#lib:atomic%3cweak_ptr%3cT%3e%3e,constructor_) `constexpr atomic(weak_ptr desired) noexcept; ` [2](#util.smartptr.atomic.weak-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6520) *Effects*: Initializes the object with the value desired[.](#util.smartptr.atomic.weak-2.sentence-1) Initialization is not an atomic operation ([[intro.multithread]](intro.multithread "6.10.2 Multi-threaded executions and data races"))[.](#util.smartptr.atomic.weak-2.sentence-2) [*Note [1](#util.smartptr.atomic.weak-note-1)*: It is possible to have an access to an atomic object A race with its construction, for example, by communicating the address of the just-constructed object A to another thread via memory_order​::​relaxed operations on a suitable atomic pointer variable, and then immediately accessing A in the receiving thread[.](#util.smartptr.atomic.weak-2.sentence-3) This results in undefined behavior[.](#util.smartptr.atomic.weak-2.sentence-4) — *end note*] [🔗](#lib:store,atomic%3cweak_ptr%3cT%3e%3e) `constexpr void store(weak_ptr desired, memory_order order = memory_order::seq_cst) noexcept; ` [3](#util.smartptr.atomic.weak-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6542) *Preconditions*: order ismemory_order​::​relaxed,memory_order​::​release, ormemory_order​::​seq_cst[.](#util.smartptr.atomic.weak-3.sentence-1) [4](#util.smartptr.atomic.weak-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6549) *Effects*: Atomically replaces the value pointed to by this with the value of desired as if by p.swap(desired)[.](#util.smartptr.atomic.weak-4.sentence-1) Memory is affected according to the value of order[.](#util.smartptr.atomic.weak-4.sentence-2) [🔗](#lib:operator=,atomic%3cweak_ptr%3cT%3e%3e) `constexpr void operator=(weak_ptr desired) noexcept; ` [5](#util.smartptr.atomic.weak-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6562) *Effects*: Equivalent to store(desired)[.](#util.smartptr.atomic.weak-5.sentence-1) [🔗](#lib:load,atomic%3cweak_ptr%3cT%3e%3e) `constexpr weak_ptr load(memory_order order = memory_order::seq_cst) const noexcept; ` [6](#util.smartptr.atomic.weak-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6573) *Preconditions*: order ismemory_order​::​relaxed,memory_order​::​acquire, ormemory_order​::​seq_cst[.](#util.smartptr.atomic.weak-6.sentence-1) [7](#util.smartptr.atomic.weak-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6580) *Effects*: Memory is affected according to the value of order[.](#util.smartptr.atomic.weak-7.sentence-1) [8](#util.smartptr.atomic.weak-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6584) *Returns*: Atomically returns p[.](#util.smartptr.atomic.weak-8.sentence-1) [🔗](#lib:operator_weak_ptr%3cT%3e,atomic%3cweak_ptr%3cT%3e%3e) `constexpr operator weak_ptr() const noexcept; ` [9](#util.smartptr.atomic.weak-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6595) *Effects*: Equivalent to: return load(); [🔗](#lib:exchange,atomic%3cweak_ptr%3cT%3e%3e) `constexpr weak_ptr exchange(weak_ptr desired, memory_order order = memory_order::seq_cst) noexcept; ` [10](#util.smartptr.atomic.weak-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6607) *Effects*: Atomically replaces p with desired as if by p.swap(desired)[.](#util.smartptr.atomic.weak-10.sentence-1) Memory is affected according to the value of order[.](#util.smartptr.atomic.weak-10.sentence-2) This is an atomic read-modify-write operation ([[intro.races]](intro.races "6.10.2.2 Data races"))[.](#util.smartptr.atomic.weak-10.sentence-3) [11](#util.smartptr.atomic.weak-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6614) *Returns*: Atomically returns the value of p immediately before the effects[.](#util.smartptr.atomic.weak-11.sentence-1) [🔗](#lib:compare_exchange_weak,atomic%3cweak_ptr%3cT%3e%3e) `constexpr bool compare_exchange_weak(weak_ptr& expected, weak_ptr desired, memory_order success, memory_order failure) noexcept; constexpr bool compare_exchange_strong(weak_ptr& expected, weak_ptr desired, memory_order success, memory_order failure) noexcept; ` [12](#util.smartptr.atomic.weak-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6628) *Preconditions*: failure ismemory_order​::​relaxed,memory_order​::​acquire, ormemory_order​::​seq_cst[.](#util.smartptr.atomic.weak-12.sentence-1) [13](#util.smartptr.atomic.weak-13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6635) *Effects*: If p is equivalent to expected, assigns desired to p and has synchronization semantics corresponding to the value of success, otherwise assigns p to expected and has synchronization semantics corresponding to the value of failure[.](#util.smartptr.atomic.weak-13.sentence-1) [14](#util.smartptr.atomic.weak-14) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6643) *Returns*: true if p was equivalent to expected,false otherwise[.](#util.smartptr.atomic.weak-14.sentence-1) [15](#util.smartptr.atomic.weak-15) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6648) *Remarks*: Two weak_ptr objects are equivalent if they store the same pointer value and either share ownership or are both empty[.](#util.smartptr.atomic.weak-15.sentence-1) The weak form may fail spuriously[.](#util.smartptr.atomic.weak-15.sentence-2) See [[atomics.types.operations]](#types.operations "32.5.8.2 Operations on atomic types")[.](#util.smartptr.atomic.weak-15.sentence-3) [16](#util.smartptr.atomic.weak-16) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6655) If the operation returns true,expected is not accessed after the atomic update and the operation is an atomic read-modify-write operation ([[intro.multithread]](intro.multithread "6.10.2 Multi-threaded executions and data races")) on the memory pointed to by this[.](#util.smartptr.atomic.weak-16.sentence-1) Otherwise, the operation is an atomic load operation on that memory, andexpected is updated with the existing value read from the atomic object in the attempted atomic update[.](#util.smartptr.atomic.weak-16.sentence-2) The use_count update corresponding to the write to expected is part of the atomic operation[.](#util.smartptr.atomic.weak-16.sentence-3) The write to expected itself is not required to be part of the atomic operation[.](#util.smartptr.atomic.weak-16.sentence-4) [🔗](#lib:compare_exchange_weak,atomic%3cweak_ptr%3cT%3e%3e_) `constexpr bool compare_exchange_weak(weak_ptr& expected, weak_ptr desired, memory_order order = memory_order::seq_cst) noexcept; ` [17](#util.smartptr.atomic.weak-17) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6676) *Effects*: Equivalent to:return compare_exchange_weak(expected, desired, order, fail_order); where fail_order is the same as order except that a value of memory_order​::​acq_rel shall be replaced by the value memory_order​::​acquire and a value of memory_order​::​release shall be replaced by the value memory_order​::​relaxed[.](#util.smartptr.atomic.weak-17.sentence-1) [🔗](#lib:compare_exchange_strong,atomic%3cweak_ptr%3cT%3e%3e) `constexpr bool compare_exchange_strong(weak_ptr& expected, weak_ptr desired, memory_order order = memory_order::seq_cst) noexcept; ` [18](#util.smartptr.atomic.weak-18) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6696) *Effects*: Equivalent to:return compare_exchange_strong(expected, desired, order, fail_order); where fail_order is the same as order except that a value of memory_order​::​acq_rel shall be replaced by the value memory_order​::​acquire and a value of memory_order​::​release shall be replaced by the value memory_order​::​relaxed[.](#util.smartptr.atomic.weak-18.sentence-1) [🔗](#lib:wait,atomic%3cweak_ptr%3cT%3e%3e) `constexpr void wait(weak_ptr old, memory_order order = memory_order::seq_cst) const noexcept; ` [19](#util.smartptr.atomic.weak-19) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6715) *Preconditions*: order ismemory_order​::​relaxed,memory_order​::​acquire, ormemory_order​::​seq_cst[.](#util.smartptr.atomic.weak-19.sentence-1) [20](#util.smartptr.atomic.weak-20) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6722) *Effects*: Repeatedly performs the following steps, in order: - [(20.1)](#util.smartptr.atomic.weak-20.1) Evaluates load(order) and compares it to old[.](#util.smartptr.atomic.weak-20.1.sentence-1) - [(20.2)](#util.smartptr.atomic.weak-20.2) If the two are not equivalent, returns[.](#util.smartptr.atomic.weak-20.2.sentence-1) - [(20.3)](#util.smartptr.atomic.weak-20.3) Blocks until it is unblocked by an atomic notifying operation or is unblocked spuriously[.](#util.smartptr.atomic.weak-20.3.sentence-1) [21](#util.smartptr.atomic.weak-21) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6735) *Remarks*: Two weak_ptr objects are equivalent if they store the same pointer and either share ownership or are both empty[.](#util.smartptr.atomic.weak-21.sentence-1) This function is an atomic waiting operation ([[atomics.wait]](#wait "32.5.6 Waiting and notifying"))[.](#util.smartptr.atomic.weak-21.sentence-2) [🔗](#lib:notify_one,atomic%3cweak_ptr%3cT%3e%3e) `constexpr void notify_one() noexcept; ` [22](#util.smartptr.atomic.weak-22) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6749) *Effects*: Unblocks the execution of at least one atomic waiting operation that is eligible to be unblocked ([[atomics.wait]](#wait "32.5.6 Waiting and notifying")) by this call, if any such atomic waiting operations exist[.](#util.smartptr.atomic.weak-22.sentence-1) [23](#util.smartptr.atomic.weak-23) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6755) *Remarks*: This function is an atomic notifying operation ([[atomics.wait]](#wait "32.5.6 Waiting and notifying"))[.](#util.smartptr.atomic.weak-23.sentence-1) [🔗](#lib:notify_all,atomic%3cweak_ptr%3cT%3e%3e) `constexpr void notify_all() noexcept; ` [24](#util.smartptr.atomic.weak-24) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6766) *Effects*: Unblocks the execution of all atomic waiting operations that are eligible to be unblocked ([[atomics.wait]](#wait "32.5.6 Waiting and notifying")) by this call[.](#util.smartptr.atomic.weak-24.sentence-1) [25](#util.smartptr.atomic.weak-25) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6771) *Remarks*: This function is an atomic notifying operation ([[atomics.wait]](#wait "32.5.6 Waiting and notifying"))[.](#util.smartptr.atomic.weak-25.sentence-1) ### [32.5.9](#nonmembers) Non-member functions [[atomics.nonmembers]](atomics.nonmembers) [1](#nonmembers-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6779) A non-member function template whose name matches the patternatomic_*f* or the pattern atomic_*f*_explicit invokes the member function *f*, with the value of the first parameter as the object expression and the values of the remaining parameters (if any) as the arguments of the member function call, in order[.](#nonmembers-1.sentence-1) An argument for a parameter of type atomic​::​value_type* is dereferenced when passed to the member function call[.](#nonmembers-1.sentence-2) If no such member function exists, the program is ill-formed[.](#nonmembers-1.sentence-3) [2](#nonmembers-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6789) [*Note [1](#nonmembers-note-1)*: The non-member functions enable programmers to write code that can be compiled as either C or C++, for example in a shared header file[.](#nonmembers-2.sentence-1) — *end note*] ### [32.5.10](#flag) Flag type and operations [[atomics.flag]](atomics.flag) namespace std {struct atomic_flag {constexpr atomic_flag() noexcept; atomic_flag(const atomic_flag&) = delete; atomic_flag& operator=(const atomic_flag&) = delete; atomic_flag& operator=(const atomic_flag&) volatile = delete; bool test(memory_order = memory_order::seq_cst) const volatile noexcept; constexpr bool test(memory_order = memory_order::seq_cst) const noexcept; bool test_and_set(memory_order = memory_order::seq_cst) volatile noexcept; constexpr bool test_and_set(memory_order = memory_order::seq_cst) noexcept; void clear(memory_order = memory_order::seq_cst) volatile noexcept; constexpr void clear(memory_order = memory_order::seq_cst) noexcept; void wait(bool, memory_order = memory_order::seq_cst) const volatile noexcept; constexpr void wait(bool, memory_order = memory_order::seq_cst) const noexcept; void notify_one() volatile noexcept; constexpr void notify_one() noexcept; void notify_all() volatile noexcept; constexpr void notify_all() noexcept; };} [1](#flag-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6822) The atomic_flag type provides the classic test-and-set functionality[.](#flag-1.sentence-1) It has two states, set and clear[.](#flag-1.sentence-2) [2](#flag-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6825) Operations on an object of type atomic_flag shall be lock-free[.](#flag-2.sentence-1) The operations should also be address-free[.](#flag-2.sentence-2) [3](#flag-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6829) The atomic_flag type is a standard-layout struct[.](#flag-3.sentence-1) It has a trivial destructor[.](#flag-3.sentence-2) [🔗](#lib:atomic_flag,constructor) `constexpr atomic_flag::atomic_flag() noexcept; ` [4](#flag-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6839) *Effects*: Initializes *this to the clear state[.](#flag-4.sentence-1) [🔗](#lib:atomic_flag_test) `bool atomic_flag_test(const volatile atomic_flag* object) noexcept; constexpr bool atomic_flag_test(const atomic_flag* object) noexcept; bool atomic_flag_test_explicit(const volatile atomic_flag* object, memory_order order) noexcept; constexpr bool atomic_flag_test_explicit(const atomic_flag* object, memory_order order) noexcept; bool atomic_flag::test(memory_order order = memory_order::seq_cst) const volatile noexcept; constexpr bool atomic_flag::test(memory_order order = memory_order::seq_cst) const noexcept; ` [5](#flag-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6859) For atomic_flag_test, let order be memory_order​::​seq_cst[.](#flag-5.sentence-1) [6](#flag-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6862) *Preconditions*: order ismemory_order​::​relaxed,memory_order​::​acquire, ormemory_order​::​seq_cst[.](#flag-6.sentence-1) [7](#flag-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6869) *Effects*: Memory is affected according to the value of order[.](#flag-7.sentence-1) [8](#flag-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6873) *Returns*: Atomically returns the value pointed to by object or this[.](#flag-8.sentence-1) [🔗](#lib:atomic_flag_test_and_set) `bool atomic_flag_test_and_set(volatile atomic_flag* object) noexcept; constexpr bool atomic_flag_test_and_set(atomic_flag* object) noexcept; bool atomic_flag_test_and_set_explicit(volatile atomic_flag* object, memory_order order) noexcept; constexpr bool atomic_flag_test_and_set_explicit(atomic_flag* object, memory_order order) noexcept; bool atomic_flag::test_and_set(memory_order order = memory_order::seq_cst) volatile noexcept; constexpr bool atomic_flag::test_and_set(memory_order order = memory_order::seq_cst) noexcept; ` [9](#flag-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6891) *Effects*: Atomically sets the value pointed to by object or by this to true[.](#flag-9.sentence-1) Memory is affected according to the value oforder[.](#flag-9.sentence-2) These operations are atomic read-modify-write operations ([[intro.multithread]](intro.multithread "6.10.2 Multi-threaded executions and data races"))[.](#flag-9.sentence-3) [10](#flag-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6896) *Returns*: Atomically, the value of the object immediately before the effects[.](#flag-10.sentence-1) [🔗](#lib:atomic_flag_clear) `void atomic_flag_clear(volatile atomic_flag* object) noexcept; constexpr void atomic_flag_clear(atomic_flag* object) noexcept; void atomic_flag_clear_explicit(volatile atomic_flag* object, memory_order order) noexcept; constexpr void atomic_flag_clear_explicit(atomic_flag* object, memory_order order) noexcept; void atomic_flag::clear(memory_order order = memory_order::seq_cst) volatile noexcept; constexpr void atomic_flag::clear(memory_order order = memory_order::seq_cst) noexcept; ` [11](#flag-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6914) *Preconditions*: order ismemory_order​::​relaxed,memory_order​::​release, ormemory_order​::​seq_cst[.](#flag-11.sentence-1) [12](#flag-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6921) *Effects*: Atomically sets the value pointed to by object or by this tofalse[.](#flag-12.sentence-1) Memory is affected according to the value of order[.](#flag-12.sentence-2) [🔗](#lib:atomic_flag_wait) `void atomic_flag_wait(const volatile atomic_flag* object, bool old) noexcept; constexpr void atomic_flag_wait(const atomic_flag* object, bool old) noexcept; void atomic_flag_wait_explicit(const volatile atomic_flag* object, bool old, memory_order order) noexcept; constexpr void atomic_flag_wait_explicit(const atomic_flag* object, bool old, memory_order order) noexcept; void atomic_flag::wait(bool old, memory_order order = memory_order::seq_cst) const volatile noexcept; constexpr void atomic_flag::wait(bool old, memory_order order = memory_order::seq_cst) const noexcept; ` [13](#flag-13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6944) For atomic_flag_wait, let order be memory_order​::​seq_cst[.](#flag-13.sentence-1) Let flag be object for the non-member functions andthis for the member functions[.](#flag-13.sentence-2) [14](#flag-14) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6950) *Preconditions*: order ismemory_order​::​relaxed,memory_order​::​acquire, ormemory_order​::​seq_cst[.](#flag-14.sentence-1) [15](#flag-15) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6957) *Effects*: Repeatedly performs the following steps, in order: - [(15.1)](#flag-15.1) Evaluates flag->test(order) != old[.](#flag-15.1.sentence-1) - [(15.2)](#flag-15.2) If the result of that evaluation is true, returns[.](#flag-15.2.sentence-1) - [(15.3)](#flag-15.3) Blocks until it is unblocked by an atomic notifying operation or is unblocked spuriously[.](#flag-15.3.sentence-1) [16](#flag-16) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6970) *Remarks*: This function is an atomic waiting operation ([[atomics.wait]](#wait "32.5.6 Waiting and notifying"))[.](#flag-16.sentence-1) [🔗](#flag-itemdecl:6) `void atomic_flag_notify_one(volatile atomic_flag* object) noexcept; constexpr void atomic_flag_notify_one(atomic_flag* object) noexcept; void atomic_flag::notify_one() volatile noexcept; constexpr void atomic_flag::notify_one() noexcept; ` [17](#flag-17) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6983) *Effects*: Unblocks the execution of at least one atomic waiting operation that is eligible to be unblocked ([[atomics.wait]](#wait "32.5.6 Waiting and notifying")) by this call, if any such atomic waiting operations exist[.](#flag-17.sentence-1) [18](#flag-18) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6989) *Remarks*: This function is an atomic notifying operation ([[atomics.wait]](#wait "32.5.6 Waiting and notifying"))[.](#flag-18.sentence-1) [🔗](#flag-itemdecl:7) `void atomic_flag_notify_all(volatile atomic_flag* object) noexcept; constexpr void atomic_flag_notify_all(atomic_flag* object) noexcept; void atomic_flag::notify_all() volatile noexcept; constexpr void atomic_flag::notify_all() noexcept; ` [19](#flag-19) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7002) *Effects*: Unblocks the execution of all atomic waiting operations that are eligible to be unblocked ([[atomics.wait]](#wait "32.5.6 Waiting and notifying")) by this call[.](#flag-19.sentence-1) [20](#flag-20) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7007) *Remarks*: This function is an atomic notifying operation ([[atomics.wait]](#wait "32.5.6 Waiting and notifying"))[.](#flag-20.sentence-1) [🔗](#flag-itemdecl:8) `#define ATOMIC_FLAG_INIT see below ` [21](#flag-21) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7017) *Remarks*: The macro ATOMIC_FLAG_INIT is defined in such a way that it can be used to initialize an object of type atomic_flag to the clear state[.](#flag-21.sentence-1) The macro can be used in the form:atomic_flag guard = ATOMIC_FLAG_INIT; It is unspecified whether the macro can be used in other initialization contexts[.](#flag-21.sentence-3) For a complete static-duration object, that initialization shall be static[.](#flag-21.sentence-4) ### [32.5.11](#fences) Fences [[atomics.fences]](atomics.fences) [1](#fences-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7033) This subclause introduces synchronization primitives called [*fences*](#def:fences)[.](#fences-1.sentence-1) Fences can have acquire semantics, release semantics, or both[.](#fences-1.sentence-2) A fence with acquire semantics is called an [*acquire fence*](#def:acquire_fence)[.](#fences-1.sentence-3) A fence with release semantics is called a [*release fence*](#def:release_fence)[.](#fences-1.sentence-4) [2](#fences-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7039) A release fence A synchronizes with an acquire fence B if there exist atomic operations X and Y, where Y is not an atomic modify-write operation ([[atomics.order]](#order "32.5.4 Order and consistency")), both operating on some atomic objectM, such that A is sequenced before X, X modifiesM, Y is sequenced before B, and Y reads the value written by X or a value written by any side effect in the hypothetical release sequence X would head if it were a release operation[.](#fences-2.sentence-1) [3](#fences-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7049) A release fence A synchronizes with an atomic operation B that performs an acquire operation on an atomic object M if there exists an atomic operation X such that A is sequenced before X, X modifies M, and B reads the value written by X or a value written by any side effect in the hypothetical release sequence X would head if it were a release operation[.](#fences-3.sentence-1) [4](#fences-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7057) An atomic operation A that is a release operation on an atomic objectM synchronizes with an acquire fence B if there exists some atomic operation X on M such that X is sequenced before B and reads the value written by A or a value written by any side effect in the release sequence headed by A[.](#fences-4.sentence-1) [🔗](#lib:atomic_thread_fence) `extern "C" constexpr void atomic_thread_fence(memory_order order) noexcept; ` [5](#fences-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7070) *Effects*: Depending on the value of order, this operation: - [(5.1)](#fences-5.1) has no effects, if order == memory_order​::​relaxed; - [(5.2)](#fences-5.2) is an acquire fence, if order == memory_order​::​acquire; - [(5.3)](#fences-5.3) is a release fence, if order == memory_order​::​release; - [(5.4)](#fences-5.4) is both an acquire fence and a release fence, if order == memory_order​::​acq_rel; - [(5.5)](#fences-5.5) is a sequentially consistent acquire and release fence, if order == memory_order​::​seq_cst[.](#fences-5.sentence-1) [🔗](#lib:atomic_signal_fence) `extern "C" constexpr void atomic_signal_fence(memory_order order) noexcept; ` [6](#fences-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7092) *Effects*: Equivalent to atomic_thread_fence(order), except that the resulting ordering constraints are established only between a thread and a signal handler executed in the same thread[.](#fences-6.sentence-1) [7](#fences-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7098) [*Note [1](#fences-note-1)*: atomic_signal_fence can be used to specify the order in which actions performed by the thread become visible to the signal handler[.](#fences-7.sentence-1) Compiler optimizations and reorderings of loads and stores are inhibited in the same way as with atomic_thread_fence, but the hardware fence instructions that atomic_thread_fence would have inserted are not emitted[.](#fences-7.sentence-2) — *end note*] ### [32.5.12](#stdatomic.h.syn) C compatibility [[stdatomic.h.syn]](stdatomic.h.syn) The header provides the following definitions: templateusing *std-atomic* = std::atomic; // *exposition only*#define _Atomic(T) *std-atomic*#define ATOMIC_BOOL_LOCK_FREE *see below*#define ATOMIC_CHAR_LOCK_FREE *see below*#define ATOMIC_CHAR16_T_LOCK_FREE *see below*#define ATOMIC_CHAR32_T_LOCK_FREE *see below*#define ATOMIC_WCHAR_T_LOCK_FREE *see below*#define ATOMIC_SHORT_LOCK_FREE *see below*#define ATOMIC_INT_LOCK_FREE *see below*#define ATOMIC_LONG_LOCK_FREE *see below*#define ATOMIC_LLONG_LOCK_FREE *see below*#define ATOMIC_POINTER_LOCK_FREE *see below*using std::[memory_order](depr.atomics.order#lib:memory_order "D.23.5 memory_­order​::​consume [depr.atomics.order]"); // *see below*using std::[memory_order_relaxed](#lib:memory_order_relaxed "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[memory_order_consume](#lib:memory_order_consume "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[memory_order_acquire](#lib:memory_order_acquire "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[memory_order_release](#lib:memory_order_release "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[memory_order_acq_rel](#lib:memory_order_acq_rel "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[memory_order_seq_cst](#lib:memory_order_seq_cst "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_flag](#lib:atomic_flag "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_bool](#lib:atomic_bool "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_char](#lib:atomic_char "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_schar](#lib:atomic_schar "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_uchar](#lib:atomic_uchar "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_short](#lib:atomic_short "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_ushort](#lib:atomic_ushort "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_int](#lib:atomic_int "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_uint](#lib:atomic_uint "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_long](#lib:atomic_long "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_ulong](#lib:atomic_ulong "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_llong](#lib:atomic_llong "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_ullong](#lib:atomic_ullong "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_char8_t](#lib:atomic_char8_t "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_char16_t](#lib:atomic_char16_t "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_char32_t](#lib:atomic_char32_t "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_wchar_t](#lib:atomic_wchar_t "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_int8_t](#lib:atomic_int8_t "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_uint8_t](#lib:atomic_uint8_t "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_int16_t](#lib:atomic_int16_t "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_uint16_t](#lib:atomic_uint16_t "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_int32_t](#lib:atomic_int32_t "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_uint32_t](#lib:atomic_uint32_t "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_int64_t](#lib:atomic_int64_t "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_uint64_t](#lib:atomic_uint64_t "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_int_least8_t](#lib:atomic_int_least8_t "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_uint_least8_t](#lib:atomic_uint_least8_t "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_int_least16_t](#lib:atomic_int_least16_t "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_uint_least16_t](#lib:atomic_uint_least16_t "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_int_least32_t](#lib:atomic_int_least32_t "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_uint_least32_t](#lib:atomic_uint_least32_t "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_int_least64_t](#lib:atomic_int_least64_t "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_uint_least64_t](#lib:atomic_uint_least64_t "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_int_fast8_t](#lib:atomic_int_fast8_t "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_uint_fast8_t](#lib:atomic_uint_fast8_t "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_int_fast16_t](#lib:atomic_int_fast16_t "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_uint_fast16_t](#lib:atomic_uint_fast16_t "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_int_fast32_t](#lib:atomic_int_fast32_t "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_uint_fast32_t](#lib:atomic_uint_fast32_t "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_int_fast64_t](#lib:atomic_int_fast64_t "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_uint_fast64_t](#lib:atomic_uint_fast64_t "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_intptr_t](#lib:atomic_intptr_t "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_uintptr_t](#lib:atomic_uintptr_t "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_size_t](#lib:atomic_size_t "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_ptrdiff_t](#lib:atomic_ptrdiff_t "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_intmax_t](#lib:atomic_intmax_t "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_uintmax_t](#lib:atomic_uintmax_t "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_is_lock_free](#lib:atomic_is_lock_free "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_load](#lib:atomic_load "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_load_explicit](#lib:atomic_load_explicit "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_store](#lib:atomic_store "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_store_explicit](#lib:atomic_store_explicit "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_exchange](#lib:atomic_exchange "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_exchange_explicit](#lib:atomic_exchange_explicit "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_compare_exchange_strong](#lib:atomic_compare_exchange_strong "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_compare_exchange_strong_explicit](#lib:atomic_compare_exchange_strong_explicit "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_compare_exchange_weak](#lib:atomic_compare_exchange_weak "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_compare_exchange_weak_explicit](#lib:atomic_compare_exchange_weak_explicit "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_fetch_add](#lib:atomic_fetch_add "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_fetch_add_explicit](#lib:atomic_fetch_add_explicit "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_fetch_sub](#lib:atomic_fetch_sub "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_fetch_sub_explicit](#lib:atomic_fetch_sub_explicit "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_fetch_and](#lib:atomic_fetch_and "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_fetch_and_explicit](#lib:atomic_fetch_and_explicit "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_fetch_or](#lib:atomic_fetch_or "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_fetch_or_explicit](#lib:atomic_fetch_or_explicit "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_fetch_xor](#lib:atomic_fetch_xor "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_fetch_xor_explicit](#lib:atomic_fetch_xor_explicit "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_flag_test_and_set](#lib:atomic_flag_test_and_set "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_flag_test_and_set_explicit](#lib:atomic_flag_test_and_set_explicit "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_flag_clear](#lib:atomic_flag_clear "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_flag_clear_explicit](#lib:atomic_flag_clear_explicit "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*#define ATOMIC_FLAG_INIT *see below*using std::[atomic_thread_fence](#lib:atomic_thread_fence "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below*using std::[atomic_signal_fence](#lib:atomic_signal_fence "32.5.12 C compatibility [stdatomic.h.syn]"); // *see below* [1](#stdatomic.h.syn-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7217) Each [*using-declaration*](namespace.udecl#nt:using-declaration "9.10 The using declaration [namespace.udecl]") for some name A in the synopsis above makes available the same entity as std​::​A declared in [](#header:%3catomic%3e "32.5.2 Header synopsis [atomics.syn]")[.](#stdatomic.h.syn-1.sentence-1) Each macro listed above other than _Atomic(T) is defined as in [](#header:%3catomic%3e "32.5.2 Header synopsis [atomics.syn]")[.](#stdatomic.h.syn-1.sentence-2) It is unspecified whether [](#header:%3cstdatomic.h%3e "32.5.12 C compatibility [stdatomic.h.syn]") makes available any declarations in namespace std[.](#stdatomic.h.syn-1.sentence-3) [2](#stdatomic.h.syn-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7226) Each of the [*using-declaration*](namespace.udecl#nt:using-declaration "9.10 The using declaration [namespace.udecl]")*s* forintN_t, uintN_t, intptr_t, and uintptr_t listed above is defined if and only if the implementation defines the corresponding [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]") in [[atomics.syn]](#syn "32.5.2 Header synopsis")[.](#stdatomic.h.syn-2.sentence-1) [3](#stdatomic.h.syn-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7232) Neither the _Atomic macro, nor any of the non-macro global namespace declarations, are provided by any C++ standard library header other than [](#header:%3cstdatomic.h%3e "32.5.12 C compatibility [stdatomic.h.syn]")[.](#stdatomic.h.syn-3.sentence-1) [4](#stdatomic.h.syn-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7238) *Recommended practice*: Implementations should ensure that C and C++ representations of atomic objects are compatible, so that the same object can be accessed as both an _Atomic(T) from C code and an atomic from C++ code[.](#stdatomic.h.syn-4.sentence-1) The representations should be the same, and the mechanisms used to ensure atomicity and memory ordering should be compatible[.](#stdatomic.h.syn-4.sentence-2)