From Jason Turner

[atomics]

Large diff (155.2 KB) - rendering may be slow on some devices

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmp0u6y4ozk/{from.md → to.md} +1176 -568
tmp/tmp0u6y4ozk/{from.md → to.md} RENAMED
@@ -6,292 +6,358 @@ 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
 
@@ -314,11 +380,11 @@ operations [[atomics.wait]] are most efficient.
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
@@ -328,21 +394,15 @@ enumerated values and their meanings are as follows:
328
 
329
  - `memory_order::relaxed`: no operation orders memory.
330
  - `memory_order::release`, `memory_order::acq_rel`, and
331
  `memory_order::seq_cst`: a store operation performs a release
332
  operation on the affected memory location.
333
- - `memory_order::consume`: a load operation performs a consume operation
334
- on the affected memory location. \[*Note 1*: Prefer
335
- `memory_order::acquire`, which provides stronger guarantees than
336
- `memory_order::consume`. Implementations have found it infeasible to
337
- provide performance better than that of `memory_order::acquire`.
338
- Specification revisions are under consideration. — *end note*]
339
  - `memory_order::acquire`, `memory_order::acq_rel`, and
340
  `memory_order::seq_cst`: a load operation performs an acquire
341
  operation on the affected memory location.
342
 
343
- [*Note 2*: Atomic operations specifying `memory_order::relaxed` are
344
  relaxed with respect to memory ordering. Implementations must still
345
  guarantee that any given atomic access to a particular atomic object be
346
  indivisible with respect to all other atomic accesses to that
347
  object. — *end note*]
348
 
@@ -377,35 +437,35 @@ S:
377
  - if a `memory_order::seq_cst` fence X happens before A and B is a
378
  `memory_order::seq_cst` operation, then X precedes B in S; and
379
  - if a `memory_order::seq_cst` fence X happens before A and B happens
380
  before a `memory_order::seq_cst` fence Y, then X precedes Y in S.
381
 
382
- [*Note 3*: This definition ensures that S is consistent with the
383
  modification order of any atomic object M. It also ensures that a
384
  `memory_order::seq_cst` load A of M gets its value either from the last
385
  modification of M that precedes A in S or from some
386
  non-`memory_order::seq_cst` modification of M that does not happen
387
  before any modification of M that precedes A in S. — *end note*]
388
 
389
- [*Note 4*: We do not require that S be consistent with “happens before”
390
  [[intro.races]]. This allows more efficient implementation of
391
  `memory_order::acquire` and `memory_order::release` on some machine
392
  architectures. It can produce surprising results when these are mixed
393
  with `memory_order::seq_cst` accesses. — *end note*]
394
 
395
- [*Note 5*: `memory_order::seq_cst` ensures sequential consistency only
396
  for a program that is free of data races and uses exclusively
397
  `memory_order::seq_cst` atomic operations. Any use of weaker ordering
398
  will invalidate this guarantee unless extreme care is used. In many
399
  cases, `memory_order::seq_cst` atomic operations are reorderable with
400
  respect to other atomic operations performed by the same
401
  thread. — *end note*]
402
 
403
  Implementations should ensure that no “out-of-thin-air” values are
404
  computed that circularly depend on their own computation.
405
 
406
- [*Note 6*:
407
 
408
  For example, with `x` and `y` initially zero,
409
 
410
  ``` cpp
411
  // Thread 1:
@@ -424,11 +484,11 @@ 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
 
431
  The recommendation similarly disallows `r1 == r2 == 42` in the following
432
  example, with `x` and `y` again initially zero:
433
 
434
  ``` cpp
@@ -447,22 +507,23 @@ if (r2 == 42) x.store(42, memory_order::relaxed);
447
 
448
  Atomic read-modify-write operations shall always read the last value (in
449
  the modification order) written before the write associated with the
450
  read-modify-write operation.
451
 
452
- Implementations should make atomic stores visible to atomic loads within
453
- a reasonable amount of time.
 
454
 
455
- ``` cpp
456
- template<class T>
457
- T kill_dependency(T y) noexcept;
458
- ```
 
459
 
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
@@ -563,38 +624,40 @@ 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;
572
  bool is_lock_free() const noexcept;
573
 
574
- explicit atomic_ref(T&);
575
- atomic_ref(const atomic_ref&) noexcept;
576
  atomic_ref& operator=(const atomic_ref&) = delete;
577
 
578
- void store(T, memory_order = memory_order::seq_cst) const noexcept;
579
- T operator=(T) const noexcept;
580
- T load(memory_order = memory_order::seq_cst) const noexcept;
581
- operator T() const noexcept;
582
 
583
- T exchange(T, memory_order = memory_order::seq_cst) const noexcept;
584
- bool compare_exchange_weak(T&, T,
 
585
  memory_order, memory_order) const noexcept;
586
- bool compare_exchange_strong(T&, T,
587
  memory_order, memory_order) const noexcept;
588
- bool compare_exchange_weak(T&, T,
589
  memory_order = memory_order::seq_cst) const noexcept;
590
- bool compare_exchange_strong(T&, T,
591
  memory_order = memory_order::seq_cst) const noexcept;
592
 
593
- void wait(T, memory_order = memory_order::seq_cst) const noexcept;
594
- void notify_one() const noexcept;
595
- void notify_all() const noexcept;
 
596
  };
597
  }
598
  ```
599
 
600
  An `atomic_ref` object applies atomic operations [[atomics.general]] to
@@ -619,10 +682,13 @@ through any other `atomic_ref` referencing the same object.
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
  ```
@@ -651,94 +717,103 @@ bool is_lock_free() const noexcept;
651
 
652
  *Returns:* `true` if operations on all objects of the type
653
  `atomic_ref<T>` are lock-free, `false` otherwise.
654
 
655
  ``` cpp
656
- atomic_ref(T& obj);
657
  ```
658
 
659
  *Preconditions:* The referenced object is aligned to
660
  `required_alignment`.
661
 
662
  *Ensures:* `*this` references `obj`.
663
 
664
  *Throws:* Nothing.
665
 
666
  ``` cpp
667
- atomic_ref(const atomic_ref& ref) noexcept;
668
  ```
669
 
670
  *Ensures:* `*this` references the object referenced by `ref`.
671
 
672
  ``` cpp
673
- void store(T desired, memory_order order = memory_order::seq_cst) const noexcept;
 
674
  ```
675
 
676
- *Preconditions:* The `order` argument is neither
677
- `memory_order::consume`, `memory_order::acquire`, nor
678
- `memory_order::acq_rel`.
 
679
 
680
  *Effects:* Atomically replaces the value referenced by `*ptr` with the
681
  value of `desired`. Memory is affected according to the value of
682
  `order`.
683
 
684
  ``` cpp
685
- T operator=(T desired) const noexcept;
686
  ```
687
 
 
 
688
  *Effects:* Equivalent to:
689
 
690
  ``` cpp
691
  store(desired);
692
  return desired;
693
  ```
694
 
695
  ``` cpp
696
- T load(memory_order order = memory_order::seq_cst) const noexcept;
697
  ```
698
 
699
- *Preconditions:* The `order` argument is neither `memory_order::release`
700
- nor `memory_order::acq_rel`.
701
 
702
  *Effects:* Memory is affected according to the value of `order`.
703
 
704
  *Returns:* Atomically returns the value referenced by `*ptr`.
705
 
706
  ``` cpp
707
- operator T() const noexcept;
708
  ```
709
 
710
  *Effects:* Equivalent to: `return load();`
711
 
712
  ``` cpp
713
- T exchange(T desired, memory_order order = memory_order::seq_cst) const noexcept;
 
714
  ```
715
 
 
 
716
  *Effects:* Atomically replaces the value referenced by `*ptr` with
717
  `desired`. Memory is affected according to the value of `order`. This
718
  operation is an atomic read-modify-write
719
  operation [[intro.multithread]].
720
 
721
  *Returns:* Atomically returns the value referenced by `*ptr` immediately
722
  before the effects.
723
 
724
  ``` cpp
725
- bool compare_exchange_weak(T& expected, T desired,
726
  memory_order success, memory_order failure) const noexcept;
727
 
728
- bool compare_exchange_strong(T& expected, T desired,
729
  memory_order success, memory_order failure) const noexcept;
730
 
731
- bool compare_exchange_weak(T& expected, T desired,
732
  memory_order order = memory_order::seq_cst) const noexcept;
733
 
734
- bool compare_exchange_strong(T& expected, T desired,
735
  memory_order order = memory_order::seq_cst) const noexcept;
736
  ```
737
 
738
- *Preconditions:* The `failure` argument is neither
739
- `memory_order::release` nor `memory_order::acq_rel`.
 
 
740
 
741
  *Effects:* Retrieves the value in `expected`. It then atomically
742
  compares the value representation of the value referenced by `*ptr` for
743
  equality with that previously retrieved from `expected`, and if `true`,
744
  replaces the value referenced by `*ptr` with that in `desired`. If and
@@ -772,15 +847,15 @@ compare-and-exchange is in a loop, the weak version will yield better
772
  performance on some platforms. When a weak compare-and-exchange would
773
  require a loop and a strong one would not, the strong one is
774
  preferable. — *end note*]
775
 
776
  ``` cpp
777
- void wait(T old, memory_order order = memory_order::seq_cst) const noexcept;
778
  ```
779
 
780
- *Preconditions:* `order` is neither `memory_order::release` nor
781
- `memory_order::acq_rel`.
782
 
783
  *Effects:* Repeatedly performs the following steps, in order:
784
 
785
  - Evaluates `load(order)` and compares its value representation for
786
  equality against that of `old`.
@@ -790,102 +865,131 @@ void wait(T old, memory_order order = memory_order::seq_cst) const noexcept;
790
 
791
  *Remarks:* This function is an atomic waiting operation [[atomics.wait]]
792
  on atomic object `*ptr`.
793
 
794
  ``` cpp
795
- void notify_one() const noexcept;
796
  ```
797
 
 
 
798
  *Effects:* Unblocks the execution of at least one atomic waiting
799
  operation on `*ptr` that is eligible to be unblocked [[atomics.wait]] by
800
  this call, if any such atomic waiting operations exist.
801
 
802
  *Remarks:* This function is an atomic notifying
803
  operation [[atomics.wait]] on atomic object `*ptr`.
804
 
805
  ``` cpp
806
- void notify_all() const noexcept;
807
  ```
808
 
 
 
809
  *Effects:* Unblocks the execution of all atomic waiting operations on
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
@@ -894,107 +998,177 @@ primary template.
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`.
906
  These operations are atomic read-modify-write
907
  operations [[intro.races]].
908
 
909
  *Returns:* Atomically, the value referenced by `*ptr` immediately before
910
  the effects.
911
 
912
- *Remarks:* For signed integer types, the result is as if the object
913
- value and parameters were converted to their corresponding unsigned
914
- types, the computation performed on those types, and the result
915
- converted back to the signed type.
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
998
  the given operand. Memory is affected according to the value of `order`.
999
  These operations are atomic read-modify-write
1000
  operations [[intro.races]].
@@ -1004,71 +1178,167 @@ 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
 
1035
  static constexpr bool is_always_lock_free = implementation-defined // whether a given atomic_ref type's operations are always lock free;
1036
  bool is_lock_free() const noexcept;
1037
 
1038
- explicit atomic_ref(T*&);
1039
- atomic_ref(const atomic_ref&) noexcept;
1040
  atomic_ref& operator=(const atomic_ref&) = delete;
1041
 
1042
- void store(T*, memory_order = memory_order::seq_cst) const noexcept;
1043
- T* operator=(T*) const noexcept;
1044
- T* load(memory_order = memory_order::seq_cst) const noexcept;
1045
- operator T*() const noexcept;
1046
 
1047
- T* exchange(T*, memory_order = memory_order::seq_cst) const noexcept;
1048
- bool compare_exchange_weak(T*&, T*,
 
1049
  memory_order, memory_order) const noexcept;
1050
- bool compare_exchange_strong(T*&, T*,
1051
  memory_order, memory_order) const noexcept;
1052
- bool compare_exchange_weak(T*&, T*,
 
 
 
 
 
 
 
1053
  memory_order = memory_order::seq_cst) const noexcept;
1054
- bool compare_exchange_strong(T*&, T*,
 
 
1055
  memory_order = memory_order::seq_cst) const noexcept;
1056
 
1057
- T* fetch_add(difference_type, memory_order = memory_order::seq_cst) const noexcept;
1058
- T* fetch_sub(difference_type, memory_order = memory_order::seq_cst) const noexcept;
 
 
 
 
 
 
1059
 
1060
- T* operator++(int) const noexcept;
1061
- T* operator--(int) const noexcept;
1062
- T* operator++() const noexcept;
1063
- T* operator--() const noexcept;
1064
- T* operator+=(difference_type) const noexcept;
1065
- T* operator-=(difference_type) const noexcept;
1066
 
1067
- void wait(T*, memory_order = memory_order::seq_cst) const noexcept;
1068
- void notify_one() const noexcept;
1069
- void notify_all() const noexcept;
 
1070
  };
1071
  }
1072
  ```
1073
 
1074
  Descriptions are provided below only for members that differ from the
@@ -1077,14 +1347,18 @@ primary template.
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
  ```
1084
 
1085
- *Mandates:* `T` is a complete object type.
 
 
 
1086
 
1087
  *Effects:* Atomically replaces the value referenced by `*ptr` with the
1088
  result of the computation applied to the value referenced by `*ptr` and
1089
  the given operand. Memory is affected according to the value of `order`.
1090
  These operations are atomic read-modify-write
@@ -1094,41 +1368,91 @@ operations [[intro.races]].
1094
  the effects.
1095
 
1096
  *Remarks:* The result may be an undefined address, but the operations
1097
  otherwise have no undefined behavior.
1098
 
 
 
 
 
 
 
 
 
 
1099
  ``` cpp
1100
- T* operator op=(difference_type operand) const noexcept;
 
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
 
 
 
1112
  *Effects:* Equivalent to: `return fetch_add(1);`
1113
 
1114
  ``` cpp
1115
- value_type operator--(int) const noexcept;
1116
  ```
1117
 
 
 
1118
  *Effects:* Equivalent to: `return fetch_sub(1);`
1119
 
1120
  ``` cpp
1121
- value_type operator++() const noexcept;
1122
  ```
1123
 
 
 
1124
  *Effects:* Equivalent to: `return fetch_add(1) + 1;`
1125
 
1126
  ``` cpp
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>
@@ -1148,35 +1472,35 @@ namespace std {
1148
  atomic(const atomic&) = delete;
1149
  atomic& operator=(const atomic&) = delete;
1150
  atomic& operator=(const atomic&) volatile = delete;
1151
 
1152
  T load(memory_order = memory_order::seq_cst) const volatile noexcept;
1153
- T load(memory_order = memory_order::seq_cst) const noexcept;
1154
  operator T() const volatile noexcept;
1155
- operator T() const noexcept;
1156
  void store(T, memory_order = memory_order::seq_cst) volatile noexcept;
1157
- void store(T, memory_order = memory_order::seq_cst) noexcept;
1158
  T operator=(T) volatile noexcept;
1159
- T operator=(T) noexcept;
1160
 
1161
  T exchange(T, memory_order = memory_order::seq_cst) volatile noexcept;
1162
- T exchange(T, memory_order = memory_order::seq_cst) noexcept;
1163
  bool compare_exchange_weak(T&, T, memory_order, memory_order) volatile noexcept;
1164
- bool compare_exchange_weak(T&, T, memory_order, memory_order) noexcept;
1165
  bool compare_exchange_strong(T&, T, memory_order, memory_order) volatile noexcept;
1166
- bool compare_exchange_strong(T&, T, memory_order, memory_order) noexcept;
1167
  bool compare_exchange_weak(T&, T, memory_order = memory_order::seq_cst) volatile noexcept;
1168
- bool compare_exchange_weak(T&, T, memory_order = memory_order::seq_cst) noexcept;
1169
  bool compare_exchange_strong(T&, T, memory_order = memory_order::seq_cst) volatile noexcept;
1170
- bool compare_exchange_strong(T&, T, memory_order = memory_order::seq_cst) noexcept;
1171
 
1172
  void wait(T, memory_order = memory_order::seq_cst) const volatile noexcept;
1173
- void wait(T, memory_order = memory_order::seq_cst) const noexcept;
1174
  void notify_one() volatile noexcept;
1175
- void notify_one() noexcept;
1176
  void notify_all() volatile noexcept;
1177
- void notify_all() noexcept;
1178
  };
1179
  }
1180
  ```
1181
 
1182
  The template argument for `T` shall meet the *Cpp17CopyConstructible*
@@ -1184,19 +1508,21 @@ and *Cpp17CopyAssignable* requirements. The program is ill-formed if any
1184
  of
1185
 
1186
  - `is_trivially_copyable_v<T>`,
1187
  - `is_copy_constructible_v<T>`,
1188
  - `is_move_constructible_v<T>`,
1189
- - `is_copy_assignable_v<T>`, or
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
 
@@ -1204,11 +1530,11 @@ type. — *end note*]
1204
 
1205
  ``` cpp
1206
  constexpr atomic() noexcept(is_nothrow_default_constructible_v<T>);
1207
  ```
1208
 
1209
- *Mandates:* `is_default_constructible_v<T>` is `true`.
1210
 
1211
  *Effects:* Initializes the atomic object with the value of `T()`.
1212
  Initialization is not an atomic operation [[intro.multithread]].
1213
 
1214
  ``` cpp
@@ -1248,27 +1574,26 @@ otherwise.
1248
  consistent with the value of `is_always_lock_free` for the same
1249
  type. — *end note*]
1250
 
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
1268
  T operator=(T desired) volatile noexcept;
1269
- T operator=(T desired) noexcept;
1270
  ```
1271
 
1272
  *Constraints:* For the `volatile` overload of this function,
1273
  `is_always_lock_free` is `true`.
1274
 
@@ -1276,36 +1601,36 @@ T operator=(T desired) noexcept;
1276
 
1277
  *Returns:* `desired`.
1278
 
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
1295
  operator T() const volatile noexcept;
1296
- operator T() const noexcept;
1297
  ```
1298
 
1299
  *Constraints:* For the `volatile` overload of this function,
1300
  `is_always_lock_free` is `true`.
1301
 
1302
  *Effects:* Equivalent to: `return load();`
1303
 
1304
  ``` cpp
1305
  T exchange(T desired, memory_order order = memory_order::seq_cst) volatile noexcept;
1306
- T exchange(T desired, memory_order order = memory_order::seq_cst) noexcept;
1307
  ```
1308
 
1309
  *Constraints:* For the `volatile` overload of this function,
1310
  `is_always_lock_free` is `true`.
1311
 
@@ -1318,31 +1643,31 @@ operations [[intro.multithread]].
1318
  before the effects.
1319
 
1320
  ``` cpp
1321
  bool compare_exchange_weak(T& expected, T desired,
1322
  memory_order success, memory_order failure) volatile noexcept;
1323
- bool compare_exchange_weak(T& expected, T desired,
1324
  memory_order success, memory_order failure) noexcept;
1325
  bool compare_exchange_strong(T& expected, T desired,
1326
  memory_order success, memory_order failure) volatile noexcept;
1327
- bool compare_exchange_strong(T& expected, T desired,
1328
  memory_order success, memory_order failure) noexcept;
1329
  bool compare_exchange_weak(T& expected, T desired,
1330
  memory_order order = memory_order::seq_cst) volatile noexcept;
1331
- bool compare_exchange_weak(T& expected, T desired,
1332
  memory_order order = memory_order::seq_cst) noexcept;
1333
  bool compare_exchange_strong(T& expected, T desired,
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
@@ -1427,14 +1752,14 @@ 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,
@@ -1481,15 +1806,15 @@ bool party(pony desired) {
1481
 
1482
  — *end note*]
1483
 
1484
  ``` cpp
1485
  void wait(T old, memory_order order = memory_order::seq_cst) const volatile noexcept;
1486
- void wait(T old, memory_order order = memory_order::seq_cst) const noexcept;
1487
  ```
1488
 
1489
- *Preconditions:* `order` is neither `memory_order::release` nor
1490
- `memory_order::acq_rel`.
1491
 
1492
  *Effects:* Repeatedly performs the following steps, in order:
1493
 
1494
  - Evaluates `load(order)` and compares its value representation for
1495
  equality against that of `old`.
@@ -1500,11 +1825,11 @@ void wait(T old, memory_order order = memory_order::seq_cst) const noexcept;
1500
  *Remarks:* This function is an atomic waiting
1501
  operation [[atomics.wait]].
1502
 
1503
  ``` cpp
1504
  void notify_one() volatile noexcept;
1505
- void notify_one() noexcept;
1506
  ```
1507
 
1508
  *Effects:* Unblocks the execution of at least one atomic waiting
1509
  operation that is eligible to be unblocked [[atomics.wait]] by this
1510
  call, if any such atomic waiting operations exist.
@@ -1512,11 +1837,11 @@ call, if any such atomic waiting operations exist.
1512
  *Remarks:* This function is an atomic notifying
1513
  operation [[atomics.wait]].
1514
 
1515
  ``` cpp
1516
  void notify_all() volatile noexcept;
1517
- void notify_all() noexcept;
1518
  ```
1519
 
1520
  *Effects:* Unblocks the execution of all atomic waiting operations that
1521
  are eligible to be unblocked [[atomics.wait]] by this call.
1522
 
@@ -1552,85 +1877,122 @@ namespace std {
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
  };
1633
  }
1634
  ```
1635
 
1636
  The atomic integral specializations are standard-layout structs. They
@@ -1644,18 +2006,21 @@ 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
- | ----- | --- | -------------------- | ----- | --- | -------------------- |
1650
- | `add` | `+` | addition | `sub` | `-` | subtraction |
1651
- | `or` | `|` | bitwise inclusive or | `xor` | `^` | bitwise exclusive or |
1652
- | `and` | `&` | bitwise and | | | |
 
1653
 
1654
  ``` cpp
1655
- T fetch_key(T operand, memory_order order = memory_order::seq_cst) volatile noexcept;
1656
- T fetch_key(T operand, memory_order order = memory_order::seq_cst) noexcept;
 
 
1657
  ```
1658
 
1659
  *Constraints:* For the `volatile` overload of this function,
1660
  `is_always_lock_free` is `true`.
1661
 
@@ -1666,21 +2031,59 @@ the given `operand`. Memory is affected according to the value of
1666
  operations [[intro.multithread]].
1667
 
1668
  *Returns:* Atomically, the value pointed to by `this` immediately before
1669
  the effects.
1670
 
1671
- *Remarks:* For signed integer types, the result is as if the object
1672
- value and parameters were converted to their corresponding unsigned
1673
- types, the computation performed on those types, and the result
1674
- converted back to the signed type.
1675
 
1676
  [*Note 1*: There are no undefined results arising from the
1677
  computation. — *end note*]
1678
 
 
 
 
 
 
1679
  ``` cpp
