From Jason Turner

[atomics]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmpmevuj5r9/{from.md → to.md} +592 -452
tmp/tmpmevuj5r9/{from.md → to.md} RENAMED
@@ -1,291 +1,301 @@
1
- # Atomic operations library <a id="atomics">[[atomics]]</a>
2
 
3
- ## General <a id="atomics.general">[[atomics.general]]</a>
4
 
5
- This Clause describes components for fine-grained atomic access. This
6
- access is provided via operations on atomic objects.
7
 
8
- The following subclauses describe atomics requirements and components
9
- for types and operations, as summarized in [[atomics.summary]].
10
-
11
- **Table: Atomics library summary** <a id="atomics.summary">[atomics.summary]</a>
12
-
13
- | Subclause | | Header |
14
- | ------------------------- | --------------------------- | ---------- |
15
- | [[atomics.alias]] | Type aliases | `<atomic>` |
16
- | [[atomics.order]] | Order and consistency | |
17
- | [[atomics.lockfree]] | Lock-free property | |
18
- | [[atomics.wait]] | Waiting and notifying | |
19
- | [[atomics.ref.generic]] | Class template `atomic_ref` | |
20
- | [[atomics.types.generic]] | Class template `atomic` | |
21
- | [[atomics.nonmembers]] | Non-member functions | |
22
- | [[atomics.flag]] | Flag type and operations | |
23
- | [[atomics.fences]] | Fences | |
24
-
25
-
26
- ## Header `<atomic>` synopsis <a id="atomics.syn">[[atomics.syn]]</a>
27
 
28
  ``` cpp
29
  namespace std {
30
  // [atomics.order], order and consistency
31
- enum class memory_order : unspecified;
 
 
 
 
 
 
 
32
  template<class T>
33
- T kill_dependency(T y) noexcept;
 
34
 
35
  // [atomics.lockfree], lock-free property
36
- #define ATOMIC_BOOL_LOCK_FREE unspecified
37
- #define ATOMIC_CHAR_LOCK_FREE unspecified
38
- #define ATOMIC_CHAR8_T_LOCK_FREE unspecified
39
- #define ATOMIC_CHAR16_T_LOCK_FREE unspecified
40
- #define ATOMIC_CHAR32_T_LOCK_FREE unspecified
41
- #define ATOMIC_WCHAR_T_LOCK_FREE unspecified
42
- #define ATOMIC_SHORT_LOCK_FREE unspecified
43
- #define ATOMIC_INT_LOCK_FREE unspecified
44
- #define ATOMIC_LONG_LOCK_FREE unspecified
45
- #define ATOMIC_LLONG_LOCK_FREE unspecified
46
- #define ATOMIC_POINTER_LOCK_FREE unspecified
47
 
 
48
  // [atomics.ref.generic], class template atomic_ref
49
- template<class T> struct atomic_ref;
50
  // [atomics.ref.pointer], partial specialization for pointers
51
- template<class T> struct atomic_ref<T*>;
52
 
53
  // [atomics.types.generic], class template atomic
54
- template<class T> struct atomic;
55
  // [atomics.types.pointer], partial specialization for pointers
56
- template<class T> struct atomic<T*>;
57
 
58
  // [atomics.nonmembers], non-member functions
59
  template<class T>
60
- bool atomic_is_lock_free(const volatile atomic<T>*) noexcept;
61
  template<class T>
62
- bool atomic_is_lock_free(const atomic<T>*) noexcept;
63
  template<class T>
64
- void atomic_store(volatile atomic<T>*, typename atomic<T>::value_type) noexcept;
 
65
  template<class T>
66
- void atomic_store(atomic<T>*, typename atomic<T>::value_type) noexcept;
67
  template<class T>
68
- void atomic_store_explicit(volatile atomic<T>*, typename atomic<T>::value_type,
 
69
  memory_order) noexcept;
70
  template<class T>
71
- void atomic_store_explicit(atomic<T>*, typename atomic<T>::value_type,
72
  memory_order) noexcept;
73
  template<class T>
74
- T atomic_load(const volatile atomic<T>*) noexcept;
75
  template<class T>
76
- T atomic_load(const atomic<T>*) noexcept;
77
  template<class T>
78
- T atomic_load_explicit(const volatile atomic<T>*, memory_order) noexcept;
79
  template<class T>
80
- T atomic_load_explicit(const atomic<T>*, memory_order) noexcept;
81
  template<class T>
82
- T atomic_exchange(volatile atomic<T>*, typename atomic<T>::value_type) noexcept;
 
83
  template<class T>
84
- T atomic_exchange(atomic<T>*, typename atomic<T>::value_type) noexcept;
85
  template<class T>
86
- T atomic_exchange_explicit(volatile atomic<T>*, typename atomic<T>::value_type,
 
87
  memory_order) noexcept;
88
  template<class T>
89
- T atomic_exchange_explicit(atomic<T>*, typename atomic<T>::value_type,
90
  memory_order) noexcept;
91
  template<class T>
92
- bool atomic_compare_exchange_weak(volatile atomic<T>*,
93
  typename atomic<T>::value_type*,
94
  typename atomic<T>::value_type) noexcept;
95
  template<class T>
96
- bool atomic_compare_exchange_weak(atomic<T>*,
97
  typename atomic<T>::value_type*,
98
  typename atomic<T>::value_type) noexcept;
99
  template<class T>
100
- bool atomic_compare_exchange_strong(volatile atomic<T>*,
101
  typename atomic<T>::value_type*,
102
  typename atomic<T>::value_type) noexcept;
103
  template<class T>
104
- bool atomic_compare_exchange_strong(atomic<T>*,
105
  typename atomic<T>::value_type*,
106
  typename atomic<T>::value_type) noexcept;
107
  template<class T>
108
- bool atomic_compare_exchange_weak_explicit(volatile atomic<T>*,
109
  typename atomic<T>::value_type*,
110
  typename atomic<T>::value_type,
111
  memory_order, memory_order) noexcept;
112
  template<class T>
113
- bool atomic_compare_exchange_weak_explicit(atomic<T>*,
114
  typename atomic<T>::value_type*,
115
  typename atomic<T>::value_type,
116
  memory_order, memory_order) noexcept;
117
  template<class T>
118
- bool atomic_compare_exchange_strong_explicit(volatile atomic<T>*,
119
  typename atomic<T>::value_type*,
120
  typename atomic<T>::value_type,
121
  memory_order, memory_order) noexcept;
122
  template<class T>
123
- bool atomic_compare_exchange_strong_explicit(atomic<T>*,
124
  typename atomic<T>::value_type*,
125
  typename atomic<T>::value_type,
126
  memory_order, memory_order) noexcept;
127
 
128
  template<class T>
129
- T atomic_fetch_add(volatile atomic<T>*, typename atomic<T>::difference_type) noexcept;
 
130
  template<class T>
131
- T atomic_fetch_add(atomic<T>*, typename atomic<T>::difference_type) noexcept;
132
  template<class T>
133
- T atomic_fetch_add_explicit(volatile atomic<T>*, typename atomic<T>::difference_type,
 
134
  memory_order) noexcept;
135
  template<class T>
136
- T atomic_fetch_add_explicit(atomic<T>*, typename atomic<T>::difference_type,
137
  memory_order) noexcept;
138
  template<class T>
139
- T atomic_fetch_sub(volatile atomic<T>*, typename atomic<T>::difference_type) noexcept;
 
140
  template<class T>
141
- T atomic_fetch_sub(atomic<T>*, typename atomic<T>::difference_type) noexcept;
142
  template<class T>
143
- T atomic_fetch_sub_explicit(volatile atomic<T>*, typename atomic<T>::difference_type,
 
144
  memory_order) noexcept;
145
  template<class T>
146
- T atomic_fetch_sub_explicit(atomic<T>*, typename atomic<T>::difference_type,
147
  memory_order) noexcept;
148
  template<class T>
149
- T atomic_fetch_and(volatile atomic<T>*, typename atomic<T>::value_type) noexcept;
 
150
  template<class T>
151
- T atomic_fetch_and(atomic<T>*, typename atomic<T>::value_type) noexcept;
152
  template<class T>
153
- T atomic_fetch_and_explicit(volatile atomic<T>*, typename atomic<T>::value_type,
 
154
  memory_order) noexcept;
155
  template<class T>
156
- T atomic_fetch_and_explicit(atomic<T>*, typename atomic<T>::value_type,
157
  memory_order) noexcept;
158
  template<class T>
159
- T atomic_fetch_or(volatile atomic<T>*, typename atomic<T>::value_type) noexcept;
 
160
  template<class T>
161
- T atomic_fetch_or(atomic<T>*, typename atomic<T>::value_type) noexcept;
162
  template<class T>
163
- T atomic_fetch_or_explicit(volatile atomic<T>*, typename atomic<T>::value_type,
 
164
  memory_order) noexcept;
165
  template<class T>
166
- T atomic_fetch_or_explicit(atomic<T>*, typename atomic<T>::value_type,
167
  memory_order) noexcept;
168
  template<class T>
169
- T atomic_fetch_xor(volatile atomic<T>*, typename atomic<T>::value_type) noexcept;
 
170
  template<class T>
171
- T atomic_fetch_xor(atomic<T>*, typename atomic<T>::value_type) noexcept;
172
  template<class T>
173
- T atomic_fetch_xor_explicit(volatile atomic<T>*, typename atomic<T>::value_type,
 
174
  memory_order) noexcept;
175
  template<class T>
176
- T atomic_fetch_xor_explicit(atomic<T>*, typename atomic<T>::value_type,
177
  memory_order) noexcept;
178
 
179
  template<class T>
180
- void atomic_wait(const volatile atomic<T>*, typename atomic<T>::value_type);
 
181
  template<class T>
182
- void atomic_wait(const atomic<T>*, typename atomic<T>::value_type);
183
  template<class T>
184
- void atomic_wait_explicit(const volatile atomic<T>*, typename atomic<T>::value_type,
185
- memory_order);
 
186
  template<class T>
187
- void atomic_wait_explicit(const atomic<T>*, typename atomic<T>::value_type,
188
- memory_order);
189
  template<class T>
190
- void atomic_notify_one(volatile atomic<T>*);
191
  template<class T>
192
- void atomic_notify_one(atomic<T>*);
193
  template<class T>
194
- void atomic_notify_all(volatile atomic<T>*);
195
  template<class T>
196
- void atomic_notify_all(atomic<T>*);
197
 
198
  // [atomics.alias], type aliases
199
- using atomic_bool = atomic<bool>;
200
- using atomic_char = atomic<char>;
201
- using atomic_schar = atomic<signed char>;
202
- using atomic_uchar = atomic<unsigned char>;
203
- using atomic_short = atomic<short>;
204
- using atomic_ushort = atomic<unsigned short>;
205
- using atomic_int = atomic<int>;
206
- using atomic_uint = atomic<unsigned int>;
207
- using atomic_long = atomic<long>;
208
- using atomic_ulong = atomic<unsigned long>;
209
- using atomic_llong = atomic<long long>;
210
- using atomic_ullong = atomic<unsigned long long>;
211
- using atomic_char8_t = atomic<char8_t>;
212
- using atomic_char16_t = atomic<char16_t>;
213
- using atomic_char32_t = atomic<char32_t>;
214
- using atomic_wchar_t = atomic<wchar_t>;
215
 
216
- using atomic_int8_t = atomic<int8_t>;
217
- using atomic_uint8_t = atomic<uint8_t>;
218
- using atomic_int16_t = atomic<int16_t>;
219
- using atomic_uint16_t = atomic<uint16_t>;
220
- using atomic_int32_t = atomic<int32_t>;
221
- using atomic_uint32_t = atomic<uint32_t>;
222
- using atomic_int64_t = atomic<int64_t>;
223
- using atomic_uint64_t = atomic<uint64_t>;
224
 
225
- using atomic_int_least8_t = atomic<int_least8_t>;
226
- using atomic_uint_least8_t = atomic<uint_least8_t>;
227
- using atomic_int_least16_t = atomic<int_least16_t>;
228
- using atomic_uint_least16_t = atomic<uint_least16_t>;
229
- using atomic_int_least32_t = atomic<int_least32_t>;
230
- using atomic_uint_least32_t = atomic<uint_least32_t>;
231
- using atomic_int_least64_t = atomic<int_least64_t>;
232
- using atomic_uint_least64_t = atomic<uint_least64_t>;
233
 
234
- using atomic_int_fast8_t = atomic<int_fast8_t>;
235
- using atomic_uint_fast8_t = atomic<uint_fast8_t>;
236
- using atomic_int_fast16_t = atomic<int_fast16_t>;
237
- using atomic_uint_fast16_t = atomic<uint_fast16_t>;
238
- using atomic_int_fast32_t = atomic<int_fast32_t>;
239
- using atomic_uint_fast32_t = atomic<uint_fast32_t>;
240
- using atomic_int_fast64_t = atomic<int_fast64_t>;
241
- using atomic_uint_fast64_t = atomic<uint_fast64_t>;
242
 
243
- using atomic_intptr_t = atomic<intptr_t>;
244
- using atomic_uintptr_t = atomic<uintptr_t>;
245
- using atomic_size_t = atomic<size_t>;
246
- using atomic_ptrdiff_t = atomic<ptrdiff_t>;
247
- using atomic_intmax_t = atomic<intmax_t>;
248
- using atomic_uintmax_t = atomic<uintmax_t>;
249
 
250
  using atomic_signed_lock_free = see below;
251
  using atomic_unsigned_lock_free = see below;
252
 
253
  // [atomics.flag], flag type and operations
254
- struct atomic_flag;
255
 
256
- bool atomic_flag_test(const volatile atomic_flag*) noexcept;
257
- bool atomic_flag_test(const atomic_flag*) noexcept;
258
- bool atomic_flag_test_explicit(const volatile atomic_flag*, memory_order) noexcept;
259
- bool atomic_flag_test_explicit(const atomic_flag*, memory_order) noexcept;
260
- bool atomic_flag_test_and_set(volatile atomic_flag*) noexcept;
261
- bool atomic_flag_test_and_set(atomic_flag*) noexcept;
262
- bool atomic_flag_test_and_set_explicit(volatile atomic_flag*, memory_order) noexcept;
263
- bool atomic_flag_test_and_set_explicit(atomic_flag*, memory_order) noexcept;
264
- void atomic_flag_clear(volatile atomic_flag*) noexcept;
265
- void atomic_flag_clear(atomic_flag*) noexcept;
266
- void atomic_flag_clear_explicit(volatile atomic_flag*, memory_order) noexcept;
267
- void atomic_flag_clear_explicit(atomic_flag*, memory_order) noexcept;
 
 
268
 
269
- void atomic_flag_wait(const volatile atomic_flag*, bool) noexcept;
270
- void atomic_flag_wait(const atomic_flag*, bool) noexcept;
271
- void atomic_flag_wait_explicit(const volatile atomic_flag*,
272
  bool, memory_order) noexcept;
273
- void atomic_flag_wait_explicit(const atomic_flag*,
274
  bool, memory_order) noexcept;
275
- void atomic_flag_notify_one(volatile atomic_flag*) noexcept;
276
- void atomic_flag_notify_one(atomic_flag*) noexcept;
277
- void atomic_flag_notify_all(volatile atomic_flag*) noexcept;
278
- void atomic_flag_notify_all(atomic_flag*) noexcept;
 
279
 
280
  // [atomics.fences], fences
281
- extern "C" void atomic_thread_fence(memory_order) noexcept;
282
- extern "C" void atomic_signal_fence(memory_order) noexcept;
283
  }
284
  ```
285
 
286
- ## Type aliases <a id="atomics.alias">[[atomics.alias]]</a>
287
 
288
  The type aliases `atomic_intN_t`, `atomic_uintN_t`, `atomic_intptr_t`,
289
  and `atomic_uintptr_t` are defined if and only if `intN_t`, `uintN_t`,
