[util.smartptr.atomic]

# 32 Concurrency support library [[thread]](./#thread)

## 32.5 Atomic operations [[atomics]](atomics#util.smartptr.atomic)

### 32.5.8 Class template atomic [[atomics.types.generic]](atomics.types.generic#util.smartptr.atomic)

#### 32.5.8.7 Partial specializations for smart pointers [util.smartptr.atomic]

#### [32.5.8.7.1](#general) General [[util.smartptr.atomic.general]](util.smartptr.atomic.general)

[1](#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"))[.](#general-1.sentence-1)

[*Note [1](#general-note-1)*:

The partial specializations are declared in header [<memory>](memory.syn#header:%3cmemory%3e "20.2.2 Header <memory> synopsis [memory.syn]")[.](#general-1.sentence-2)

â *end note*]

The behavior of all operations is as specified in [[atomics.types.generic]](atomics.types.generic "32.5.8 Class template atomic"),
unless specified otherwise[.](#general-1.sentence-3)

The template parameter T of these partial specializations
may be an incomplete type[.](#general-1.sentence-4)

[2](#general-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6083)

All changes to an atomic smart pointer in [util.smartptr.atomic], and
all associated use_count increments,
are guaranteed to be performed atomically[.](#general-2.sentence-1)

Associated use_count decrements
are sequenced after the atomic operation,
but are not required to be part of it[.](#general-2.sentence-2)

Any associated deletion and deallocation
are sequenced after the atomic update step and
are not part of the atomic operation[.](#general-2.sentence-3)

[*Note [2](#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[.](#general-2.sentence-4)

â *end note*]

[3](#general-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6101)

[*Example [1](#general-example-1)*: template<typename T> class atomic_list {struct node { T t;
 shared_ptr<node> next; };
 atomic<shared_ptr<node>> head;

public: shared_ptr<node> 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<node>();
 p->t = t;
 p->next = head; while (!head.compare_exchange_weak(p->next, p)) {}}}; â *end example*]

#### [32.5.8.7.2](#shared) Partial specialization for shared_ptr [[util.smartptr.atomic.shared]](util.smartptr.atomic.shared)

[ð](#lib:atomic%3cshared_ptr%3cT%3e%3e)

namespace std {template<class T> struct atomic<shared_ptr<T>> {using value_type = shared_ptr<T>; 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<T> desired) noexcept;
 atomic(const atomic&) = delete; void operator=(const atomic&) = delete; constexpr shared_ptr<T> load(memory_order order = memory_order::seq_cst) const noexcept; constexpr operator shared_ptr<T>() const noexcept; constexpr void store(shared_ptr<T> desired,
 memory_order order = memory_order::seq_cst) noexcept; constexpr void operator=(shared_ptr<T> desired) noexcept; constexpr void operator=(nullptr_t) noexcept; constexpr shared_ptr<T> exchange(shared_ptr<T> desired,
 memory_order order = memory_order::seq_cst) noexcept; constexpr bool compare_exchange_weak(shared_ptr<T>& expected, shared_ptr<T> desired,
 memory_order success, memory_order failure) noexcept; constexpr bool compare_exchange_strong(shared_ptr<T>& expected, shared_ptr<T> desired,
 memory_order success, memory_order failure) noexcept; constexpr bool compare_exchange_weak(shared_ptr<T>& expected, shared_ptr<T> desired,
 memory_order order = memory_order::seq_cst) noexcept; constexpr bool compare_exchange_strong(shared_ptr<T>& expected, shared_ptr<T> desired,
 memory_order order = memory_order::seq_cst) noexcept; constexpr void wait(shared_ptr<T> old,
 memory_order order = memory_order::seq_cst) const noexcept; constexpr void notify_one() noexcept; constexpr void notify_all() noexcept; private: shared_ptr<T> p; // *exposition only*};}

[ð](#lib:atomic%3cshared_ptr%3cT%3e%3e,constructor)

`constexpr atomic() noexcept;
`

[1](#shared-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6181)

*Effects*: Value-initializes p[.](#shared-1.sentence-1)

[ð](#lib:atomic%3cshared_ptr%3cT%3e%3e,constructor_)

`constexpr atomic(shared_ptr<T> desired) noexcept;
`

[2](#shared-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6192)

*Effects*: Initializes the object with the value desired[.](#shared-2.sentence-1)

Initialization is not an atomic operation ([[intro.multithread]](intro.multithread "6.10.2 Multi-threaded executions and data races"))[.](#shared-2.sentence-2)

[*Note [1](#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[.](#shared-2.sentence-3)

This results in undefined behavior[.](#shared-2.sentence-4)

â *end note*]

[ð](#lib:store,atomic%3cshared_ptr%3cT%3e%3e)

`constexpr void store(shared_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept;
`

[3](#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[.](#shared-3.sentence-1)

[4](#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)[.](#shared-4.sentence-1)

Memory is affected according to the value of order[.](#shared-4.sentence-2)

[ð](#lib:operator=,atomic%3cshared_ptr%3cT%3e%3e)

`constexpr void operator=(shared_ptr<T> desired) noexcept;
`

[5](#shared-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6234)

*Effects*: Equivalent to store(desired)[.](#shared-5.sentence-1)

[ð](#lib:operator=,atomic%3cshared_ptr%3cT%3e%3e_)

`constexpr void operator=(nullptr_t) noexcept;
`

[6](#shared-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6245)

*Effects*: Equivalent to store(nullptr)[.](#shared-6.sentence-1)

[ð](#lib:load,atomic%3cshared_ptr%3cT%3e%3e)

`constexpr shared_ptr<T> load(memory_order order = memory_order::seq_cst) const noexcept;
`

[7](#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[.](#shared-7.sentence-1)

[8](#shared-8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6263)

*Effects*: Memory is affected according to the value of order[.](#shared-8.sentence-1)

[9](#shared-9)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6267)

*Returns*: Atomically returns p[.](#shared-9.sentence-1)

[ð](#lib:operator_shared_ptr%3cT%3e,atomic%3cshared_ptr%3cT%3e%3e)

`constexpr operator shared_ptr<T>() const noexcept;
`

[10](#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<T> exchange(shared_ptr<T> desired,
                                 memory_order order = memory_order::seq_cst) noexcept;
`

[11](#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)[.](#shared-11.sentence-1)

Memory is affected according to the value of order[.](#shared-11.sentence-2)

This is an atomic read-modify-write operation ([[intro.races]](intro.races "6.10.2.2 Data races"))[.](#shared-11.sentence-3)

[12](#shared-12)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6297)

*Returns*: Atomically returns the value of p immediately before the effects[.](#shared-12.sentence-1)

[ð](#lib:compare_exchange_weak,atomic%3cshared_ptr%3cT%3e%3e)

`constexpr bool compare_exchange_weak(shared_ptr<T>& expected, shared_ptr<T> desired,
                                     memory_order success, memory_order failure) noexcept;
constexpr bool compare_exchange_strong(shared_ptr<T>& expected, shared_ptr<T> desired,
                                       memory_order success, memory_order failure) noexcept;
`

[13](#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[.](#shared-13.sentence-1)

[14](#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[.](#shared-14.sentence-1)

[15](#shared-15)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6327)

*Returns*: true if p was equivalent to expected,false otherwise[.](#shared-15.sentence-1)

[16](#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[.](#shared-16.sentence-1)

The weak form may fail spuriously[.](#shared-16.sentence-2)

See [[atomics.types.operations]](atomics.types.operations "32.5.8.2 Operations on atomic types")[.](#shared-16.sentence-3)

[17](#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[.](#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[.](#shared-17.sentence-2)

The use_count update corresponding to the write to expected is part of the atomic operation[.](#shared-17.sentence-3)

The write to expected itself
is not required to be part of the atomic operation[.](#shared-17.sentence-4)

[ð](#lib:compare_exchange_weak,atomic%3cshared_ptr%3cT%3e%3e_)

`constexpr bool compare_exchange_weak(shared_ptr<T>& expected, shared_ptr<T> desired,
                                     memory_order order = memory_order::seq_cst) noexcept;
`

[18](#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[.](#shared-18.sentence-1)

[ð](#lib:compare_exchange_strong,atomic%3cshared_ptr%3cT%3e%3e_)

`constexpr bool compare_exchange_strong(shared_ptr<T>& expected, shared_ptr<T> desired,
                                       memory_order order = memory_order::seq_cst) noexcept;
`

[19](#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[.](#shared-19.sentence-1)

[ð](#lib:wait,atomic%3cshared_ptr%3cT%3e%3e)

`constexpr void wait(shared_ptr<T> old, memory_order order = memory_order::seq_cst) const noexcept;
`

[20](#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[.](#shared-20.sentence-1)

[21](#shared-21)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6406)

*Effects*: Repeatedly performs the following steps, in order:

- [(21.1)](#shared-21.1)

  Evaluates load(order) and compares it to old[.](#shared-21.1.sentence-1)

- [(21.2)](#shared-21.2)

  If the two are not equivalent, returns[.](#shared-21.2.sentence-1)

- [(21.3)](#shared-21.3)

  Blocks until it
 is unblocked by an atomic notifying operation or is unblocked spuriously[.](#shared-21.3.sentence-1)

[22](#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[.](#shared-22.sentence-1)

This function is an atomic waiting operation ([[atomics.wait]](atomics.wait "32.5.6 Waiting and notifying"))[.](#shared-22.sentence-2)

[ð](#lib:notify_one,atomic%3cshared_ptr%3cT%3e%3e)

`constexpr void notify_one() noexcept;
`

[23](#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]](atomics.wait "32.5.6 Waiting and notifying")) by this call,
if any such atomic waiting operations exist[.](#shared-23.sentence-1)

[24](#shared-24)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6438)

*Remarks*: This function is an atomic notifying operation ([[atomics.wait]](atomics.wait "32.5.6 Waiting and notifying"))[.](#shared-24.sentence-1)

[ð](#lib:notify_all,atomic%3cshared_ptr%3cT%3e%3e)

`constexpr void notify_all() noexcept;
`

[25](#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]](atomics.wait "32.5.6 Waiting and notifying")) by this call[.](#shared-25.sentence-1)

[26](#shared-26)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6454)

*Remarks*: This function is an atomic notifying operation ([[atomics.wait]](atomics.wait "32.5.6 Waiting and notifying"))[.](#shared-26.sentence-1)

#### [32.5.8.7.3](#weak) Partial specialization for weak_ptr [[util.smartptr.atomic.weak]](util.smartptr.atomic.weak)

[ð](#lib:atomic%3cweak_ptr%3cT%3e%3e)

namespace std {template<class T> struct atomic<weak_ptr<T>> {using value_type = weak_ptr<T>; static constexpr bool is_always_lock_free = *implementation-defined*; bool is_lock_free() const noexcept; constexpr atomic() noexcept; constexpr atomic(weak_ptr<T> desired) noexcept;
 atomic(const atomic&) = delete; void operator=(const atomic&) = delete; constexpr weak_ptr<T> load(memory_order order = memory_order::seq_cst) const noexcept; constexpr operator weak_ptr<T>() const noexcept; constexpr void store(weak_ptr<T> desired,
 memory_order order = memory_order::seq_cst) noexcept; constexpr void operator=(weak_ptr<T> desired) noexcept; constexpr weak_ptr<T> exchange(weak_ptr<T> desired,
 memory_order order = memory_order::seq_cst) noexcept; constexpr bool compare_exchange_weak(weak_ptr<T>& expected, weak_ptr<T> desired,
 memory_order success, memory_order failure) noexcept; constexpr bool compare_exchange_strong(weak_ptr<T>& expected, weak_ptr<T> desired,
 memory_order success, memory_order failure) noexcept; constexpr bool compare_exchange_weak(weak_ptr<T>& expected, weak_ptr<T> desired,
 memory_order order = memory_order::seq_cst) noexcept; constexpr bool compare_exchange_strong(weak_ptr<T>& expected, weak_ptr<T> desired,
 memory_order order = memory_order::seq_cst) noexcept; constexpr void wait(weak_ptr<T> old,
 memory_order order = memory_order::seq_cst) const noexcept; constexpr void notify_one() noexcept; constexpr void notify_all() noexcept; private: weak_ptr<T> p; // *exposition only*};}

[ð](#lib:atomic%3cweak_ptr%3cT%3e%3e,constructor)

`constexpr atomic() noexcept;
`

[1](#weak-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6509)

*Effects*: Value-initializes p[.](#weak-1.sentence-1)

[ð](#lib:atomic%3cweak_ptr%3cT%3e%3e,constructor_)

`constexpr atomic(weak_ptr<T> desired) noexcept;
`

[2](#weak-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6520)

*Effects*: Initializes the object with the value desired[.](#weak-2.sentence-1)

Initialization is not an atomic operation ([[intro.multithread]](intro.multithread "6.10.2 Multi-threaded executions and data races"))[.](#weak-2.sentence-2)

[*Note [1](#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[.](#weak-2.sentence-3)

This results in undefined behavior[.](#weak-2.sentence-4)

â *end note*]

[ð](#lib:store,atomic%3cweak_ptr%3cT%3e%3e)

`constexpr void store(weak_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept;
`

[3](#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[.](#weak-3.sentence-1)

[4](#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)[.](#weak-4.sentence-1)

Memory is affected according to the value of order[.](#weak-4.sentence-2)

[ð](#lib:operator=,atomic%3cweak_ptr%3cT%3e%3e)

`constexpr void operator=(weak_ptr<T> desired) noexcept;
`

[5](#weak-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6562)

*Effects*: Equivalent to store(desired)[.](#weak-5.sentence-1)

[ð](#lib:load,atomic%3cweak_ptr%3cT%3e%3e)

`constexpr weak_ptr<T> load(memory_order order = memory_order::seq_cst) const noexcept;
`

[6](#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[.](#weak-6.sentence-1)

[7](#weak-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6580)

*Effects*: Memory is affected according to the value of order[.](#weak-7.sentence-1)

[8](#weak-8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6584)

*Returns*: Atomically returns p[.](#weak-8.sentence-1)

[ð](#lib:operator_weak_ptr%3cT%3e,atomic%3cweak_ptr%3cT%3e%3e)

`constexpr operator weak_ptr<T>() const noexcept;
`

[9](#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<T> exchange(weak_ptr<T> desired,
                               memory_order order = memory_order::seq_cst) noexcept;
`

[10](#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)[.](#weak-10.sentence-1)

Memory is affected according to the value of order[.](#weak-10.sentence-2)

This is an atomic read-modify-write operation ([[intro.races]](intro.races "6.10.2.2 Data races"))[.](#weak-10.sentence-3)

[11](#weak-11)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6614)

*Returns*: Atomically returns the value of p immediately before the effects[.](#weak-11.sentence-1)

[ð](#lib:compare_exchange_weak,atomic%3cweak_ptr%3cT%3e%3e)

`constexpr bool compare_exchange_weak(weak_ptr<T>& expected, weak_ptr<T> desired,
                                     memory_order success, memory_order failure) noexcept;
constexpr bool compare_exchange_strong(weak_ptr<T>& expected, weak_ptr<T> desired,
                                       memory_order success, memory_order failure) noexcept;
`

[12](#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[.](#weak-12.sentence-1)

[13](#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[.](#weak-13.sentence-1)

[14](#weak-14)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6643)

*Returns*: true if p was equivalent to expected,false otherwise[.](#weak-14.sentence-1)

[15](#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[.](#weak-15.sentence-1)

The weak form may fail spuriously[.](#weak-15.sentence-2)

See [[atomics.types.operations]](atomics.types.operations "32.5.8.2 Operations on atomic types")[.](#weak-15.sentence-3)

[16](#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[.](#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[.](#weak-16.sentence-2)

The use_count update corresponding to the write to expected is part of the atomic operation[.](#weak-16.sentence-3)

The write to expected itself
is not required to be part of the atomic operation[.](#weak-16.sentence-4)

[ð](#lib:compare_exchange_weak,atomic%3cweak_ptr%3cT%3e%3e_)

`constexpr bool compare_exchange_weak(weak_ptr<T>& expected, weak_ptr<T> desired,
                                     memory_order order = memory_order::seq_cst) noexcept;
`

[17](#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[.](#weak-17.sentence-1)

[ð](#lib:compare_exchange_strong,atomic%3cweak_ptr%3cT%3e%3e)

`constexpr bool compare_exchange_strong(weak_ptr<T>& expected, weak_ptr<T> desired,
                                       memory_order order = memory_order::seq_cst) noexcept;
`

[18](#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[.](#weak-18.sentence-1)

[ð](#lib:wait,atomic%3cweak_ptr%3cT%3e%3e)

`constexpr void wait(weak_ptr<T> old, memory_order order = memory_order::seq_cst) const noexcept;
`

[19](#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[.](#weak-19.sentence-1)

[20](#weak-20)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6722)

*Effects*: Repeatedly performs the following steps, in order:

- [(20.1)](#weak-20.1)

  Evaluates load(order) and compares it to old[.](#weak-20.1.sentence-1)

- [(20.2)](#weak-20.2)

  If the two are not equivalent, returns[.](#weak-20.2.sentence-1)

- [(20.3)](#weak-20.3)

  Blocks until it
 is unblocked by an atomic notifying operation or is unblocked spuriously[.](#weak-20.3.sentence-1)

[21](#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[.](#weak-21.sentence-1)

This function is an atomic waiting operation ([[atomics.wait]](atomics.wait "32.5.6 Waiting and notifying"))[.](#weak-21.sentence-2)

[ð](#lib:notify_one,atomic%3cweak_ptr%3cT%3e%3e)

`constexpr void notify_one() noexcept;
`

[22](#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]](atomics.wait "32.5.6 Waiting and notifying")) by this call,
if any such atomic waiting operations exist[.](#weak-22.sentence-1)

[23](#weak-23)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6755)

*Remarks*: This function is an atomic notifying operation ([[atomics.wait]](atomics.wait "32.5.6 Waiting and notifying"))[.](#weak-23.sentence-1)

[ð](#lib:notify_all,atomic%3cweak_ptr%3cT%3e%3e)

`constexpr void notify_all() noexcept;
`

[24](#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]](atomics.wait "32.5.6 Waiting and notifying")) by this call[.](#weak-24.sentence-1)

[25](#weak-25)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6771)

*Remarks*: This function is an atomic notifying operation ([[atomics.wait]](atomics.wait "32.5.6 Waiting and notifying"))[.](#weak-25.sentence-1)