1680
- T operator op=(T operand) volatile noexcept;
1681
- T operator op=(T operand) noexcept;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1682
  ```
1683
 
1684
  *Constraints:* For the `volatile` overload of this function,
1685
  `is_always_lock_free` is `true`.
1686
 
@@ -1710,59 +2113,117 @@ namespace std {
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
  };
1765
  }
1766
  ```
1767
 
1768
  The atomic floating-point specializations are standard-layout structs.
@@ -1771,15 +2232,19 @@ They each have a trivial destructor.
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
  ```
1782
 
1783
  *Constraints:* For the `volatile` overload of this function,
1784
  `is_always_lock_free` is `true`.
1785
 
@@ -1800,13 +2265,92 @@ otherwise have no undefined behavior. Atomic arithmetic operations on
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;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1808
  ```
1809
 
1810
  *Constraints:* For the `volatile` overload of this function,
1811
  `is_always_lock_free` is `true`.
1812
 
@@ -1840,57 +2384,70 @@ namespace std {
1840
  atomic(const atomic&) = delete;
1841
  atomic& operator=(const atomic&) = delete;
1842
  atomic& operator=(const atomic&) volatile = delete;
1843
 
1844
  void store(T*, memory_order = memory_order::seq_cst) volatile noexcept;
1845
- void store(T*, memory_order = memory_order::seq_cst) noexcept;
1846
  T* operator=(T*) volatile noexcept;
1847
- T* operator=(T*) noexcept;
1848
  T* load(memory_order = memory_order::seq_cst) const volatile noexcept;
1849
- T* load(memory_order = memory_order::seq_cst) const noexcept;
1850
  operator T*() const volatile noexcept;
1851
- operator T*() const noexcept;
1852
 
1853
  T* exchange(T*, memory_order = memory_order::seq_cst) volatile noexcept;
1854
- T* exchange(T*, memory_order = memory_order::seq_cst) noexcept;
1855
  bool compare_exchange_weak(T*&, T*, memory_order, memory_order) volatile noexcept;
1856
- bool compare_exchange_weak(T*&, T*, memory_order, memory_order) noexcept;
1857
  bool compare_exchange_strong(T*&, T*, memory_order, memory_order) volatile noexcept;
1858
- bool compare_exchange_strong(T*&, T*, memory_order, memory_order) noexcept;
1859
  bool compare_exchange_weak(T*&, T*,
1860
  memory_order = memory_order::seq_cst) volatile noexcept;
1861
- bool compare_exchange_weak(T*&, T*,
1862
  memory_order = memory_order::seq_cst) noexcept;
1863
  bool compare_exchange_strong(T*&, T*,
1864
  memory_order = memory_order::seq_cst) volatile noexcept;
1865
- bool compare_exchange_strong(T*&, T*,
1866
  memory_order = memory_order::seq_cst) noexcept;
1867
 
1868
  T* fetch_add(ptrdiff_t, memory_order = memory_order::seq_cst) volatile noexcept;
1869
- T* fetch_add(ptrdiff_t, memory_order = memory_order::seq_cst) noexcept;
1870
  T* fetch_sub(ptrdiff_t, memory_order = memory_order::seq_cst) volatile noexcept;
1871
- T* fetch_sub(ptrdiff_t, memory_order = memory_order::seq_cst) noexcept;
 
 
 
 
 
 
 
 
 
 
 
 
 
1872
 
1873
  T* operator++(int) volatile noexcept;
1874
- T* operator++(int) noexcept;
1875
  T* operator--(int) volatile noexcept;
1876
- T* operator--(int) noexcept;
1877
  T* operator++() volatile noexcept;
1878
- T* operator++() noexcept;
1879
  T* operator--() volatile noexcept;
1880
- T* operator--() noexcept;
1881
  T* operator+=(ptrdiff_t) volatile noexcept;
1882
- T* operator+=(ptrdiff_t) noexcept;
1883
  T* operator-=(ptrdiff_t) volatile noexcept;
1884
- T* operator-=(ptrdiff_t) noexcept;
1885
 
1886
  void wait(T*, memory_order = memory_order::seq_cst) const volatile noexcept;
1887
- void wait(T*, memory_order = memory_order::seq_cst) const noexcept;
1888
  void notify_one() volatile noexcept;
1889
- void notify_one() noexcept;
1890
  void notify_all() volatile noexcept;
1891
- void notify_all() noexcept;
1892
  };
1893
  }
1894
  ```
1895
 
1896
  There is a partial specialization of the `atomic` class template for
@@ -1907,14 +2464,15 @@ among key, operator, and computation is specified in
1907
  **Table: Atomic pointer computations** <a id="atomic.types.pointer.comp">[atomic.types.pointer.comp]</a>
1908
 
1909
  | | | | | | |
1910
  | ----- | --- | -------- | ----- | --- | ----------- |
1911
  | `add` | `+` | addition | `sub` | `-` | subtraction |
 
1912
 
1913
  ``` cpp
1914
- T* fetch_key(ptrdiff_t operand, memory_order order = memory_order::seq_cst) volatile noexcept;
1915
- T* fetch_key(ptrdiff_t operand, memory_order order = memory_order::seq_cst) noexcept;
1916
  ```
1917
 
1918
  *Constraints:* For the `volatile` overload of this function,
1919
  `is_always_lock_free` is `true`.
1920
 
@@ -1933,13 +2491,51 @@ operations [[intro.multithread]].
1933
  the effects.
1934
 
1935
  *Remarks:* The result may be an undefined address, but the operations
1936
  otherwise have no undefined behavior.
1937
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1938
  ``` cpp
1939
  T* operator op=(ptrdiff_t operand) volatile noexcept;
1940
- T* operator op=(ptrdiff_t operand) noexcept;
1941
  ```
1942
 
1943
  *Constraints:* For the `volatile` overload of this function,
1944
  `is_always_lock_free` is `true`.
1945
 
@@ -1948,41 +2544,41 @@ T* operator op=(ptrdiff_t operand) noexcept;
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
  ```
1955
 
1956
  *Constraints:* For the `volatile` overload of this function,
1957
  `is_always_lock_free` is `true`.
1958
 
1959
  *Effects:* Equivalent to: `return fetch_add(1);`
1960
 
1961
  ``` cpp
1962
  value_type operator--(int) volatile noexcept;
1963
- value_type operator--(int) noexcept;
1964
  ```
1965
 
1966
  *Constraints:* For the `volatile` overload of this function,
1967
  `is_always_lock_free` is `true`.
1968
 
1969
  *Effects:* Equivalent to: `return fetch_sub(1);`
1970
 
1971
  ``` cpp
1972
  value_type operator++() volatile noexcept;
1973
- value_type operator++() noexcept;
1974
  ```
1975
 
1976
  *Constraints:* For the `volatile` overload of this function,
1977
  `is_always_lock_free` is `true`.
1978
 
1979
  *Effects:* Equivalent to: `return fetch_add(1) + 1;`
1980
 
1981
  ``` cpp
1982
  value_type operator--() volatile noexcept;
1983
- value_type operator--() noexcept;
1984
  ```
1985
 
1986
  *Constraints:* For the `volatile` overload of this function,
1987
  `is_always_lock_free` is `true`.
1988
 
@@ -2055,33 +2651,36 @@ namespace std {
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;
2065
- operator shared_ptr<T>() const noexcept;
2066
- void store(shared_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept;
2067
- void operator=(shared_ptr<T> desired) noexcept;
 
 
2068
 
2069
- shared_ptr<T> exchange(shared_ptr<T> desired,
2070
  memory_order order = memory_order::seq_cst) noexcept;
2071
- bool compare_exchange_weak(shared_ptr<T>& expected, shared_ptr<T> desired,
2072
  memory_order success, memory_order failure) noexcept;
2073
- bool compare_exchange_strong(shared_ptr<T>& expected, shared_ptr<T> desired,
2074
  memory_order success, memory_order failure) noexcept;
2075
- bool compare_exchange_weak(shared_ptr<T>& expected, shared_ptr<T> desired,
2076
  memory_order order = memory_order::seq_cst) noexcept;
2077
- bool compare_exchange_strong(shared_ptr<T>& expected, shared_ptr<T> desired,
2078
  memory_order order = memory_order::seq_cst) noexcept;
2079
 
2080
- void wait(shared_ptr<T> old, memory_order order = memory_order::seq_cst) const noexcept;
2081
- void notify_one() noexcept;
2082
- void notify_all() noexcept;
 
2083
 
2084
  private:
2085
  shared_ptr<T> p; // exposition only
2086
  };
2087
  }
@@ -2089,14 +2688,14 @@ namespace std {
2089
 
2090
  ``` cpp
2091
  constexpr atomic() noexcept;
2092
  ```
2093
 
2094
- *Effects:* Initializes `p{}`.
2095
 
2096
  ``` cpp
2097
- atomic(shared_ptr<T> desired) noexcept;
2098
  ```
2099
 
2100
  *Effects:* Initializes the object with the value `desired`.
2101
  Initialization is not an atomic operation [[intro.multithread]].
2102
 
@@ -2106,63 +2705,70 @@ the just-constructed object `A` to another thread via
2106
  `memory_order::relaxed` operations on a suitable atomic pointer
2107
  variable, and then immediately accessing `A` in the receiving thread.
2108
  This results in undefined behavior. — *end note*]
2109
 
2110
  ``` cpp
2111
- void store(shared_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept;
2112
  ```
2113
 
2114
- *Preconditions:* `order` is neither `memory_order::consume`,
2115
- `memory_order::acquire`, nor `memory_order::acq_rel`.
2116
 
2117
  *Effects:* Atomically replaces the value pointed to by `this` with the
2118
  value of `desired` as if by `p.swap(desired)`. Memory is affected
2119
  according to the value of `order`.
2120
 
2121
  ``` cpp
2122
- void operator=(shared_ptr<T> desired) noexcept;
2123
  ```
2124
 
2125
  *Effects:* Equivalent to `store(desired)`.
2126
 
2127
  ``` cpp
2128
- shared_ptr<T> load(memory_order order = memory_order::seq_cst) const noexcept;
2129
  ```
2130
 
2131
- *Preconditions:* `order` is neither `memory_order::release` nor
2132
- `memory_order::acq_rel`.
 
 
 
 
 
 
2133
 
2134
  *Effects:* Memory is affected according to the value of `order`.
2135
 
2136
  *Returns:* Atomically returns `p`.
2137
 
2138
  ``` cpp
2139
- operator shared_ptr<T>() const noexcept;
2140
  ```
2141
 
2142
  *Effects:* Equivalent to: `return load();`
2143
 
2144
  ``` cpp
2145
- shared_ptr<T> exchange(shared_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept;
 
2146
  ```
2147
 
2148
  *Effects:* Atomically replaces `p` with `desired` as if by
2149
  `p.swap(desired)`. Memory is affected according to the value of `order`.
2150
  This is an atomic read-modify-write operation [[intro.races]].
2151
 
2152
  *Returns:* Atomically returns the value of `p` immediately before the
2153
  effects.
2154
 
2155
  ``` cpp
2156
- bool compare_exchange_weak(shared_ptr<T>& expected, shared_ptr<T> desired,
2157
  memory_order success, memory_order failure) noexcept;
2158
- bool compare_exchange_strong(shared_ptr<T>& expected, shared_ptr<T> desired,
2159
  memory_order success, memory_order failure) noexcept;
2160
  ```
2161
 
2162
- *Preconditions:* `failure` is neither `memory_order::release` nor
2163
- `memory_order::acq_rel`.
2164
 
2165
  *Effects:* If `p` is equivalent to `expected`, assigns `desired` to `p`
2166
  and has synchronization semantics corresponding to the value of
2167
  `success`, otherwise assigns `p` to `expected` and has synchronization
2168
  semantics corresponding to the value of `failure`.
@@ -2183,11 +2789,11 @@ object in the attempted atomic update. The `use_count` update
2183
  corresponding to the write to `expected` is part of the atomic
2184
  operation. The write to `expected` itself is not required to be part of
2185
  the atomic operation.
2186
 
2187
  ``` cpp
2188
- bool compare_exchange_weak(shared_ptr<T>& expected, shared_ptr<T> desired,
2189
  memory_order order = memory_order::seq_cst) noexcept;
2190
  ```
2191
 
2192
  *Effects:* Equivalent to:
2193
 
@@ -2199,11 +2805,11 @@ where `fail_order` is the same as `order` except that a value of
2199
  `memory_order::acq_rel` shall be replaced by the value
2200
  `memory_order::acquire` and a value of `memory_order::release` shall be
2201
  replaced by the value `memory_order::relaxed`.
2202
 
2203
  ``` cpp
2204
- bool compare_exchange_strong(shared_ptr<T>& expected, shared_ptr<T> desired,
2205
  memory_order order = memory_order::seq_cst) noexcept;
2206
  ```
2207
 
2208
  *Effects:* Equivalent to:
2209
 
@@ -2215,15 +2821,15 @@ where `fail_order` is the same as `order` except that a value of
2215
  `memory_order::acq_rel` shall be replaced by the value
2216
  `memory_order::acquire` and a value of `memory_order::release` shall be
2217
  replaced by the value `memory_order::relaxed`.
2218
 
2219
  ``` cpp
2220
- void wait(shared_ptr<T> old, memory_order order = memory_order::seq_cst) const noexcept;
2221
  ```
2222
 
2223
- *Preconditions:* `order` is neither `memory_order::release` nor
2224
- `memory_order::acq_rel`.
2225
 
2226
  *Effects:* Repeatedly performs the following steps, in order:
2227
 
2228
  - Evaluates `load(order)` and compares it to `old`.
2229
  - If the two are not equivalent, returns.
@@ -2233,22 +2839,22 @@ void wait(shared_ptr<T> old, memory_order order = memory_order::seq_cst) const n
2233
  *Remarks:* Two `shared_ptr` objects are equivalent if they store the
2234
  same pointer and either share ownership or are both empty. This function
2235
  is an atomic waiting operation [[atomics.wait]].
2236
 
2237
  ``` cpp
2238
- void notify_one() noexcept;
2239
  ```
2240
 
2241
  *Effects:* Unblocks the execution of at least one atomic waiting
2242
  operation that is eligible to be unblocked [[atomics.wait]] by this
2243
  call, if any such atomic waiting operations exist.
2244
 
2245
  *Remarks:* This function is an atomic notifying
2246
  operation [[atomics.wait]].
2247
 
2248
  ``` cpp
2249
- void notify_all() noexcept;
2250
  ```
2251
 
2252
  *Effects:* Unblocks the execution of all atomic waiting operations that
2253
  are eligible to be unblocked [[atomics.wait]] by this call.
2254
 
@@ -2264,33 +2870,35 @@ namespace std {
2264
 
2265
  static constexpr bool is_always_lock_free = implementation-defined // whether a given atomic type's operations are always lock free;
2266
  bool is_lock_free() const noexcept;
2267
 
2268
  constexpr atomic() noexcept;
2269
- atomic(weak_ptr<T> desired) noexcept;
2270
  atomic(const atomic&) = delete;
2271
  void operator=(const atomic&) = delete;
2272
 
2273
- weak_ptr<T> load(memory_order order = memory_order::seq_cst) const noexcept;
2274
- operator weak_ptr<T>() const noexcept;
2275
- void store(weak_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept;
2276
- void operator=(weak_ptr<T> desired) noexcept;
 
2277
 
2278
- weak_ptr<T> exchange(weak_ptr<T> desired,
2279
  memory_order order = memory_order::seq_cst) noexcept;
2280
- bool compare_exchange_weak(weak_ptr<T>& expected, weak_ptr<T> desired,
2281
  memory_order success, memory_order failure) noexcept;
2282
- bool compare_exchange_strong(weak_ptr<T>& expected, weak_ptr<T> desired,
2283
  memory_order success, memory_order failure) noexcept;
2284
- bool compare_exchange_weak(weak_ptr<T>& expected, weak_ptr<T> desired,
2285
  memory_order order = memory_order::seq_cst) noexcept;
2286
- bool compare_exchange_strong(weak_ptr<T>& expected, weak_ptr<T> desired,
2287
  memory_order order = memory_order::seq_cst) noexcept;
2288
 
2289
- void wait(weak_ptr<T> old, memory_order order = memory_order::seq_cst) const noexcept;
2290
- void notify_one() noexcept;
2291
- void notify_all() noexcept;
 
2292
 
2293
  private:
2294
  weak_ptr<T> p; // exposition only
2295
  };
2296
  }
@@ -2298,14 +2906,14 @@ namespace std {
2298
 
2299
  ``` cpp
2300
  constexpr atomic() noexcept;
2301
  ```
2302
 
2303
- *Effects:* Initializes `p{}`.
2304
 
2305
  ``` cpp
2306
- atomic(weak_ptr<T> desired) noexcept;
2307
  ```
2308
 
2309
  *Effects:* Initializes the object with the value `desired`.
2310
  Initialization is not an atomic operation [[intro.multithread]].
2311
 
@@ -2315,63 +2923,64 @@ 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*]
2318
 
2319
  ``` cpp
2320
- void store(weak_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept;
2321
  ```
2322
 
2323
- *Preconditions:* `order` is neither `memory_order::consume`,
2324
- `memory_order::acquire`, nor `memory_order::acq_rel`.
2325
 
2326
  *Effects:* Atomically replaces the value pointed to by `this` with the
2327
  value of `desired` as if by `p.swap(desired)`. Memory is affected
2328
  according to the value of `order`.
2329
 
2330
  ``` cpp
2331
- void operator=(weak_ptr<T> desired) noexcept;
2332
  ```
2333
 
2334
  *Effects:* Equivalent to `store(desired)`.
2335
 
2336
  ``` cpp
2337
- weak_ptr<T> load(memory_order order = memory_order::seq_cst) const noexcept;
2338
  ```
2339
 
2340
- *Preconditions:* `order` is neither `memory_order::release` nor
2341
- `memory_order::acq_rel`.
2342
 
2343
  *Effects:* Memory is affected according to the value of `order`.
2344
 
2345
  *Returns:* Atomically returns `p`.
2346
 
2347
  ``` cpp
2348
- operator weak_ptr<T>() const noexcept;
2349
  ```
2350
 
2351
  *Effects:* Equivalent to: `return load();`
2352
 
2353
  ``` cpp
2354
- weak_ptr<T> exchange(weak_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept;
 
2355
  ```
2356
 
2357
  *Effects:* Atomically replaces `p` with `desired` as if by
2358
  `p.swap(desired)`. Memory is affected according to the value of `order`.
2359
  This is an atomic read-modify-write operation [[intro.races]].
2360
 
2361
  *Returns:* Atomically returns the value of `p` immediately before the
2362
  effects.
2363
 
2364
  ``` cpp
2365
- bool compare_exchange_weak(weak_ptr<T>& expected, weak_ptr<T> desired,
2366
  memory_order success, memory_order failure) noexcept;
2367
- bool compare_exchange_strong(weak_ptr<T>& expected, weak_ptr<T> desired,
2368
  memory_order success, memory_order failure) noexcept;
2369
  ```
2370
 
2371
- *Preconditions:* `failure` is neither `memory_order::release` nor
2372
- `memory_order::acq_rel`.
2373
 
2374
  *Effects:* If `p` is equivalent to `expected`, assigns `desired` to `p`
2375
  and has synchronization semantics corresponding to the value of
2376
  `success`, otherwise assigns `p` to `expected` and has synchronization
2377
  semantics corresponding to the value of `failure`.
@@ -2392,11 +3001,11 @@ object in the attempted atomic update. The `use_count` update
2392
  corresponding to the write to `expected` is part of the atomic
2393
  operation. The write to `expected` itself is not required to be part of
2394
  the atomic operation.
2395
 
2396
  ``` cpp
2397
- bool compare_exchange_weak(weak_ptr<T>& expected, weak_ptr<T> desired,
2398
  memory_order order = memory_order::seq_cst) noexcept;
2399
  ```
2400
 
2401
  *Effects:* Equivalent to:
2402
 
@@ -2408,11 +3017,11 @@ where `fail_order` is the same as `order` except that a value of
2408
  `memory_order::acq_rel` shall be replaced by the value
2409
  `memory_order::acquire` and a value of `memory_order::release` shall be
2410
  replaced by the value `memory_order::relaxed`.
2411
 
2412
  ``` cpp
2413
- bool compare_exchange_strong(weak_ptr<T>& expected, weak_ptr<T> desired,
2414
  memory_order order = memory_order::seq_cst) noexcept;
2415
  ```
2416
 
2417
  *Effects:* Equivalent to:
2418
 
@@ -2424,15 +3033,15 @@ where `fail_order` is the same as `order` except that a value of
2424
  `memory_order::acq_rel` shall be replaced by the value
2425
  `memory_order::acquire` and a value of `memory_order::release` shall be
2426
  replaced by the value `memory_order::relaxed`.
2427
 
2428
  ``` cpp
2429
- void wait(weak_ptr<T> old, memory_order order = memory_order::seq_cst) const noexcept;
2430
  ```
2431
 
2432
- *Preconditions:* `order` is neither `memory_order::release` nor
2433
- `memory_order::acq_rel`.
2434
 
2435
  *Effects:* Repeatedly performs the following steps, in order:
2436
 
2437
  - Evaluates `load(order)` and compares it to `old`.
2438
  - If the two are not equivalent, returns.
@@ -2442,22 +3051,22 @@ void wait(weak_ptr<T> old, memory_order order = memory_order::seq_cst) const noe
2442
  *Remarks:* Two `weak_ptr` objects are equivalent if they store the same
2443
  pointer and either share ownership or are both empty. This function is
2444
  an atomic waiting operation [[atomics.wait]].
2445
 
2446
  ``` cpp
2447
- void notify_one() noexcept;
2448
  ```
2449
 
2450
  *Effects:* Unblocks the execution of at least one atomic waiting
2451
  operation that is eligible to be unblocked [[atomics.wait]] by this
2452
  call, if any such atomic waiting operations exist.
2453
 
2454
  *Remarks:* This function is an atomic notifying
2455
  operation [[atomics.wait]].
2456
 
2457
  ``` cpp
2458
- void notify_all() noexcept;
2459
  ```
2460
 
2461
  *Effects:* Unblocks the execution of all atomic waiting operations that
2462
  are eligible to be unblocked [[atomics.wait]] by this call.
2463
 
@@ -2488,22 +3097,22 @@ namespace std {
2488
  atomic_flag(const atomic_flag&) = delete;
2489
  atomic_flag& operator=(const atomic_flag&) = delete;
2490
  atomic_flag& operator=(const atomic_flag&) volatile = delete;
2491
 
2492
  bool test(memory_order = memory_order::seq_cst) const volatile noexcept;
2493
- bool test(memory_order = memory_order::seq_cst) const noexcept;
2494
  bool test_and_set(memory_order = memory_order::seq_cst) volatile noexcept;
2495
- bool test_and_set(memory_order = memory_order::seq_cst) noexcept;
2496
  void clear(memory_order = memory_order::seq_cst) volatile noexcept;
2497
- void clear(memory_order = memory_order::seq_cst) noexcept;
2498
 
2499
  void wait(bool, memory_order = memory_order::seq_cst) const volatile noexcept;
2500
- void wait(bool, memory_order = memory_order::seq_cst) const noexcept;
2501
  void notify_one() volatile noexcept;
2502
- void notify_one() noexcept;
2503
  void notify_all() volatile noexcept;
2504
- void notify_all() noexcept;
2505
  };
