184 lines
8.8 KiB
Markdown
184 lines
8.8 KiB
Markdown
[atomics.ref.pointer]
|
||
|
||
# 32 Concurrency support library [[thread]](./#thread)
|
||
|
||
## 32.5 Atomic operations [[atomics]](atomics#ref.pointer)
|
||
|
||
### 32.5.7 Class template atomic_ref [[atomics.ref.generic]](atomics.ref.generic#atomics.ref.pointer)
|
||
|
||
#### 32.5.7.5 Specialization for pointers [atomics.ref.pointer]
|
||
|
||
[1](#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[.](#1.sentence-1)
|
||
|
||
For each such type *pointer-type*,
|
||
the specialization atomic_ref<*pointer-type*> provides
|
||
additional atomic operations appropriate to pointer types[.](#1.sentence-2)
|
||
|
||
[2](#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[.](#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](#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[.](#3.sentence-1)
|
||
|
||
[4](#4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4256)
|
||
|
||
The following operations perform arithmetic computations[.](#4.sentence-1)
|
||
|
||
The correspondence among key, operator, and computation is specified
|
||
in Table [156](atomics.types.pointer#tab:atomic.types.pointer.comp "Table 156: Atomic pointer computations")[.](#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](#5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4271)
|
||
|
||
*Constraints*: is_const_v<*pointer-type*> is false[.](#5.sentence-1)
|
||
|
||
[6](#6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4275)
|
||
|
||
*Mandates*: remove_pointer_t<*pointer-type*> is a complete object type[.](#6.sentence-1)
|
||
|
||
[7](#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[.](#7.sentence-1)
|
||
|
||
Memory is affected according to the value of order[.](#7.sentence-2)
|
||
|
||
These operations are atomic read-modify-write operations ([[intro.races]](intro.races "6.10.2.2 Data races"))[.](#7.sentence-3)
|
||
|
||
[8](#8)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4287)
|
||
|
||
*Returns*: Atomically, the value referenced by *ptr immediately before the effects[.](#8.sentence-1)
|
||
|
||
[9](#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[.](#9.sentence-1)
|
||
|
||
[10](#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[.](#10.sentence-1)
|
||
|
||
[*Note [1](#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"))[.](#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](#11)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4320)
|
||
|
||
*Mandates*: T is a complete object type[.](#11.sentence-1)
|
||
|
||
[12](#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[.](#12.sentence-1)
|
||
|
||
[13](#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[.](#13.sentence-1)
|
||
|
||
Memory is affected according to the value of order[.](#13.sentence-2)
|
||
|
||
These operations are atomic modify-write operations ([[atomics.order]](atomics.order "32.5.4 Order and consistency"))[.](#13.sentence-3)
|
||
|
||
[14](#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[.](#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[.](#14.sentence-2)
|
||
|
||
[*Note [2](#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"))[.](#14.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
[ð](#lib:operator+=,atomic_ref%3cpointer-type%3e)
|
||
|
||
`constexpr value_type operator op=(difference_type operand) const noexcept;
|
||
`
|
||
|
||
[15](#15)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4360)
|
||
|
||
*Constraints*: is_const_v<*pointer-type*> is false[.](#15.sentence-1)
|
||
|
||
[16](#16)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4364)
|
||
|
||
*Effects*: Equivalent to:return fetch_*key*(operand) *op* operand;
|