290
  `intptr_t`, and `uintptr_t` are defined, respectively.
291
 
@@ -299,23 +309,17 @@ and whose `is_always_lock_free` property is `true`.
299
 
300
  Implementations should choose for these aliases the integral
301
  specializations of `atomic` for which the atomic waiting and notifying
302
  operations [[atomics.wait]] are most efficient.
303
 
304
- ## Order and consistency <a id="atomics.order">[[atomics.order]]</a>
305
 
306
  ``` cpp
307
  namespace std {
308
  enum class memory_order : unspecified {
309
  relaxed, consume, acquire, release, acq_rel, seq_cst
310
  };
311
- inline constexpr memory_order memory_order_relaxed = memory_order::relaxed;
312
- inline constexpr memory_order memory_order_consume = memory_order::consume;
313
- inline constexpr memory_order memory_order_acquire = memory_order::acquire;
314
- inline constexpr memory_order memory_order_release = memory_order::release;
315
- inline constexpr memory_order memory_order_acq_rel = memory_order::acq_rel;
316
- inline constexpr memory_order memory_order_seq_cst = memory_order::seq_cst;
317
  }
318
  ```
319
 
320
  The enumeration `memory_order` specifies the detailed regular
321
  (non-atomic) memory synchronization order as defined in
@@ -413,14 +417,14 @@ x.store(r1, memory_order::relaxed);
413
  // Thread 2:
414
  r2 = x.load(memory_order::relaxed);
415
  y.store(r2, memory_order::relaxed);
416
  ```
417
 
418
- should not produce `r1 == r2 == 42`, since the store of 42 to `y` is
419
- only possible if the store to `x` stores `42`, which circularly depends
420
- on the store to `y` storing `42`. Note that without this restriction,
421
- such an execution is possible.
422
 
423
  — *end note*]
424
 
425
  [*Note 7*:
426
 
@@ -456,11 +460,11 @@ template<class T>
456
  *Effects:* The argument does not carry a dependency to the return
457
  value [[intro.multithread]].
458
 
459
  *Returns:* `y`.
460
 
461
- ## Lock-free property <a id="atomics.lockfree">[[atomics.lockfree]]</a>
462
 
463
  ``` cpp
464
  #define ATOMIC_BOOL_LOCK_FREE unspecified
465
  #define ATOMIC_CHAR_LOCK_FREE unspecified
466
  #define ATOMIC_CHAR8_T_LOCK_FREE unspecified
@@ -480,33 +484,34 @@ grouped together. The properties also apply to the corresponding
480
  (partial) specializations of the `atomic` template. A value of 0
481
  indicates that the types are never lock-free. A value of 1 indicates
482
  that the types are sometimes lock-free. A value of 2 indicates that the
483
  types are always lock-free.
484
 
485
- At least one signed integral specialization of the `atomic` template,
486
- along with the specialization for the corresponding unsigned type
487
- [[basic.fundamental]], is always lock-free.
 
488
 
489
- [*Note 1*: This requirement is optional in freestanding implementations
490
- [[compliance]]. *end note*]
491
-
492
- The function `atomic_is_lock_free` [[atomics.types.operations]]
493
- indicates whether the object is lock-free. In any given program
494
- execution, the result of the lock-free query shall be consistent for all
495
- pointers of the same type.
496
 
497
  Atomic operations that are not lock-free are considered to potentially
498
  block [[intro.progress]].
499
 
500
- [*Note 2*: Operations that are lock-free should also be address-free.
501
- That is, atomic operations on the same memory location via two different
502
- addresses will communicate atomically. The implementation should not
503
- depend on any per-process state. This restriction enables communication
504
- by memory that is mapped into a process more than once and by memory
505
- that is shared between two processes. — *end note*]
506
 
507
- ## Waiting and notifying <a id="atomics.wait">[[atomics.wait]]</a>
 
 
 
 
 
 
 
508
 
509
  *Atomic waiting operations* and *atomic notifying operations* provide a
510
  mechanism to wait for the value of an atomic object to change more
511
  efficiently than can be achieved with polling. An atomic waiting
512
  operation may block until it is unblocked by an atomic notifying
@@ -547,17 +552,20 @@ A call to an atomic waiting operation on an atomic object `M` is
547
  - the atomic waiting operation has blocked after observing the result of
548
  `X`,
549
  - `X` precedes `Y` in the modification order of `M`, and
550
  - `Y` happens before the call to the atomic notifying operation.
551
 
552
- ## Class template `atomic_ref` <a id="atomics.ref.generic">[[atomics.ref.generic]]</a>
 
 
553
 
554
  ``` cpp
555
  namespace std {
556
  template<class T> struct atomic_ref {
557
  private:
558
  T* ptr; // exposition only
 
559
  public:
560
  using value_type = T;
561
  static constexpr size_t required_alignment = implementation-defined // required alignment for atomic_ref type's operations;
562
 
563
  static constexpr bool is_always_lock_free = implementation-defined // whether a given atomic_ref type's operations are always lock free;
@@ -606,16 +614,16 @@ object.
606
 
607
  Atomic operations applied to an object through a referencing
608
  `atomic_ref` are atomic with respect to atomic operations applied
609
  through any other `atomic_ref` referencing the same object.
610
 
611
- [*Note 1*: Atomic operations or the `atomic_ref` constructor could
612
  acquire a shared resource, such as a lock associated with the referenced
613
  object, to enable atomic operations to be applied to the referenced
614
  object. — *end note*]
615
 
616
- ### Operations <a id="atomics.ref.ops">[[atomics.ref.ops]]</a>
617
 
618
  ``` cpp
619
  static constexpr size_t required_alignment;
620
  ```
621
 
@@ -802,94 +810,96 @@ void notify_all() const noexcept;
802
  `*ptr` that are eligible to be unblocked [[atomics.wait]] by this call.
803
 
804
  *Remarks:* This function is an atomic notifying
805
  operation [[atomics.wait]] on atomic object `*ptr`.
806
 
807
- ### Specializations for integral types <a id="atomics.ref.int">[[atomics.ref.int]]</a>
808
 
809
  There are specializations of the `atomic_ref` class template for the
810
  integral types `char`, `signed char`, `unsigned char`, `short`,
811
  `unsigned short`, `int`, `unsigned int`, `long`, `unsigned long`,
812
  `long long`, `unsigned long long`, `char8_t`, `char16_t`, `char32_t`,
813
  `wchar_t`, and any other types needed by the typedefs in the header
814
- `<cstdint>`. For each such type `integral`, the specialization
815
- `atomic_ref<integral>` provides additional atomic operations appropriate
816
- to integral types.
817
 
818
  [*Note 1*: The specialization `atomic_ref<bool>` uses the primary
819
  template [[atomics.ref.generic]]. — *end note*]
820
 
821
  ``` cpp
822
  namespace std {
823
- template<> struct atomic_ref<integral> {
824
  private:
825
- integral* ptr; // exposition only
 
826
  public:
827
- using value_type = integral;
828
  using difference_type = value_type;
829
  static constexpr size_t required_alignment = implementation-defined // required alignment for atomic_ref type's operations;
830
 
831
  static constexpr bool is_always_lock_free = implementation-defined // whether a given atomic_ref type's operations are always lock free;
832
  bool is_lock_free() const noexcept;
833
 
834
- explicit atomic_ref(integral&);
835
  atomic_ref(const atomic_ref&) noexcept;
836
  atomic_ref& operator=(const atomic_ref&) = delete;
837
 
838
- void store(integral, memory_order = memory_order::seq_cst) const noexcept;
839
- integral operator=(integral) const noexcept;
840
- integral load(memory_order = memory_order::seq_cst) const noexcept;
841
- operator integral() const noexcept;
842
 
843
- integral exchange(integral,
844
  memory_order = memory_order::seq_cst) const noexcept;
845
- bool compare_exchange_weak(integral&, integral,
846
  memory_order, memory_order) const noexcept;
847
- bool compare_exchange_strong(integral&, integral,
848
  memory_order, memory_order) const noexcept;
849
- bool compare_exchange_weak(integral&, integral,
850
  memory_order = memory_order::seq_cst) const noexcept;
851
- bool compare_exchange_strong(integral&, integral,
852
  memory_order = memory_order::seq_cst) const noexcept;
853
 
854
- integral fetch_add(integral,
855
  memory_order = memory_order::seq_cst) const noexcept;
856
- integral fetch_sub(integral,
857
  memory_order = memory_order::seq_cst) const noexcept;
858
- integral fetch_and(integral,
859
  memory_order = memory_order::seq_cst) const noexcept;
860
- integral fetch_or(integral,
861
  memory_order = memory_order::seq_cst) const noexcept;
862
- integral fetch_xor(integral,
863
  memory_order = memory_order::seq_cst) const noexcept;
864
 
865
- integral operator++(int) const noexcept;
866
- integral operator--(int) const noexcept;
867
- integral operator++() const noexcept;
868
- integral operator--() const noexcept;
869
- integral operator+=(integral) const noexcept;
870
- integral operator-=(integral) const noexcept;
871
- integral operator&=(integral) const noexcept;
872
- integral operator|=(integral) const noexcept;
873
- integral operator^=(integral) const noexcept;
874
 
875
- void wait(integral, memory_order = memory_order::seq_cst) const noexcept;
876
  void notify_one() const noexcept;
877
  void notify_all() const noexcept;
878
  };
879
  }
880
  ```
881
 
882
  Descriptions are provided below only for members that differ from the
883
  primary template.
884
 
885
- The following operations perform arithmetic computations. The key,
886
- operator, and computation correspondence is identified in
887
  [[atomic.types.int.comp]].
888
 
889
  ``` cpp
890
- integral fetch_key(integral operand, memory_order order = memory_order::seq_cst) const noexcept;
 
891
  ```
892
 
893
  *Effects:* Atomically replaces the value referenced by `*ptr` with the
894
  result of the computation applied to the value referenced by `*ptr` and
895
  the given operand. Memory is affected according to the value of `order`.
@@ -906,81 +916,82 @@ converted back to the signed type.
906
 
907
  [*Note 1*: There are no undefined results arising from the
908
  computation. — *end note*]
909
 
910
  ``` cpp
911
- integral operator op=(integral operand) const noexcept;
912
  ```
913
 
914
  *Effects:* Equivalent to:
915
  `return fetch_`*`key`*`(operand) `*`op`*` operand;`
916
 
917
- ### Specializations for floating-point types <a id="atomics.ref.float">[[atomics.ref.float]]</a>
918
 
919
- There are specializations of the `atomic_ref` class template for the
920
- floating-point types `float`, `double`, and `long double`. For each such
921
- type `floating-point`, the specialization `atomic_ref<floating-point>`
922
  provides additional atomic operations appropriate to floating-point
923
  types.
924
 
925
  ``` cpp
926
  namespace std {
927
- template<> struct atomic_ref<floating-point> {
928
  private:
929
- floating-point* ptr; // exposition only
 
930
  public:
931
- using value_type = floating-point;
932
  using difference_type = value_type;
933
  static constexpr size_t required_alignment = implementation-defined // required alignment for atomic_ref type's operations;
934
 
935
  static constexpr bool is_always_lock_free = implementation-defined // whether a given atomic_ref type's operations are always lock free;
936
  bool is_lock_free() const noexcept;
937
 
938
- explicit atomic_ref(floating-point&);
939
  atomic_ref(const atomic_ref&) noexcept;
940
  atomic_ref& operator=(const atomic_ref&) = delete;
941
 
942
- void store(floating-point, memory_order = memory_order::seq_cst) const noexcept;
943
- floating-point operator=(floating-point) const noexcept;
944
- floating-point load(memory_order = memory_order::seq_cst) const noexcept;
945
- operator floating-point() const noexcept;
946
 
947
- floating-point exchange(floating-point,
948
  memory_order = memory_order::seq_cst) const noexcept;
949
- bool compare_exchange_weak(floating-point&, floating-point,
950
  memory_order, memory_order) const noexcept;
951
- bool compare_exchange_strong(floating-point&, floating-point,
952
  memory_order, memory_order) const noexcept;
953
- bool compare_exchange_weak(floating-point&, floating-point,
954
  memory_order = memory_order::seq_cst) const noexcept;
955
- bool compare_exchange_strong(floating-point&, floating-point,
956
  memory_order = memory_order::seq_cst) const noexcept;
957
 
958
- floating-point fetch_add(floating-point,
959
  memory_order = memory_order::seq_cst) const noexcept;
960
- floating-point fetch_sub(floating-point,
961
  memory_order = memory_order::seq_cst) const noexcept;
962
 
963
- floating-point operator+=(floating-point) const noexcept;
964
- floating-point operator-=(floating-point) const noexcept;
965
 
966
- void wait(floating-point, memory_order = memory_order::seq_cst) const noexcept;
967
  void notify_one() const noexcept;
968
  void notify_all() const noexcept;
969
  };
970
  }
971
  ```
972
 
973
  Descriptions are provided below only for members that differ from the
974
  primary template.
975
 
976
- The following operations perform arithmetic computations. The key,
977
- operator, and computation correspondence are identified in
978
  [[atomic.types.int.comp]].
979
 
980
  ``` cpp
981
- floating-point fetch_key(floating-point operand,
982
  memory_order order = memory_order::seq_cst) const noexcept;
983
  ```
984
 
985
  *Effects:* Atomically replaces the value referenced by `*ptr` with the
986
  result of the computation applied to the value referenced by `*ptr` and
@@ -992,31 +1003,32 @@ operations [[intro.races]].
992
  the effects.
993
 
994
  *Remarks:* If the result is not a representable value for its
995
  type [[expr.pre]], the result is unspecified, but the operations
996
  otherwise have no undefined behavior. Atomic arithmetic operations on
997
- *`floating-point`* should conform to the
998
- `std::numeric_limits<`*`floating-point`*`>` traits associated with the
999
- floating-point type [[limits.syn]]. The floating-point
1000
  environment [[cfenv]] for atomic arithmetic operations on
1001
- *`floating-point`* may be different than the calling thread’s
1002
  floating-point environment.
1003
 
1004
  ``` cpp
1005
- floating-point operator op=(floating-point operand) const noexcept;
1006
  ```
1007
 
1008
  *Effects:* Equivalent to:
1009
  `return fetch_`*`key`*`(operand) `*`op`*` operand;`
1010
 
1011
- ### Partial specialization for pointers <a id="atomics.ref.pointer">[[atomics.ref.pointer]]</a>
1012
 
1013
  ``` cpp