2506
  }
2507
  ```
2508
 
2509
  The `atomic_flag` type provides the classic test-and-set functionality.
@@ -2521,36 +3130,36 @@ constexpr atomic_flag::atomic_flag() noexcept;
2521
 
2522
  *Effects:* Initializes `*this` to the clear state.
2523
 
2524
  ``` cpp
2525
  bool atomic_flag_test(const volatile atomic_flag* object) noexcept;
2526
- bool atomic_flag_test(const atomic_flag* object) noexcept;
2527
  bool atomic_flag_test_explicit(const volatile atomic_flag* object,
2528
  memory_order order) noexcept;
2529
- bool atomic_flag_test_explicit(const atomic_flag* object,
2530
  memory_order order) noexcept;
2531
  bool atomic_flag::test(memory_order order = memory_order::seq_cst) const volatile noexcept;
2532
- bool atomic_flag::test(memory_order order = memory_order::seq_cst) const noexcept;
2533
  ```
2534
 
2535
  For `atomic_flag_test`, let `order` be `memory_order::seq_cst`.
2536
 
2537
- *Preconditions:* `order` is neither `memory_order::release` nor
2538
- `memory_order::acq_rel`.
2539
 
2540
  *Effects:* Memory is affected according to the value of `order`.
2541
 
2542
  *Returns:* Atomically returns the value pointed to by `object` or
2543
  `this`.
2544
 
2545
  ``` cpp
2546
  bool atomic_flag_test_and_set(volatile atomic_flag* object) noexcept;
2547
- bool atomic_flag_test_and_set(atomic_flag* object) noexcept;
2548
  bool atomic_flag_test_and_set_explicit(volatile atomic_flag* object, memory_order order) noexcept;
2549
- bool atomic_flag_test_and_set_explicit(atomic_flag* object, memory_order order) noexcept;
2550
  bool atomic_flag::test_and_set(memory_order order = memory_order::seq_cst) volatile noexcept;
2551
- bool atomic_flag::test_and_set(memory_order order = memory_order::seq_cst) noexcept;
2552
  ```
2553
 
2554
  *Effects:* Atomically sets the value pointed to by `object` or by `this`
2555
  to `true`. Memory is affected according to the value of `order`. These
2556
  operations are atomic read-modify-write
@@ -2559,43 +3168,42 @@ operations [[intro.multithread]].
2559
  *Returns:* Atomically, the value of the object immediately before the
2560
  effects.
2561
 
2562
  ``` cpp
2563
  void atomic_flag_clear(volatile atomic_flag* object) noexcept;
2564
- void atomic_flag_clear(atomic_flag* object) noexcept;
2565
  void atomic_flag_clear_explicit(volatile atomic_flag* object, memory_order order) noexcept;
2566
- void atomic_flag_clear_explicit(atomic_flag* object, memory_order order) noexcept;
2567
  void atomic_flag::clear(memory_order order = memory_order::seq_cst) volatile noexcept;
2568
- void atomic_flag::clear(memory_order order = memory_order::seq_cst) noexcept;
2569
  ```
2570
 
2571
- *Preconditions:* The `order` argument is neither
2572
- `memory_order::consume`, `memory_order::acquire`, nor
2573
- `memory_order::acq_rel`.
2574
 
2575
  *Effects:* Atomically sets the value pointed to by `object` or by `this`
2576
  to `false`. Memory is affected according to the value of `order`.
2577
 
2578
  ``` cpp
2579
  void atomic_flag_wait(const volatile atomic_flag* object, bool old) noexcept;
2580
- void atomic_flag_wait(const atomic_flag* object, bool old) noexcept;
2581
  void atomic_flag_wait_explicit(const volatile atomic_flag* object,
2582
  bool old, memory_order order) noexcept;
2583
- void atomic_flag_wait_explicit(const atomic_flag* object,
2584
  bool old, memory_order order) noexcept;
2585
  void atomic_flag::wait(bool old, memory_order order =
2586
  memory_order::seq_cst) const volatile noexcept;
2587
- void atomic_flag::wait(bool old, memory_order order =
2588
  memory_order::seq_cst) const noexcept;
2589
  ```
2590
 
2591
  For `atomic_flag_wait`, let `order` be `memory_order::seq_cst`. Let
2592
  `flag` be `object` for the non-member functions and `this` for the
2593
  member functions.
2594
 
2595
- *Preconditions:* `order` is neither `memory_order::release` nor
2596
- `memory_order::acq_rel`.
2597
 
2598
  *Effects:* Repeatedly performs the following steps, in order:
2599
 
2600
  - Evaluates `flag->test(order) != old`.
2601
  - If the result of that evaluation is `true`, returns.
@@ -2605,13 +3213,13 @@ member functions.
2605
  *Remarks:* This function is an atomic waiting
2606
  operation [[atomics.wait]].
2607
 
2608
  ``` cpp
2609
  void atomic_flag_notify_one(volatile atomic_flag* object) noexcept;
2610
- void atomic_flag_notify_one(atomic_flag* object) noexcept;
2611
  void atomic_flag::notify_one() volatile noexcept;
2612
- void atomic_flag::notify_one() noexcept;
2613
  ```
2614
 
2615
  *Effects:* Unblocks the execution of at least one atomic waiting
2616
  operation that is eligible to be unblocked [[atomics.wait]] by this
2617
  call, if any such atomic waiting operations exist.
@@ -2619,13 +3227,13 @@ call, if any such atomic waiting operations exist.
2619
  *Remarks:* This function is an atomic notifying
2620
  operation [[atomics.wait]].
2621
 
2622
  ``` cpp
2623
  void atomic_flag_notify_all(volatile atomic_flag* object) noexcept;
2624
- void atomic_flag_notify_all(atomic_flag* object) noexcept;
2625
  void atomic_flag::notify_all() volatile noexcept;
2626
- void atomic_flag::notify_all() noexcept;
2627
  ```
2628
 
2629
  *Effects:* Unblocks the execution of all atomic waiting operations that
2630
  are eligible to be unblocked [[atomics.wait]] by this call.
2631
 
@@ -2654,15 +3262,16 @@ 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*.
2657
 
2658
  A release fence A synchronizes with an acquire fence B if there exist
2659
- atomic operations X and Y, both operating on some atomic object M, such
2660
- that A is sequenced before X, X modifies M, Y is sequenced before B, and
2661
- Y reads the value written by X or a value written by any side effect in
2662
- the hypothetical release sequence X would head if it were a release
2663
- operation.
 
2664
 
2665
  A release fence A synchronizes with an atomic operation B that performs
2666
  an acquire operation on an atomic object M if there exists an atomic
2667
  operation X such that A is sequenced before X, X modifies M, and B reads
2668
  the value written by X or a value written by any side effect in the
@@ -2674,26 +3283,25 @@ synchronizes with an acquire fence B if there exists some atomic
2674
  operation X on M such that X is sequenced before B and reads the value
2675
  written by A or a value written by any side effect in the release
2676
  sequence headed by A.
2677
 
2678
  ``` cpp
2679
- extern "C" void atomic_thread_fence(memory_order order) noexcept;
2680
  ```
2681
 
2682
  *Effects:* Depending on the value of `order`, this operation:
2683
 
2684
  - has no effects, if `order == memory_order::relaxed`;
2685
- - is an acquire fence, if `order == memory_order::acquire` or
2686
- `order == memory_order::consume`;
2687
  - is a release fence, if `order == memory_order::release`;
2688
  - is both an acquire fence and a release fence, if
2689
  `order == memory_order::acq_rel`;
2690
  - is a sequentially consistent acquire and release fence, if
2691
  `order == memory_order::seq_cst`.
2692
 
2693
  ``` cpp
2694
- extern "C" void atomic_signal_fence(memory_order order) noexcept;
2695
  ```
2696
 
2697
  *Effects:* Equivalent to `atomic_thread_fence(order)`, except that the
2698
  resulting ordering constraints are established only between a thread and
2699
  a signal handler executed in the same thread.
 
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
+ // mostly freestanding
12
  namespace std {
13
  // [atomics.order], order and consistency
14
+ enum class memory_order : unspecified;
15
+ inline constexpr memory_order memory_order_relaxed = memory_order::relaxed;
16
+ inline constexpr memory_order memory_order_acquire = memory_order::acquire;
17
+ inline constexpr memory_order memory_order_release = memory_order::release;
18
+ inline constexpr memory_order memory_order_acq_rel = memory_order::acq_rel;
19
+ inline constexpr memory_order memory_order_seq_cst = memory_order::seq_cst;
 
 
 
 
20
  }
21
 
22
  // [atomics.lockfree], lock-free property
23
+ #define ATOMIC_BOOL_LOCK_FREE unspecified
24
+ #define ATOMIC_CHAR_LOCK_FREE unspecified
25
+ #define ATOMIC_CHAR8_T_LOCK_FREE unspecified
26
+ #define ATOMIC_CHAR16_T_LOCK_FREE unspecified
27
+ #define ATOMIC_CHAR32_T_LOCK_FREE unspecified
28
+ #define ATOMIC_WCHAR_T_LOCK_FREE unspecified
29
+ #define ATOMIC_SHORT_LOCK_FREE unspecified
30
+ #define ATOMIC_INT_LOCK_FREE unspecified
31
+ #define ATOMIC_LONG_LOCK_FREE unspecified
32
+ #define ATOMIC_LLONG_LOCK_FREE unspecified
33
+ #define ATOMIC_POINTER_LOCK_FREE unspecified
34
 
35
  namespace std {
36
  // [atomics.ref.generic], class template atomic_ref
37
+ template<class T> struct atomic_ref;
 
 
38
 
39
  // [atomics.types.generic], class template atomic
40
+ template<class T> struct atomic;
41
  // [atomics.types.pointer], partial specialization for pointers
42
+ template<class T> struct atomic<T*>;
43
 
44
  // [atomics.nonmembers], non-member functions
45
  template<class T>
46
+ bool atomic_is_lock_free(const volatile atomic<T>*) noexcept;
47
  template<class T>
48
+ bool atomic_is_lock_free(const atomic<T>*) noexcept;
49
  template<class T>
50
+ void atomic_store(volatile atomic<T>*, typename atomic<T>::value_type) noexcept;
 
51
  template<class T>
52
+ constexpr void atomic_store(atomic<T>*, typename atomic<T>::value_type) noexcept;
53
  template<class T>
54
+ void atomic_store_explicit(volatile atomic<T>*, typename atomic<T>::value_type,
 
55
  memory_order) noexcept;
56
  template<class T>
57
+ constexpr void atomic_store_explicit(atomic<T>*, typename atomic<T>::value_type,
58
  memory_order) noexcept;
59
  template<class T>
60
+ T atomic_load(const volatile atomic<T>*) noexcept;
61
  template<class T>
62
+ constexpr T atomic_load(const atomic<T>*) noexcept;
63
  template<class T>
64
+ T atomic_load_explicit(const volatile atomic<T>*, memory_order) noexcept;
65
  template<class T>
66
+ constexpr T atomic_load_explicit(const atomic<T>*, memory_order) noexcept;
67
  template<class T>
68
+ T atomic_exchange(volatile atomic<T>*, typename atomic<T>::value_type) noexcept;
 
69
  template<class T>
70
+ constexpr T atomic_exchange(atomic<T>*, typename atomic<T>::value_type) noexcept;
71
  template<class T>
72
+ T atomic_exchange_explicit(volatile atomic<T>*, typename atomic<T>::value_type,
 
73
  memory_order) noexcept;
74
  template<class T>
75
+ constexpr T atomic_exchange_explicit(atomic<T>*, typename atomic<T>::value_type,
76
  memory_order) noexcept;
77
  template<class T>
78
+ bool atomic_compare_exchange_weak(volatile atomic<T>*,
79
  typename atomic<T>::value_type*,
80
  typename atomic<T>::value_type) noexcept;
81
  template<class T>
82
+ constexpr bool atomic_compare_exchange_weak(atomic<T>*,
83
  typename atomic<T>::value_type*,
84
  typename atomic<T>::value_type) noexcept;
85
  template<class T>
86
+ bool atomic_compare_exchange_strong(volatile atomic<T>*,
87
  typename atomic<T>::value_type*,
88
  typename atomic<T>::value_type) noexcept;
89
  template<class T>
90
+ constexpr bool atomic_compare_exchange_strong(atomic<T>*,
91
  typename atomic<T>::value_type*,
92
  typename atomic<T>::value_type) noexcept;
93
  template<class T>
94
+ bool atomic_compare_exchange_weak_explicit(volatile atomic<T>*,
95
  typename atomic<T>::value_type*,
96
  typename atomic<T>::value_type,
97
  memory_order, memory_order) noexcept;
98
  template<class T>
99
+ constexpr bool atomic_compare_exchange_weak_explicit(atomic<T>*,
100
  typename atomic<T>::value_type*,
101
  typename atomic<T>::value_type,
102
  memory_order, memory_order) noexcept;
103
  template<class T>
104
+ bool atomic_compare_exchange_strong_explicit(volatile atomic<T>*,
105
  typename atomic<T>::value_type*,
106
  typename atomic<T>::value_type,
107
  memory_order, memory_order) noexcept;
108
  template<class T>
109
+ constexpr bool atomic_compare_exchange_strong_explicit(atomic<T>*,
110
  typename atomic<T>::value_type*,
111
  typename atomic<T>::value_type,
112
  memory_order, memory_order) noexcept;
113
 
114
  template<class T>
115
+ T atomic_fetch_add(volatile atomic<T>*, typename atomic<T>::difference_type) noexcept;
 
116
  template<class T>
117
+ constexpr T atomic_fetch_add(atomic<T>*, typename atomic<T>::difference_type) noexcept;
118
  template<class T>
119
+ T atomic_fetch_add_explicit(volatile atomic<T>*, typename atomic<T>::difference_type,
 
120
  memory_order) noexcept;
121
  template<class T>
122
+ constexpr T atomic_fetch_add_explicit(atomic<T>*, typename atomic<T>::difference_type,
123
  memory_order) noexcept;
124
  template<class T>
125
+ T atomic_fetch_sub(volatile atomic<T>*, typename atomic<T>::difference_type) noexcept;
 
126
  template<class T>
127
+ constexpr T atomic_fetch_sub(atomic<T>*, typename atomic<T>::difference_type) noexcept;
128
  template<class T>
129
+ T atomic_fetch_sub_explicit(volatile atomic<T>*, typename atomic<T>::difference_type,
 
130
  memory_order) noexcept;
131
  template<class T>
132
+ constexpr T atomic_fetch_sub_explicit(atomic<T>*, typename atomic<T>::difference_type,
133
  memory_order) noexcept;
134
  template<class T>
135
+ T atomic_fetch_and(volatile atomic<T>*, typename atomic<T>::value_type) noexcept;
 
136
  template<class T>
137
+ constexpr T atomic_fetch_and(atomic<T>*, typename atomic<T>::value_type) noexcept;
138
  template<class T>
139
+ T atomic_fetch_and_explicit(volatile atomic<T>*, typename atomic<T>::value_type,
 
140
  memory_order) noexcept;
141
  template<class T>
142
+ constexpr T atomic_fetch_and_explicit(atomic<T>*, typename atomic<T>::value_type,
143
  memory_order) noexcept;
144
  template<class T>
145
+ T atomic_fetch_or(volatile atomic<T>*, typename atomic<T>::value_type) noexcept;
 
146
  template<class T>
147
+ constexpr T atomic_fetch_or(atomic<T>*, typename atomic<T>::value_type) noexcept;
148
  template<class T>
149
+ T atomic_fetch_or_explicit(volatile atomic<T>*, typename atomic<T>::value_type,
 
150
  memory_order) noexcept;
151
  template<class T>
152
+ constexpr T atomic_fetch_or_explicit(atomic<T>*, typename atomic<T>::value_type,
153
  memory_order) noexcept;
154
  template<class T>
155
+ T atomic_fetch_xor(volatile atomic<T>*, typename atomic<T>::value_type) noexcept;
 
156
  template<class T>
157
+ constexpr T atomic_fetch_xor(atomic<T>*, typename atomic<T>::value_type) noexcept;
158
  template<class T>
159
+ T atomic_fetch_xor_explicit(volatile atomic<T>*, typename atomic<T>::value_type,
160
+ memory_order) noexcept;
161
+ template<class T>
162
+ constexpr T atomic_fetch_xor_explicit(atomic<T>*, typename atomic<T>::value_type,
163
+ memory_order) noexcept;
164
+ template<class T>
165
+ T atomic_fetch_max(volatile atomic<T>*, typename atomic<T>::value_type) noexcept;
166
+ template<class T>
167
+ constexpr T atomic_fetch_max(atomic<T>*, typename atomic<T>::value_type) noexcept;
168
+ template<class T>
169
+ T atomic_fetch_max_explicit(volatile atomic<T>*, typename atomic<T>::value_type,
170
+ memory_order) noexcept;
171
+ template<class T>
172
+ constexpr T atomic_fetch_max_explicit(atomic<T>*, typename atomic<T>::value_type,
173
+ memory_order) noexcept;
174
+ template<class T>
175
+ T atomic_fetch_min(volatile atomic<T>*, typename atomic<T>::value_type) noexcept;
176
+ template<class T>
177
+ constexpr T atomic_fetch_min(atomic<T>*, typename atomic<T>::value_type) noexcept;
178
+ template<class T>
179
+ T atomic_fetch_min_explicit(volatile atomic<T>*, typename atomic<T>::value_type,
180
  memory_order) noexcept;
181
  template<class T>
182
+ constexpr T atomic_fetch_min_explicit(atomic<T>*, typename atomic<T>::value_type,
183
  memory_order) noexcept;
184
 
185
  template<class T>
186
+ void atomic_store_add(volatile atomic<T>*, typename atomic<T>::difference_type) noexcept;
 
187
  template<class T>
188
+ constexpr void atomic_store_add(atomic<T>*, typename atomic<T>::difference_type) noexcept;
189
  template<class T>
190
+ void atomic_store_add_explicit(volatile atomic<T>*, typename atomic<T>::difference_type,
191
+ memory_order) noexcept;
192
+ template<class T>
193
+ constexpr void atomic_store_add_explicit(atomic<T>*, typename atomic<T>::difference_type,
194
+ memory_order) noexcept;
195
+ template<class T>
196
+ void atomic_store_sub(volatile atomic<T>*, typename atomic<T>::difference_type) noexcept;
197
+ template<class T>
198
+ constexpr void atomic_store_sub(atomic<T>*, typename atomic<T>::difference_type) noexcept;
199
+ template<class T>
200
+ void atomic_store_sub_explicit(volatile atomic<T>*, typename atomic<T>::difference_type,
201
+ memory_order) noexcept;
202
+ template<class T>
203
+ constexpr void atomic_store_sub_explicit(atomic<T>*, typename atomic<T>::difference_type,
204
+ memory_order) noexcept;
205
+ template<class T>
206
+ void atomic_store_and(volatile atomic<T>*, typename atomic<T>::value_type) noexcept;
207
+ template<class T>
208
+ constexpr void atomic_store_and(atomic<T>*, typename atomic<T>::value_type) noexcept;
209
+ template<class T>
210
+ void atomic_store_and_explicit(volatile atomic<T>*, typename atomic<T>::value_type,
211
+ memory_order) noexcept;
212
+ template<class T>
213
+ constexpr void atomic_store_and_explicit(atomic<T>*, typename atomic<T>::value_type,
214
+ memory_order) noexcept;
215
+ template<class T>
216
+ void atomic_store_or(volatile atomic<T>*, typename atomic<T>::value_type) noexcept;
217
+ template<class T>
218
+ constexpr void atomic_store_or(atomic<T>*, typename atomic<T>::value_type) noexcept;
219
+ template<class T>
220
+ void atomic_store_or_explicit(volatile atomic<T>*, typename atomic<T>::value_type,
221
+ memory_order) noexcept;
222
+ template<class T>
223
+ constexpr void atomic_store_or_explicit(atomic<T>*, typename atomic<T>::value_type,
224
+ memory_order) noexcept;
225
+ template<class T>
226
+ void atomic_store_xor(volatile atomic<T>*, typename atomic<T>::value_type) noexcept;
227
+ template<class T>
228
+ constexpr void atomic_store_xor(atomic<T>*, typename atomic<T>::value_type) noexcept;
229
+ template<class T>
230
+ void atomic_store_xor_explicit(volatile atomic<T>*, typename atomic<T>::value_type,
231
+ memory_order) noexcept;
232
+ template<class T>
233
+ constexpr void atomic_store_xor_explicit(atomic<T>*, typename atomic<T>::value_type,
234
+ memory_order) noexcept;
235
+ template<class T>
236
+ void atomic_store_max(volatile atomic<T>*, typename atomic<T>::value_type) noexcept;
237
+ template<class T>
238
+ constexpr void atomic_store_max(atomic<T>*, typename atomic<T>::value_type) noexcept;
239
+ template<class T>
240
+ void atomic_store_max_explicit(volatile atomic<T>*, typename atomic<T>::value_type,
241
+ memory_order) noexcept;
242
+ template<class T>
243
+ constexpr void atomic_store_max_explicit(atomic<T>*, typename atomic<T>::value_type,
244
+ memory_order) noexcept;
245
+ template<class T>
246
+ void atomic_store_min(volatile atomic<T>*, typename atomic<T>::value_type) noexcept;
247
+ template<class T>
248
+ constexpr void atomic_store_min(atomic<T>*, typename atomic<T>::value_type) noexcept;
249
+ template<class T>
250
+ void atomic_store_min_explicit(volatile atomic<T>*, typename atomic<T>::value_type,
251
+ memory_order) noexcept;
252
+ template<class T>
253
+ constexpr void atomic_store_min_explicit(atomic<T>*, typename atomic<T>::value_type,
254
+ memory_order) noexcept;
255
+
256
+ template<class T>
257
+ void atomic_wait(const volatile atomic<T>*, typename atomic<T>::value_type) noexcept;
258
+ template<class T>
259
+ constexpr void atomic_wait(const atomic<T>*, typename atomic<T>::value_type) noexcept;
260
+ template<class T>
261
+ void atomic_wait_explicit(const volatile atomic<T>*, typename atomic<T>::value_type,
262
  memory_order) noexcept;
263
  template<class T>
264
+ constexpr void atomic_wait_explicit(const atomic<T>*, typename atomic<T>::value_type,
265
  memory_order) noexcept;
266
  template<class T>
267
+ void atomic_notify_one(volatile atomic<T>*) noexcept;
268
  template<class T>
269
+ constexpr void atomic_notify_one(atomic<T>*) noexcept;
270
  template<class T>
271
+ void atomic_notify_all(volatile atomic<T>*) noexcept;
272
  template<class T>
273
+ constexpr void atomic_notify_all(atomic<T>*) noexcept;
274
 
275
  // [atomics.alias], type aliases
276
+ using atomic_bool = atomic<bool>;
277
+ using atomic_char = atomic<char>;
278
+ using atomic_schar = atomic<signed char>;
279
+ using atomic_uchar = atomic<unsigned char>;
280
+ using atomic_short = atomic<short>;
281
+ using atomic_ushort = atomic<unsigned short>;
282
+ using atomic_int = atomic<int>;
283
+ using atomic_uint = atomic<unsigned int>;
284
+ using atomic_long = atomic<long>;
285
+ using atomic_ulong = atomic<unsigned long>;
286
+ using atomic_llong = atomic<long long>;
287
+ using atomic_ullong = atomic<unsigned long long>;
288
+ using atomic_char8_t = atomic<char8_t>;
289
+ using atomic_char16_t = atomic<char16_t>;
290
+ using atomic_char32_t = atomic<char32_t>;
291
+ using atomic_wchar_t = atomic<wchar_t>;
292
 
293
+ using atomic_int8_t = atomic<int8_t>;
294
+ using atomic_uint8_t = atomic<uint8_t>;
295
+ using atomic_int16_t = atomic<int16_t>;
296
+ using atomic_uint16_t = atomic<uint16_t>;
297
+ using atomic_int32_t = atomic<int32_t>;
298
+ using atomic_uint32_t = atomic<uint32_t>;
299
+ using atomic_int64_t = atomic<int64_t>;
300
+ using atomic_uint64_t = atomic<uint64_t>;
301
 
302
+ using atomic_int_least8_t = atomic<int_least8_t>;
303
+ using atomic_uint_least8_t = atomic<uint_least8_t>;
304
+ using atomic_int_least16_t = atomic<int_least16_t>;
305
+ using atomic_uint_least16_t = atomic<uint_least16_t>;
306
+ using atomic_int_least32_t = atomic<int_least32_t>;
307
+ using atomic_uint_least32_t = atomic<uint_least32_t>;
308
+ using atomic_int_least64_t = atomic<int_least64_t>;
309
+ using atomic_uint_least64_t = atomic<uint_least64_t>;
310
 
311
+ using atomic_int_fast8_t = atomic<int_fast8_t>;
312
+ using atomic_uint_fast8_t = atomic<uint_fast8_t>;
313
+ using atomic_int_fast16_t = atomic<int_fast16_t>;
314
+ using atomic_uint_fast16_t = atomic<uint_fast16_t>;
315
+ using atomic_int_fast32_t = atomic<int_fast32_t>;
316
+ using atomic_uint_fast32_t = atomic<uint_fast32_t>;
317
+ using atomic_int_fast64_t = atomic<int_fast64_t>;
318
+ using atomic_uint_fast64_t = atomic<uint_fast64_t>;
319
 
320
+ using atomic_intptr_t = atomic<intptr_t>;
321
+ using atomic_uintptr_t = atomic<uintptr_t>;
322
+ using atomic_size_t = atomic<size_t>;
323
+ using atomic_ptrdiff_t = atomic<ptrdiff_t>;
324
+ using atomic_intmax_t = atomic<intmax_t>;
325
+ using atomic_uintmax_t = atomic<uintmax_t>;
326
 
327
+ using atomic_signed_lock_free = see below; // hosted
328
+ using atomic_unsigned_lock_free = see below; // hosted
329
 
330
  // [atomics.flag], flag type and operations
331
+ struct atomic_flag;
332
 
333
+ bool atomic_flag_test(const volatile atomic_flag*) noexcept;
334
+ constexpr bool atomic_flag_test(const atomic_flag*) noexcept;
335
+ bool atomic_flag_test_explicit(const volatile atomic_flag*, memory_order) noexcept;
336
+ constexpr bool atomic_flag_test_explicit(const atomic_flag*, memory_order) noexcept;
337
+ bool atomic_flag_test_and_set(volatile atomic_flag*) noexcept;
338
+ constexpr bool atomic_flag_test_and_set(atomic_flag*) noexcept;
339
+ bool atomic_flag_test_and_set_explicit(volatile atomic_flag*, memory_order) noexcept;
340
+ constexpr bool atomic_flag_test_and_set_explicit(atomic_flag*, memory_order) noexcept;
341
+ void atomic_flag_clear(volatile atomic_flag*) noexcept;
342
+ constexpr void atomic_flag_clear(atomic_flag*) noexcept;
343
+ void atomic_flag_clear_explicit(volatile atomic_flag*, memory_order) noexcept;
344
+ constexpr void atomic_flag_clear_explicit(atomic_flag*, memory_order) noexcept;
 
 
345
 
346
+ void atomic_flag_wait(const volatile atomic_flag*, bool) noexcept;
347
+ constexpr void atomic_flag_wait(const atomic_flag*, bool) noexcept;
348
+ void atomic_flag_wait_explicit(const volatile atomic_flag*, bool, memory_order) noexcept;
349
+ constexpr void atomic_flag_wait_explicit(const atomic_flag*, bool, memory_order) noexcept;
350
+ void atomic_flag_notify_one(volatile atomic_flag*) noexcept;
351
+ constexpr void atomic_flag_notify_one(atomic_flag*) noexcept;
352
+ void atomic_flag_notify_all(volatile atomic_flag*) noexcept;
353
+ constexpr void atomic_flag_notify_all(atomic_flag*) noexcept;
354
+ #define ATOMIC_FLAG_INIT see belownc
 
 
355
 
356
  // [atomics.fences], fences
357
+ extern "C" constexpr void atomic_thread_fence(memory_order) noexcept;
358
+ extern "C" constexpr void atomic_signal_fence(memory_order) noexcept;
359
  }
360
  ```
