[util.smartptr.atomic.shared]

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

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

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

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

#### 32.5.8.7.2 Partial specialization for shared_ptr [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](#1)

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

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

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

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

[2](#2)

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

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

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

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

This results in undefined behavior[.](#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](#3)

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

*Preconditions*: order ismemory_order​::​relaxed,memory_order​::​release, ormemory_order​::​seq_cst[.](#3.sentence-1)

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

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

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

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

[5](#5)

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

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

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

`constexpr void operator=(nullptr_t) noexcept;
`

[6](#6)

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

*Effects*: Equivalent to store(nullptr)[.](#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](#7)

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

*Preconditions*: order ismemory_order​::​relaxed,memory_order​::​acquire, ormemory_order​::​seq_cst[.](#7.sentence-1)

[8](#8)

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

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

[9](#9)

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

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

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

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

[10](#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](#11)

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

*Effects*: Atomically replaces p with desired as if by p.swap(desired)[.](#11.sentence-1)

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

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

[12](#12)

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

*Returns*: Atomically returns the value of p immediately before the effects[.](#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](#13)

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

*Preconditions*: failure ismemory_order​::​relaxed,memory_order​::​acquire, ormemory_order​::​seq_cst[.](#13.sentence-1)

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

[15](#15)

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

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

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

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

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

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

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

The write to expected itself
is not required to be part of the atomic operation[.](#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](#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[.](#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](#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[.](#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](#20)

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

*Preconditions*: order ismemory_order​::​relaxed,memory_order​::​acquire, ormemory_order​::​seq_cst[.](#20.sentence-1)

[21](#21)

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

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

- [(21.1)](#21.1)

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

- [(21.2)](#21.2)

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

- [(21.3)](#21.3)

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

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

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

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

`constexpr void notify_one() noexcept;
`

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

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

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

`constexpr void notify_all() noexcept;
`

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

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