1014
  namespace std {
1015
  template<class T> struct atomic_ref<T*> {
1016
  private:
1017
  T** ptr; // exposition only
 
1018
  public:
1019
  using value_type = T*;
1020
  using difference_type = ptrdiff_t;
1021
  static constexpr size_t required_alignment = implementation-defined // required alignment for atomic_ref type's operations;
1022
 
@@ -1060,12 +1072,12 @@ namespace std {
1060
  ```
1061
 
1062
  Descriptions are provided below only for members that differ from the
1063
  primary template.
1064
 
1065
- The following operations perform arithmetic computations. The key,
1066
- operator, and computation correspondence is identified in
1067
  [[atomic.types.pointer.comp]].
1068
 
1069
  ``` cpp
1070
  T* fetch_key(difference_type operand, memory_order order = memory_order::seq_cst) const noexcept;
1071
  ```
@@ -1089,11 +1101,11 @@ T* operator op=(difference_type operand) const noexcept;
1089
  ```
1090
 
1091
  *Effects:* Equivalent to:
1092
  `return fetch_`*`key`*`(operand) `*`op`*` operand;`
1093
 
1094
- ### Member operators common to integers and pointers to objects <a id="atomics.ref.memop">[[atomics.ref.memop]]</a>
1095
 
1096
  ``` cpp
1097
  value_type operator++(int) const noexcept;
1098
  ```
1099
 
@@ -1115,11 +1127,13 @@ value_type operator++() const noexcept;
1115
  value_type operator--() const noexcept;
1116
  ```
1117
 
1118
  *Effects:* Equivalent to: `return fetch_sub(1) - 1;`
1119
 
1120
- ## Class template `atomic` <a id="atomics.types.generic">[[atomics.types.generic]]</a>
 
 
1121
 
1122
  ``` cpp
1123
  namespace std {
1124
  template<class T> struct atomic {
1125
  using value_type = T;
@@ -1176,19 +1190,19 @@ of
1176
  - `is_move_assignable_v<T>`
1177
 
1178
  is `false`.
1179
 
1180
  [*Note 1*: Type arguments that are not also statically initializable
1181
- may be difficult to use. — *end note*]
1182
 
1183
  The specialization `atomic<bool>` is a standard-layout struct.
1184
 
1185
  [*Note 2*: The representation of an atomic specialization need not have
1186
  the same size and alignment requirement as its corresponding argument
1187
  type. — *end note*]
1188
 
1189
- ### Operations on atomic types <a id="atomics.types.operations">[[atomics.types.operations]]</a>
1190
 
1191
  ``` cpp
1192
  constexpr atomic() noexcept(is_nothrow_default_constructible_v<T>);
1193
  ```
1194
 
@@ -1237,17 +1251,17 @@ type. — *end note*]
1237
  ``` cpp
1238
  void store(T desired, memory_order order = memory_order::seq_cst) volatile noexcept;
1239
  void store(T desired, memory_order order = memory_order::seq_cst) noexcept;
1240
  ```
1241
 
 
 
 
1242
  *Preconditions:* The `order` argument is neither
1243
  `memory_order::consume`, `memory_order::acquire`, nor
1244
  `memory_order::acq_rel`.
1245
 
1246
- *Constraints:* For the `volatile` overload of this function,
1247
- `is_always_lock_free` is `true`.
1248
-
1249
  *Effects:* Atomically replaces the value pointed to by `this` with the
1250
  value of `desired`. Memory is affected according to the value of
1251
  `order`.
1252
 
1253
  ``` cpp
@@ -1265,16 +1279,16 @@ T operator=(T desired) noexcept;
1265
  ``` cpp
1266
  T load(memory_order order = memory_order::seq_cst) const volatile noexcept;
1267
  T load(memory_order order = memory_order::seq_cst) const noexcept;
1268
  ```
1269
 
1270
- *Preconditions:* The `order` argument is neither `memory_order::release`
1271
- nor `memory_order::acq_rel`.
1272
-
1273
  *Constraints:* For the `volatile` overload of this function,
1274
  `is_always_lock_free` is `true`.
1275
 
 
 
 
1276
  *Effects:* Memory is affected according to the value of `order`.
1277
 
1278
  *Returns:* Atomically returns the value pointed to by `this`.
1279
 
1280
  ``` cpp
@@ -1320,16 +1334,16 @@ bool compare_exchange_strong(T& expected, T desired,
1320
  memory_order order = memory_order::seq_cst) volatile noexcept;
1321
  bool compare_exchange_strong(T& expected, T desired,
1322
  memory_order order = memory_order::seq_cst) noexcept;
1323
  ```
1324
 
1325
- *Preconditions:* The `failure` argument is neither
1326
- `memory_order::release` nor `memory_order::acq_rel`.
1327
-
1328
  *Constraints:* For the `volatile` overload of this function,
1329
  `is_always_lock_free` is `true`.
1330
 
 
 
 
1331
  *Effects:* Retrieves the value in `expected`. It then atomically
1332
  compares the value representation of the value pointed to by `this` for
1333
  equality with that previously retrieved from `expected`, and if true,
1334
  replaces the value pointed to by `this` with that in `desired`. If and
1335
  only if the comparison is `true`, memory is affected according to the
@@ -1349,17 +1363,17 @@ Otherwise, these operations are atomic load operations on that memory.
1349
  *Returns:* The result of the comparison.
1350
 
1351
  [*Note 4*:
1352
 
1353
  For example, the effect of `compare_exchange_strong` on objects without
1354
- padding bits [[basic.types]] is
1355
 
1356
  ``` cpp
1357
  if (memcmp(this, &expected, sizeof(*this)) == 0)
1358
  memcpy(this, &desired, sizeof(*this));
1359
  else
1360
- memcpy(expected, this, sizeof(*this));
1361
  ```
1362
 
1363
  — *end note*]
1364
 
1365
  [*Example 1*:
@@ -1410,17 +1424,17 @@ compare-and-exchange is in a loop, the weak version will yield better
1410
  performance on some platforms. When a weak compare-and-exchange would
1411
  require a loop and a strong one would not, the strong one is
1412
  preferable. — *end note*]
1413
 
1414
  [*Note 6*: Under cases where the `memcpy` and `memcmp` semantics of the
1415
- compare-and-exchange operations apply, the outcome might be failed
1416
- comparisons for values that compare equal with `operator==` if the value
1417
- representation has trap bits or alternate representations of the same
1418
- value. Notably, on implementations conforming to ISO/IEC/IEEE 60559,
1419
- floating-point `-0.0` and `+0.0` will not compare equal with `memcmp`
1420
- but will compare equal with `operator==`, and NaNs with the same payload
1421
- will compare equal with `memcmp` but will not compare equal with
1422
  `operator==`. — *end note*]
1423
 
1424
  [*Note 7*:
1425
 
1426
  Because compare-and-exchange acts on an object’s value representation,
@@ -1507,100 +1521,112 @@ void notify_all() noexcept;
1507
  are eligible to be unblocked [[atomics.wait]] by this call.
1508
 
1509
  *Remarks:* This function is an atomic notifying
1510
  operation [[atomics.wait]].
1511
 
1512
- ### Specializations for integers <a id="atomics.types.int">[[atomics.types.int]]</a>
1513
 
1514
  There are specializations of the `atomic` class template for the
1515
  integral types `char`, `signed char`, `unsigned char`, `short`,
1516
  `unsigned short`, `int`, `unsigned int`, `long`, `unsigned long`,
1517
  `long long`, `unsigned long long`, `char8_t`, `char16_t`, `char32_t`,
1518
  `wchar_t`, and any other types needed by the typedefs in the header
1519
- `<cstdint>`. For each such type `integral`, the specialization
1520
- `atomic<integral>` provides additional atomic operations appropriate to
1521
- integral types.
1522
 
1523
  [*Note 1*: The specialization `atomic<bool>` uses the primary template
1524
  [[atomics.types.generic]]. — *end note*]
1525
 
1526
  ``` cpp
1527
  namespace std {
1528
- template<> struct atomic<integral> {
1529
- using value_type = integral;
1530
  using difference_type = value_type;
1531
 
1532
  static constexpr bool is_always_lock_free = implementation-defined // whether a given atomic type's operations are always lock free;
1533
  bool is_lock_free() const volatile noexcept;
1534
  bool is_lock_free() const noexcept;
1535
 
1536
  constexpr atomic() noexcept;
1537
- constexpr atomic(integral) noexcept;
1538
  atomic(const atomic&) = delete;
1539
  atomic& operator=(const atomic&) = delete;
1540
  atomic& operator=(const atomic&) volatile = delete;
1541
 
1542
- void store(integral, memory_order = memory_order::seq_cst) volatile noexcept;
1543
- void store(integral, memory_order = memory_order::seq_cst) noexcept;
1544
- integral operator=(integral) volatile noexcept;
1545
- integral operator=(integral) noexcept;
1546
- integral load(memory_order = memory_order::seq_cst) const volatile noexcept;
1547
- integral load(memory_order = memory_order::seq_cst) const noexcept;
1548
- operator integral() const volatile noexcept;
1549
- operator integral() const noexcept;
1550
 
1551
- integral exchange(integral, memory_order = memory_order::seq_cst) volatile noexcept;
1552
- integral exchange(integral, memory_order = memory_order::seq_cst) noexcept;
1553
- bool compare_exchange_weak(integral&, integral,
 
 
1554
  memory_order, memory_order) volatile noexcept;
1555
- bool compare_exchange_weak(integral&, integral,
1556
  memory_order, memory_order) noexcept;
1557
- bool compare_exchange_strong(integral&, integral,
1558
  memory_order, memory_order) volatile noexcept;
1559
- bool compare_exchange_strong(integral&, integral,
1560
  memory_order, memory_order) noexcept;
1561
- bool compare_exchange_weak(integral&, integral,
1562
  memory_order = memory_order::seq_cst) volatile noexcept;
1563
- bool compare_exchange_weak(integral&, integral,
1564
  memory_order = memory_order::seq_cst) noexcept;
1565
- bool compare_exchange_strong(integral&, integral,
1566
  memory_order = memory_order::seq_cst) volatile noexcept;
1567
- bool compare_exchange_strong(integral&, integral,
1568
  memory_order = memory_order::seq_cst) noexcept;
1569
 
1570
- integral fetch_add(integral, memory_order = memory_order::seq_cst) volatile noexcept;
1571
- integral fetch_add(integral, memory_order = memory_order::seq_cst) noexcept;
1572
- integral fetch_sub(integral, memory_order = memory_order::seq_cst) volatile noexcept;
1573
- integral fetch_sub(integral, memory_order = memory_order::seq_cst) noexcept;
1574
- integral fetch_and(integral, memory_order = memory_order::seq_cst) volatile noexcept;
1575
- integral fetch_and(integral, memory_order = memory_order::seq_cst) noexcept;
1576
- integral fetch_or(integral, memory_order = memory_order::seq_cst) volatile noexcept;
1577
- integral fetch_or(integral, memory_order = memory_order::seq_cst) noexcept;
1578
- integral fetch_xor(integral, memory_order = memory_order::seq_cst) volatile noexcept;
1579
- integral fetch_xor(integral, memory_order = memory_order::seq_cst) noexcept;
 
 
 
 
 
 
 
 
 
 
1580
 
1581
- integral operator++(int) volatile noexcept;
1582
- integral operator++(int) noexcept;
1583
- integral operator--(int) volatile noexcept;
1584
- integral operator--(int) noexcept;
1585
- integral operator++() volatile noexcept;
1586
- integral operator++() noexcept;
1587
- integral operator--() volatile noexcept;
1588
- integral operator--() noexcept;
1589
- integral operator+=(integral) volatile noexcept;
1590
- integral operator+=(integral) noexcept;
1591
- integral operator-=(integral) volatile noexcept;
1592
- integral operator-=(integral) noexcept;
1593
- integral operator&=(integral) volatile noexcept;
1594
- integral operator&=(integral) noexcept;
1595
- integral operator|=(integral) volatile noexcept;
1596
- integral operator|=(integral) noexcept;
1597
- integral operator^=(integral) volatile noexcept;
1598
- integral operator^=(integral) noexcept;
1599
 
1600
- void wait(integral, memory_order = memory_order::seq_cst) const volatile noexcept;
1601
- void wait(integral, memory_order = memory_order::seq_cst) const noexcept;
1602
  void notify_one() volatile noexcept;
1603
  void notify_one() noexcept;
1604
  void notify_all() volatile noexcept;
1605
  void notify_all() noexcept;
1606
  };
@@ -1611,12 +1637,13 @@ The atomic integral specializations are standard-layout structs. They
1611
  each have a trivial destructor.
1612
 
1613
  Descriptions are provided below only for members that differ from the
1614
  primary template.
1615
 
1616
- The following operations perform arithmetic computations. The key,
1617
- operator, and computation correspondence is:
 
1618
 
1619
  **Table: Atomic arithmetic computations** <a id="atomic.types.int.comp">[atomic.types.int.comp]</a>
1620
 
1621
  | | | | | | |
1622
  | ----- | --- | -------------------- | ----- | --- | -------------------- |
@@ -1658,80 +1685,80 @@ T operator op=(T operand) noexcept;
1658
  `is_always_lock_free` is `true`.
1659
 
1660
  *Effects:* Equivalent to:
1661
  `return fetch_`*`key`*`(operand) `*`op`*` operand;`
1662
 
1663
- ### Specializations for floating-point types <a id="atomics.types.float">[[atomics.types.float]]</a>
1664
 
1665
- There are specializations of the `atomic` class template for the
1666
- floating-point types `float`, `double`, and `long double`. For each such
1667
- type `floating-point`, the specialization `atomic<floating-point>`
1668
  provides additional atomic operations appropriate to floating-point
1669
  types.
1670
 
1671
  ``` cpp
1672
  namespace std {
1673
- template<> struct atomic<floating-point> {
1674
- using value_type = floating-point;
1675
  using difference_type = value_type;
1676
 
1677
  static constexpr bool is_always_lock_free = implementation-defined // whether a given atomic type's operations are always lock free;
1678
  bool is_lock_free() const volatile noexcept;
1679
  bool is_lock_free() const noexcept;
1680
 
1681
  constexpr atomic() noexcept;
1682
- constexpr atomic(floating-point) noexcept;
1683
  atomic(const atomic&) = delete;
1684
  atomic& operator=(const atomic&) = delete;
1685
  atomic& operator=(const atomic&) volatile = delete;
1686
 
1687
- void store(floating-point, memory_order = memory_order::seq_cst) volatile noexcept;
1688
- void store(floating-point, memory_order = memory_order::seq_cst) noexcept;
1689
- floating-point operator=(floating-point) volatile noexcept;
1690
- floating-point operator=(floating-point) noexcept;
1691
- floating-point load(memory_order = memory_order::seq_cst) volatile noexcept;
1692
- floating-point load(memory_order = memory_order::seq_cst) noexcept;
1693
- operator floating-point() volatile noexcept;
1694
- operator floating-point() noexcept;
1695
 
1696
- floating-point exchange(floating-point,
1697
  memory_order = memory_order::seq_cst) volatile noexcept;
1698
- floating-point exchange(floating-point,
1699
  memory_order = memory_order::seq_cst) noexcept;
1700
- bool compare_exchange_weak(floating-point&, floating-point,
1701
  memory_order, memory_order) volatile noexcept;
1702
- bool compare_exchange_weak(floating-point&, floating-point,
1703
  memory_order, memory_order) noexcept;
1704
- bool compare_exchange_strong(floating-point&, floating-point,
1705
  memory_order, memory_order) volatile noexcept;
1706
- bool compare_exchange_strong(floating-point&, floating-point,
1707
  memory_order, memory_order) noexcept;
1708
- bool compare_exchange_weak(floating-point&, floating-point,
1709
  memory_order = memory_order::seq_cst) volatile noexcept;
1710
- bool compare_exchange_weak(floating-point&, floating-point,
1711
  memory_order = memory_order::seq_cst) noexcept;
1712
- bool compare_exchange_strong(floating-point&, floating-point,
1713
  memory_order = memory_order::seq_cst) volatile noexcept;
1714
- bool compare_exchange_strong(floating-point&, floating-point,
1715
  memory_order = memory_order::seq_cst) noexcept;
1716
 
1717
- floating-point fetch_add(floating-point,
1718
  memory_order = memory_order::seq_cst) volatile noexcept;
1719
- floating-point fetch_add(floating-point,
1720
  memory_order = memory_order::seq_cst) noexcept;
1721
- floating-point fetch_sub(floating-point,
1722
  memory_order = memory_order::seq_cst) volatile noexcept;
1723
- floating-point fetch_sub(floating-point,
1724
  memory_order = memory_order::seq_cst) noexcept;
1725
 
1726
- floating-point operator+=(floating-point) volatile noexcept;
1727
- floating-point operator+=(floating-point) noexcept;
1728
- floating-point operator-=(floating-point) volatile noexcept;
1729
- floating-point operator-=(floating-point) noexcept;
1730
 
1731
- void wait(floating-point, memory_order = memory_order::seq_cst) const volatile noexcept;
1732
- void wait(floating-point, memory_order = memory_order::seq_cst) const noexcept;
1733
  void notify_one() volatile noexcept;
1734
  void notify_one() noexcept;
1735
  void notify_all() volatile noexcept;
1736
  void notify_all() noexcept;
1737
  };
@@ -1743,12 +1770,12 @@ They each have a trivial destructor.
1743
 
1744
  Descriptions are provided below only for members that differ from the
1745
  primary template.
1746
 
1747
  The following operations perform arithmetic addition and subtraction
1748
- computations. The key, operator, and computation correspondence are
1749
- identified in [[atomic.types.int.comp]].
1750
 
1751
  ``` cpp
1752
  T fetch_key(T operand, memory_order order = memory_order::seq_cst) volatile noexcept;
1753
  T fetch_key(T operand, memory_order order = memory_order::seq_cst) noexcept;
1754
  ```
@@ -1766,15 +1793,15 @@ operations [[intro.multithread]].
1766
  the effects.
1767
 
1768
  *Remarks:* If the result is not a representable value for its
1769
  type [[expr.pre]] the result is unspecified, but the operations
1770
  otherwise have no undefined behavior. Atomic arithmetic operations on
1771
- *`floating-point`* should conform to the
1772
- `std::numeric_limits<`*`floating-point`*`>` traits associated with the
1773
- floating-point type [[limits.syn]]. The floating-point
1774
  environment [[cfenv]] for atomic arithmetic operations on
1775
- *`floating-point`* may be different than the calling thread’s
1776
  floating-point environment.
1777
 
1778
  ``` cpp
1779
  T operator op=(T operand) volatile noexcept;
1780
  T operator op=(T operand) noexcept;
@@ -1787,18 +1814,18 @@ T operator op=(T operand) noexcept;
1787
  `return fetch_`*`key`*`(operand) `*`op`*` operand;`
1788
 
1789
  *Remarks:* If the result is not a representable value for its
1790
  type [[expr.pre]] the result is unspecified, but the operations
1791
  otherwise have no undefined behavior. Atomic arithmetic operations on
1792
- *`floating-point`* should conform to the
1793
- `std::numeric_limits<`*`floating-point`*`>` traits associated with the
1794
- floating-point type [[limits.syn]]. The floating-point
1795
  environment [[cfenv]] for atomic arithmetic operations on
1796
- *`floating-point`* may be different than the calling thread’s
1797
  floating-point environment.
1798
 
1799
- ### Partial specialization for pointers <a id="atomics.types.pointer">[[atomics.types.pointer]]</a>
1800
 
1801
  ``` cpp
1802
  namespace std {
1803
  template<class T> struct atomic<T*> {
1804
  using value_type = T*;
@@ -1871,12 +1898,13 @@ pointers. Specializations of this partial specialization are
1871
  standard-layout structs. They each have a trivial destructor.
1872
 
1873
  Descriptions are provided below only for members that differ from the
1874
  primary template.
1875
 
1876
- The following operations perform pointer arithmetic. The key, operator,
1877
- and computation correspondence is:
 
1878
 
1879
  **Table: Atomic pointer computations** <a id="atomic.types.pointer.comp">[atomic.types.pointer.comp]</a>
1880
 
1881
  | | | | | | |
1882
  | ----- | --- | -------- | ----- | --- | ----------- |
@@ -1916,11 +1944,11 @@ T* operator op=(ptrdiff_t operand) noexcept;
1916
  `is_always_lock_free` is `true`.
1917
 
1918
  *Effects:* Equivalent to:
1919
  `return fetch_`*`key`*`(operand) `*`op`*` operand;`
1920
 
1921
- ### Member operators common to integers and pointers to objects <a id="atomics.types.memop">[[atomics.types.memop]]</a>
1922
 
1923
  ``` cpp
1924
  value_type operator++(int) volatile noexcept;
1925
  value_type operator++(int) noexcept;
1926
  ```
@@ -1958,26 +1986,33 @@ value_type operator--() noexcept;
1958
  *Constraints:* For the `volatile` overload of this function,
1959
  `is_always_lock_free` is `true`.
1960
 
1961
  *Effects:* Equivalent to: `return fetch_sub(1) - 1;`
1962
 
1963
- ### Partial specializations for smart pointers <a id="util.smartptr.atomic">[[util.smartptr.atomic]]</a>
 
 
1964
 
1965
  The library provides partial specializations of the `atomic` template
1966
- for shared-ownership smart pointers [[smartptr]]. The behavior of all
1967
- operations is as specified in [[atomics.types.generic]], unless
1968
- specified otherwise. The template parameter `T` of these partial
1969
- specializations may be an incomplete type.
1970
 
1971
- All changes to an atomic smart pointer in this subclause, and all
1972
- associated `use_count` increments, are guaranteed to be performed
 
 
 
 
 
 
 
 
1973
  atomically. Associated `use_count` decrements are sequenced after the
1974
  atomic operation, but are not required to be part of it. Any associated
1975
  deletion and deallocation are sequenced after the atomic update step and
1976
  are not part of the atomic operation.
1977
 
1978
- [*Note 1*: If the atomic operation uses locks, locks acquired by the
1979
  implementation will be held when any `use_count` adjustments are
1980
  performed, and will not be held when any destruction or deallocation
1981
  resulting from this is performed. — *end note*]
1982
 
1983
  [*Example 1*:
@@ -1989,16 +2024,16 @@ template<typename T> class atomic_list {
1989
  shared_ptr<node> next;
1990
  };
1991
  atomic<shared_ptr<node>> head;
1992
 
1993
  public:
1994
- auto find(T t) const {
1995
  auto p = head.load();
1996
  while (p && p->t != t)
1997
  p = p->next;
1998
 
1999
- return shared_ptr<node>(move(p));
2000
  }
2001
 
2002
  void push_front(T t) {
2003
  auto p = make_shared<node>();
2004
  p->t = t;
@@ -2008,21 +2043,22 @@ public:
2008
  };
2009
  ```
2010
 
2011
  — *end example*]
2012
 
2013
- #### Partial specialization for `shared_ptr` <a id="util.smartptr.atomic.shared">[[util.smartptr.atomic.shared]]</a>
2014
 
2015
  ``` cpp
2016
  namespace std {
2017
  template<class T> struct atomic<shared_ptr<T>> {
2018
  using value_type = shared_ptr<T>;
2019
 
2020
  static constexpr bool is_always_lock_free = implementation-defined // whether a given atomic type's operations are always lock free;
2021
  bool is_lock_free() const noexcept;
2022
 
2023
  constexpr atomic() noexcept;
 
2024
  atomic(shared_ptr<T> desired) noexcept;
2025
  atomic(const atomic&) = delete;
2026
  void operator=(const atomic&) = delete;
2027
 
2028
  shared_ptr<T> load(memory_order order = memory_order::seq_cst) const noexcept;
@@ -2217,11 +2253,11 @@ void notify_all() noexcept;
2217
  are eligible to be unblocked [[atomics.wait]] by this call.
2218
 
2219
  *Remarks:* This function is an atomic notifying
2220
  operation [[atomics.wait]].
2221
 
2222
- #### Partial specialization for `weak_ptr` <a id="util.smartptr.atomic.weak">[[util.smartptr.atomic.weak]]</a>
2223
 
2224
  ``` cpp
2225
  namespace std {
2226
  template<class T> struct atomic<weak_ptr<T>> {
2227
  using value_type = weak_ptr<T>;
@@ -2271,11 +2307,11 @@ atomic(weak_ptr<T> desired) noexcept;
2271
  ```
2272
 
2273
  *Effects:* Initializes the object with the value `desired`.
2274
  Initialization is not an atomic operation [[intro.multithread]].
2275
 
2276
- [*Note 1*: It is possible to have an access to an atomic object `A`
2277
  race with its construction, for example, by communicating the address of
2278
  the just-constructed object `A` to another thread via
2279
  `memory_order::relaxed` operations on a suitable atomic pointer
2280
  variable, and then immediately accessing `A` in the receiving thread.
2281
  This results in undefined behavior. — *end note*]
@@ -2426,11 +2462,11 @@ void notify_all() noexcept;
2426
  are eligible to be unblocked [[atomics.wait]] by this call.
2427
 
2428
  *Remarks:* This function is an atomic notifying
2429
  operation [[atomics.wait]].
2430
 
2431
- ## Non-member functions <a id="atomics.nonmembers">[[atomics.nonmembers]]</a>
2432
 
2433
  A non-member function template whose name matches the pattern `atomic_f`
2434
  or the pattern `atomic_f_explicit` invokes the member function `f`, with
2435
  the value of the first parameter as the object expression and the values
2436
  of the remaining parameters (if any) as the arguments of the member
@@ -2441,11 +2477,11 @@ ill-formed.
2441
 
2442
  [*Note 1*: The non-member functions enable programmers to write code
2443
  that can be compiled as either C or C++, for example in a shared header
2444
  file. — *end note*]
2445
 
2446
- ## Flag type and operations <a id="atomics.flag">[[atomics.flag]]</a>
2447
 
2448
  ``` cpp
2449
  namespace std {
2450
  struct atomic_flag {
2451
  constexpr atomic_flag() noexcept;
@@ -2471,14 +2507,12 @@ namespace std {
2471
  ```
2472
 
2473
  The `atomic_flag` type provides the classic test-and-set functionality.
2474
  It has two states, set and clear.
2475
 
2476
- Operations on an object of type `atomic_flag` shall be lock-free.
2477
-
2478
- [*Note 1*: Hence the operations should also be
2479
- address-free. — *end note*]
2480
 
2481
  The `atomic_flag` type is a standard-layout struct. It has a trivial
2482
  destructor.
2483
 
2484
  ``` cpp
@@ -2596,11 +2630,27 @@ void atomic_flag::notify_all() noexcept;
2596
  are eligible to be unblocked [[atomics.wait]] by this call.
2597
 
2598
  *Remarks:* This function is an atomic notifying
2599
  operation [[atomics.wait]].
2600
 
2601
- ## Fences <a id="atomics.fences">[[atomics.fences]]</a>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2602
 
2603
  This subclause introduces synchronization primitives called *fences*.
2604
  Fences can have acquire semantics, release semantics, or both. A fence
2605
  with acquire semantics is called an *acquire fence*. A fence with
2606
  release semantics is called a *release fence*.
@@ -2653,46 +2703,136 @@ which actions performed by the thread become visible to the signal
2653
  handler. Compiler optimizations and reorderings of loads and stores are
2654
  inhibited in the same way as with `atomic_thread_fence`, but the
2655
  hardware fence instructions that `atomic_thread_fence` would have
2656
  inserted are not emitted. — *end note*]
2657
 
2658
- <!-- Link reference definitions -->
2659
- [atomic.types.int.comp]: #atomic.types.int.comp
2660
- [atomic.types.pointer.comp]: #atomic.types.pointer.comp
2661
- [atomics]: #atomics
2662
- [atomics.alias]: #atomics.alias
2663
- [atomics.fences]: #atomics.fences
2664
- [atomics.flag]: #atomics.flag
2665
- [atomics.general]: #atomics.general
2666
- [atomics.lockfree]: #atomics.lockfree
2667
- [atomics.nonmembers]: #atomics.nonmembers
2668
- [atomics.order]: #atomics.order
2669
- [atomics.ref.float]: #atomics.ref.float
2670
- [atomics.ref.generic]: #atomics.ref.generic
2671
- [atomics.ref.int]: #atomics.ref.int
2672
- [atomics.ref.memop]: #atomics.ref.memop
2673
- [atomics.ref.ops]: #atomics.ref.ops
2674
- [atomics.ref.pointer]: #atomics.ref.pointer
2675
- [atomics.summary]: #atomics.summary
2676
- [atomics.syn]: #atomics.syn
2677
- [atomics.types.float]: #atomics.types.float
2678
- [atomics.types.generic]: #atomics.types.generic
2679
- [atomics.types.int]: #atomics.types.int
2680
- [atomics.types.memop]: #atomics.types.memop
2681
- [atomics.types.operations]: #atomics.types.operations
2682
- [atomics.types.pointer]: #atomics.types.pointer
2683
- [atomics.wait]: #atomics.wait
2684
- [basic.align]: basic.md#basic.align
2685
- [basic.fundamental]: basic.md#basic.fundamental
2686
- [basic.life]: basic.md#basic.life
2687
- [basic.types]: basic.md#basic.types
2688
- [cfenv]: numerics.md#cfenv
2689
- [compliance]: library.md#compliance
2690
- [expr.pre]: expr.md#expr.pre
2691
- [intro.multithread]: basic.md#intro.multithread
2692
- [intro.progress]: basic.md#intro.progress
2693
- [intro.races]: basic.md#intro.races
2694
- [limits.syn]: support.md#limits.syn
2695
- [smartptr]: utilities.md#smartptr
2696
- [util.smartptr.atomic]: #util.smartptr.atomic
2697
- [util.smartptr.atomic.shared]: #util.smartptr.atomic.shared
2698
- [util.smartptr.atomic.weak]: #util.smartptr.atomic.weak
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## Atomic operations <a id="atomics">[[atomics]]</a>
2
 
3
+ ### General <a id="atomics.general">[[atomics.general]]</a>
4
 
5
+ Subclause [[atomics]] describes components for fine-grained atomic
6
+ access. This access is provided via operations on atomic objects.
7
 
8
+ ### Header `<atomic>` synopsis <a id="atomics.syn">[[atomics.syn]]</a>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
 
10
  ``` cpp
11
  namespace std {
12
  // [atomics.order], order and consistency
13
+ enum class memory_order : unspecified; // freestanding
14
+ inline constexpr memory_order memory_order_relaxed = memory_order::relaxed; // freestanding
15
+ inline constexpr memory_order memory_order_consume = memory_order::consume; // freestanding
16
+ inline constexpr memory_order memory_order_acquire = memory_order::acquire; // freestanding
17
+ inline constexpr memory_order memory_order_release = memory_order::release; // freestanding
18
+ inline constexpr memory_order memory_order_acq_rel = memory_order::acq_rel; // freestanding
19
+ inline constexpr memory_order memory_order_seq_cst = memory_order::seq_cst; // freestanding
20
+
21
  template<class T>
22
+ T kill_dependency(T y) noexcept; // freestanding
23
+ }
24
 
25
  // [atomics.lockfree], lock-free property
26
+ #define ATOMIC_BOOL_LOCK_FREE unspecified // freestanding
27
+ #define ATOMIC_CHAR_LOCK_FREE unspecified // freestanding
28
+ #define ATOMIC_CHAR8_T_LOCK_FREE unspecified // freestanding
29
+ #define ATOMIC_CHAR16_T_LOCK_FREE unspecified // freestanding
30
+ #define ATOMIC_CHAR32_T_LOCK_FREE unspecified // freestanding
31
+ #define ATOMIC_WCHAR_T_LOCK_FREE unspecified // freestanding
32
+ #define ATOMIC_SHORT_LOCK_FREE unspecified // freestanding
33
+ #define ATOMIC_INT_LOCK_FREE unspecified // freestanding
34
+ #define ATOMIC_LONG_LOCK_FREE unspecified // freestanding
35
+ #define ATOMIC_LLONG_LOCK_FREE unspecified // freestanding
36
+ #define ATOMIC_POINTER_LOCK_FREE unspecified // freestanding
37
 
38
+ namespace std {
39
  // [atomics.ref.generic], class template atomic_ref
40
+ template<class T> struct atomic_ref; // freestanding
41
  // [atomics.ref.pointer], partial specialization for pointers
42
+ template<class T> struct atomic_ref<T*>; // freestanding
43
 
44
  // [atomics.types.generic], class template atomic
45
+ template<class T> struct atomic; // freestanding
46
  // [atomics.types.pointer], partial specialization for pointers
47
+ template<class T> struct atomic<T*>; // freestanding
48
 
49
  // [atomics.nonmembers], non-member functions
50
  template<class T>
51
+ bool atomic_is_lock_free(const volatile atomic<T>*) noexcept; // freestanding
52
  template<class T>
53
+ bool atomic_is_lock_free(const atomic<T>*) noexcept; // freestanding
54
  template<class T>
55
+ void atomic_store(volatile atomic<T>*, // freestanding
56
+ typename atomic<T>::value_type) noexcept;
57
  template<class T>
58
+ void atomic_store(atomic<T>*, typename atomic<T>::value_type) noexcept; // freestanding
59
  template<class T>
60
+ void atomic_store_explicit(volatile atomic<T>*, // freestanding
61
+ typename atomic<T>::value_type,
62
  memory_order) noexcept;
63
  template<class T>
64
+ void atomic_store_explicit(atomic<T>*, typename atomic<T>::value_type, // freestanding
65
  memory_order) noexcept;
66
  template<class T>
67
+ T atomic_load(const volatile atomic<T>*) noexcept; // freestanding
68
  template<class T>
69
+ T atomic_load(const atomic<T>*) noexcept; // freestanding
70
  template<class T>
71
+ T atomic_load_explicit(const volatile atomic<T>*, memory_order) noexcept; // freestanding
72
  template<class T>
73
+ T atomic_load_explicit(const atomic<T>*, memory_order) noexcept; // freestanding
74
  template<class T>
75
+ T atomic_exchange(volatile atomic<T>*, // freestanding
76
+ typename atomic<T>::value_type) noexcept;
77
  template<class T>
78
+ T atomic_exchange(atomic<T>*, typename atomic<T>::value_type) noexcept; // freestanding
79
  template<class T>
80
+ T atomic_exchange_explicit(volatile atomic<T>*, // freestanding
81
+ typename atomic<T>::value_type,
82
  memory_order) noexcept;
83
  template<class T>
84
+ T atomic_exchange_explicit(atomic<T>*, typename atomic<T>::value_type, // freestanding
85
  memory_order) noexcept;
86
  template<class T>
87
+ bool atomic_compare_exchange_weak(volatile atomic<T>*, // freestanding
88
  typename atomic<T>::value_type*,
89
  typename atomic<T>::value_type) noexcept;
90
  template<class T>
91
+ bool atomic_compare_exchange_weak(atomic<T>*, // freestanding
92
  typename atomic<T>::value_type*,
93
  typename atomic<T>::value_type) noexcept;
94
  template<class T>
95
+ bool atomic_compare_exchange_strong(volatile atomic<T>*, // freestanding
96
  typename atomic<T>::value_type*,
97
  typename atomic<T>::value_type) noexcept;
98
  template<class T>
99
+ bool atomic_compare_exchange_strong(atomic<T>*, // freestanding
100
  typename atomic<T>::value_type*,
101
  typename atomic<T>::value_type) noexcept;
102
  template<class T>
103
+ bool atomic_compare_exchange_weak_explicit(volatile atomic<T>*, // freestanding
104
  typename atomic<T>::value_type*,
105
  typename atomic<T>::value_type,
106
  memory_order, memory_order) noexcept;
107
  template<class T>
108
+ bool atomic_compare_exchange_weak_explicit(atomic<T>*, // freestanding
109
  typename atomic<T>::value_type*,
110
  typename atomic<T>::value_type,
111
  memory_order, memory_order) noexcept;
112
  template<class T>
113
+ bool atomic_compare_exchange_strong_explicit(volatile atomic<T>*, // freestanding
114
  typename atomic<T>::value_type*,
115
  typename atomic<T>::value_type,
116
  memory_order, memory_order) noexcept;
117
  template<class T>
118
+ bool atomic_compare_exchange_strong_explicit(atomic<T>*, // freestanding
119
  typename atomic<T>::value_type*,
120
  typename atomic<T>::value_type,
121
  memory_order, memory_order) noexcept;
122
 
123
  template<class T>
124
+ T atomic_fetch_add(volatile atomic<T>*, // freestanding
125
+ typename atomic<T>::difference_type) noexcept;
126
  template<class T>
127
+ T atomic_fetch_add(atomic<T>*, typename atomic<T>::difference_type) noexcept; // freestanding
128
  template<class T>
129
+ T atomic_fetch_add_explicit(volatile atomic<T>*, // freestanding
130
+ typename atomic<T>::difference_type,
131
  memory_order) noexcept;
132
  template<class T>
133
+ T atomic_fetch_add_explicit(atomic<T>*, typename atomic<T>::difference_type, // freestanding
134
  memory_order) noexcept;
135
  template<class T>
136
+ T atomic_fetch_sub(volatile atomic<T>*, // freestanding
137
+ typename atomic<T>::difference_type) noexcept;
138
  template<class T>
139
+ T atomic_fetch_sub(atomic<T>*, typename atomic<T>::difference_type) noexcept; // freestanding
140
  template<class T>
141
+ T atomic_fetch_sub_explicit(volatile atomic<T>*, // freestanding
142
+ typename atomic<T>::difference_type,
143
  memory_order) noexcept;
144
  template<class T>
145
+ T atomic_fetch_sub_explicit(atomic<T>*, typename atomic<T>::difference_type, // freestanding
146
  memory_order) noexcept;
147
  template<class T>
148
+ T atomic_fetch_and(volatile atomic<T>*, // freestanding
149
+ typename atomic<T>::value_type) noexcept;
150
  template<class T>
151
+ T atomic_fetch_and(atomic<T>*, typename atomic<T>::value_type) noexcept; // freestanding
152
  template<class T>
153
+ T atomic_fetch_and_explicit(volatile atomic<T>*, // freestanding
154
+ typename atomic<T>::value_type,
155
  memory_order) noexcept;
156
  template<class T>
157
+ T atomic_fetch_and_explicit(atomic<T>*, typename atomic<T>::value_type, // freestanding
158
  memory_order) noexcept;
159
  template<class T>
160
+ T atomic_fetch_or(volatile atomic<T>*, // freestanding
161
+ typename atomic<T>::value_type) noexcept;
162
  template<class T>
163
+ T atomic_fetch_or(atomic<T>*, typename atomic<T>::value_type) noexcept; // freestanding
164
  template<class T>
165
+ T atomic_fetch_or_explicit(volatile atomic<T>*, // freestanding
166
+ typename atomic<T>::value_type,
167
  memory_order) noexcept;
168
  template<class T>
169
+ T atomic_fetch_or_explicit(atomic<T>*, typename atomic<T>::value_type, // freestanding
170
  memory_order) noexcept;
171
  template<class T>
172
+ T atomic_fetch_xor(volatile atomic<T>*, // freestanding
173
+ typename atomic<T>::value_type) noexcept;
174
  template<class T>
175
+ T atomic_fetch_xor(atomic<T>*, typename atomic<T>::value_type) noexcept; // freestanding
176
  template<class T>
177
+ T atomic_fetch_xor_explicit(volatile atomic<T>*, // freestanding
178
+ typename atomic<T>::value_type,
179
  memory_order) noexcept;
180
  template<class T>
181
+ T atomic_fetch_xor_explicit(atomic<T>*, typename atomic<T>::value_type, // freestanding
182
  memory_order) noexcept;
183
 
184
  template<class T>
185
+ void atomic_wait(const volatile atomic<T>*, // freestanding
186
+ typename atomic<T>::value_type) noexcept;
187
  template<class T>
188
+ void atomic_wait(const atomic<T>*, typename atomic<T>::value_type) noexcept; // freestanding
189
  template<class T>
190
+ void atomic_wait_explicit(const volatile atomic<T>*, // freestanding
191
+ typename atomic<T>::value_type,
192
+ memory_order) noexcept;
193
  template<class T>
194
+ void atomic_wait_explicit(const atomic<T>*, typename atomic<T>::value_type, // freestanding
195
+ memory_order) noexcept;
196
  template<class T>
197
+ void atomic_notify_one(volatile atomic<T>*) noexcept; // freestanding
198
  template<class T>
199
+ void atomic_notify_one(atomic<T>*) noexcept; // freestanding
200
  template<class T>
201
+ void atomic_notify_all(volatile atomic<T>*) noexcept; // freestanding
202
  template<class T>
203
+ void atomic_notify_all(atomic<T>*) noexcept; // freestanding
204
 
205
  // [atomics.alias], type aliases
206
+ using atomic_bool = atomic<bool>; // freestanding
207
+ using atomic_char = atomic<char>; // freestanding
208
+ using atomic_schar = atomic<signed char>; // freestanding
209
+ using atomic_uchar = atomic<unsigned char>; // freestanding
210
+ using atomic_short = atomic<short>; // freestanding
211
+ using atomic_ushort = atomic<unsigned short>; // freestanding
212
+ using atomic_int = atomic<int>; // freestanding
213
+ using atomic_uint = atomic<unsigned int>; // freestanding
214
+ using atomic_long = atomic<long>; // freestanding
215
+ using atomic_ulong = atomic<unsigned long>; // freestanding
216
+ using atomic_llong = atomic<long long>; // freestanding
217
+ using atomic_ullong = atomic<unsigned long long>; // freestanding
218
+ using atomic_char8_t = atomic<char8_t>; // freestanding
219
+ using atomic_char16_t = atomic<char16_t>; // freestanding
220
+ using atomic_char32_t = atomic<char32_t>; // freestanding
221
+ using atomic_wchar_t = atomic<wchar_t>; // freestanding
222
 
223
+ using atomic_int8_t = atomic<int8_t>; // freestanding
224
+ using atomic_uint8_t = atomic<uint8_t>; // freestanding
225
+ using atomic_int16_t = atomic<int16_t>; // freestanding
226
+ using atomic_uint16_t = atomic<uint16_t>; // freestanding
227
+ using atomic_int32_t = atomic<int32_t>; // freestanding
228
+ using atomic_uint32_t = atomic<uint32_t>; // freestanding
229
+ using atomic_int64_t = atomic<int64_t>; // freestanding
230
+ using atomic_uint64_t = atomic<uint64_t>; // freestanding
231
 
232
+ using atomic_int_least8_t = atomic<int_least8_t>; // freestanding
233
+ using atomic_uint_least8_t = atomic<uint_least8_t>; // freestanding
234
+ using atomic_int_least16_t = atomic<int_least16_t>; // freestanding
235
+ using atomic_uint_least16_t = atomic<uint_least16_t>; // freestanding
236
+ using atomic_int_least32_t = atomic<int_least32_t>; // freestanding
237
+ using atomic_uint_least32_t = atomic<uint_least32_t>; // freestanding
238
+ using atomic_int_least64_t = atomic<int_least64_t>; // freestanding
239
+ using atomic_uint_least64_t = atomic<uint_least64_t>; // freestanding
240
 
241
+ using atomic_int_fast8_t = atomic<int_fast8_t>; // freestanding
242
+ using atomic_uint_fast8_t = atomic<uint_fast8_t>; // freestanding
243
+ using atomic_int_fast16_t = atomic<int_fast16_t>; // freestanding
244
+ using atomic_uint_fast16_t = atomic<uint_fast16_t>; // freestanding
245
+ using atomic_int_fast32_t = atomic<int_fast32_t>; // freestanding
246
+ using atomic_uint_fast32_t = atomic<uint_fast32_t>; // freestanding
247
+ using atomic_int_fast64_t = atomic<int_fast64_t>; // freestanding
248
+ using atomic_uint_fast64_t = atomic<uint_fast64_t>; // freestanding
249
 
250
+ using atomic_intptr_t = atomic<intptr_t>; // freestanding
251
+ using atomic_uintptr_t = atomic<uintptr_t>; // freestanding
252
+ using atomic_size_t = atomic<size_t>; // freestanding
253
+ using atomic_ptrdiff_t = atomic<ptrdiff_t>; // freestanding
254
+ using atomic_intmax_t = atomic<intmax_t>; // freestanding
255
+ using atomic_uintmax_t = atomic<uintmax_t>; // freestanding
256
 
257
  using atomic_signed_lock_free = see below;
258
  using atomic_unsigned_lock_free = see below;
259
 
260
  // [atomics.flag], flag type and operations
261
+ struct atomic_flag; // freestanding
262
 
263
+ bool atomic_flag_test(const volatile atomic_flag*) noexcept; // freestanding
264
+ bool atomic_flag_test(const atomic_flag*) noexcept; // freestanding
265
+ bool atomic_flag_test_explicit(const volatile atomic_flag*, // freestanding
266
+ memory_order) noexcept;
267
+ bool atomic_flag_test_explicit(const atomic_flag*, memory_order) noexcept; // freestanding
268
+ bool atomic_flag_test_and_set(volatile atomic_flag*) noexcept; // freestanding
269
+ bool atomic_flag_test_and_set(atomic_flag*) noexcept; // freestanding
270
+ bool atomic_flag_test_and_set_explicit(volatile atomic_flag*, // freestanding
271
+ memory_order) noexcept;
272
+ bool atomic_flag_test_and_set_explicit(atomic_flag*, memory_order) noexcept; // freestanding
273
+ void atomic_flag_clear(volatile atomic_flag*) noexcept; // freestanding
274
+ void atomic_flag_clear(atomic_flag*) noexcept; // freestanding
275
+ void atomic_flag_clear_explicit(volatile atomic_flag*, memory_order) noexcept; // freestanding
276
+ void atomic_flag_clear_explicit(atomic_flag*, memory_order) noexcept; // freestanding
277
 
278
+ void atomic_flag_wait(const volatile atomic_flag*, bool) noexcept; // freestanding
279
+ void atomic_flag_wait(const atomic_flag*, bool) noexcept; // freestanding
280
+ void atomic_flag_wait_explicit(const volatile atomic_flag*, // freestanding
281
  bool, memory_order) noexcept;
282
+ void atomic_flag_wait_explicit(const atomic_flag*, // freestanding
283
  bool, memory_order) noexcept;
284
+ void atomic_flag_notify_one(volatile atomic_flag*) noexcept; // freestanding
285
+ void atomic_flag_notify_one(atomic_flag*) noexcept; // freestanding
286
+ void atomic_flag_notify_all(volatile atomic_flag*) noexcept; // freestanding
287
+ void atomic_flag_notify_all(atomic_flag*) noexcept; // freestanding
288
+ #define ATOMIC_FLAG_INIT see belownc // freestanding
289
 
290
  // [atomics.fences], fences
291
+ extern "C" void atomic_thread_fence(memory_order) noexcept; // freestanding
292
+ extern "C" void atomic_signal_fence(memory_order) noexcept; // freestanding
293
  }
294
  ```
295
 
296
+ ### Type aliases <a id="atomics.alias">[[atomics.alias]]</a>
297
 
298
  The type aliases `atomic_intN_t`, `atomic_uintN_t`, `atomic_intptr_t`,
299
  and `atomic_uintptr_t` are defined if and only if `intN_t`, `uintN_t`,
300
  `intptr_t`, and `uintptr_t` are defined, respectively.
301
 
 
309
 
310
  Implementations should choose for these aliases the integral
311
  specializations of `atomic` for which the atomic waiting and notifying
312
  operations [[atomics.wait]] are most efficient.
313
 
314
+ ### Order and consistency <a id="atomics.order">[[atomics.order]]</a>
315
 
316
  ``` cpp
317
  namespace std {
318
  enum class memory_order : unspecified {
319
  relaxed, consume, acquire, release, acq_rel, seq_cst
320
  };
 
 
 
 
 
 
321
  }
322
  ```
323
 
324
  The enumeration `memory_order` specifies the detailed regular
325
  (non-atomic) memory synchronization order as defined in
 
417
  // Thread 2:
418
  r2 = x.load(memory_order::relaxed);
419
  y.store(r2, memory_order::relaxed);
420
  ```
421
 
422
+ this recommendation discourages producing `r1 == r2 == 42`, since the
423
+ store of 42 to `y` is only possible if the store to `x` stores `42`,
424
+ which circularly depends on the store to `y` storing `42`. Note that
425
+ without this restriction, such an execution is possible.
426
 
427
  — *end note*]
428
 
429
  [*Note 7*:
430
 
 
460
  *Effects:* The argument does not carry a dependency to the return
461
  value [[intro.multithread]].
462
 
463
  *Returns:* `y`.
464
 
465
+ ### Lock-free property <a id="atomics.lockfree">[[atomics.lockfree]]</a>
466
 
467
  ``` cpp
468
  #define ATOMIC_BOOL_LOCK_FREE unspecified
469
  #define ATOMIC_CHAR_LOCK_FREE unspecified
470
  #define ATOMIC_CHAR8_T_LOCK_FREE unspecified
 
484
  (partial) specializations of the `atomic` template. A value of 0
485
  indicates that the types are never lock-free. A value of 1 indicates
486
  that the types are sometimes lock-free. A value of 2 indicates that the
487
  types are always lock-free.
488
 
489
+ On a hosted implementation [[compliance]], at least one signed integral
490
+ specialization of the `atomic` template, along with the specialization
491
+ for the corresponding unsigned type [[basic.fundamental]], is always
492
+ lock-free.
493
 
494
+ The functions `atomic<T>::is_lock_free` and `atomic_is_lock_free`
495
+ [[atomics.types.operations]] indicate whether the object is lock-free.
496
+ In any given program execution, the result of the lock-free query is the
497
+ same for all atomic objects of the same type.
 
 
 
498
 
499
  Atomic operations that are not lock-free are considered to potentially
500
  block [[intro.progress]].
501
 
502
+ *Recommended practice:* Operations that are lock-free should also be
503
+ address-free.[^2]
 
 
 
 
504
 
505
+ The implementation of these operations should not depend on any
506
+ per-process state.
507
+
508
+ [*Note 1*: This restriction enables communication by memory that is
509
+ mapped into a process more than once and by memory that is shared
510
+ between two processes. — *end note*]
511
+
512
+ ### Waiting and notifying <a id="atomics.wait">[[atomics.wait]]</a>
513
 
514
  *Atomic waiting operations* and *atomic notifying operations* provide a
515
  mechanism to wait for the value of an atomic object to change more
516
  efficiently than can be achieved with polling. An atomic waiting
517
  operation may block until it is unblocked by an atomic notifying
 
552
  - the atomic waiting operation has blocked after observing the result of
553
  `X`,
554
  - `X` precedes `Y` in the modification order of `M`, and
555
  - `Y` happens before the call to the atomic notifying operation.
556
 
557
+ ### Class template `atomic_ref` <a id="atomics.ref.generic">[[atomics.ref.generic]]</a>
558
+
559
+ #### General <a id="atomics.ref.generic.general">[[atomics.ref.generic.general]]</a>
560
 
561
  ``` cpp
562
  namespace std {
563
  template<class T> struct atomic_ref {
564
  private:
565
  T* ptr; // exposition only
566
+
567
  public:
568
  using value_type = T;
569
  static constexpr size_t required_alignment = implementation-defined // required alignment for atomic_ref type's operations;
570
 
571
  static constexpr bool is_always_lock_free = implementation-defined // whether a given atomic_ref type's operations are always lock free;
 
614
 
615
  Atomic operations applied to an object through a referencing
616
  `atomic_ref` are atomic with respect to atomic operations applied
617
  through any other `atomic_ref` referencing the same object.
618
 
619
+ [*Note 1*: Atomic operations or the `atomic_ref` constructor can
620
  acquire a shared resource, such as a lock associated with the referenced
621
  object, to enable atomic operations to be applied to the referenced
622
  object. — *end note*]
623
 
624
+ #### Operations <a id="atomics.ref.ops">[[atomics.ref.ops]]</a>
625
 
626
  ``` cpp
627
  static constexpr size_t required_alignment;
628
  ```
629
 
 
810
  `*ptr` that are eligible to be unblocked [[atomics.wait]] by this call.
811
 
812
  *Remarks:* This function is an atomic notifying
813
  operation [[atomics.wait]] on atomic object `*ptr`.
814
 
815
+ #### Specializations for integral types <a id="atomics.ref.int">[[atomics.ref.int]]</a>
816
 
817
  There are specializations of the `atomic_ref` class template for the
818
  integral types `char`, `signed char`, `unsigned char`, `short`,
819
  `unsigned short`, `int`, `unsigned int`, `long`, `unsigned long`,
820
  `long long`, `unsigned long long`, `char8_t`, `char16_t`, `char32_t`,
821
  `wchar_t`, and any other types needed by the typedefs in the header
822
+ `<cstdint>`. For each such type `integral-type`, the specialization
823
+ `atomic_ref<integral-type>` provides additional atomic operations
824
+ appropriate to integral types.
825
 
826
  [*Note 1*: The specialization `atomic_ref<bool>` uses the primary
827
  template [[atomics.ref.generic]]. — *end note*]
828
 
829
  ``` cpp
830
  namespace std {
831
+ template<> struct atomic_ref<integral-type> {
832
  private:
833
+ integral-type* ptr; // exposition only
834
+
835
  public:
836
+ using value_type = integral-type;
837
  using difference_type = value_type;
838
  static constexpr size_t required_alignment = implementation-defined // required alignment for atomic_ref type's operations;
839
 
840
  static constexpr bool is_always_lock_free = implementation-defined // whether a given atomic_ref type's operations are always lock free;
841
  bool is_lock_free() const noexcept;
842
 
843
+ explicit atomic_ref(integral-type&);
844
  atomic_ref(const atomic_ref&) noexcept;
845
  atomic_ref& operator=(const atomic_ref&) = delete;
846
 
847
+ void store(integral-type, memory_order = memory_order::seq_cst) const noexcept;
848
+ integral-type operator=(integral-type) const noexcept;
849
+ integral-type load(memory_order = memory_order::seq_cst) const noexcept;
850
+ operator integral-type() const noexcept;
851
 
852
+ integral-type exchange(integral-type,
853
  memory_order = memory_order::seq_cst) const noexcept;
854
+ bool compare_exchange_weak(integral-type&, integral-type,
855
  memory_order, memory_order) const noexcept;
856
+ bool compare_exchange_strong(integral-type&, integral-type,
857
  memory_order, memory_order) const noexcept;
858
+ bool compare_exchange_weak(integral-type&, integral-type,
859
  memory_order = memory_order::seq_cst) const noexcept;
860
+ bool compare_exchange_strong(integral-type&, integral-type,
861
  memory_order = memory_order::seq_cst) const noexcept;
862
 
863
+ integral-type fetch_add(integral-type,
864
  memory_order = memory_order::seq_cst) const noexcept;
865
+ integral-type fetch_sub(integral-type,
866
  memory_order = memory_order::seq_cst) const noexcept;
867
+ integral-type fetch_and(integral-type,
868
  memory_order = memory_order::seq_cst) const noexcept;
869
+ integral-type fetch_or(integral-type,
870
  memory_order = memory_order::seq_cst) const noexcept;
871
+ integral-type fetch_xor(integral-type,
872
  memory_order = memory_order::seq_cst) const noexcept;
873
 
874
+ integral-type operator++(int) const noexcept;
875
+ integral-type operator--(int) const noexcept;
876
+ integral-type operator++() const noexcept;
877
+ integral-type operator--() const noexcept;
878
+ integral-type operator+=(integral-type) const noexcept;
879
+ integral-type operator-=(integral-type) const noexcept;
880
+ integral-type operator&=(integral-type) const noexcept;
881
+ integral-type operator|=(integral-type) const noexcept;
882
+ integral-type operator^=(integral-type) const noexcept;
883
 
884
+ void wait(integral-type, memory_order = memory_order::seq_cst) const noexcept;
885
  void notify_one() const noexcept;
886
  void notify_all() const noexcept;
887
  };
888
  }
889
  ```
890
 
891
  Descriptions are provided below only for members that differ from the
892
  primary template.
893
 
894
+ The following operations perform arithmetic computations. The
895
+ correspondence among key, operator, and computation is specified in
896
  [[atomic.types.int.comp]].
897
 
898
  ``` cpp
899
+ integral-type fetch_key(integral-type operand,
900
+ memory_order order = memory_order::seq_cst) const noexcept;
901
  ```
902
 
903
  *Effects:* Atomically replaces the value referenced by `*ptr` with the
904
  result of the computation applied to the value referenced by `*ptr` and
905
  the given operand. Memory is affected according to the value of `order`.
 
916
 
917
  [*Note 1*: There are no undefined results arising from the
918
  computation. — *end note*]
919
 
920
  ``` cpp
921
+ integral-type operator op=(integral-type operand) const noexcept;
922
  ```
923
 
924
  *Effects:* Equivalent to:
925
  `return fetch_`*`key`*`(operand) `*`op`*` operand;`
926
 
927
+ #### Specializations for floating-point types <a id="atomics.ref.float">[[atomics.ref.float]]</a>
928
 
929
+ There are specializations of the `atomic_ref` class template for all
930
+ cv-unqualified floating-point types. For each such type
931
+ `floating-point-type`, the specialization `atomic_ref<floating-point>`
932
  provides additional atomic operations appropriate to floating-point
933
  types.
934
 
935
  ``` cpp
936
  namespace std {
937
+ template<> struct atomic_ref<floating-point-type> {
938
  private:
939
+ floating-point-type* ptr; // exposition only
940
+
941
  public:
942
+ using value_type = floating-point-type;
943
  using difference_type = value_type;
944
  static constexpr size_t required_alignment = implementation-defined // required alignment for atomic_ref type's operations;
945
 
946
  static constexpr bool is_always_lock_free = implementation-defined // whether a given atomic_ref type's operations are always lock free;
947
  bool is_lock_free() const noexcept;
948
 
949
+ explicit atomic_ref(floating-point-type&);
950
  atomic_ref(const atomic_ref&) noexcept;
951
  atomic_ref& operator=(const atomic_ref&) = delete;
952
 
953
+ void store(floating-point-type, memory_order = memory_order::seq_cst) const noexcept;
954
+ floating-point-type operator=(floating-point-type) const noexcept;
955
+ floating-point-type load(memory_order = memory_order::seq_cst) const noexcept;
956
+ operator floating-point-type() const noexcept;
957
 
958
+ floating-point-type exchange(floating-point-type,
959
  memory_order = memory_order::seq_cst) const noexcept;
960
+ bool compare_exchange_weak(floating-point-type&, floating-point-type,
961
  memory_order, memory_order) const noexcept;
962
+ bool compare_exchange_strong(floating-point-type&, floating-point-type,
963
  memory_order, memory_order) const noexcept;
964
+ bool compare_exchange_weak(floating-point-type&, floating-point-type,
965
  memory_order = memory_order::seq_cst) const noexcept;
966
+ bool compare_exchange_strong(floating-point-type&, floating-point-type,
967
  memory_order = memory_order::seq_cst) const noexcept;
968
 
969
+ floating-point-type fetch_add(floating-point-type,
970
  memory_order = memory_order::seq_cst) const noexcept;
971
+ floating-point-type fetch_sub(floating-point-type,
972
  memory_order = memory_order::seq_cst) const noexcept;
973
 
974
+ floating-point-type operator+=(floating-point-type) const noexcept;
975
+ floating-point-type operator-=(floating-point-type) const noexcept;
976
 
977
+ void wait(floating-point-type, memory_order = memory_order::seq_cst) const noexcept;
978
  void notify_one() const noexcept;
979
  void notify_all() const noexcept;
980
  };
981
  }
982
  ```
983
 
984
  Descriptions are provided below only for members that differ from the
985
  primary template.
986
 
987
+ The following operations perform arithmetic computations. The
988
+ correspondence among key, operator, and computation is specified in
989
  [[atomic.types.int.comp]].
990
 
991
  ``` cpp
992
+ floating-point-type fetch_key(floating-point-type operand,
993
  memory_order order = memory_order::seq_cst) const noexcept;
994
  ```
995
 
996
  *Effects:* Atomically replaces the value referenced by `*ptr` with the
997
  result of the computation applied to the value referenced by `*ptr` and
 
1003
  the effects.
1004
 
1005
  *Remarks:* If the result is not a representable value for its
1006
  type [[expr.pre]], the result is unspecified, but the operations
1007
  otherwise have no undefined behavior. Atomic arithmetic operations on
1008
+ *`floating-point-type`* should conform to the
1009
+ `std::numeric_limits<`*`floating-point-type`*`>` traits associated with
1010
+ the floating-point type [[limits.syn]]. The floating-point
1011
  environment [[cfenv]] for atomic arithmetic operations on
1012
+ *`floating-point-type`* may be different than the calling thread’s
1013
  floating-point environment.
1014
 
1015
  ``` cpp
1016
+ floating-point-type operator op=(floating-point-type operand) const noexcept;
1017
  ```
1018
 
1019
  *Effects:* Equivalent to:
1020
  `return fetch_`*`key`*`(operand) `*`op`*` operand;`
1021
 
1022
+ #### Partial specialization for pointers <a id="atomics.ref.pointer">[[atomics.ref.pointer]]</a>
1023
 
1024
  ``` cpp
1025
  namespace std {
1026
  template<class T> struct atomic_ref<T*> {
1027
  private:
1028
  T** ptr; // exposition only
1029
+
1030
  public:
1031
  using value_type = T*;
1032
  using difference_type = ptrdiff_t;
1033
  static constexpr size_t required_alignment = implementation-defined // required alignment for atomic_ref type's operations;
1034
 
 
1072
  ```
1073
 
1074
  Descriptions are provided below only for members that differ from the
1075
  primary template.
1076
 
1077
+ The following operations perform arithmetic computations. The
1078
+ correspondence among key, operator, and computation is specified in
1079
  [[atomic.types.pointer.comp]].
1080
 
1081
  ``` cpp
1082
  T* fetch_key(difference_type operand, memory_order order = memory_order::seq_cst) const noexcept;
1083
  ```
 
1101
  ```
1102
 
1103
  *Effects:* Equivalent to:
1104
  `return fetch_`*`key`*`(operand) `*`op`*` operand;`
1105
 
1106
+ #### Member operators common to integers and pointers to objects <a id="atomics.ref.memop">[[atomics.ref.memop]]</a>
1107
 
1108
  ``` cpp
1109
  value_type operator++(int) const noexcept;
1110
  ```
1111
 
 
1127
  value_type operator--() const noexcept;
1128
  ```
1129
 
1130
  *Effects:* Equivalent to: `return fetch_sub(1) - 1;`
1131
 
1132
+ ### Class template `atomic` <a id="atomics.types.generic">[[atomics.types.generic]]</a>
1133
+
1134
+ #### General <a id="atomics.types.generic.general">[[atomics.types.generic.general]]</a>
1135
 
1136
  ``` cpp
1137
  namespace std {
1138
  template<class T> struct atomic {
1139
  using value_type = T;
 
1190
  - `is_move_assignable_v<T>`
1191
 
1192
  is `false`.
1193
 
1194
  [*Note 1*: Type arguments that are not also statically initializable
1195
+ can be difficult to use. — *end note*]
1196
 
1197
  The specialization `atomic<bool>` is a standard-layout struct.
1198
 
1199
  [*Note 2*: The representation of an atomic specialization need not have
1200
  the same size and alignment requirement as its corresponding argument
1201
  type. — *end note*]
1202
 
1203
+ #### Operations on atomic types <a id="atomics.types.operations">[[atomics.types.operations]]</a>
1204
 
1205
  ``` cpp
1206
  constexpr atomic() noexcept(is_nothrow_default_constructible_v<T>);
1207
  ```
1208
 
 
1251
  ``` cpp
1252
  void store(T desired, memory_order order = memory_order::seq_cst) volatile noexcept;
1253
  void store(T desired, memory_order order = memory_order::seq_cst) noexcept;
1254
  ```
1255
 
1256
+ *Constraints:* For the `volatile` overload of this function,
1257
+ `is_always_lock_free` is `true`.
1258
+
1259
  *Preconditions:* The `order` argument is neither
1260
  `memory_order::consume`, `memory_order::acquire`, nor
1261
  `memory_order::acq_rel`.
1262
 
 
 
 
1263
  *Effects:* Atomically replaces the value pointed to by `this` with the
1264
  value of `desired`. Memory is affected according to the value of
1265
  `order`.
1266
 
1267
  ``` cpp
 
1279
  ``` cpp
1280
  T load(memory_order order = memory_order::seq_cst) const volatile noexcept;
1281
  T load(memory_order order = memory_order::seq_cst) const noexcept;
1282
  ```
1283
 
 
 
 
1284
  *Constraints:* For the `volatile` overload of this function,
1285
  `is_always_lock_free` is `true`.
1286
 
1287
+ *Preconditions:* The `order` argument is neither `memory_order::release`
1288
+ nor `memory_order::acq_rel`.
1289
+
1290
  *Effects:* Memory is affected according to the value of `order`.
1291
 
1292
  *Returns:* Atomically returns the value pointed to by `this`.
1293
 
1294
  ``` cpp
 
1334
  memory_order order = memory_order::seq_cst) volatile noexcept;
1335
  bool compare_exchange_strong(T& expected, T desired,
1336
  memory_order order = memory_order::seq_cst) noexcept;
1337
  ```
1338
 
 
 
 
1339
  *Constraints:* For the `volatile` overload of this function,
1340
  `is_always_lock_free` is `true`.
1341
 
1342
+ *Preconditions:* The `failure` argument is neither
1343
+ `memory_order::release` nor `memory_order::acq_rel`.
1344
+
1345
  *Effects:* Retrieves the value in `expected`. It then atomically
1346
  compares the value representation of the value pointed to by `this` for
1347
  equality with that previously retrieved from `expected`, and if true,
1348
  replaces the value pointed to by `this` with that in `desired`. If and
1349
  only if the comparison is `true`, memory is affected according to the
 
1363
  *Returns:* The result of the comparison.
1364
 
1365
  [*Note 4*:
1366
 
1367
  For example, the effect of `compare_exchange_strong` on objects without
1368
+ padding bits [[term.padding.bits]] is
1369
 
1370
  ``` cpp
1371
  if (memcmp(this, &expected, sizeof(*this)) == 0)
1372
  memcpy(this, &desired, sizeof(*this));
1373
  else
1374
+ memcpy(&expected, this, sizeof(*this));
1375
  ```
1376
 
1377
  — *end note*]
1378
 
1379
  [*Example 1*:
 
1424
  performance on some platforms. When a weak compare-and-exchange would
1425
  require a loop and a strong one would not, the strong one is
1426
  preferable. — *end note*]
1427
 
1428
  [*Note 6*: Under cases where the `memcpy` and `memcmp` semantics of the
1429
+ compare-and-exchange operations apply, the comparisons can fail for
1430
+ values that compare equal with `operator==` if the value representation
1431
+ has trap bits or alternate representations of the same value. Notably,
1432
+ on implementations conforming to ISO/IEC/IEEE 60559, floating-point
1433
+ `-0.0` and `+0.0` will not compare equal with `memcmp` but will compare
1434
+ equal with `operator==`, and NaNs with the same payload will compare
1435
+ equal with `memcmp` but will not compare equal with
1436
  `operator==`. — *end note*]
1437
 
1438
  [*Note 7*:
1439
 
1440
  Because compare-and-exchange acts on an object’s value representation,
 
1521
  are eligible to be unblocked [[atomics.wait]] by this call.
1522
 
1523
  *Remarks:* This function is an atomic notifying
1524
  operation [[atomics.wait]].
1525
 
1526
+ #### Specializations for integers <a id="atomics.types.int">[[atomics.types.int]]</a>
1527
 
1528
  There are specializations of the `atomic` class template for the
1529
  integral types `char`, `signed char`, `unsigned char`, `short`,
1530
  `unsigned short`, `int`, `unsigned int`, `long`, `unsigned long`,
1531
  `long long`, `unsigned long long`, `char8_t`, `char16_t`, `char32_t`,
1532
  `wchar_t`, and any other types needed by the typedefs in the header
1533
+ `<cstdint>`. For each such type `integral-type`, the specialization
1534
+ `atomic<integral-type>` provides additional atomic operations
1535
+ appropriate to integral types.
1536
 
1537
  [*Note 1*: The specialization `atomic<bool>` uses the primary template
1538
  [[atomics.types.generic]]. — *end note*]
1539
 
1540
  ``` cpp
1541
  namespace std {
1542
+ template<> struct atomic<integral-type> {
1543
+ using value_type = integral-type;
1544
  using difference_type = value_type;
1545
 
1546
  static constexpr bool is_always_lock_free = implementation-defined // whether a given atomic type's operations are always lock free;
1547
  bool is_lock_free() const volatile noexcept;
1548
  bool is_lock_free() const noexcept;
1549
 
1550
  constexpr atomic() noexcept;
1551
+ constexpr atomic(integral-type) noexcept;
1552
  atomic(const atomic&) = delete;
1553
  atomic& operator=(const atomic&) = delete;
1554
  atomic& operator=(const atomic&) volatile = delete;
1555
 
1556
+ void store(integral-type, memory_order = memory_order::seq_cst) volatile noexcept;
1557
+ void store(integral-type, memory_order = memory_order::seq_cst) noexcept;
1558
+ integral-type operator=(integral-type) volatile noexcept;
1559
+ integral-type operator=(integral-type) noexcept;
1560
+ integral-type load(memory_order = memory_order::seq_cst) const volatile noexcept;
1561
+ integral-type load(memory_order = memory_order::seq_cst) const noexcept;
1562
+ operator integral-type() const volatile noexcept;
1563
+ operator integral-type() const noexcept;
1564
 
1565
+ integral-type exchange(integral-type,
1566
+ memory_order = memory_order::seq_cst) volatile noexcept;
1567
+ integral-type exchange(integral-type,
1568
+ memory_order = memory_order::seq_cst) noexcept;
1569
+ bool compare_exchange_weak(integral-type&, integral-type,
1570
  memory_order, memory_order) volatile noexcept;
1571
+ bool compare_exchange_weak(integral-type&, integral-type,
1572
  memory_order, memory_order) noexcept;
1573
+ bool compare_exchange_strong(integral-type&, integral-type,
1574
  memory_order, memory_order) volatile noexcept;
1575
+ bool compare_exchange_strong(integral-type&, integral-type,
1576
  memory_order, memory_order) noexcept;
1577
+ bool compare_exchange_weak(integral-type&, integral-type,
1578
  memory_order = memory_order::seq_cst) volatile noexcept;
1579
+ bool compare_exchange_weak(integral-type&, integral-type,
1580
  memory_order = memory_order::seq_cst) noexcept;
1581
+ bool compare_exchange_strong(integral-type&, integral-type,
1582
  memory_order = memory_order::seq_cst) volatile noexcept;
1583
+ bool compare_exchange_strong(integral-type&, integral-type,
1584
  memory_order = memory_order::seq_cst) noexcept;
1585
 
1586
+ integral-type fetch_add(integral-type,
1587
+ memory_order = memory_order::seq_cst) volatile noexcept;
1588
+ integral-type fetch_add(integral-type,
1589
+ memory_order = memory_order::seq_cst) noexcept;
1590
+ integral-type fetch_sub(integral-type,
1591
+ memory_order = memory_order::seq_cst) volatile noexcept;
1592
+ integral-type fetch_sub(integral-type,
1593
+ memory_order = memory_order::seq_cst) noexcept;
1594
+ integral-type fetch_and(integral-type,
1595
+ memory_order = memory_order::seq_cst) volatile noexcept;
1596
+ integral-type fetch_and(integral-type,
1597
+ memory_order = memory_order::seq_cst) noexcept;
1598
+ integral-type fetch_or(integral-type,
1599
+ memory_order = memory_order::seq_cst) volatile noexcept;
1600
+ integral-type fetch_or(integral-type,
1601
+ memory_order = memory_order::seq_cst) noexcept;
1602
+ integral-type fetch_xor(integral-type,
1603
+ memory_order = memory_order::seq_cst) volatile noexcept;
1604
+ integral-type fetch_xor(integral-type,
1605
+ memory_order = memory_order::seq_cst) noexcept;
1606
 
1607
+ integral-type operator++(int) volatile noexcept;
1608
+ integral-type operator++(int) noexcept;
1609
+ integral-type operator--(int) volatile noexcept;
1610
+ integral-type operator--(int) noexcept;
1611
+ integral-type operator++() volatile noexcept;
1612
+ integral-type operator++() noexcept;
1613
+ integral-type operator--() volatile noexcept;
1614
+ integral-type operator--() noexcept;
1615
+ integral-type operator+=(integral-type) volatile noexcept;
1616
+ integral-type operator+=(integral-type) noexcept;
1617
+ integral-type operator-=(integral-type) volatile noexcept;
1618
+ integral-type operator-=(integral-type) noexcept;
1619
+ integral-type operator&=(integral-type) volatile noexcept;
1620
+ integral-type operator&=(integral-type) noexcept;
1621
+ integral-type operator|=(integral-type) volatile noexcept;
1622
+ integral-type operator|=(integral-type) noexcept;
1623
+ integral-type operator^=(integral-type) volatile noexcept;
1624
+ integral-type operator^=(integral-type) noexcept;
1625
 
1626
+ void wait(integral-type, memory_order = memory_order::seq_cst) const volatile noexcept;
1627
+ void wait(integral-type, memory_order = memory_order::seq_cst) const noexcept;
1628
  void notify_one() volatile noexcept;
1629
  void notify_one() noexcept;
1630
  void notify_all() volatile noexcept;
1631
  void notify_all() noexcept;
1632
  };
 
1637
  each have a trivial destructor.
1638
 
1639
  Descriptions are provided below only for members that differ from the
1640
  primary template.
1641
 
1642
+ The following operations perform arithmetic computations. The
1643
+ correspondence among key, operator, and computation is specified in
1644
+ [[atomic.types.int.comp]].
1645
 
1646
  **Table: Atomic arithmetic computations** <a id="atomic.types.int.comp">[atomic.types.int.comp]</a>
1647
 
1648
  | | | | | | |
1649
  | ----- | --- | -------------------- | ----- | --- | -------------------- |
 
1685
  `is_always_lock_free` is `true`.
1686
 
1687
  *Effects:* Equivalent to:
1688
  `return fetch_`*`key`*`(operand) `*`op`*` operand;`
1689
 
1690
+ #### Specializations for floating-point types <a id="atomics.types.float">[[atomics.types.float]]</a>
1691
 
1692
+ There are specializations of the `atomic` class template for all
1693
+ cv-unqualified floating-point types. For each such type
1694
+ `floating-point-type`, the specialization `atomic<floating-point-type>`
1695
  provides additional atomic operations appropriate to floating-point
1696
  types.
1697
 
1698
  ``` cpp
1699
  namespace std {
1700
+ template<> struct atomic<floating-point-type> {
1701
+ using value_type = floating-point-type;
1702
  using difference_type = value_type;
1703
 
1704
  static constexpr bool is_always_lock_free = implementation-defined // whether a given atomic type's operations are always lock free;
1705
  bool is_lock_free() const volatile noexcept;
1706
  bool is_lock_free() const noexcept;
1707
 
1708
  constexpr atomic() noexcept;
1709
+ constexpr atomic(floating-point-type) noexcept;
1710
  atomic(const atomic&) = delete;
1711
  atomic& operator=(const atomic&) = delete;
1712
  atomic& operator=(const atomic&) volatile = delete;
1713
 
1714
+ void store(floating-point-type, memory_order = memory_order::seq_cst) volatile noexcept;
1715
+ void store(floating-point-type, memory_order = memory_order::seq_cst) noexcept;
1716
+ floating-point-type operator=(floating-point-type) volatile noexcept;
1717
+ floating-point-type operator=(floating-point-type) noexcept;
1718
+ floating-point-type load(memory_order = memory_order::seq_cst) volatile noexcept;
1719
+ floating-point-type load(memory_order = memory_order::seq_cst) noexcept;
1720
+ operator floating-point-type() volatile noexcept;
1721
+ operator floating-point-type() noexcept;
1722
 
1723
+ floating-point-type exchange(floating-point-type,
1724
  memory_order = memory_order::seq_cst) volatile noexcept;
1725
+ floating-point-type exchange(floating-point-type,
1726
  memory_order = memory_order::seq_cst) noexcept;
1727
+ bool compare_exchange_weak(floating-point-type&, floating-point-type,
1728
  memory_order, memory_order) volatile noexcept;
1729
+ bool compare_exchange_weak(floating-point-type&, floating-point-type,
1730
  memory_order, memory_order) noexcept;
1731
+ bool compare_exchange_strong(floating-point-type&, floating-point-type,
1732
  memory_order, memory_order) volatile noexcept;
1733
+ bool compare_exchange_strong(floating-point-type&, floating-point-type,
1734
  memory_order, memory_order) noexcept;
1735
+ bool compare_exchange_weak(floating-point-type&, floating-point-type,
1736
  memory_order = memory_order::seq_cst) volatile noexcept;
1737
+ bool compare_exchange_weak(floating-point-type&, floating-point-type,
1738
  memory_order = memory_order::seq_cst) noexcept;
1739
+ bool compare_exchange_strong(floating-point-type&, floating-point-type,
1740
  memory_order = memory_order::seq_cst) volatile noexcept;
1741
+ bool compare_exchange_strong(floating-point-type&, floating-point-type,
1742
  memory_order = memory_order::seq_cst) noexcept;
1743
 
1744
+ floating-point-type fetch_add(floating-point-type,
1745
  memory_order = memory_order::seq_cst) volatile noexcept;
1746
+ floating-point-type fetch_add(floating-point-type,
1747
  memory_order = memory_order::seq_cst) noexcept;
1748
+ floating-point-type fetch_sub(floating-point-type,
1749
  memory_order = memory_order::seq_cst) volatile noexcept;
1750
+ floating-point-type fetch_sub(floating-point-type,
1751
  memory_order = memory_order::seq_cst) noexcept;
1752
 
1753
+ floating-point-type operator+=(floating-point-type) volatile noexcept;
1754
+ floating-point-type operator+=(floating-point-type) noexcept;
1755
+ floating-point-type operator-=(floating-point-type) volatile noexcept;
1756
+ floating-point-type operator-=(floating-point-type) noexcept;
1757
 
1758
+ void wait(floating-point-type, memory_order = memory_order::seq_cst) const volatile noexcept;
1759
+ void wait(floating-point-type, memory_order = memory_order::seq_cst) const noexcept;
1760
  void notify_one() volatile noexcept;
1761
  void notify_one() noexcept;
1762
  void notify_all() volatile noexcept;
1763
  void notify_all() noexcept;
1764
  };
 
1770
 
1771
  Descriptions are provided below only for members that differ from the
1772
  primary template.
1773
 
1774
  The following operations perform arithmetic addition and subtraction
1775
+ computations. The correspondence among key, operator, and computation is
1776
+ specified in [[atomic.types.int.comp]].
1777
 
1778
  ``` cpp
1779
  T fetch_key(T operand, memory_order order = memory_order::seq_cst) volatile noexcept;
1780
  T fetch_key(T operand, memory_order order = memory_order::seq_cst) noexcept;
1781
  ```
 
1793
  the effects.
1794
 
1795
  *Remarks:* If the result is not a representable value for its
1796
  type [[expr.pre]] the result is unspecified, but the operations
1797
  otherwise have no undefined behavior. Atomic arithmetic operations on
1798
+ *`floating-point-type`* should conform to the
1799
+ `std::numeric_limits<`*`floating-point-type`*`>` traits associated with
1800
+ the floating-point type [[limits.syn]]. The floating-point
1801
  environment [[cfenv]] for atomic arithmetic operations on
1802
+ *`floating-point-type`* may be different than the calling thread’s
1803
  floating-point environment.
1804
 
1805
  ``` cpp
1806
  T operator op=(T operand) volatile noexcept;
1807
  T operator op=(T operand) noexcept;
 
1814
  `return fetch_`*`key`*`(operand) `*`op`*` operand;`
1815
 
1816
  *Remarks:* If the result is not a representable value for its
1817
  type [[expr.pre]] the result is unspecified, but the operations
1818
  otherwise have no undefined behavior. Atomic arithmetic operations on
1819
+ *`floating-point-type`* should conform to the
1820
+ `std::numeric_limits<`*`floating-point-type`*`>` traits associated with
1821
+ the floating-point type [[limits.syn]]. The floating-point
1822
  environment [[cfenv]] for atomic arithmetic operations on
1823
+ *`floating-point-type`* may be different than the calling thread’s
1824
  floating-point environment.
1825
 
1826
+ #### Partial specialization for pointers <a id="atomics.types.pointer">[[atomics.types.pointer]]</a>
1827
 
1828
  ``` cpp
1829
  namespace std {
1830
  template<class T> struct atomic<T*> {
1831
  using value_type = T*;
 
1898
  standard-layout structs. They each have a trivial destructor.
1899
 
1900
  Descriptions are provided below only for members that differ from the
1901
  primary template.
1902
 
1903
+ The following operations perform pointer arithmetic. The correspondence
1904
+ among key, operator, and computation is specified in
1905
+ [[atomic.types.pointer.comp]].
1906
 
1907
  **Table: Atomic pointer computations** <a id="atomic.types.pointer.comp">[atomic.types.pointer.comp]</a>
1908
 
1909
  | | | | | | |
1910
  | ----- | --- | -------- | ----- | --- | ----------- |
 
1944
  `is_always_lock_free` is `true`.
1945
 
1946
  *Effects:* Equivalent to:
1947
  `return fetch_`*`key`*`(operand) `*`op`*` operand;`
1948
 
1949
+ #### Member operators common to integers and pointers to objects <a id="atomics.types.memop">[[atomics.types.memop]]</a>
1950
 
1951
  ``` cpp
1952
  value_type operator++(int) volatile noexcept;
1953
  value_type operator++(int) noexcept;
1954
  ```
 
1986
  *Constraints:* For the `volatile` overload of this function,
1987
  `is_always_lock_free` is `true`.
1988
 
1989
  *Effects:* Equivalent to: `return fetch_sub(1) - 1;`
1990
 
1991
+ #### Partial specializations for smart pointers <a id="util.smartptr.atomic">[[util.smartptr.atomic]]</a>
1992
+
1993
+ ##### General <a id="util.smartptr.atomic.general">[[util.smartptr.atomic.general]]</a>
1994
 
1995
  The library provides partial specializations of the `atomic` template
1996
+ for shared-ownership smart pointers [[util.sharedptr]].
 
 
 
1997
 
1998
+ [*Note 1*: The partial specializations are declared in header
1999
+ `<memory>`. *end note*]
2000
+
2001
+ The behavior of all operations is as specified in
2002
+ [[atomics.types.generic]], unless specified otherwise. The template
2003
+ parameter `T` of these partial specializations may be an incomplete
2004
+ type.
2005
+
2006
+ All changes to an atomic smart pointer in [[util.smartptr.atomic]], and
2007
+ all associated `use_count` increments, are guaranteed to be performed
2008
  atomically. Associated `use_count` decrements are sequenced after the
2009
  atomic operation, but are not required to be part of it. Any associated
2010
  deletion and deallocation are sequenced after the atomic update step and
2011
  are not part of the atomic operation.
2012
 
2013
+ [*Note 2*: If the atomic operation uses locks, locks acquired by the
2014
  implementation will be held when any `use_count` adjustments are
2015
  performed, and will not be held when any destruction or deallocation
2016
  resulting from this is performed. — *end note*]
2017
 
2018
  [*Example 1*:
 
2024
  shared_ptr<node> next;
2025
  };
2026
  atomic<shared_ptr<node>> head;
2027
 
2028
  public:
2029
+ shared_ptr<node> find(T t) const {
2030
  auto p = head.load();
2031
  while (p && p->t != t)
2032
  p = p->next;
2033
 
2034
+ return p;
2035
  }
2036
 
2037
  void push_front(T t) {
2038
  auto p = make_shared<node>();
2039
  p->t = t;
 
2043
  };
2044
  ```
2045
 
2046
  — *end example*]
2047
 
2048
+ ##### Partial specialization for `shared_ptr` <a id="util.smartptr.atomic.shared">[[util.smartptr.atomic.shared]]</a>
2049
 
2050
  ``` cpp
2051
  namespace std {
2052
  template<class T> struct atomic<shared_ptr<T>> {
2053
  using value_type = shared_ptr<T>;
2054
 
2055
  static constexpr bool is_always_lock_free = implementation-defined // whether a given atomic type's operations are always lock free;
2056
  bool is_lock_free() const noexcept;
2057
 
2058
  constexpr atomic() noexcept;
2059
+ constexpr atomic(nullptr_t) noexcept : atomic() { }
2060
  atomic(shared_ptr<T> desired) noexcept;
2061
  atomic(const atomic&) = delete;
2062
  void operator=(const atomic&) = delete;
2063
 
2064
  shared_ptr<T> load(memory_order order = memory_order::seq_cst) const noexcept;
 
2253
  are eligible to be unblocked [[atomics.wait]] by this call.
2254
 
2255
  *Remarks:* This function is an atomic notifying
2256
  operation [[atomics.wait]].
2257
 
2258
+ ##### Partial specialization for `weak_ptr` <a id="util.smartptr.atomic.weak">[[util.smartptr.atomic.weak]]</a>
2259
 
2260
  ``` cpp
2261
  namespace std {
2262
  template<class T> struct atomic<weak_ptr<T>> {
2263
  using value_type = weak_ptr<T>;
 
2307
  ```
2308
 
2309
  *Effects:* Initializes the object with the value `desired`.
2310
  Initialization is not an atomic operation [[intro.multithread]].
2311
 
2312
+ [*Note 2*: It is possible to have an access to an atomic object `A`
2313
  race with its construction, for example, by communicating the address of
2314
  the just-constructed object `A` to another thread via
2315
  `memory_order::relaxed` operations on a suitable atomic pointer
2316
  variable, and then immediately accessing `A` in the receiving thread.
2317
  This results in undefined behavior. — *end note*]
 
2462
  are eligible to be unblocked [[atomics.wait]] by this call.
2463
 
2464
  *Remarks:* This function is an atomic notifying
2465
  operation [[atomics.wait]].
2466
 
2467
+ ### Non-member functions <a id="atomics.nonmembers">[[atomics.nonmembers]]</a>
2468
 
2469
  A non-member function template whose name matches the pattern `atomic_f`
2470
  or the pattern `atomic_f_explicit` invokes the member function `f`, with
2471
  the value of the first parameter as the object expression and the values
2472
  of the remaining parameters (if any) as the arguments of the member
 
2477
 
2478
  [*Note 1*: The non-member functions enable programmers to write code
2479
  that can be compiled as either C or C++, for example in a shared header
2480
  file. — *end note*]
2481
 
2482
+ ### Flag type and operations <a id="atomics.flag">[[atomics.flag]]</a>
2483
 
2484
  ``` cpp
2485
  namespace std {
2486
  struct atomic_flag {
2487
  constexpr atomic_flag() noexcept;
 
2507
  ```
2508
 
2509
  The `atomic_flag` type provides the classic test-and-set functionality.
2510
  It has two states, set and clear.
2511
 
2512
+ Operations on an object of type `atomic_flag` shall be lock-free. The
2513
+ operations should also be address-free.
 
 
2514
 
2515
  The `atomic_flag` type is a standard-layout struct. It has a trivial
2516
  destructor.
2517
 
2518
  ``` cpp
 
2630
  are eligible to be unblocked [[atomics.wait]] by this call.
2631
 
2632
  *Remarks:* This function is an atomic notifying
2633
  operation [[atomics.wait]].
2634
 
2635
+ ``` cpp
2636
+ #define ATOMIC_FLAG_INIT see below
2637
+ ```
2638
+
2639
+ *Remarks:* The macro `ATOMIC_FLAG_INIT` is defined in such a way that it
2640
+ can be used to initialize an object of type `atomic_flag` to the clear
2641
+ state. The macro can be used in the form:
2642
+
2643
+ ``` cpp
2644
+ atomic_flag guard = ATOMIC_FLAG_INIT;
2645
+ ```
2646
+
2647
+ It is unspecified whether the macro can be used in other initialization
2648
+ contexts. For a complete static-duration object, that initialization
2649
+ shall be static.
2650
+
2651
+ ### Fences <a id="atomics.fences">[[atomics.fences]]</a>
2652
 
2653
  This subclause introduces synchronization primitives called *fences*.
2654
  Fences can have acquire semantics, release semantics, or both. A fence
2655
  with acquire semantics is called an *acquire fence*. A fence with
2656
  release semantics is called a *release fence*.
 
2703
  handler. Compiler optimizations and reorderings of loads and stores are
2704
  inhibited in the same way as with `atomic_thread_fence`, but the
2705
  hardware fence instructions that `atomic_thread_fence` would have
2706
  inserted are not emitted. — *end note*]
2707
 
2708
+ ### C compatibility <a id="stdatomic.h.syn">[[stdatomic.h.syn]]</a>
2709
+
2710
+ The header `<stdatomic.h>` provides the following definitions:
2711
+
2712
+ ``` cpp
2713
+ template<class T>
2714
+ using std-atomic = std::atomic<T>; // exposition only
2715
+
2716
+ #define _Atomic(T) std-atomic<T>
2717
+
2718
+ #define ATOMIC_BOOL_LOCK_FREE see below
2719
+ #define ATOMIC_CHAR_LOCK_FREE see below
2720
+ #define ATOMIC_CHAR16_T_LOCK_FREE see below
2721
+ #define ATOMIC_CHAR32_T_LOCK_FREE see below
2722
+ #define ATOMIC_WCHAR_T_LOCK_FREE see below
2723
+ #define ATOMIC_SHORT_LOCK_FREE see below
2724
+ #define ATOMIC_INT_LOCK_FREE see below
2725
+ #define ATOMIC_LONG_LOCK_FREE see below
2726
+ #define ATOMIC_LLONG_LOCK_FREE see below
2727
+ #define ATOMIC_POINTER_LOCK_FREE see below
2728
+
2729
+ using std::memory_order; // see below
2730
+ using std::memory_order_relaxed; // see below
2731
+ using std::memory_order_consume; // see below
2732
+ using std::memory_order_acquire; // see below
2733
+ using std::memory_order_release; // see below
2734
+ using std::memory_order_acq_rel; // see below
2735
+ using std::memory_order_seq_cst; // see below
2736
+
2737
+ using std::atomic_flag; // see below
2738
+
2739
+ using std::atomic_bool; // see below
2740
+ using std::atomic_char; // see below
2741
+ using std::atomic_schar; // see below
2742
+ using std::atomic_uchar; // see below
2743
+ using std::atomic_short; // see below
2744
+ using std::atomic_ushort; // see below
2745
+ using std::atomic_int; // see below
2746
+ using std::atomic_uint; // see below
2747
+ using std::atomic_long; // see below
2748
+ using std::atomic_ulong; // see below
2749
+ using std::atomic_llong; // see below
2750
+ using std::atomic_ullong; // see below
2751
+ using std::atomic_char8_t; // see below
2752
+ using std::atomic_char16_t; // see below
2753
+ using std::atomic_char32_t; // see below
2754
+ using std::atomic_wchar_t; // see below
2755
+ using std::atomic_int8_t; // see below
2756
+ using std::atomic_uint8_t; // see below
2757
+ using std::atomic_int16_t; // see below
2758
+ using std::atomic_uint16_t; // see below
2759
+ using std::atomic_int32_t; // see below
2760
+ using std::atomic_uint32_t; // see below
2761
+ using std::atomic_int64_t; // see below
2762
+ using std::atomic_uint64_t; // see below
2763
+ using std::atomic_int_least8_t; // see below
2764
+ using std::atomic_uint_least8_t; // see below
2765
+ using std::atomic_int_least16_t; // see below
2766
+ using std::atomic_uint_least16_t; // see below
2767
+ using std::atomic_int_least32_t; // see below
2768
+ using std::atomic_uint_least32_t; // see below
2769
+ using std::atomic_int_least64_t; // see below
2770
+ using std::atomic_uint_least64_t; // see below
2771
+ using std::atomic_int_fast8_t; // see below
2772
+ using std::atomic_uint_fast8_t; // see below
2773
+ using std::atomic_int_fast16_t; // see below
2774
+ using std::atomic_uint_fast16_t; // see below
2775
+ using std::atomic_int_fast32_t; // see below
2776
+ using std::atomic_uint_fast32_t; // see below
2777
+ using std::atomic_int_fast64_t; // see below
2778
+ using std::atomic_uint_fast64_t; // see below
2779
+ using std::atomic_intptr_t; // see below
2780
+ using std::atomic_uintptr_t; // see below
2781
+ using std::atomic_size_t; // see below
2782
+ using std::atomic_ptrdiff_t; // see below
2783
+ using std::atomic_intmax_t; // see below
2784
+ using std::atomic_uintmax_t; // see below
2785
+
2786
+ using std::atomic_is_lock_free; // see below
2787
+ using std::atomic_load; // see below
2788
+ using std::atomic_load_explicit; // see below
2789
+ using std::atomic_store; // see below
2790
+ using std::atomic_store_explicit; // see below
2791
+ using std::atomic_exchange; // see below
2792
+ using std::atomic_exchange_explicit; // see below
2793
+ using std::atomic_compare_exchange_strong; // see below
2794
+ using std::atomic_compare_exchange_strong_explicit; // see below
2795
+ using std::atomic_compare_exchange_weak; // see below
2796
+ using std::atomic_compare_exchange_weak_explicit; // see below
2797
+ using std::atomic_fetch_add; // see below
2798
+ using std::atomic_fetch_add_explicit; // see below
2799
+ using std::atomic_fetch_sub; // see below
2800
+ using std::atomic_fetch_sub_explicit; // see below
2801
+ using std::atomic_fetch_and; // see below
2802
+ using std::atomic_fetch_and_explicit; // see below
2803
+ using std::atomic_fetch_or; // see below
2804
+ using std::atomic_fetch_or_explicit; // see below
2805
+ using std::atomic_fetch_xor; // see below
2806
+ using std::atomic_fetch_xor_explicit; // see below
2807
+ using std::atomic_flag_test_and_set; // see below
2808
+ using std::atomic_flag_test_and_set_explicit; // see below
2809
+ using std::atomic_flag_clear; // see below
2810
+ using std::atomic_flag_clear_explicit; // see below
2811
+ #define ATOMIC_FLAG_INIT see below
2812
+
2813
+ using std::atomic_thread_fence; // see below
2814
+ using std::atomic_signal_fence; // see below
2815
+ ```
2816
+
2817
+ Each *using-declaration* for some name A in the synopsis above makes
2818
+ available the same entity as `std::A` declared in `<atomic>`. Each macro
2819
+ listed above other than `_Atomic(T)` is defined as in `<atomic>`. It is
2820
+ unspecified whether `<stdatomic.h>` makes available any declarations in
2821
+ namespace `std`.
2822
+
2823
+ Each of the *using-declaration*s for `intN_t`, `uintN_t`, `intptr_t`,
2824
+ and `uintptr_t` listed above is defined if and only if the
2825
+ implementation defines the corresponding *typedef-name* in
2826
+ [[atomics.syn]].
2827
+
2828
+ Neither the `_Atomic` macro, nor any of the non-macro global namespace
2829
+ declarations, are provided by any C++ standard library header other than
2830
+ `<stdatomic.h>`.
2831
+
2832
+ *Recommended practice:* Implementations should ensure that C and C++
2833
+ representations of atomic objects are compatible, so that the same
2834
+ object can be accessed as both an `_Atomic(T)` from C code and an
2835
+ `atomic<T>` from C++ code. The representations should be the same, and
2836
+ the mechanisms used to ensure atomicity and memory ordering should be
2837
+ compatible.
2838
+