361
 
362
  ### Type aliases <a id="atomics.alias">[[atomics.alias]]</a>
363
 
 
380
  ### Order and consistency <a id="atomics.order">[[atomics.order]]</a>
381
 
382
  ``` cpp
383
  namespace std {
384
  enum class memory_order : unspecified {
385
+ relaxed = 0, acquire = 2, release = 3, acq_rel = 4, seq_cst = 5
386
  };
387
  }
388
  ```
389
 
390
  The enumeration `memory_order` specifies the detailed regular
 
394
 
395
  - `memory_order::relaxed`: no operation orders memory.
396
  - `memory_order::release`, `memory_order::acq_rel`, and
397
  `memory_order::seq_cst`: a store operation performs a release
398
  operation on the affected memory location.
 
 
 
 
 
 
399
  - `memory_order::acquire`, `memory_order::acq_rel`, and
400
  `memory_order::seq_cst`: a load operation performs an acquire
401
  operation on the affected memory location.
402
 
403
+ [*Note 1*: Atomic operations specifying `memory_order::relaxed` are
404
  relaxed with respect to memory ordering. Implementations must still
405
  guarantee that any given atomic access to a particular atomic object be
406
  indivisible with respect to all other atomic accesses to that
407
  object. — *end note*]
408
 
 
437
  - if a `memory_order::seq_cst` fence X happens before A and B is a
438
  `memory_order::seq_cst` operation, then X precedes B in S; and
439
  - if a `memory_order::seq_cst` fence X happens before A and B happens
440
  before a `memory_order::seq_cst` fence Y, then X precedes Y in S.
441
 
442
+ [*Note 2*: This definition ensures that S is consistent with the
443
  modification order of any atomic object M. It also ensures that a
444
  `memory_order::seq_cst` load A of M gets its value either from the last
445
  modification of M that precedes A in S or from some
446
  non-`memory_order::seq_cst` modification of M that does not happen
447
  before any modification of M that precedes A in S. — *end note*]
448
 
449
+ [*Note 3*: We do not require that S be consistent with “happens before”
450
  [[intro.races]]. This allows more efficient implementation of
451
  `memory_order::acquire` and `memory_order::release` on some machine
452
  architectures. It can produce surprising results when these are mixed
453
  with `memory_order::seq_cst` accesses. — *end note*]
454
 
455
+ [*Note 4*: `memory_order::seq_cst` ensures sequential consistency only
456
  for a program that is free of data races and uses exclusively
457
  `memory_order::seq_cst` atomic operations. Any use of weaker ordering
458
  will invalidate this guarantee unless extreme care is used. In many
459
  cases, `memory_order::seq_cst` atomic operations are reorderable with
460
  respect to other atomic operations performed by the same
461
  thread. — *end note*]
462
 
463
  Implementations should ensure that no “out-of-thin-air” values are
464
  computed that circularly depend on their own computation.
465
 
466
+ [*Note 5*:
467
 
468
  For example, with `x` and `y` initially zero,
469
 
470
  ``` cpp
471
  // Thread 1:
 
484
  which circularly depends on the store to `y` storing `42`. Note that
485
  without this restriction, such an execution is possible.
486
 
487
  — *end note*]
488
 
489
+ [*Note 6*:
490
 
491
  The recommendation similarly disallows `r1 == r2 == 42` in the following
492
  example, with `x` and `y` again initially zero:
493
 
494
  ``` cpp
 
507
 
508
  Atomic read-modify-write operations shall always read the last value (in
509
  the modification order) written before the write associated with the
510
  read-modify-write operation.
511
 
512
+ An *atomic modify-write operation* is an atomic read-modify-write
513
+ operation with weaker synchronization requirements as specified in 
514
+ [[atomics.fences]].
515
 
516
+ [*Note 7*: The intent is for atomic modify-write operations to be
517
+ implemented using mechanisms that are not ordered, in hardware, by the
518
+ implementation of acquire fences. No other semantic or hardware property
519
+ (e.g., that the mechanism is a far atomic operation) is
520
+ implied. — *end note*]
521
 
522
+ *Recommended practice:* The implementation should make atomic stores
523
+ visible to atomic loads, and atomic loads should observe atomic stores,
524
+ within a reasonable amount of time.
 
525
 
526
  ### Lock-free property <a id="atomics.lockfree">[[atomics.lockfree]]</a>
527
 
528
  ``` cpp
529
  #define ATOMIC_BOOL_LOCK_FREE unspecified
 
624
  template<class T> struct atomic_ref {
625
  private:
626
  T* ptr; // exposition only
627
 
628
  public:
629
+ using value_type = remove_cv_t<T>;
630
  static constexpr size_t required_alignment = implementation-defined // required alignment for atomic_ref type's operations;
631
 
632
  static constexpr bool is_always_lock_free = implementation-defined // whether a given atomic_ref type's operations are always lock free;
633
  bool is_lock_free() const noexcept;
634
 
635
+ constexpr explicit atomic_ref(T&);
636
+ constexpr atomic_ref(const atomic_ref&) noexcept;
637
  atomic_ref& operator=(const atomic_ref&) = delete;
638
 
639
+ constexpr void store(value_type, memory_order = memory_order::seq_cst) const noexcept;
640
+ constexpr value_type operator=(value_type) const noexcept;
641
+ constexpr value_type load(memory_order = memory_order::seq_cst) const noexcept;
642
+ constexpr operator value_type() const noexcept;
643
 
644
+ constexpr value_type exchange(value_type,
645
+ memory_order = memory_order::seq_cst) const noexcept;
646
+ constexpr bool compare_exchange_weak(value_type&, value_type,
647
  memory_order, memory_order) const noexcept;
648
+ constexpr bool compare_exchange_strong(value_type&, value_type,
649
  memory_order, memory_order) const noexcept;
650
+ constexpr bool compare_exchange_weak(value_type&, value_type,
651
  memory_order = memory_order::seq_cst) const noexcept;
652
+ constexpr bool compare_exchange_strong(value_type&, value_type,
653
  memory_order = memory_order::seq_cst) const noexcept;
654
 
655
+ constexpr void wait(value_type, memory_order = memory_order::seq_cst) const noexcept;
656
+ constexpr void notify_one() const noexcept;
657
+ constexpr void notify_all() const noexcept;
658
+ constexpr T* address() const noexcept;
659
  };
660
  }
661
  ```
662
 
663
  An `atomic_ref` object applies atomic operations [[atomics.general]] to
 
682
  [*Note 1*: Atomic operations or the `atomic_ref` constructor can
683
  acquire a shared resource, such as a lock associated with the referenced
684
  object, to enable atomic operations to be applied to the referenced
685
  object. — *end note*]
686
 
687
+ The program is ill-formed if `is_always_lock_free` is `false` and
688
+ `is_volatile_v<T>` is `true`.
689
+
690
  #### Operations <a id="atomics.ref.ops">[[atomics.ref.ops]]</a>
691
 
692
  ``` cpp
693
  static constexpr size_t required_alignment;
694
  ```
 
717
 
718
  *Returns:* `true` if operations on all objects of the type
719
  `atomic_ref<T>` are lock-free, `false` otherwise.
720
 
721
  ``` cpp
722
+ constexpr atomic_ref(T& obj);
723
  ```
724
 
725
  *Preconditions:* The referenced object is aligned to
726
  `required_alignment`.
727
 
728
  *Ensures:* `*this` references `obj`.
729
 
730
  *Throws:* Nothing.
731
 
732
  ``` cpp
733
+ constexpr atomic_ref(const atomic_ref& ref) noexcept;
734
  ```
735
 
736
  *Ensures:* `*this` references the object referenced by `ref`.
737
 
738
  ``` cpp
739
+ constexpr void store(value_type desired,
740
+ memory_order order = memory_order::seq_cst) const noexcept;
741
  ```
742
 
743
+ *Constraints:* `is_const_v<T>` is `false`.
744
+
745
+ *Preconditions:* `order` is `memory_order::relaxed`,
746
+ `memory_order::release`, or `memory_order::seq_cst`.
747
 
748
  *Effects:* Atomically replaces the value referenced by `*ptr` with the
749
  value of `desired`. Memory is affected according to the value of
750
  `order`.
751
 
752
  ``` cpp
753
+ constexpr value_type operator=(value_type desired) const noexcept;
754
  ```
755
 
756
+ *Constraints:* `is_const_v<T>` is `false`.
757
+
758
  *Effects:* Equivalent to:
759
 
760
  ``` cpp
761
  store(desired);
762
  return desired;
763
  ```
764
 
765
  ``` cpp
766
+ constexpr value_type load(memory_order order = memory_order::seq_cst) const noexcept;
767
  ```
768
 
769
+ *Preconditions:* `order` is `memory_order::relaxed`,
770
+ `memory_order::acquire`, or `memory_order::seq_cst`.
771
 
772
  *Effects:* Memory is affected according to the value of `order`.
773
 
774
  *Returns:* Atomically returns the value referenced by `*ptr`.
775
 
776
  ``` cpp
777
+ constexpr operator value_type() const noexcept;
778
  ```
779
 
780
  *Effects:* Equivalent to: `return load();`
781
 
782
  ``` cpp
783
+ constexpr value_type exchange(value_type desired,
784
+ memory_order order = memory_order::seq_cst) const noexcept;
785
  ```
786
 
787
+ *Constraints:* `is_const_v<T>` is `false`.
788
+
789
  *Effects:* Atomically replaces the value referenced by `*ptr` with
790
  `desired`. Memory is affected according to the value of `order`. This
791
  operation is an atomic read-modify-write
792
  operation [[intro.multithread]].
793
 
794
  *Returns:* Atomically returns the value referenced by `*ptr` immediately
795
  before the effects.
796
 
797
  ``` cpp
798
+ constexpr bool compare_exchange_weak(value_type& expected, value_type desired,
799
  memory_order success, memory_order failure) const noexcept;
800
 
801
+ constexpr bool compare_exchange_strong(value_type& expected, value_type desired,
802
  memory_order success, memory_order failure) const noexcept;
803
 
804
+ constexpr bool compare_exchange_weak(value_type& expected, value_type desired,
805
  memory_order order = memory_order::seq_cst) const noexcept;
806
 
807
+ constexpr bool compare_exchange_strong(value_type& expected, value_type desired,
808
  memory_order order = memory_order::seq_cst) const noexcept;
809
  ```
810
 
811
+ *Constraints:* `is_const_v<T>` is `false`.
812
+
813
+ *Preconditions:* `failure` is `memory_order::relaxed`,
814
+ `memory_order::acquire`, or `memory_order::seq_cst`.
815
 
816
  *Effects:* Retrieves the value in `expected`. It then atomically
817
  compares the value representation of the value referenced by `*ptr` for
818
  equality with that previously retrieved from `expected`, and if `true`,
819
  replaces the value referenced by `*ptr` with that in `desired`. If and
 
847
  performance on some platforms. When a weak compare-and-exchange would
848
  require a loop and a strong one would not, the strong one is
849
  preferable. — *end note*]
850
 
851
  ``` cpp
852
+ constexpr void wait(value_type old, memory_order order = memory_order::seq_cst) const noexcept;
853
  ```
854
 
855
+ *Preconditions:* `order` is `memory_order::relaxed`,
856
+ `memory_order::acquire`, or `memory_order::seq_cst`.
857
 
858
  *Effects:* Repeatedly performs the following steps, in order:
859
 
860
  - Evaluates `load(order)` and compares its value representation for
861
  equality against that of `old`.
 
865
 
866
  *Remarks:* This function is an atomic waiting operation [[atomics.wait]]
867
  on atomic object `*ptr`.
868
 
869
  ``` cpp
870
+ constexpr void notify_one() const noexcept;
871
  ```
872
 
873
+ *Constraints:* `is_const_v<T>` is `false`.
874
+
875
  *Effects:* Unblocks the execution of at least one atomic waiting
876
  operation on `*ptr` that is eligible to be unblocked [[atomics.wait]] by
877
  this call, if any such atomic waiting operations exist.
878
 
879
  *Remarks:* This function is an atomic notifying
880
  operation [[atomics.wait]] on atomic object `*ptr`.
881
 
882
  ``` cpp
883
+ constexpr void notify_all() const noexcept;
884
  ```
885
 
886
+ *Constraints:* `is_const_v<T>` is `false`.
887
+
888
  *Effects:* Unblocks the execution of all atomic waiting operations on
889
  `*ptr` that are eligible to be unblocked [[atomics.wait]] by this call.
890
 
891
  *Remarks:* This function is an atomic notifying
892
  operation [[atomics.wait]] on atomic object `*ptr`.
893
 
894
+ ``` cpp
895
+ constexpr T* address() const noexcept;
896
+ ```
897
+
898
+ *Returns:* `ptr`.
899
+
900
  #### Specializations for integral types <a id="atomics.ref.int">[[atomics.ref.int]]</a>
901
 
902
+ There are specializations of the `atomic_ref` class template for all
903
+ integral types except cv `bool`. For each such type `integral-type`, the
904
+ specialization `atomic_ref<integral-type>` provides additional atomic
905
+ operations appropriate to integral types.
 
 
 
 
906
 
907
  [*Note 1*: The specialization `atomic_ref<bool>` uses the primary
908
  template [[atomics.ref.generic]]. — *end note*]
909
 
910
+ The program is ill-formed if `is_always_lock_free` is `false` and
911
+ `is_volatile_v<integral-type>` is `true`.
912
+
913
  ``` cpp
914
  namespace std {
915
  template<> struct atomic_ref<integral-type> {
916
  private:
917
  integral-type* ptr; // exposition only
918
 
919
  public:
920
+ using value_type = remove_cv_t<integral-type>;
921
  using difference_type = value_type;
922
  static constexpr size_t required_alignment = implementation-defined // required alignment for atomic_ref type's operations;
923
 
924
  static constexpr bool is_always_lock_free = implementation-defined // whether a given atomic_ref type's operations are always lock free;
925
  bool is_lock_free() const noexcept;
926
 
927
+ constexpr explicit atomic_ref(integral-type&);
928
+ constexpr atomic_ref(const atomic_ref&) noexcept;
929
  atomic_ref& operator=(const atomic_ref&) = delete;
930
 
931
+ constexpr void store(value_type, memory_order = memory_order::seq_cst) const noexcept;
932
+ constexpr value_type operator=(value_type) const noexcept;
933
+ constexpr value_type load(memory_order = memory_order::seq_cst) const noexcept;
934
+ constexpr operator value_type() const noexcept;
935
 
936
+ constexpr value_type exchange(value_type,
937
  memory_order = memory_order::seq_cst) const noexcept;
938
+ constexpr bool compare_exchange_weak(value_type&, value_type,
939
  memory_order, memory_order) const noexcept;
940
+ constexpr bool compare_exchange_strong(value_type&, value_type,
941
  memory_order, memory_order) const noexcept;
942
+ constexpr bool compare_exchange_weak(value_type&, value_type,
943
  memory_order = memory_order::seq_cst) const noexcept;
944
+ constexpr bool compare_exchange_strong(value_type&, value_type,
945
  memory_order = memory_order::seq_cst) const noexcept;
946
 
947
+ constexpr value_type fetch_add(value_type,
948
  memory_order = memory_order::seq_cst) const noexcept;
949
+ constexpr value_type fetch_sub(value_type,
950
  memory_order = memory_order::seq_cst) const noexcept;
951
+ constexpr value_type fetch_and(value_type,
952
  memory_order = memory_order::seq_cst) const noexcept;
953
+ constexpr value_type fetch_or(value_type,
954
  memory_order = memory_order::seq_cst) const noexcept;
955
+ constexpr value_type fetch_xor(value_type,
956
+ memory_order = memory_order::seq_cst) const noexcept;
957
+ constexpr value_type fetch_max(value_type,
958
+ memory_order = memory_order::seq_cst) const noexcept;
959
+ constexpr value_type fetch_min(value_type,
960
+ memory_order = memory_order::seq_cst) const noexcept;
961
+
962
+ constexpr void store_add(value_type,
963
+ memory_order = memory_order::seq_cst) const noexcept;
964
+ constexpr void store_sub(value_type,
965
+ memory_order = memory_order::seq_cst) const noexcept;
966
+ constexpr void store_and(value_type,
967
+ memory_order = memory_order::seq_cst) const noexcept;
968
+ constexpr void store_or(value_type,
969
+ memory_order = memory_order::seq_cst) const noexcept;
970
+ constexpr void store_xor(value_type,
971
+ memory_order = memory_order::seq_cst) const noexcept;
972
+ constexpr void store_max(value_type,
973
+ memory_order = memory_order::seq_cst) const noexcept;
974
+ constexpr void store_min(value_type,
975
  memory_order = memory_order::seq_cst) const noexcept;
976
 
977
+ constexpr value_type operator++(int) const noexcept;
978
+ constexpr value_type operator--(int) const noexcept;
979
+ constexpr value_type operator++() const noexcept;
980
+ constexpr value_type operator--() const noexcept;
981
+ constexpr value_type operator+=(value_type) const noexcept;
982
+ constexpr value_type operator-=(value_type) const noexcept;
983
+ constexpr value_type operator&=(value_type) const noexcept;
984
+ constexpr value_type operator|=(value_type) const noexcept;
985
+ constexpr value_type operator^=(value_type) const noexcept;
986
 
987
+ constexpr void wait(value_type, memory_order = memory_order::seq_cst) const noexcept;
988
+ constexpr void notify_one() const noexcept;
989
+ constexpr void notify_all() const noexcept;
990
+ constexpr integral-type* address() const noexcept;
991
  };
992
  }
993
  ```
994
 
995
  Descriptions are provided below only for members that differ from the
 
998
  The following operations perform arithmetic computations. The
999
  correspondence among key, operator, and computation is specified in
1000
  [[atomic.types.int.comp]].
1001
 
1002
  ``` cpp
1003
+ constexpr value_type fetch_key(value_type operand,
1004
  memory_order order = memory_order::seq_cst) const noexcept;
1005
  ```
1006
 
1007
+ *Constraints:* `is_const_v<`*`integral-type`*`>` is `false`.
1008
+
1009
  *Effects:* Atomically replaces the value referenced by `*ptr` with the
1010
  result of the computation applied to the value referenced by `*ptr` and
1011
  the given operand. Memory is affected according to the value of `order`.
1012
  These operations are atomic read-modify-write
1013
  operations [[intro.races]].
1014
 
1015
  *Returns:* Atomically, the value referenced by `*ptr` immediately before
1016
  the effects.
1017
 
1018
+ *Remarks:* Except for `fetch_max` and `fetch_min`, for signed integer
1019
+ types the result is as if the object value and parameters were converted
1020
+ to their corresponding unsigned types, the computation performed on
1021
+ those types, and the result converted back to the signed type.
1022
 
1023
  [*Note 1*: There are no undefined results arising from the
1024
  computation. — *end note*]
1025
 
1026
+ For `fetch_max` and `fetch_min`, the maximum and minimum computation is
1027
+ performed as if by `max` and `min` algorithms [[alg.min.max]],
1028
+ respectively, with the object value and the first parameter as the
1029
+ arguments.
1030
+
1031
  ``` cpp
1032
+ constexpr void store_key(value_type operand,
1033
+ memory_order order = memory_order::seq_cst) const noexcept;
1034
  ```
1035
 
1036
+ *Preconditions:* `order` is `memory_order::relaxed`,
1037
+ `memory_order::release`, or `memory_order::seq_cst`.
1038
+
1039
+ *Effects:* Atomically replaces the value referenced by `*ptr` with the
1040
+ result of the computation applied to the value referenced by `*ptr` and
1041
+ the given `operand`. Memory is affected according to the value of
1042
+ `order`. These operations are atomic modify-write
1043
+ operations [[atomics.order]].
1044
+
1045
+ *Remarks:* Except for `store_max` and `store_min`, for signed integer
1046
+ types, the result is as if `*ptr` and parameters were converted to their
1047
+ corresponding unsigned types, the computation performed on those types,
1048
+ and the result converted back to the signed type.
1049
+
1050
+ [*Note 2*: There are no undefined results arising from the
1051
+ computation. — *end note*]
1052
+
1053
+ For `store_max` and `store_min`, the maximum and minimum computation is
1054
+ performed as if by `max` and `min` algorithms [[alg.min.max]],
1055
+ respectively, with `*ptr` and the first parameter as the arguments.
1056
+
1057
+ ``` cpp
1058
+ constexpr value_type operator op=(value_type operand) const noexcept;
1059
+ ```
1060
+
1061
+ *Constraints:* `is_const_v<`*`integral-type`*`>` is `false`.
1062
+
1063
  *Effects:* Equivalent to:
1064
  `return fetch_`*`key`*`(operand) `*`op`*` operand;`
1065
 
1066
  #### Specializations for floating-point types <a id="atomics.ref.float">[[atomics.ref.float]]</a>
1067
 
1068
  There are specializations of the `atomic_ref` class template for all
1069
+ floating-point types. For each such type `floating-point-type`, the
1070
+ specialization `atomic_ref<floating-point-type>` provides additional
1071
+ atomic operations appropriate to floating-point types.
1072
+
1073
+ The program is ill-formed if `is_always_lock_free` is `false` and
1074
+ `is_volatile_v<floating-point-type>` is `true`.
1075
 
1076
  ``` cpp
1077
  namespace std {
1078
  template<> struct atomic_ref<floating-point-type> {
1079
  private:
1080
  floating-point-type* ptr; // exposition only
1081
 
1082
  public:
1083
+ using value_type = remove_cv_t<floating-point-type>;
1084
  using difference_type = value_type;
1085
  static constexpr size_t required_alignment = implementation-defined // required alignment for atomic_ref type's operations;
1086
 
1087
  static constexpr bool is_always_lock_free = implementation-defined // whether a given atomic_ref type's operations are always lock free;
1088
  bool is_lock_free() const noexcept;
1089
 
1090
+ constexpr explicit atomic_ref(floating-point-type&);
1091
+ constexpr atomic_ref(const atomic_ref&) noexcept;
1092
  atomic_ref& operator=(const atomic_ref&) = delete;
1093
 
1094
+ constexpr void store(value_type,
1095
+ memory_order = memory_order::seq_cst) const noexcept;
1096
+ constexpr value_type operator=(value_type) const noexcept;
1097
+ constexpr value_type load(memory_order = memory_order::seq_cst) const noexcept;
1098
+ constexpr operator value_type() const noexcept;
1099
 
1100
+ constexpr value_type exchange(value_type,
1101
  memory_order = memory_order::seq_cst) const noexcept;
1102
+ constexpr bool compare_exchange_weak(value_type&, value_type,
1103
  memory_order, memory_order) const noexcept;
1104
+ constexpr bool compare_exchange_strong(value_type&, value_type,
1105
  memory_order, memory_order) const noexcept;
1106
+ constexpr bool compare_exchange_weak(value_type&, value_type,
1107
+ memory_order = memory_order::seq_cst) const noexcept;
1108
+ constexpr bool compare_exchange_strong(value_type&, value_type,
1109
+ memory_order = memory_order::seq_cst) const noexcept;
1110
+
1111
+ constexpr value_type fetch_add(value_type,
1112
+ memory_order = memory_order::seq_cst) const noexcept;
1113
+ constexpr value_type fetch_sub(value_type,
1114
+ memory_order = memory_order::seq_cst) const noexcept;
1115
+
1116
+ constexpr value_type fetch_max(value_type,
1117
  memory_order = memory_order::seq_cst) const noexcept;
1118
+ constexpr value_type fetch_min(value_type,
1119
+ memory_order = memory_order::seq_cst) const noexcept;
1120
+ constexpr value_type fetch_fmaximum(value_type,
1121
+ memory_order = memory_order::seq_cst) const noexcept;
1122
+ constexpr value_type fetch_fminimum(value_type,
1123
+ memory_order = memory_order::seq_cst) const noexcept;
1124
+ constexpr value_type fetch_fmaximum_num(value_type,
1125
+ memory_order = memory_order::seq_cst) const noexcept;
1126
+ constexpr value_type fetch_fminimum_num(value_type,
1127
  memory_order = memory_order::seq_cst) const noexcept;
1128
 
1129
+ constexpr void store_add(value_type, memory_order = memory_order::seq_cst) const noexcept;
1130
+ constexpr void store_sub(value_type, memory_order = memory_order::seq_cst) const noexcept;
1131
+ constexpr void store_max(value_type, memory_order = memory_order::seq_cst) const noexcept;
1132
+ constexpr void store_min(value_type, memory_order = memory_order::seq_cst) const noexcept;
1133
+ constexpr void store_fmaximum(value_type,
1134
  memory_order = memory_order::seq_cst) const noexcept;
1135
+ constexpr void store_fminimum(value_type,
1136
+ memory_order = memory_order::seq_cst) const noexcept;
1137
+ constexpr void store_fmaximum_num(value_type,
1138
+ memory_order = memory_order::seq_cst) const noexcept;
1139
+ constexpr void store_fminimum_num(value_type,
1140
  memory_order = memory_order::seq_cst) const noexcept;
1141
 
1142
+ constexpr value_type operator+=(value_type) const noexcept;
1143
+ constexpr value_type operator-=(value_type) const noexcept;
1144
 
1145
+ constexpr void wait(value_type,
1146
+ memory_order = memory_order::seq_cst) const noexcept;
1147
+ constexpr void notify_one() const noexcept;
1148
+ constexpr void notify_all() const noexcept;
1149
+ constexpr floating-point-type* address() const noexcept;
1150
  };
1151
  }
1152
  ```
1153
 
1154
  Descriptions are provided below only for members that differ from the
1155
  primary template.
1156
 
1157
  The following operations perform arithmetic computations. The
1158
  correspondence among key, operator, and computation is specified in
1159
+ [[atomic.types.int.comp]], except for the keys `max`, `min`, `fmaximum`,
1160
+ `fminimum`, `fmaximum_num`, and `fminimum_num`, which are specified
1161
+ below.
1162
 
1163
  ``` cpp
1164
+ constexpr value_type fetch_key(value_type operand,
1165
  memory_order order = memory_order::seq_cst) const noexcept;
1166
  ```
1167
 
1168
+ *Constraints:* `is_const_v<`*`floating-point-type`*`>` is `false`.
1169
+
1170
  *Effects:* Atomically replaces the value referenced by `*ptr` with the
1171
  result of the computation applied to the value referenced by `*ptr` and
1172
  the given operand. Memory is affected according to the value of `order`.
1173
  These operations are atomic read-modify-write
1174
  operations [[intro.races]].
 
1178
 
1179
  *Remarks:* If the result is not a representable value for its
1180
  type [[expr.pre]], the result is unspecified, but the operations
1181
  otherwise have no undefined behavior. Atomic arithmetic operations on
1182
  *`floating-point-type`* should conform to the
1183
+ `std::numeric_limits<value_type>` traits associated with the
1184
+ floating-point type [[limits.syn]]. The floating-point
1185
  environment [[cfenv]] for atomic arithmetic operations on
1186
  *`floating-point-type`* may be different than the calling thread’s
1187
  floating-point environment.
1188
 
1189
+ - For `fetch_fmaximum` and `fetch_fminimum`, the maximum and minimum
1190
+ computation is performed as if by `fmaximum` and `fminimum`,
1191
+ respectively, with `*ptr` and the first parameter as the arguments.
1192
+ - For `fetch_fmaximum_num` and `fetch_fminimum_num`, the maximum and
1193
+ minimum computation is performed as if by `fmaximum_num` and
1194
+ `fminimum_num`, respectively, with `*ptr` and the first parameter as
1195
+ the arguments.
1196
+ - For `fetch_max` and `fetch_min`, the maximum and minimum computation
1197
+ is performed as if by `fmaximum_num` and `fminimum_num`, respectively,
1198
+ with `*ptr` and the first parameter as the arguments, except that:
1199
+ - If both arguments are NaN, an unspecified NaN value is stored at
1200
+ `*ptr`.
1201
+ - If exactly one argument is a NaN, either the other argument or an
1202
+ unspecified NaN value is stored at `*ptr`; it is unspecified which.
1203
+ - If the arguments are differently signed zeros, which of these values
1204
+ is stored at `*ptr` is unspecified.
1205
+
1206
+ *Recommended practice:* The implementation of `fetch_max` and
1207
+ `fetch_min` should treat negative zero as smaller than positive zero.
1208
+
1209
  ``` cpp
1210
+ constexpr void store_key(value_type operand,
1211
+ memory_order order = memory_order::seq_cst) const noexcept;
1212
  ```
1213
 
1214
+ *Preconditions:* `order` is `memory_order::relaxed`,
1215
+ `memory_order::release`, or `memory_order::seq_cst`.
1216
+
1217
+ *Effects:* Atomically replaces the value referenced by `*ptr` with the
1218
+ result of the computation applied to the value referenced by `*ptr` and
1219
+ the given `operand`. Memory is affected according to the value of
1220
+ `order`. These operations are atomic modify-write
1221
+ operations [[atomics.order]].
1222
+
1223
+ *Remarks:* If the result is not a representable value for its
1224
+ type [[expr.pre]], the result is unspecified, but the operations
1225
+ otherwise have no undefined behavior. Atomic arithmetic operations on
1226
+ *`floating-point-type`* should conform to the
1227
+ `numeric_limits<`*`floating-point-type`*`>` traits associated with the
1228
+ floating-point type [[limits.syn]]. The floating-point
1229
+ environment [[cfenv]] for atomic arithmetic operations on
1230
+ *`floating-point-type`* may be different than the calling thread’s
1231
+ floating-point environment. The arithmetic rules of floating-point
1232
+ atomic modify-write operations may be different from operations on
1233
+ floating-point types or atomic floating-point types.
1234
+
1235
+ [*Note 1*: Tree reductions are permitted for atomic modify-write
1236
+ operations. — *end note*]
1237
+
1238
+ - For `store_fmaximum` and `store_fminimum`, the maximum and minimum
1239
+ computation is performed as if by `fmaximum` and `fminimum`,
1240
+ respectively, with `*ptr` and the first parameter as the arguments.
1241
+ - For `store_fmaximum_num` and `store_fminimum_num`, the maximum and
1242
+ minimum computation is performed as if by `fmaximum_num `and
1243
+ `fminimum_num`, respectively, with `*ptr` and the first parameter as
1244
+ the arguments.
1245
+ - For `store_max` and `store_min`, the maximum and minimum computation
1246
+ is performed as if by `fmaximum_num` and `fminimum_num`, respectively,
1247
+ with `*ptr` and the first parameter as the arguments, except that:
1248
+ - If both arguments are NaN, an unspecified NaN value is stored at
1249
+ `*ptr`.
1250
+ - If exactly one argument is a NaN, either the other argument or an
1251
+ unspecified NaN value is stored at `*ptr`, it is unspecified which.
1252
+ - If the arguments are differently signed zeros, which of these values
1253
+ is stored at `*ptr` is unspecified.
1254
+
1255
+ *Recommended practice:* The implementation of `store_max` and
1256
+ `store_min` should treat negative zero as smaller than positive zero.
1257
+
1258
+ ``` cpp
1259
+ constexpr value_type operator op=(value_type operand) const noexcept;
1260
+ ```
1261
+
1262
+ *Constraints:* `is_const_v<`*`floating-point-type`*`>` is `false`.
1263
+
1264
  *Effects:* Equivalent to:
1265
  `return fetch_`*`key`*`(operand) `*`op`*` operand;`
1266
 
1267
+ #### Specialization for pointers <a id="atomics.ref.pointer">[[atomics.ref.pointer]]</a>
1268
+
1269
+ There are specializations of the `atomic_ref` class template for all
1270
+ pointer-to-object types. For each such type `pointer-type`, the
1271
+ specialization `atomic_ref<pointer-type>` provides additional atomic
1272
+ operations appropriate to pointer types.
1273
+
1274
+ The program is ill-formed if `is_always_lock_free` is `false` and
1275
+ `is_volatile_v<pointer-type>` is `true`.
1276
 
1277
  ``` cpp
1278
  namespace std {
1279
+ template<> struct atomic_ref<pointer-type> {
1280
  private:
1281
+ pointer-type* ptr; // exposition only
1282
 
1283
  public:
1284
+ using value_type = remove_cv_t<pointer-type>;
1285
  using difference_type = ptrdiff_t;
1286
  static constexpr size_t required_alignment = implementation-defined // required alignment for atomic_ref type's operations;
1287
 
1288
  static constexpr bool is_always_lock_free = implementation-defined // whether a given atomic_ref type's operations are always lock free;
1289
  bool is_lock_free() const noexcept;
1290
 
1291
+ constexpr explicit atomic_ref(pointer-type&);
1292
+ constexpr atomic_ref(const atomic_ref&) noexcept;
1293
  atomic_ref& operator=(const atomic_ref&) = delete;
1294
 
1295
+ constexpr void store(value_type, memory_order = memory_order::seq_cst) const noexcept;
1296
+ constexpr value_type operator=(value_type) const noexcept;
1297
+ constexpr value_type load(memory_order = memory_order::seq_cst) const noexcept;
1298
+ constexpr operator value_type() const noexcept;
1299
 
1300
+ constexpr value_type exchange(value_type,
1301
+ memory_order = memory_order::seq_cst) const noexcept;
1302
+ constexpr bool compare_exchange_weak(value_type&, value_type,
1303
  memory_order, memory_order) const noexcept;
1304
+ constexpr bool compare_exchange_strong(value_type&, value_type,
1305
  memory_order, memory_order) const noexcept;
1306
+ constexpr bool compare_exchange_weak(value_type&, value_type,
1307
+ memory_order = memory_order::seq_cst) const noexcept;
1308
+ constexpr bool compare_exchange_strong(value_type&, value_type,
1309
+ memory_order = memory_order::seq_cst) const noexcept;
1310
+
1311
+ constexpr value_type fetch_add(difference_type,
1312
+ memory_order = memory_order::seq_cst) const noexcept;
1313
+ constexpr value_type fetch_sub(difference_type,
1314
  memory_order = memory_order::seq_cst) const noexcept;
1315
+ constexpr value_type fetch_max(value_type,
1316
+ memory_order = memory_order::seq_cst) const noexcept;
1317
+ constexpr value_type fetch_min(value_type,
1318
  memory_order = memory_order::seq_cst) const noexcept;
1319
 
1320
+ constexpr void store_add(difference_type,
1321
+ memory_order = memory_order::seq_cst) const noexcept;
1322
+ constexpr void store_sub(difference_type,
1323
+ memory_order = memory_order::seq_cst) const noexcept;
1324
+ constexpr void store_max(value_type,
1325
+ memory_order = memory_order::seq_cst) const noexcept;
1326
+ constexpr void store_min(value_type,
1327
+ memory_order = memory_order::seq_cst) const noexcept;
1328
 
1329
+ constexpr value_type operator++(int) const noexcept;
1330
+ constexpr value_type operator--(int) const noexcept;
1331
+ constexpr value_type operator++() const noexcept;
1332
+ constexpr value_type operator--() const noexcept;
1333
+ constexpr value_type operator+=(difference_type) const noexcept;
1334
+ constexpr value_type operator-=(difference_type) const noexcept;
1335
 
1336
+ constexpr void wait(value_type, memory_order = memory_order::seq_cst) const noexcept;
1337
+ constexpr void notify_one() const noexcept;
1338
+ constexpr void notify_all() const noexcept;
1339
+ constexpr pointer-type* address() const noexcept;
1340
  };
1341
  }
1342
  ```
1343
 
1344
  Descriptions are provided below only for members that differ from the
 
1347
  The following operations perform arithmetic computations. The
1348
  correspondence among key, operator, and computation is specified in
1349
  [[atomic.types.pointer.comp]].
1350
 
1351
  ``` cpp
1352
+ constexpr value_type fetch_key(\seeabovenc operand,
1353
+ memory_order order = memory_order::seq_cst) const noexcept;
1354
  ```
1355
 
1356
+ *Constraints:* `is_const_v<`*`pointer-type`*`>` is `false`.
1357
+
1358
+ *Mandates:* `remove_pointer_t<`*`pointer-type`*`>` is a complete object
1359
+ type.
1360
 
1361
  *Effects:* Atomically replaces the value referenced by `*ptr` with the
1362
  result of the computation applied to the value referenced by `*ptr` and
1363
  the given operand. Memory is affected according to the value of `order`.
1364
  These operations are atomic read-modify-write
 
1368
  the effects.
1369
 
1370
  *Remarks:* The result may be an undefined address, but the operations
1371
  otherwise have no undefined behavior.
1372
 
1373
+ For `fetch_max` and `fetch_min`, the maximum and minimum computation is
1374
+ performed as if by `max` and `min` algorithms [[alg.min.max]],
1375
+ respectively, with the object value and the first parameter as the
1376
+ arguments.
1377
+
1378
+ [*Note 1*: If the pointers point to different complete objects (or
1379
+ subobjects thereof), the `<` operator does not establish a strict weak
1380
+ ordering ([[cpp17.lessthancomparable]], [[expr.rel]]). — *end note*]
1381
+
1382
  ``` cpp
1383
+ constexpr void store_key(\seeabovenc operand,
1384
+ memory_order order = memory_order::seq_cst) const noexcept;
1385
  ```
1386
 
1387
+ *Mandates:* `remove_pointer_t<`*`pointer-type`*`>` is a complete object
1388
+ type.
1389
+
1390
+ *Preconditions:* `order` is `memory_order::relaxed`,
1391
+ `memory_order::release`, or `memory_order::seq_cst`.
1392
+
1393
+ *Effects:* Atomically replaces the value referenced by `*ptr` with the
1394
+ result of the computation applied to the value referenced by `*ptr` and
1395
+ the given `operand`. Memory is affected according to the value of
1396
+ `order`. These operations are atomic modify-write
1397
+ operations [[atomics.order]].
1398
+
1399
+ *Remarks:* The result may be an undefined address, but the operations
1400
+ otherwise have no undefined behavior. For `store_max` and `store_min`,
1401
+ the `maximum` and `minimum` computation is performed as if by `max` and
1402
+ `min` algorithms [[alg.min.max]], respectively, with `*ptr` and the
1403
+ first parameter as the arguments.
1404
+
1405
+ [*Note 2*: If the pointers point to different complete objects (or
1406
+ subobjects thereof), the `<` operator does not establish a strict weak
1407
+ ordering ([[cpp17.lessthancomparable]], [[expr.rel]]). — *end note*]
1408
+
1409
+ ``` cpp
1410
+ constexpr value_type operator op=(difference_type operand) const noexcept;
1411
+ ```
1412
+
1413
+ *Constraints:* `is_const_v<`*`pointer-type`*`>` is `false`.
1414
+
1415
  *Effects:* Equivalent to:
1416
  `return fetch_`*`key`*`(operand) `*`op`*` operand;`
1417
 
1418
  #### Member operators common to integers and pointers to objects <a id="atomics.ref.memop">[[atomics.ref.memop]]</a>
1419
 
1420
+ Let `referred-type` be `pointer-type` for the specializations in
1421
+ [[atomics.ref.pointer]] and be `integral-type` for the specializations
1422
+ in [[atomics.ref.int]].
1423
+
1424
  ``` cpp
1425
+ constexpr value_type operator++(int) const noexcept;
1426
  ```
1427
 
1428
+ *Constraints:* `is_const_v<`*`referred-type`*`>` is `false`.
1429
+
1430
  *Effects:* Equivalent to: `return fetch_add(1);`
1431
 
1432
  ``` cpp
1433
+ constexpr value_type operator--(int) const noexcept;
1434
  ```
1435
 
1436
+ *Constraints:* `is_const_v<`*`referred-type`*`>` is `false`.
1437
+
1438
  *Effects:* Equivalent to: `return fetch_sub(1);`
1439
 
1440
  ``` cpp
1441
+ constexpr value_type operator++() const noexcept;
1442
  ```
1443
 
1444
+ *Constraints:* `is_const_v<`*`referred-type`*`>` is `false`.
1445
+
1446
  *Effects:* Equivalent to: `return fetch_add(1) + 1;`
1447
 
1448
  ``` cpp
1449
+ constexpr value_type operator--() const noexcept;
1450
  ```
1451
 
1452
+ *Constraints:* `is_const_v<`*`referred-type`*`>` is `false`.
1453
+
1454
  *Effects:* Equivalent to: `return fetch_sub(1) - 1;`
1455
 
1456
  ### Class template `atomic` <a id="atomics.types.generic">[[atomics.types.generic]]</a>
1457
 
1458
  #### General <a id="atomics.types.generic.general">[[atomics.types.generic.general]]</a>
 
1472
  atomic(const atomic&) = delete;
1473
  atomic& operator=(const atomic&) = delete;
1474
  atomic& operator=(const atomic&) volatile = delete;
1475
 
1476
  T load(memory_order = memory_order::seq_cst) const volatile noexcept;
1477
+ constexpr T load(memory_order = memory_order::seq_cst) const noexcept;
1478
  operator T() const volatile noexcept;
1479
+ constexpr operator T() const noexcept;
1480
  void store(T, memory_order = memory_order::seq_cst) volatile noexcept;
1481
+ constexpr void store(T, memory_order = memory_order::seq_cst) noexcept;
1482
  T operator=(T) volatile noexcept;
1483
+ constexpr T operator=(T) noexcept;
1484
 
1485
  T exchange(T, memory_order = memory_order::seq_cst) volatile noexcept;
1486
+ constexpr T exchange(T, memory_order = memory_order::seq_cst) noexcept;
1487
  bool compare_exchange_weak(T&, T, memory_order, memory_order) volatile noexcept;
1488
+ constexpr bool compare_exchange_weak(T&, T, memory_order, memory_order) noexcept;
1489
  bool compare_exchange_strong(T&, T, memory_order, memory_order) volatile noexcept;
1490
+ constexpr bool compare_exchange_strong(T&, T, memory_order, memory_order) noexcept;
1491
  bool compare_exchange_weak(T&, T, memory_order = memory_order::seq_cst) volatile noexcept;
1492
+ constexpr bool compare_exchange_weak(T&, T, memory_order = memory_order::seq_cst) noexcept;
1493
  bool compare_exchange_strong(T&, T, memory_order = memory_order::seq_cst) volatile noexcept;
1494
+ constexpr bool compare_exchange_strong(T&, T, memory_order = memory_order::seq_cst) noexcept;
1495
 
1496
  void wait(T, memory_order = memory_order::seq_cst) const volatile noexcept;
1497
+ constexpr void wait(T, memory_order = memory_order::seq_cst) const noexcept;
1498
  void notify_one() volatile noexcept;
1499
+ constexpr void notify_one() noexcept;
1500
  void notify_all() volatile noexcept;
1501
+ constexpr void notify_all() noexcept;
1502
  };
1503
  }
1504
  ```
1505
 
1506
  The template argument for `T` shall meet the *Cpp17CopyConstructible*
 
1508
  of
1509
 
1510
  - `is_trivially_copyable_v<T>`,
1511
  - `is_copy_constructible_v<T>`,
1512
  - `is_move_constructible_v<T>`,
1513
+ - `is_copy_assignable_v<T>`,
1514
+ - `is_move_assignable_v<T>`, or
1515
+ - `is_same_v<T, remove_cv_t<T>>`,
1516
 
1517
  is `false`.
1518
 
1519
  [*Note 1*: Type arguments that are not also statically initializable
1520
  can be difficult to use. — *end note*]
1521
 
1522
+ The specialization `atomic<bool>` is a standard-layout struct. It has a
1523
+ trivial destructor.
1524
 
1525
  [*Note 2*: The representation of an atomic specialization need not have
1526
  the same size and alignment requirement as its corresponding argument
1527
  type. — *end note*]
1528
 
 
1530
 
1531
  ``` cpp
1532
  constexpr atomic() noexcept(is_nothrow_default_constructible_v<T>);
1533
  ```
1534
 
1535
+ *Constraints:* `is_default_constructible_v<T>` is `true`.
1536
 
1537
  *Effects:* Initializes the atomic object with the value of `T()`.
1538
  Initialization is not an atomic operation [[intro.multithread]].
1539
 
1540
  ``` cpp
 
1574
  consistent with the value of `is_always_lock_free` for the same
1575
  type. — *end note*]
1576
 
1577
  ``` cpp
1578
  void store(T desired, memory_order order = memory_order::seq_cst) volatile noexcept;
1579
+ constexpr void store(T desired, memory_order order = memory_order::seq_cst) noexcept;
1580
  ```
1581
 
1582
  *Constraints:* For the `volatile` overload of this function,
1583
  `is_always_lock_free` is `true`.
1584
 
1585
+ *Preconditions:* `order` is `memory_order::relaxed`,
1586
+ `memory_order::release`, or `memory_order::seq_cst`.
 
1587
 
1588
  *Effects:* Atomically replaces the value pointed to by `this` with the
1589
  value of `desired`. Memory is affected according to the value of
1590
  `order`.
1591
 
1592
  ``` cpp
1593
  T operator=(T desired) volatile noexcept;
1594
+ constexpr T operator=(T desired) noexcept;
1595
  ```
1596
 
1597
  *Constraints:* For the `volatile` overload of this function,
1598
  `is_always_lock_free` is `true`.
1599
 
 
1601
 
1602
  *Returns:* `desired`.
1603
 
1604
  ``` cpp
1605
  T load(memory_order order = memory_order::seq_cst) const volatile noexcept;
1606
+ constexpr T load(memory_order order = memory_order::seq_cst) const noexcept;
1607
  ```
1608
 
1609
  *Constraints:* For the `volatile` overload of this function,
1610
  `is_always_lock_free` is `true`.
1611
 
1612
+ *Preconditions:* `order` is `memory_order::relaxed`,
1613
+ `memory_order::acquire`, or `memory_order::seq_cst`.
1614
 
1615
  *Effects:* Memory is affected according to the value of `order`.
1616
 
1617
  *Returns:* Atomically returns the value pointed to by `this`.
1618
 
1619
  ``` cpp
1620
  operator T() const volatile noexcept;
1621
+ constexpr operator T() const noexcept;
1622
  ```
1623
 
1624
  *Constraints:* For the `volatile` overload of this function,
1625
  `is_always_lock_free` is `true`.
1626
 
1627
  *Effects:* Equivalent to: `return load();`
1628
 
1629
  ``` cpp
1630
  T exchange(T desired, memory_order order = memory_order::seq_cst) volatile noexcept;
1631
+ constexpr T exchange(T desired, memory_order order = memory_order::seq_cst) noexcept;
1632
  ```
1633
 
1634
  *Constraints:* For the `volatile` overload of this function,
1635
  `is_always_lock_free` is `true`.
1636
 
 
1643
  before the effects.
1644
 
1645
  ``` cpp
1646
  bool compare_exchange_weak(T& expected, T desired,
1647
  memory_order success, memory_order failure) volatile noexcept;
1648
+ constexpr bool compare_exchange_weak(T& expected, T desired,
1649
  memory_order success, memory_order failure) noexcept;
1650
  bool compare_exchange_strong(T& expected, T desired,
1651
  memory_order success, memory_order failure) volatile noexcept;
1652
+ constexpr bool compare_exchange_strong(T& expected, T desired,
1653
  memory_order success, memory_order failure) noexcept;
1654
  bool compare_exchange_weak(T& expected, T desired,
1655
  memory_order order = memory_order::seq_cst) volatile noexcept;
1656
+ constexpr bool compare_exchange_weak(T& expected, T desired,
1657
  memory_order order = memory_order::seq_cst) noexcept;
1658
  bool compare_exchange_strong(T& expected, T desired,
1659
  memory_order order = memory_order::seq_cst) volatile noexcept;
1660
+ constexpr bool compare_exchange_strong(T& expected, T desired,
1661
  memory_order order = memory_order::seq_cst) noexcept;
1662
  ```
1663
 
1664
  *Constraints:* For the `volatile` overload of this function,
1665
  `is_always_lock_free` is `true`.
1666
 
1667
+ *Preconditions:* `failure` is `memory_order::relaxed`,
1668
+ `memory_order::acquire`, or `memory_order::seq_cst`.
1669
 
1670
  *Effects:* Retrieves the value in `expected`. It then atomically
1671
  compares the value representation of the value pointed to by `this` for
1672
  equality with that previously retrieved from `expected`, and if true,
1673
  replaces the value pointed to by `this` with that in `desired`. If and
 
1752
 
1753
  [*Note 6*: Under cases where the `memcpy` and `memcmp` semantics of the
1754
  compare-and-exchange operations apply, the comparisons can fail for
1755
  values that compare equal with `operator==` if the value representation
1756
  has trap bits or alternate representations of the same value. Notably,
1757
+ on implementations conforming to ISO/IEC 60559, floating-point `-0.0`
1758
+ and `+0.0` will not compare equal with `memcmp` but will compare equal
1759
+ with `operator==`, and NaNs with the same payload will compare equal
1760
+ with `memcmp` but will not compare equal with
1761
  `operator==`. — *end note*]
1762
 
1763
  [*Note 7*:
1764
 
1765
  Because compare-and-exchange acts on an object’s value representation,
 
1806
 
1807
  — *end note*]
1808
 
1809
  ``` cpp
1810
  void wait(T old, memory_order order = memory_order::seq_cst) const volatile noexcept;
1811
+ constexpr void wait(T old, memory_order order = memory_order::seq_cst) const noexcept;
1812
  ```
1813
 
1814
+ *Preconditions:* `order` is `memory_order::relaxed`,
1815
+ `memory_order::acquire`, or `memory_order::seq_cst`.
1816
 
1817
  *Effects:* Repeatedly performs the following steps, in order:
1818
 
1819
  - Evaluates `load(order)` and compares its value representation for
1820
  equality against that of `old`.
 
1825
  *Remarks:* This function is an atomic waiting
1826
  operation [[atomics.wait]].
1827
 
1828
  ``` cpp
1829
  void notify_one() volatile noexcept;
1830
+ constexpr void notify_one() noexcept;
1831
  ```
1832
 
1833
  *Effects:* Unblocks the execution of at least one atomic waiting
1834
  operation that is eligible to be unblocked [[atomics.wait]] by this
1835
  call, if any such atomic waiting operations exist.
 
1837
  *Remarks:* This function is an atomic notifying
1838
  operation [[atomics.wait]].
1839
 
1840
  ``` cpp
1841
  void notify_all() volatile noexcept;
1842
+ constexpr void notify_all() noexcept;
1843
  ```
1844
 
1845
  *Effects:* Unblocks the execution of all atomic waiting operations that
1846
  are eligible to be unblocked [[atomics.wait]] by this call.
1847
 
 
1877
  atomic(const atomic&) = delete;
1878
  atomic& operator=(const atomic&) = delete;
1879
  atomic& operator=(const atomic&) volatile = delete;
1880
 
1881
  void store(integral-type, memory_order = memory_order::seq_cst) volatile noexcept;
1882
+ constexpr void store(integral-type, memory_order = memory_order::seq_cst) noexcept;
1883
  integral-type operator=(integral-type) volatile noexcept;
1884
+ constexpr integral-type operator=(integral-type) noexcept;
1885
  integral-type load(memory_order = memory_order::seq_cst) const volatile noexcept;
1886
+ constexpr integral-type load(memory_order = memory_order::seq_cst) const noexcept;
1887
  operator integral-type() const volatile noexcept;
1888
+ constexpr operator integral-type() const noexcept;
1889
 
1890
  integral-type exchange(integral-type,
1891
  memory_order = memory_order::seq_cst) volatile noexcept;
1892
+ constexpr integral-type exchange(integral-type,
1893
  memory_order = memory_order::seq_cst) noexcept;
1894
  bool compare_exchange_weak(integral-type&, integral-type,
1895
  memory_order, memory_order) volatile noexcept;
1896
+ constexpr bool compare_exchange_weak(integral-type&, integral-type,
1897
  memory_order, memory_order) noexcept;
1898
  bool compare_exchange_strong(integral-type&, integral-type,
1899
  memory_order, memory_order) volatile noexcept;
1900
+ constexpr bool compare_exchange_strong(integral-type&, integral-type,
1901
  memory_order, memory_order) noexcept;
1902
  bool compare_exchange_weak(integral-type&, integral-type,
1903
  memory_order = memory_order::seq_cst) volatile noexcept;
1904
+ constexpr bool compare_exchange_weak(integral-type&, integral-type,
1905
  memory_order = memory_order::seq_cst) noexcept;
1906
  bool compare_exchange_strong(integral-type&, integral-type,
1907
  memory_order = memory_order::seq_cst) volatile noexcept;
1908
+ constexpr bool compare_exchange_strong(integral-type&, integral-type,
1909
  memory_order = memory_order::seq_cst) noexcept;
1910
 
1911
  integral-type fetch_add(integral-type,
1912
  memory_order = memory_order::seq_cst) volatile noexcept;
1913
+ constexpr integral-type fetch_add(integral-type,
1914
  memory_order = memory_order::seq_cst) noexcept;
1915
  integral-type fetch_sub(integral-type,
1916
  memory_order = memory_order::seq_cst) volatile noexcept;
1917
+ constexpr integral-type fetch_sub(integral-type,
1918
  memory_order = memory_order::seq_cst) noexcept;
1919
  integral-type fetch_and(integral-type,
1920
  memory_order = memory_order::seq_cst) volatile noexcept;
1921
+ constexpr integral-type fetch_and(integral-type,
1922
  memory_order = memory_order::seq_cst) noexcept;
1923
  integral-type fetch_or(integral-type,
1924
  memory_order = memory_order::seq_cst) volatile noexcept;
1925
+ constexpr integral-type fetch_or(integral-type,
1926
  memory_order = memory_order::seq_cst) noexcept;
1927
  integral-type fetch_xor(integral-type,
1928
  memory_order = memory_order::seq_cst) volatile noexcept;
1929
+ constexpr integral-type fetch_xor(integral-type,
1930
+ memory_order = memory_order::seq_cst) noexcept;
1931
+ integral-type fetch_max(integral-type,
1932
+ memory_order = memory_order::seq_cst) volatile noexcept;
1933
+ constexpr integral-type fetch_max(integral-type,
1934
+ memory_order = memory_order::seq_cst) noexcept;
1935
+ integral-type fetch_min(integral-type,
1936
+ memory_order = memory_order::seq_cst) volatile noexcept;
1937
+ constexpr integral-type fetch_min(integral-type,
1938
+ memory_order = memory_order::seq_cst) noexcept;
1939
+
1940
+ void store_add(integral-type,
1941
+ memory_order = memory_order::seq_cst) volatile noexcept;
1942
+ constexpr void store_add(integral-type,
1943
+ memory_order = memory_order::seq_cst) noexcept;
1944
+ void store_sub(integral-type,
1945
+ memory_order = memory_order::seq_cst) volatile noexcept;
1946
+ constexpr void store_sub(integral-type,
1947
+ memory_order = memory_order::seq_cst) noexcept;
1948
+ void store_and(integral-type,
1949
+ memory_order = memory_order::seq_cst) volatile noexcept;
1950
+ constexpr void store_and(integral-type,
1951
+ memory_order = memory_order::seq_cst) noexcept;
1952
+ void store_or(integral-type,
1953
+ memory_order = memory_order::seq_cst) volatile noexcept;
1954
+ constexpr void store_or(integral-type,
1955
+ memory_order = memory_order::seq_cst) noexcept;
1956
+ void store_xor(integral-type,
1957
+ memory_order = memory_order::seq_cst) volatile noexcept;
1958
+ constexpr void store_xor(integral-type,
1959
+ memory_order = memory_order::seq_cst) noexcept;
1960
+ void store_max(integral-type,
1961
+ memory_order = memory_order::seq_cst) volatile noexcept;
1962
+ constexpr void store_max(integral-type,
1963
+ memory_order = memory_order::seq_cst) noexcept;
1964
+ void store_min(integral-type,
1965
+ memory_order = memory_order::seq_cst) volatile noexcept;
1966
+ constexpr void store_min(integral-type,
1967
  memory_order = memory_order::seq_cst) noexcept;
1968
 
1969
  integral-type operator++(int) volatile noexcept;
1970
+ constexpr integral-type operator++(int) noexcept;
1971
  integral-type operator--(int) volatile noexcept;
1972
+ constexpr integral-type operator--(int) noexcept;
1973
  integral-type operator++() volatile noexcept;
1974
+ constexpr integral-type operator++() noexcept;
1975
  integral-type operator--() volatile noexcept;
1976
+ constexpr integral-type operator--() noexcept;
1977
  integral-type operator+=(integral-type) volatile noexcept;
1978
+ constexpr integral-type operator+=(integral-type) noexcept;
1979
  integral-type operator-=(integral-type) volatile noexcept;
1980
+ constexpr integral-type operator-=(integral-type) noexcept;
1981
  integral-type operator&=(integral-type) volatile noexcept;
1982
+ constexpr integral-type operator&=(integral-type) noexcept;
1983
  integral-type operator|=(integral-type) volatile noexcept;
1984
+ constexpr integral-type operator|=(integral-type) noexcept;
1985
  integral-type operator^=(integral-type) volatile noexcept;
1986
+ constexpr integral-type operator^=(integral-type) noexcept;
1987
 
1988
  void wait(integral-type, memory_order = memory_order::seq_cst) const volatile noexcept;
1989
+ constexpr void wait(integral-type, memory_order = memory_order::seq_cst) const noexcept;
1990
  void notify_one() volatile noexcept;
1991
+ constexpr void notify_one() noexcept;
1992
  void notify_all() volatile noexcept;
1993
+ constexpr void notify_all() noexcept;
1994
  };
1995
  }
1996
  ```
1997
 
1998
  The atomic integral specializations are standard-layout structs. They
 
2006
  [[atomic.types.int.comp]].
2007
 
2008
  **Table: Atomic arithmetic computations** <a id="atomic.types.int.comp">[atomic.types.int.comp]</a>
2009
 
2010
  | | | | | | |
2011
+ | ----- | --- | ----------- | ----- | --- | -------------------- |
2012
+ | `add` | `+` | addition | `and` | `&` | bitwise and |
2013
+ | `sub` | `-` | subtraction | `or` | `|` | bitwise inclusive or |
2014
+ | `max` | | maximum | `xor` | `^` | bitwise exclusive or |
2015
+ | `min` | | minimum | | | |
2016
 
2017
  ``` cpp
2018
+ integral-type fetch_key(integral-type operand,
2019
+ memory_order order = memory_order::seq_cst) volatile noexcept;
2020
+ constexpr integral-type fetch_key(integral-type operand,
2021
+ memory_order order = memory_order::seq_cst) noexcept;
2022
  ```
2023
 
2024
  *Constraints:* For the `volatile` overload of this function,
2025
  `is_always_lock_free` is `true`.
2026
 
 
2031
  operations [[intro.multithread]].
2032
 
2033
  *Returns:* Atomically, the value pointed to by `this` immediately before
2034
  the effects.
2035
 
2036
+ *Remarks:* Except for `fetch_max` and `fetch_min`, for signed integer
2037
+ types the result is as if the object value and parameters were converted
2038
+ to their corresponding unsigned types, the computation performed on
2039
+ those types, and the result converted back to the signed type.
2040
 
2041
  [*Note 1*: There are no undefined results arising from the
2042
  computation. — *end note*]
2043
 
2044
+ For `fetch_max` and `fetch_min`, the maximum and minimum computation is
2045
+ performed as if by `max` and `min` algorithms [[alg.min.max]],
2046
+ respectively, with the object value and the first parameter as the
2047
+ arguments.
2048
+
2049
  ``` cpp
2050
+ void store_key(integral-type operand,
2051
+ memory_order order = memory_order::seq_cst) volatile noexcept;
2052
+ constexpr void store_key(integral-type operand,
2053
+ memory_order order = memory_order::seq_cst) noexcept;
2054
+ ```
2055
+
2056
+ *Constraints:* For the `volatile` overload of this function,
2057
+ `is_always_lock_free` is `true`.
2058
+
2059
+ *Preconditions:* `order` is `memory_order::relaxed`,
2060
+ `memory_order::release`, or `memory_order::seq_cst`.
2061
+
2062
+ *Effects:* Atomically replaces the value pointed to by `this` with the
2063
+ result of the computation applied to the value pointed to by `this` and
2064
+ the given `operand`. Memory is affected according to the value of
2065
+ `order`. These operations are atomic modify-write
2066
+ operations [[atomics.order]].
2067
+
2068
+ *Remarks:* Except for `store_max` and `store_min`, for signed integer
2069
+ types, the result is as if the value pointed to by `this` and parameters
2070
+ were converted to their corresponding unsigned types, the computation
2071
+ performed on those types, and the result converted back to the signed
2072
+ type.
2073
+
2074
+ [*Note 2*: There are no undefined results arising from the
2075
+ computation. — *end note*]
2076
+
2077
+ For `store_max` and `store_min`, the maximum and minimum computation is
2078
+ performed as if by `max` and `min` algorithms [[alg.min.max]],
2079
+ respectively, with the value pointed to by `this` and the first
2080
+ parameter as the arguments.
2081
+
2082
+ ``` cpp
2083
+ integral-type operator op=(integral-type operand) volatile noexcept;
2084
+ constexpr integral-type operator op=(integral-type operand) noexcept;
2085
  ```
2086
 
2087
  *Constraints:* For the `volatile` overload of this function,
2088
  `is_always_lock_free` is `true`.
2089
 
 
2113
  atomic(const atomic&) = delete;
2114
  atomic& operator=(const atomic&) = delete;
2115
  atomic& operator=(const atomic&) volatile = delete;
2116
 
2117
  void store(floating-point-type, memory_order = memory_order::seq_cst) volatile noexcept;
2118
+ constexpr void store(floating-point-type, memory_order = memory_order::seq_cst) noexcept;
2119
  floating-point-type operator=(floating-point-type) volatile noexcept;
2120
+ constexpr floating-point-type operator=(floating-point-type) noexcept;
2121
  floating-point-type load(memory_order = memory_order::seq_cst) volatile noexcept;
2122
+ constexpr floating-point-type load(memory_order = memory_order::seq_cst) noexcept;
2123
  operator floating-point-type() volatile noexcept;
2124
+ constexpr operator floating-point-type() noexcept;
2125
 
2126
  floating-point-type exchange(floating-point-type,
2127
  memory_order = memory_order::seq_cst) volatile noexcept;
2128
+ constexpr floating-point-type exchange(floating-point-type,
2129
  memory_order = memory_order::seq_cst) noexcept;
2130
  bool compare_exchange_weak(floating-point-type&, floating-point-type,
2131
  memory_order, memory_order) volatile noexcept;
2132
+ constexpr bool compare_exchange_weak(floating-point-type&, floating-point-type,
2133
  memory_order, memory_order) noexcept;
2134
  bool compare_exchange_strong(floating-point-type&, floating-point-type,
2135
  memory_order, memory_order) volatile noexcept;
2136
+ constexpr bool compare_exchange_strong(floating-point-type&, floating-point-type,
2137
  memory_order, memory_order) noexcept;
2138
  bool compare_exchange_weak(floating-point-type&, floating-point-type,
2139
  memory_order = memory_order::seq_cst) volatile noexcept;
2140
+ constexpr bool compare_exchange_weak(floating-point-type&, floating-point-type,
2141
  memory_order = memory_order::seq_cst) noexcept;
2142
  bool compare_exchange_strong(floating-point-type&, floating-point-type,
2143
  memory_order = memory_order::seq_cst) volatile noexcept;
2144
+ constexpr bool compare_exchange_strong(floating-point-type&, floating-point-type,
2145
  memory_order = memory_order::seq_cst) noexcept;
2146
 
2147
  floating-point-type fetch_add(floating-point-type,
2148
  memory_order = memory_order::seq_cst) volatile noexcept;
2149
+ constexpr floating-point-type fetch_add(floating-point-type,
2150
  memory_order = memory_order::seq_cst) noexcept;
2151
  floating-point-type fetch_sub(floating-point-type,
2152
  memory_order = memory_order::seq_cst) volatile noexcept;
2153
+ constexpr floating-point-type fetch_sub(floating-point-type,
2154
+ memory_order = memory_order::seq_cst) noexcept;
2155
+ floating-point-type fetch_max(floating-point-type,
2156
+ memory_order = memory_order::seq_cst) volatile noexcept;
2157
+ constexpr floating-point-type fetch_max(floating-point-type,
2158
+ memory_order = memory_order::seq_cst) noexcept;
2159
+ floating-point-type fetch_min(floating-point-type,
2160
+ memory_order = memory_order::seq_cst) volatile noexcept;
2161
+ constexpr floating-poin-typet fetch_min(floating-point-type,
2162
+ memory_order = memory_order::seq_cst) noexcept;
2163
+ floating-point-type fetch_fmaximum(floating-point-type,
2164
+ memory_order = memory_order::seq_cst) volatile noexcept;
2165
+ constexpr floating-point-type fetch_fmaximum(floating-point-type,
2166
+ memory_order = memory_order::seq_cst) noexcept;
2167
+ floating-point-type fetch_fminimum(floating-point-type,
2168
+ memory_order = memory_order::seq_cst) volatile noexcept;
2169
+ constexpr floating-point-type fetch_fminimum(floating-point-type,
2170
+ memory_order = memory_order::seq_cst) noexcept;
2171
+ floating-point-type fetch_fmaximum_num(
2172
+ floating-point-type, memory_order = memory_order::seq_cst) volatile noexcept;
2173
+ constexpr floating-point-type fetch_fmaximum_num(
2174
+ floating-point-type, memory_order = memory_order::seq_cst) noexcept;
2175
+ floating-point-type fetch_fminimum_num(
2176
+ floating-point-type, memory_order = memory_order::seq_cst) volatile noexcept;
2177
+ constexpr floating-point-type fetch_fminimum_num(
2178
+ floating-point-type, memory_order = memory_order::seq_cst) noexcept;
2179
+
2180
+ void store_add(floating-point-type,
2181
+ memory_order = memory_order::seq_cst) volatile noexcept;
2182
+ constexpr void store_add(floating-point-type,
2183
+ memory_order = memory_order::seq_cst) noexcept;
2184
+ void store_sub(floating-point-type,
2185
+ memory_order = memory_order::seq_cst) volatile noexcept;
2186
+ constexpr void store_sub(floating-point-type,
2187
+ memory_order = memory_order::seq_cst) noexcept;
2188
+ void store_max(floating-point-type,
2189
+ memory_order = memory_order::seq_cst) volatile noexcept;
2190
+ constexpr void store_max(floating-point-type,
2191
+ memory_order = memory_order::seq_cst) noexcept;
2192
+ void store_min(floating-point-type,
2193
+ memory_order = memory_order::seq_cst) volatile noexcept;
2194
+ constexpr void store_min(floating-point-type,
2195
+ memory_order = memory_order::seq_cst) noexcept;
2196
+ void store_fmaximum(floating-point-type,
2197
+ memory_order = memory_order::seq_cst) volatile noexcept;
2198
+ constexpr void store_fmaximum(floating-point-type,
2199
+ memory_order = memory_order::seq_cst) noexcept;
2200
+ void store_fminimum(floating-point-type,
2201
+ memory_order = memory_order::seq_cst) volatile noexcept;
2202
+ constexpr void store_fminimum(floating-point-type,
2203
+ memory_order = memory_order::seq_cst) noexcept;
2204
+ void store_fmaximum_num(floating-point-type,
2205
+ memory_order = memory_order::seq_cst) volatile noexcept;
2206
+ constexpr void store_fmaximum_num(floating-point-type,
2207
+ memory_order = memory_order::seq_cst) noexcept;
2208
+ void store_fminimum_num(floating-point-type,
2209
+ memory_order = memory_order::seq_cst) volatile noexcept;
2210
+ constexpr void store_fminimum_num(floating-point-type,
2211
  memory_order = memory_order::seq_cst) noexcept;
2212
 
2213
  floating-point-type operator+=(floating-point-type) volatile noexcept;
2214
+ constexpr floating-point-type operator+=(floating-point-type) noexcept;
2215
  floating-point-type operator-=(floating-point-type) volatile noexcept;
2216
+ constexpr floating-point-type operator-=(floating-point-type) noexcept;
2217
 
2218
  void wait(floating-point-type, memory_order = memory_order::seq_cst) const volatile noexcept;
2219
+ constexpr void wait(floating-point-type,
2220
+ memory_order = memory_order::seq_cst) const noexcept;
2221
  void notify_one() volatile noexcept;
2222
+ constexpr void notify_one() noexcept;
2223
  void notify_all() volatile noexcept;
2224
+ constexpr void notify_all() noexcept;
2225
  };
2226
  }
2227
  ```
2228
 
2229
  The atomic floating-point specializations are standard-layout structs.
 
2232
  Descriptions are provided below only for members that differ from the
2233
  primary template.
2234
 
2235
  The following operations perform arithmetic addition and subtraction
2236
  computations. The correspondence among key, operator, and computation is
2237
+ specified in [[atomic.types.int.comp]], except for the keys `max`,
2238
+ `min`, `fmaximum`, `fminimum`, `fmaximum_num`, and `fminimum_num`, which
2239
+ are specified below.
2240
 
2241
  ``` cpp
2242
+ floating-point-type fetch_key(floating-point-type operand,
2243
+ memory_order order = memory_order::seq_cst) volatile noexcept;
2244
+ constexpr floating-point-type fetch_key(floating-point-type operand,
2245
+ memory_order order = memory_order::seq_cst) noexcept;
2246
  ```
2247
 
2248
  *Constraints:* For the `volatile` overload of this function,
2249
  `is_always_lock_free` is `true`.
2250
 
 
2265
  the floating-point type [[limits.syn]]. The floating-point
2266
  environment [[cfenv]] for atomic arithmetic operations on
2267
  *`floating-point-type`* may be different than the calling thread’s
2268
  floating-point environment.
2269
 
2270
+ - For `fetch_fmaximum` and `fetch_fminimum`, the maximum and minimum
2271
+ computation is performed as if by `fmaximum` and `fminimum`,
2272
+ respectively, with the value pointed to by `this` and the first
2273
+ parameter as the arguments.
2274
+ - For `fetch_fmaximum_num` and `fetch_fminimum_num`, the maximum and
2275
+ minimum computation is performed as if by `fmaximum_num` and
2276
+ `fminimum_num`, respectively, with the value pointed to by `this` and
2277
+ the first parameter as the arguments.
2278
+ - For `fetch_max` and `fetch_min`, the maximum and minimum computation
2279
+ is performed as if by `fmaximum_num` and `fminimum_num`, respectively,
2280
+ with the value pointed to by `this` and the first parameter as the
2281
+ arguments, except that:
2282
+ - If both arguments are NaN, an unspecified NaN value replaces the
2283
+ value pointed to by `this`.
2284
+ - If exactly one argument is a NaN, either the other argument or an
2285
+ unspecified NaN value replaces the value pointed to by `this`; it is
2286
+ unspecified which.
2287
+ - If the arguments are differently signed zeros, which of these values
2288
+ replaces the value pointed to by this is unspecified.
2289
+
2290
+ *Recommended practice:* The implementation of `fetch_max` and
2291
+ `fetch_min` should treat negative zero as smaller than positive zero.
2292
+
2293
  ``` cpp
2294
+ void store_key(floating-point-type operand,
2295
+ memory_order order = memory_order::seq_cst) volatile noexcept;
2296
+ constexpr void store_key(floating-point-type operand,
2297
+ memory_order order = memory_order::seq_cst) noexcept;
2298
+ ```
2299
+
2300
+ *Constraints:* For the `volatile` overload of this function,
2301
+ `is_always_lock_free` is `true`.
2302
+
2303
+ *Preconditions:* `order` is `memory_order::relaxed`,
2304
+ `memory_order::release`, or `memory_order::seq_cst`.
2305
+
2306
+ *Effects:* Atomically replaces the value pointed to by `this` with the
2307
+ result of the computation applied to the value pointed to by `this` and
2308
+ the given operand. Memory is affected according to the value of `order`.
2309
+ These operations are atomic modify-write operations [[atomics.order]].
2310
+
2311
+ *Remarks:* If the result is not a representable value for its
2312
+ type [[expr.pre]] the result is unspecified, but the operations
2313
+ otherwise have no undefined behavior. Atomic arithmetic operations on
2314
+ *`floating-point-type`* should conform to the
2315
+ `numeric_limits<`*`floating-point-type`*`>` traits associated with the
2316
+ floating-point type [[limits.syn]]. The floating-point
2317
+ environment [[cfenv]] for atomic arithmetic operations on
2318
+ *`floating-point-type`* may be different than the calling thread’s
2319
+ floating-point environment. The arithmetic rules of floating-point
2320
+ atomic modify-write operations may be different from operations on
2321
+ floating-point types or atomic floating-point types.
2322
+
2323
+ [*Note 1*: Tree reductions are permitted for atomic modify-write
2324
+ operations. — *end note*]
2325
+
2326
+ - For `store_fmaximum` and `store_fminimum`, the maximum and minimum
2327
+ computation is performed as if by `fmaximum` and `fminimum`,
2328
+ respectively, with the value pointed to by `this` and the first
2329
+ parameter as the arguments.
2330
+ - For `store_fmaximum_num` and `store_fminimum_num`, the maximum and
2331
+ minimum computation is performed as if by `fmaximum_num` and
2332
+ `fminimum_num`, respectively, with the value pointed to by `this` and
2333
+ the first parameter as the arguments.
2334
+ - For `store_max` and `store_min`, the maximum and minimum computation
2335
+ is performed as if by `fmaximum_num` and `fminimum_num`, respectively,
2336
+ with the value pointed to by `this` and the first parameter as the
2337
+ arguments, except that:
2338
+ - If both arguments are NaN, an unspecified NaN value replaces the
2339
+ value pointed to by `this`.
2340
+ - If exactly one argument is a NaN, either the other argument or an
2341
+ unspecified NaN value replaces the value pointed to by `this`; it is
2342
+ unspecified which.
2343
+ - If the arguments are differently signed zeros, which of these values
2344
+ replaces the value pointed to by `this` is unspecified.
2345
+
2346
+ *Recommended practice:* The implementation of `store_max` and
2347
+ `store_min` should treat negative zero as smaller than positive zero.
2348
+
2349
+ ``` cpp
2350
+ floating-point-type operator op=(floating-point-type operand) volatile noexcept;
2351
+ constexpr floating-point-type operator op=(floating-point-type operand) noexcept;
2352
  ```
2353
 
2354
  *Constraints:* For the `volatile` overload of this function,
2355
  `is_always_lock_free` is `true`.
2356
 
 
2384
  atomic(const atomic&) = delete;
2385
  atomic& operator=(const atomic&) = delete;
2386
  atomic& operator=(const atomic&) volatile = delete;
2387
 
2388
  void store(T*, memory_order = memory_order::seq_cst) volatile noexcept;
2389
+ constexpr void store(T*, memory_order = memory_order::seq_cst) noexcept;
2390
  T* operator=(T*) volatile noexcept;
2391
+ constexpr T* operator=(T*) noexcept;
2392
  T* load(memory_order = memory_order::seq_cst) const volatile noexcept;
2393
+ constexpr T* load(memory_order = memory_order::seq_cst) const noexcept;
2394
  operator T*() const volatile noexcept;
2395
+ constexpr operator T*() const noexcept;
2396
 
2397
  T* exchange(T*, memory_order = memory_order::seq_cst) volatile noexcept;
2398
+ constexpr T* exchange(T*, memory_order = memory_order::seq_cst) noexcept;
2399
  bool compare_exchange_weak(T*&, T*, memory_order, memory_order) volatile noexcept;
2400
+ constexpr bool compare_exchange_weak(T*&, T*, memory_order, memory_order) noexcept;
2401
  bool compare_exchange_strong(T*&, T*, memory_order, memory_order) volatile noexcept;
2402
+ constexpr bool compare_exchange_strong(T*&, T*, memory_order, memory_order) noexcept;
2403
  bool compare_exchange_weak(T*&, T*,
2404
  memory_order = memory_order::seq_cst) volatile noexcept;
2405
+ constexpr bool compare_exchange_weak(T*&, T*,
2406
  memory_order = memory_order::seq_cst) noexcept;
2407
  bool compare_exchange_strong(T*&, T*,
2408
  memory_order = memory_order::seq_cst) volatile noexcept;
2409
+ constexpr bool compare_exchange_strong(T*&, T*,
2410
  memory_order = memory_order::seq_cst) noexcept;
2411
 
2412
  T* fetch_add(ptrdiff_t, memory_order = memory_order::seq_cst) volatile noexcept;
2413
+ constexpr T* fetch_add(ptrdiff_t, memory_order = memory_order::seq_cst) noexcept;
2414
  T* fetch_sub(ptrdiff_t, memory_order = memory_order::seq_cst) volatile noexcept;
2415
+ constexpr T* fetch_sub(ptrdiff_t, memory_order = memory_order::seq_cst) noexcept;
2416
+ T* fetch_max(T*, memory_order = memory_order::seq_cst) volatile noexcept;
2417
+ constexpr T* fetch_max(T*, memory_order = memory_order::seq_cst) noexcept;
2418
+ T* fetch_min(T*, memory_order = memory_order::seq_cst) volatile noexcept;
2419
+ constexpr T* fetch_min(T*, memory_order = memory_order::seq_cst) noexcept;
2420
+
2421
+ void store_add(ptrdiff_t, memory_order = memory_order::seq_cst) volatile noexcept;
2422
+ constexpr void store_add(ptrdiff_t, memory_order = memory_order::seq_cst) noexcept;
2423
+ void store_sub(ptrdiff_t, memory_order = memory_order::seq_cst) volatile noexcept;
2424
+ constexpr void store_sub(ptrdiff_t, memory_order = memory_order::seq_cst) noexcept;
2425
+ void store_max(T*, memory_order = memory_order::seq_cst) volatile noexcept;
2426
+ constexpr void store_max(T*, memory_order = memory_order::seq_cst) noexcept;
2427
+ void store_min(T*, memory_order = memory_order::seq_cst) volatile noexcept;
2428
+ constexpr void store_min(T*, memory_order = memory_order::seq_cst) noexcept;
2429
 
2430
  T* operator++(int) volatile noexcept;
2431
+ constexpr T* operator++(int) noexcept;
2432
  T* operator--(int) volatile noexcept;
2433
+ constexpr T* operator--(int) noexcept;
2434
  T* operator++() volatile noexcept;
2435
+ constexpr T* operator++() noexcept;
2436
  T* operator--() volatile noexcept;
2437
+ constexpr T* operator--() noexcept;
2438
  T* operator+=(ptrdiff_t) volatile noexcept;
2439
+ constexpr T* operator+=(ptrdiff_t) noexcept;
2440
  T* operator-=(ptrdiff_t) volatile noexcept;
2441
+ constexpr T* operator-=(ptrdiff_t) noexcept;
2442
 
2443
  void wait(T*, memory_order = memory_order::seq_cst) const volatile noexcept;
2444
+ constexpr void wait(T*, memory_order = memory_order::seq_cst) const noexcept;
2445
  void notify_one() volatile noexcept;
2446
+ constexpr void notify_one() noexcept;
2447
  void notify_all() volatile noexcept;
2448
+ constexpr void notify_all() noexcept;
2449
  };
2450
  }
2451
  ```
2452
 
2453
  There is a partial specialization of the `atomic` class template for
 
2464
  **Table: Atomic pointer computations** <a id="atomic.types.pointer.comp">[atomic.types.pointer.comp]</a>
2465
 
2466
  | | | | | | |
2467
  | ----- | --- | -------- | ----- | --- | ----------- |
2468
  | `add` | `+` | addition | `sub` | `-` | subtraction |
2469
+ | `max` | | maximum | `min` | | minimum |
2470
 
2471
  ``` cpp
2472
+ T* fetch_key(\seeabovenc operand, memory_order order = memory_order::seq_cst) volatile noexcept;
2473
+ constexpr T* fetch_key(\seeabovenc operand, memory_order order = memory_order::seq_cst) noexcept;
2474
  ```
2475
 
2476
  *Constraints:* For the `volatile` overload of this function,
2477
  `is_always_lock_free` is `true`.
2478
 
 
2491
  the effects.
2492
 
2493
  *Remarks:* The result may be an undefined address, but the operations
2494
  otherwise have no undefined behavior.
2495
 
2496
+ For `fetch_max` and `fetch_min`, the maximum and minimum computation is
2497
+ performed as if by `max` and `min` algorithms [[alg.min.max]],
2498
+ respectively, with the object value and the first parameter as the
2499
+ arguments.
2500
+
2501
+ [*Note 2*: If the pointers point to different complete objects (or
2502
+ subobjects thereof), the `<` operator does not establish a strict weak
2503
+ ordering ([[cpp17.lessthancomparable]], [[expr.rel]]). — *end note*]
2504
+
2505
+ ``` cpp
2506
+ void store_key(\seeabovenc operand, memory_order order = memory_order::seq_cst) volatile noexcept;
2507
+ constexpr void store_key(\seeabovenc operand, memory_order order = memory_order::seq_cst) noexcept;
2508
+ ```
2509
+
2510
+ *Constraints:* For the `volatile` overload of this function,
2511
+ `is_always_lock_free` is `true`.
2512
+
2513
+ *Mandates:* `T` is a complete object type.
2514
+
2515
+ [*Note 3*: Pointer arithmetic on `void*` or function pointers is
2516
+ ill-formed. — *end note*]
2517
+
2518
+ *Effects:* Atomically replaces the value pointed to by `this` with the
2519
+ result of the computation applied to the value pointed to by `this` and
2520
+ the given `operand`. Memory is affected according to the value of
2521
+ `order`. These operations are atomic modify-write
2522
+ operations [[atomics.order]].
2523
+
2524
+ *Remarks:* The result may be an undefined address, but the operations
2525
+ otherwise have no undefined behavior. For `store_max` and `store_min`,
2526
+ the maximum and minimum computation is performed as if by `max` and
2527
+ `min` algorithms [[alg.min.max]], respectively, with the value pointed
2528
+ to by `this` and the first parameter as the arguments.
2529
+
2530
+ [*Note 4*: If the pointers point to different complete objects (or
2531
+ subobjects thereof), the `<` operator does not establish a strict weak
2532
+ ordering ([[cpp17.lessthancomparable]], [[expr.rel]]). — *end note*]
2533
+
2534
  ``` cpp
2535
  T* operator op=(ptrdiff_t operand) volatile noexcept;
2536
+ constexpr T* operator op=(ptrdiff_t operand) noexcept;
2537
  ```
2538
 
2539
  *Constraints:* For the `volatile` overload of this function,
2540
  `is_always_lock_free` is `true`.
2541
 
 
2544
 
2545
  #### Member operators common to integers and pointers to objects <a id="atomics.types.memop">[[atomics.types.memop]]</a>
2546
 
2547
  ``` cpp
2548
  value_type operator++(int) volatile noexcept;
2549
+ constexpr value_type operator++(int) noexcept;
2550
  ```
2551
 
2552
  *Constraints:* For the `volatile` overload of this function,
2553
  `is_always_lock_free` is `true`.
2554
 
2555
  *Effects:* Equivalent to: `return fetch_add(1);`
2556
 
2557
  ``` cpp
2558
  value_type operator--(int) volatile noexcept;
2559
+ constexpr value_type operator--(int) noexcept;
2560
  ```
2561
 
2562
  *Constraints:* For the `volatile` overload of this function,
2563
  `is_always_lock_free` is `true`.
2564
 
2565
  *Effects:* Equivalent to: `return fetch_sub(1);`
2566
 
2567
  ``` cpp
2568
  value_type operator++() volatile noexcept;
2569
+ constexpr value_type operator++() noexcept;
2570
  ```
2571
 
2572
  *Constraints:* For the `volatile` overload of this function,
2573
  `is_always_lock_free` is `true`.
2574
 
2575
  *Effects:* Equivalent to: `return fetch_add(1) + 1;`
2576
 
2577
  ``` cpp
2578
  value_type operator--() volatile noexcept;
2579
+ constexpr value_type operator--() noexcept;
2580
  ```
2581
 
2582
  *Constraints:* For the `volatile` overload of this function,
2583
  `is_always_lock_free` is `true`.
2584
 
 
2651
  static constexpr bool is_always_lock_free = implementation-defined // whether a given atomic type's operations are always lock free;
2652
  bool is_lock_free() const noexcept;
2653
 
2654
  constexpr atomic() noexcept;
2655
  constexpr atomic(nullptr_t) noexcept : atomic() { }
2656
+ constexpr atomic(shared_ptr<T> desired) noexcept;
2657
  atomic(const atomic&) = delete;
2658
  void operator=(const atomic&) = delete;
2659
 
2660
+ constexpr shared_ptr<T> load(memory_order order = memory_order::seq_cst) const noexcept;
2661
+ constexpr operator shared_ptr<T>() const noexcept;
2662
+ constexpr void store(shared_ptr<T> desired,
2663
+ memory_order order = memory_order::seq_cst) noexcept;
2664
+ constexpr void operator=(shared_ptr<T> desired) noexcept;
2665
+ constexpr void operator=(nullptr_t) noexcept;
2666
 
2667
+ constexpr shared_ptr<T> exchange(shared_ptr<T> desired,
2668
  memory_order order = memory_order::seq_cst) noexcept;
2669
+ constexpr bool compare_exchange_weak(shared_ptr<T>& expected, shared_ptr<T> desired,
2670
  memory_order success, memory_order failure) noexcept;
2671
+ constexpr bool compare_exchange_strong(shared_ptr<T>& expected, shared_ptr<T> desired,
2672
  memory_order success, memory_order failure) noexcept;
2673
+ constexpr bool compare_exchange_weak(shared_ptr<T>& expected, shared_ptr<T> desired,
2674
  memory_order order = memory_order::seq_cst) noexcept;
2675
+ constexpr bool compare_exchange_strong(shared_ptr<T>& expected, shared_ptr<T> desired,
2676
  memory_order order = memory_order::seq_cst) noexcept;
2677
 
2678
+ constexpr void wait(shared_ptr<T> old,
2679
+ memory_order order = memory_order::seq_cst) const noexcept;
2680
+ constexpr void notify_one() noexcept;
2681
+ constexpr void notify_all() noexcept;
2682
 
2683
  private:
2684
  shared_ptr<T> p; // exposition only
2685
  };
2686
  }
 
2688
 
2689
  ``` cpp
2690
  constexpr atomic() noexcept;
2691
  ```
2692
 
2693
+ *Effects:* Value-initializes `p`.
2694
 
2695
  ``` cpp
2696
+ constexpr atomic(shared_ptr<T> desired) noexcept;
2697
  ```
2698
 
2699
  *Effects:* Initializes the object with the value `desired`.
2700
  Initialization is not an atomic operation [[intro.multithread]].
2701
 
 
2705
  `memory_order::relaxed` operations on a suitable atomic pointer
2706
  variable, and then immediately accessing `A` in the receiving thread.
2707
  This results in undefined behavior. — *end note*]
2708
 
2709
  ``` cpp
2710
+ constexpr void store(shared_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept;
2711
  ```
2712
 
2713
+ *Preconditions:* `order` is `memory_order::relaxed`,
2714
+ `memory_order::release`, or `memory_order::seq_cst`.
2715
 
2716
  *Effects:* Atomically replaces the value pointed to by `this` with the
2717
  value of `desired` as if by `p.swap(desired)`. Memory is affected
2718
  according to the value of `order`.
2719
 
2720
  ``` cpp
2721
+ constexpr void operator=(shared_ptr<T> desired) noexcept;
2722
  ```
2723
 
2724
  *Effects:* Equivalent to `store(desired)`.
2725
 
2726
  ``` cpp
2727
+ constexpr void operator=(nullptr_t) noexcept;
2728
  ```
2729
 
2730
+ *Effects:* Equivalent to `store(nullptr)`.
2731
+
2732
+ ``` cpp
2733
+ constexpr shared_ptr<T> load(memory_order order = memory_order::seq_cst) const noexcept;
2734
+ ```
2735
+
2736
+ *Preconditions:* `order` is `memory_order::relaxed`,
2737
+ `memory_order::acquire`, or `memory_order::seq_cst`.
2738
 
2739
  *Effects:* Memory is affected according to the value of `order`.
2740
 
2741
  *Returns:* Atomically returns `p`.
2742
 
2743
  ``` cpp
2744
+ constexpr operator shared_ptr<T>() const noexcept;
2745
  ```
2746
 
2747
  *Effects:* Equivalent to: `return load();`
2748
 
2749
  ``` cpp
2750
+ constexpr shared_ptr<T> exchange(shared_ptr<T> desired,
2751
+ memory_order order = memory_order::seq_cst) noexcept;
2752
  ```
2753
 
2754
  *Effects:* Atomically replaces `p` with `desired` as if by
2755
  `p.swap(desired)`. Memory is affected according to the value of `order`.
2756
  This is an atomic read-modify-write operation [[intro.races]].
2757
 
2758
  *Returns:* Atomically returns the value of `p` immediately before the
2759
  effects.
2760
 
2761
  ``` cpp
2762
+ constexpr bool compare_exchange_weak(shared_ptr<T>& expected, shared_ptr<T> desired,
2763
  memory_order success, memory_order failure) noexcept;
2764
+ constexpr bool compare_exchange_strong(shared_ptr<T>& expected, shared_ptr<T> desired,
2765
  memory_order success, memory_order failure) noexcept;
2766
  ```
2767
 
2768
+ *Preconditions:* `failure` is `memory_order::relaxed`,
2769
+ `memory_order::acquire`, or `memory_order::seq_cst`.
2770
 
2771
  *Effects:* If `p` is equivalent to `expected`, assigns `desired` to `p`
2772
  and has synchronization semantics corresponding to the value of
2773
  `success`, otherwise assigns `p` to `expected` and has synchronization
2774
  semantics corresponding to the value of `failure`.
 
2789
  corresponding to the write to `expected` is part of the atomic
2790
  operation. The write to `expected` itself is not required to be part of
2791
  the atomic operation.
2792
 
2793
  ``` cpp
2794
+ constexpr bool compare_exchange_weak(shared_ptr<T>& expected, shared_ptr<T> desired,
2795
  memory_order order = memory_order::seq_cst) noexcept;
2796
  ```
2797
 
2798
  *Effects:* Equivalent to:
2799
 
 
2805
  `memory_order::acq_rel` shall be replaced by the value
2806
  `memory_order::acquire` and a value of `memory_order::release` shall be
2807
  replaced by the value `memory_order::relaxed`.
2808
 
2809
  ``` cpp
2810
+ constexpr bool compare_exchange_strong(shared_ptr<T>& expected, shared_ptr<T> desired,
2811
  memory_order order = memory_order::seq_cst) noexcept;
2812
  ```
2813
 
2814
  *Effects:* Equivalent to:
2815
 
 
2821
  `memory_order::acq_rel` shall be replaced by the value
2822
  `memory_order::acquire` and a value of `memory_order::release` shall be
2823
  replaced by the value `memory_order::relaxed`.
2824
 
2825
  ``` cpp
2826
+ constexpr void wait(shared_ptr<T> old, memory_order order = memory_order::seq_cst) const noexcept;
2827
  ```
2828
 
2829
+ *Preconditions:* `order` is `memory_order::relaxed`,
2830
+ `memory_order::acquire`, or `memory_order::seq_cst`.
2831
 
2832
  *Effects:* Repeatedly performs the following steps, in order:
2833
 
2834
  - Evaluates `load(order)` and compares it to `old`.
2835
  - If the two are not equivalent, returns.
 
2839
  *Remarks:* Two `shared_ptr` objects are equivalent if they store the
2840
  same pointer and either share ownership or are both empty. This function
2841
  is an atomic waiting operation [[atomics.wait]].
2842
 
2843
  ``` cpp
2844
+ constexpr void notify_one() noexcept;
2845
  ```
2846
 
2847
  *Effects:* Unblocks the execution of at least one atomic waiting
2848
  operation that is eligible to be unblocked [[atomics.wait]] by this
2849
  call, if any such atomic waiting operations exist.
2850
 
2851
  *Remarks:* This function is an atomic notifying
2852
  operation [[atomics.wait]].
2853
 
2854
  ``` cpp
2855
+ constexpr void notify_all() noexcept;
2856
  ```
2857
 
2858
  *Effects:* Unblocks the execution of all atomic waiting operations that
2859
  are eligible to be unblocked [[atomics.wait]] by this call.
2860
 
 
2870
 
2871
  static constexpr bool is_always_lock_free = implementation-defined // whether a given atomic type's operations are always lock free;
2872
  bool is_lock_free() const noexcept;
2873
 
2874
  constexpr atomic() noexcept;
2875
+ constexpr atomic(weak_ptr<T> desired) noexcept;
2876
  atomic(const atomic&) = delete;
2877
  void operator=(const atomic&) = delete;
2878
 
2879
+ constexpr weak_ptr<T> load(memory_order order = memory_order::seq_cst) const noexcept;
2880
+ constexpr operator weak_ptr<T>() const noexcept;
2881
+ constexpr void store(weak_ptr<T> desired,
2882
+ memory_order order = memory_order::seq_cst) noexcept;
2883
+ constexpr void operator=(weak_ptr<T> desired) noexcept;
2884
 
2885
+ constexpr weak_ptr<T> exchange(weak_ptr<T> desired,
2886
  memory_order order = memory_order::seq_cst) noexcept;
2887
+ constexpr bool compare_exchange_weak(weak_ptr<T>& expected, weak_ptr<T> desired,
2888
  memory_order success, memory_order failure) noexcept;
2889
+ constexpr bool compare_exchange_strong(weak_ptr<T>& expected, weak_ptr<T> desired,
2890
  memory_order success, memory_order failure) noexcept;
2891
+ constexpr bool compare_exchange_weak(weak_ptr<T>& expected, weak_ptr<T> desired,
2892
  memory_order order = memory_order::seq_cst) noexcept;
2893
+ constexpr bool compare_exchange_strong(weak_ptr<T>& expected, weak_ptr<T> desired,
2894
  memory_order order = memory_order::seq_cst) noexcept;
2895
 
2896
+ constexpr void wait(weak_ptr<T> old,
2897
+ memory_order order = memory_order::seq_cst) const noexcept;
2898
+ constexpr void notify_one() noexcept;
2899
+ constexpr void notify_all() noexcept;
2900
 
2901
  private:
2902
  weak_ptr<T> p; // exposition only
2903
  };
2904
  }
 
2906
 
2907
  ``` cpp
2908
  constexpr atomic() noexcept;
2909
  ```
2910
 
2911
+ *Effects:* Value-initializes `p`.
2912
 
2913
  ``` cpp
2914
+ constexpr atomic(weak_ptr<T> desired) noexcept;
2915
  ```
2916
 
2917
  *Effects:* Initializes the object with the value `desired`.
2918
  Initialization is not an atomic operation [[intro.multithread]].
2919
 
 
2923
  `memory_order::relaxed` operations on a suitable atomic pointer
2924
  variable, and then immediately accessing `A` in the receiving thread.
2925
  This results in undefined behavior. — *end note*]
2926
 
2927
  ``` cpp
2928
+ constexpr void store(weak_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept;
2929
  ```
2930
 
2931
+ *Preconditions:* `order` is `memory_order::relaxed`,
2932
+ `memory_order::release`, or `memory_order::seq_cst`.
2933
 
2934
  *Effects:* Atomically replaces the value pointed to by `this` with the
2935
  value of `desired` as if by `p.swap(desired)`. Memory is affected
2936
  according to the value of `order`.
2937
 
2938
  ``` cpp
2939
+ constexpr void operator=(weak_ptr<T> desired) noexcept;
2940
  ```
2941
 
2942
  *Effects:* Equivalent to `store(desired)`.
2943
 
2944
  ``` cpp
2945
+ constexpr weak_ptr<T> load(memory_order order = memory_order::seq_cst) const noexcept;
2946
  ```
2947
 
2948
+ *Preconditions:* `order` is `memory_order::relaxed`,
2949
+ `memory_order::acquire`, or `memory_order::seq_cst`.
2950
 
2951
  *Effects:* Memory is affected according to the value of `order`.
2952
 
2953
  *Returns:* Atomically returns `p`.
2954
 
2955
  ``` cpp
2956
+ constexpr operator weak_ptr<T>() const noexcept;
2957
  ```
2958
 
2959
  *Effects:* Equivalent to: `return load();`
2960
 
2961
  ``` cpp
2962
+ constexpr weak_ptr<T> exchange(weak_ptr<T> desired,
2963
+ memory_order order = memory_order::seq_cst) noexcept;
2964
  ```
2965
 
2966
  *Effects:* Atomically replaces `p` with `desired` as if by
2967
  `p.swap(desired)`. Memory is affected according to the value of `order`.
2968
  This is an atomic read-modify-write operation [[intro.races]].
2969
 
2970
  *Returns:* Atomically returns the value of `p` immediately before the
2971
  effects.
2972
 
2973
  ``` cpp
2974
+ constexpr bool compare_exchange_weak(weak_ptr<T>& expected, weak_ptr<T> desired,
2975
  memory_order success, memory_order failure) noexcept;
2976
+ constexpr bool compare_exchange_strong(weak_ptr<T>& expected, weak_ptr<T> desired,
2977
  memory_order success, memory_order failure) noexcept;
2978
  ```
2979
 
2980
+ *Preconditions:* `failure` is `memory_order::relaxed`,
2981
+ `memory_order::acquire`, or `memory_order::seq_cst`.
2982
 
2983
  *Effects:* If `p` is equivalent to `expected`, assigns `desired` to `p`
2984
  and has synchronization semantics corresponding to the value of
2985
  `success`, otherwise assigns `p` to `expected` and has synchronization
2986
  semantics corresponding to the value of `failure`.
 
3001
  corresponding to the write to `expected` is part of the atomic
3002
  operation. The write to `expected` itself is not required to be part of
3003
  the atomic operation.
3004
 
3005
  ``` cpp
3006
+ constexpr bool compare_exchange_weak(weak_ptr<T>& expected, weak_ptr<T> desired,
3007
  memory_order order = memory_order::seq_cst) noexcept;
3008
  ```
3009
 
3010
  *Effects:* Equivalent to:
3011
 
 
3017
  `memory_order::acq_rel` shall be replaced by the value
3018
  `memory_order::acquire` and a value of `memory_order::release` shall be
3019
  replaced by the value `memory_order::relaxed`.
3020
 
3021
  ``` cpp
3022
+ constexpr bool compare_exchange_strong(weak_ptr<T>& expected, weak_ptr<T> desired,
3023
  memory_order order = memory_order::seq_cst) noexcept;
3024
  ```
3025
 
3026
  *Effects:* Equivalent to:
3027
 
 
3033
  `memory_order::acq_rel` shall be replaced by the value
3034
  `memory_order::acquire` and a value of `memory_order::release` shall be
3035
  replaced by the value `memory_order::relaxed`.
3036
 
3037
  ``` cpp
3038
+ constexpr void wait(weak_ptr<T> old, memory_order order = memory_order::seq_cst) const noexcept;
3039
  ```
3040
 
3041
+ *Preconditions:* `order` is `memory_order::relaxed`,
3042
+ `memory_order::acquire`, or `memory_order::seq_cst`.
3043
 
3044
  *Effects:* Repeatedly performs the following steps, in order:
3045
 
3046
  - Evaluates `load(order)` and compares it to `old`.
3047
  - If the two are not equivalent, returns.
 
3051
  *Remarks:* Two `weak_ptr` objects are equivalent if they store the same
3052
  pointer and either share ownership or are both empty. This function is
3053
  an atomic waiting operation [[atomics.wait]].
3054
 
3055
  ``` cpp
3056
+ constexpr void notify_one() noexcept;
3057
  ```
3058
 
3059
  *Effects:* Unblocks the execution of at least one atomic waiting
3060
  operation that is eligible to be unblocked [[atomics.wait]] by this
3061
  call, if any such atomic waiting operations exist.
3062
 
3063
  *Remarks:* This function is an atomic notifying
3064
  operation [[atomics.wait]].
3065
 
3066
  ``` cpp
3067
+ constexpr void notify_all() noexcept;
3068
  ```
3069
 
3070
  *Effects:* Unblocks the execution of all atomic waiting operations that
3071
  are eligible to be unblocked [[atomics.wait]] by this call.
3072
 
 
3097
  atomic_flag(const atomic_flag&) = delete;
3098
  atomic_flag& operator=(const atomic_flag&) = delete;
3099
  atomic_flag& operator=(const atomic_flag&) volatile = delete;
3100
 
3101
  bool test(memory_order = memory_order::seq_cst) const volatile noexcept;
3102
+ constexpr bool test(memory_order = memory_order::seq_cst) const noexcept;
3103
  bool test_and_set(memory_order = memory_order::seq_cst) volatile noexcept;
3104
+ constexpr bool test_and_set(memory_order = memory_order::seq_cst) noexcept;
3105
  void clear(memory_order = memory_order::seq_cst) volatile noexcept;
3106
+ constexpr void clear(memory_order = memory_order::seq_cst) noexcept;
3107
 
3108
  void wait(bool, memory_order = memory_order::seq_cst) const volatile noexcept;
3109
+ constexpr void wait(bool, memory_order = memory_order::seq_cst) const noexcept;
3110
  void notify_one() volatile noexcept;
3111
+ constexpr void notify_one() noexcept;
3112
  void notify_all() volatile noexcept;
3113
+ constexpr void notify_all() noexcept;
3114
  };
3115
  }
3116
  ```
3117
 
3118
  The `atomic_flag` type provides the classic test-and-set functionality.
 
3130
 
3131
  *Effects:* Initializes `*this` to the clear state.
3132
 
3133
  ``` cpp
3134
  bool atomic_flag_test(const volatile atomic_flag* object) noexcept;
3135
+ constexpr bool atomic_flag_test(const atomic_flag* object) noexcept;
3136
  bool atomic_flag_test_explicit(const volatile atomic_flag* object,
3137
  memory_order order) noexcept;
3138
+ constexpr bool atomic_flag_test_explicit(const atomic_flag* object,
3139
  memory_order order) noexcept;
3140
  bool atomic_flag::test(memory_order order = memory_order::seq_cst) const volatile noexcept;
3141
+ constexpr bool atomic_flag::test(memory_order order = memory_order::seq_cst) const noexcept;
3142
  ```
3143
 
3144
  For `atomic_flag_test`, let `order` be `memory_order::seq_cst`.
3145
 
3146
+ *Preconditions:* `order` is `memory_order::relaxed`,
3147
+ `memory_order::acquire`, or `memory_order::seq_cst`.
3148
 
3149
  *Effects:* Memory is affected according to the value of `order`.
3150
 
3151
  *Returns:* Atomically returns the value pointed to by `object` or
3152
  `this`.
3153
 
3154
  ``` cpp
3155
  bool atomic_flag_test_and_set(volatile atomic_flag* object) noexcept;
3156
+ constexpr bool atomic_flag_test_and_set(atomic_flag* object) noexcept;
3157
  bool atomic_flag_test_and_set_explicit(volatile atomic_flag* object, memory_order order) noexcept;
3158
+ constexpr bool atomic_flag_test_and_set_explicit(atomic_flag* object, memory_order order) noexcept;
3159
  bool atomic_flag::test_and_set(memory_order order = memory_order::seq_cst) volatile noexcept;
3160
+ constexpr bool atomic_flag::test_and_set(memory_order order = memory_order::seq_cst) noexcept;
3161
  ```
3162
 
3163
  *Effects:* Atomically sets the value pointed to by `object` or by `this`
3164
  to `true`. Memory is affected according to the value of `order`. These
3165
  operations are atomic read-modify-write
 
3168
  *Returns:* Atomically, the value of the object immediately before the
3169
  effects.
3170
 
3171
  ``` cpp
3172
  void atomic_flag_clear(volatile atomic_flag* object) noexcept;
3173
+ constexpr void atomic_flag_clear(atomic_flag* object) noexcept;
3174
  void atomic_flag_clear_explicit(volatile atomic_flag* object, memory_order order) noexcept;
3175
+ constexpr void atomic_flag_clear_explicit(atomic_flag* object, memory_order order) noexcept;
3176
  void atomic_flag::clear(memory_order order = memory_order::seq_cst) volatile noexcept;
3177
+ constexpr void atomic_flag::clear(memory_order order = memory_order::seq_cst) noexcept;
3178
  ```
3179
 
3180
+ *Preconditions:* `order` is `memory_order::relaxed`,
3181
+ `memory_order::release`, or `memory_order::seq_cst`.
 
3182
 
3183
  *Effects:* Atomically sets the value pointed to by `object` or by `this`
3184
  to `false`. Memory is affected according to the value of `order`.
3185
 
3186
  ``` cpp
3187
  void atomic_flag_wait(const volatile atomic_flag* object, bool old) noexcept;
3188
+ constexpr void atomic_flag_wait(const atomic_flag* object, bool old) noexcept;
3189
  void atomic_flag_wait_explicit(const volatile atomic_flag* object,
3190
  bool old, memory_order order) noexcept;
3191
+ constexpr void atomic_flag_wait_explicit(const atomic_flag* object,
3192
  bool old, memory_order order) noexcept;
3193
  void atomic_flag::wait(bool old, memory_order order =
3194
  memory_order::seq_cst) const volatile noexcept;
3195
+ constexpr void atomic_flag::wait(bool old, memory_order order =
3196
  memory_order::seq_cst) const noexcept;
3197
  ```
3198
 
3199
  For `atomic_flag_wait`, let `order` be `memory_order::seq_cst`. Let
3200
  `flag` be `object` for the non-member functions and `this` for the
3201
  member functions.
3202
 
3203
+ *Preconditions:* `order` is `memory_order::relaxed`,
3204
+ `memory_order::acquire`, or `memory_order::seq_cst`.
3205
 
3206
  *Effects:* Repeatedly performs the following steps, in order:
3207
 
3208
  - Evaluates `flag->test(order) != old`.
3209
  - If the result of that evaluation is `true`, returns.
 
3213
  *Remarks:* This function is an atomic waiting
3214
  operation [[atomics.wait]].
3215
 
3216
  ``` cpp
3217
  void atomic_flag_notify_one(volatile atomic_flag* object) noexcept;
3218
+ constexpr void atomic_flag_notify_one(atomic_flag* object) noexcept;
3219
  void atomic_flag::notify_one() volatile noexcept;
3220
+ constexpr void atomic_flag::notify_one() noexcept;
3221
  ```
3222
 
3223
  *Effects:* Unblocks the execution of at least one atomic waiting
3224
  operation that is eligible to be unblocked [[atomics.wait]] by this
3225
  call, if any such atomic waiting operations exist.
 
3227
  *Remarks:* This function is an atomic notifying
3228
  operation [[atomics.wait]].
3229
 
3230
  ``` cpp
3231
  void atomic_flag_notify_all(volatile atomic_flag* object) noexcept;
3232
+ constexpr void atomic_flag_notify_all(atomic_flag* object) noexcept;
3233
  void atomic_flag::notify_all() volatile noexcept;
3234
+ constexpr void atomic_flag::notify_all() noexcept;
3235
  ```
3236
 
3237
  *Effects:* Unblocks the execution of all atomic waiting operations that
3238
  are eligible to be unblocked [[atomics.wait]] by this call.
3239
 
 
3262
  Fences can have acquire semantics, release semantics, or both. A fence
3263
  with acquire semantics is called an *acquire fence*. A fence with
3264
  release semantics is called a *release fence*.
3265
 
3266
  A release fence A synchronizes with an acquire fence B if there exist
3267
+ atomic operations X and Y, where Y is not an atomic modify-write
3268
+ operation [[atomics.order]], both operating on some atomic object M,
3269
+ such that A is sequenced before X, X modifies M, Y is sequenced before
3270
+ B, and Y reads the value written by X or a value written by any side
3271
+ effect in the hypothetical release sequence X would head if it were a
3272
+ release operation.
3273
 
3274
  A release fence A synchronizes with an atomic operation B that performs
3275
  an acquire operation on an atomic object M if there exists an atomic
3276
  operation X such that A is sequenced before X, X modifies M, and B reads
3277
  the value written by X or a value written by any side effect in the
 
3283
  operation X on M such that X is sequenced before B and reads the value
3284
  written by A or a value written by any side effect in the release
3285
  sequence headed by A.
3286
 
3287
  ``` cpp
3288
+ extern "C" constexpr void atomic_thread_fence(memory_order order) noexcept;
3289
  ```
3290
 
3291
  *Effects:* Depending on the value of `order`, this operation:
3292
 
3293
  - has no effects, if `order == memory_order::relaxed`;
3294
+ - is an acquire fence, if `order == memory_order::acquire`;
 
3295
  - is a release fence, if `order == memory_order::release`;
3296
  - is both an acquire fence and a release fence, if
3297
  `order == memory_order::acq_rel`;
3298
  - is a sequentially consistent acquire and release fence, if
3299
  `order == memory_order::seq_cst`.
3300
 
3301
  ``` cpp
3302
+ extern "C" constexpr void atomic_signal_fence(memory_order order) noexcept;
3303
  ```
3304
 
3305
  *Effects:* Equivalent to `atomic_thread_fence(order)`, except that the
3306
  resulting ordering constraints are established only between a thread and
3307
  a signal handler executed in the same thread.