From Jason Turner

[atomics.types.generic]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmpf15hb7gm/{from.md → to.md} +164 -140
tmp/tmpf15hb7gm/{from.md → to.md} RENAMED
@@ -1,6 +1,8 @@
1
- ## Class template `atomic` <a id="atomics.types.generic">[[atomics.types.generic]]</a>
 
 
2
 
3
  ``` cpp
4
  namespace std {
5
  template<class T> struct atomic {
6
  using value_type = T;
@@ -57,19 +59,19 @@ of
57
  - `is_move_assignable_v<T>`
58
 
59
  is `false`.
60
 
61
  [*Note 1*: Type arguments that are not also statically initializable
62
- may be difficult to use. — *end note*]
63
 
64
  The specialization `atomic<bool>` is a standard-layout struct.
65
 
66
  [*Note 2*: The representation of an atomic specialization need not have
67
  the same size and alignment requirement as its corresponding argument
68
  type. — *end note*]
69
 
70
- ### Operations on atomic types <a id="atomics.types.operations">[[atomics.types.operations]]</a>
71
 
72
  ``` cpp
73
  constexpr atomic() noexcept(is_nothrow_default_constructible_v<T>);
74
  ```
75
 
@@ -118,17 +120,17 @@ type. — *end note*]
118
  ``` cpp
119
  void store(T desired, memory_order order = memory_order::seq_cst) volatile noexcept;
120
  void store(T desired, memory_order order = memory_order::seq_cst) noexcept;
121
  ```
122
 
 
 
 
123
  *Preconditions:* The `order` argument is neither
124
  `memory_order::consume`, `memory_order::acquire`, nor
125
  `memory_order::acq_rel`.
126
 
127
- *Constraints:* For the `volatile` overload of this function,
128
- `is_always_lock_free` is `true`.
129
-
130
  *Effects:* Atomically replaces the value pointed to by `this` with the
131
  value of `desired`. Memory is affected according to the value of
132
  `order`.
133
 
134
  ``` cpp
@@ -146,16 +148,16 @@ T operator=(T desired) noexcept;
146
  ``` cpp
147
  T load(memory_order order = memory_order::seq_cst) const volatile noexcept;
148
  T load(memory_order order = memory_order::seq_cst) const noexcept;
149
  ```
150
 
 
 
 
151
  *Preconditions:* The `order` argument is neither `memory_order::release`
152
  nor `memory_order::acq_rel`.
153
 
154
- *Constraints:* For the `volatile` overload of this function,
155
- `is_always_lock_free` is `true`.
156
-
157
  *Effects:* Memory is affected according to the value of `order`.
158
 
159
  *Returns:* Atomically returns the value pointed to by `this`.
160
 
161
  ``` cpp
@@ -201,16 +203,16 @@ bool compare_exchange_strong(T& expected, T desired,
201
  memory_order order = memory_order::seq_cst) volatile noexcept;
202
  bool compare_exchange_strong(T& expected, T desired,
203
  memory_order order = memory_order::seq_cst) noexcept;
204
  ```
205
 
 
 
 
206
  *Preconditions:* The `failure` argument is neither
207
  `memory_order::release` nor `memory_order::acq_rel`.
208
 
209
- *Constraints:* For the `volatile` overload of this function,
210
- `is_always_lock_free` is `true`.
211
-
212
  *Effects:* Retrieves the value in `expected`. It then atomically
213
  compares the value representation of the value pointed to by `this` for
214
  equality with that previously retrieved from `expected`, and if true,
215
  replaces the value pointed to by `this` with that in `desired`. If and
216
  only if the comparison is `true`, memory is affected according to the
@@ -230,17 +232,17 @@ Otherwise, these operations are atomic load operations on that memory.
230
  *Returns:* The result of the comparison.
231
 
232
  [*Note 4*:
233
 
234
  For example, the effect of `compare_exchange_strong` on objects without
235
- padding bits [[basic.types]] is
236
 
237
  ``` cpp
238
  if (memcmp(this, &expected, sizeof(*this)) == 0)
239
  memcpy(this, &desired, sizeof(*this));
240
  else
241
- memcpy(expected, this, sizeof(*this));
242
  ```
243
 
244
  — *end note*]
245
 
246
  [*Example 1*:
@@ -291,17 +293,17 @@ compare-and-exchange is in a loop, the weak version will yield better
291
  performance on some platforms. When a weak compare-and-exchange would
292
  require a loop and a strong one would not, the strong one is
293
  preferable. — *end note*]
294
 
295
  [*Note 6*: Under cases where the `memcpy` and `memcmp` semantics of the
296
- compare-and-exchange operations apply, the outcome might be failed
297
- comparisons for values that compare equal with `operator==` if the value
298
- representation has trap bits or alternate representations of the same
299
- value. Notably, on implementations conforming to ISO/IEC/IEEE 60559,
300
- floating-point `-0.0` and `+0.0` will not compare equal with `memcmp`
301
- but will compare equal with `operator==`, and NaNs with the same payload
302
- will compare equal with `memcmp` but will not compare equal with
303
  `operator==`. — *end note*]
304
 
305
  [*Note 7*:
306
 
307
  Because compare-and-exchange acts on an object’s value representation,
@@ -388,100 +390,112 @@ void notify_all() noexcept;
388
  are eligible to be unblocked [[atomics.wait]] by this call.
389
 
390
  *Remarks:* This function is an atomic notifying
391
  operation [[atomics.wait]].
392
 
393
- ### Specializations for integers <a id="atomics.types.int">[[atomics.types.int]]</a>
394
 
395
  There are specializations of the `atomic` class template for the
396
  integral types `char`, `signed char`, `unsigned char`, `short`,
397
  `unsigned short`, `int`, `unsigned int`, `long`, `unsigned long`,
398
  `long long`, `unsigned long long`, `char8_t`, `char16_t`, `char32_t`,
399
  `wchar_t`, and any other types needed by the typedefs in the header
400
- `<cstdint>`. For each such type `integral`, the specialization
401
- `atomic<integral>` provides additional atomic operations appropriate to
402
- integral types.
403
 
404
  [*Note 1*: The specialization `atomic<bool>` uses the primary template
405
  [[atomics.types.generic]]. — *end note*]
406
 
407
  ``` cpp
408
  namespace std {
409
- template<> struct atomic<integral> {
410
- using value_type = integral;
411
  using difference_type = value_type;
412
 
413
  static constexpr bool is_always_lock_free = implementation-defined // whether a given atomic type's operations are always lock free;
414
  bool is_lock_free() const volatile noexcept;
415
  bool is_lock_free() const noexcept;
416
 
417
  constexpr atomic() noexcept;
418
- constexpr atomic(integral) noexcept;
419
  atomic(const atomic&) = delete;
420
  atomic& operator=(const atomic&) = delete;
421
  atomic& operator=(const atomic&) volatile = delete;
422
 
423
- void store(integral, memory_order = memory_order::seq_cst) volatile noexcept;
424
- void store(integral, memory_order = memory_order::seq_cst) noexcept;
425
- integral operator=(integral) volatile noexcept;
426
- integral operator=(integral) noexcept;
427
- integral load(memory_order = memory_order::seq_cst) const volatile noexcept;
428
- integral load(memory_order = memory_order::seq_cst) const noexcept;
429
- operator integral() const volatile noexcept;
430
- operator integral() const noexcept;
431
 
432
- integral exchange(integral, memory_order = memory_order::seq_cst) volatile noexcept;
433
- integral exchange(integral, memory_order = memory_order::seq_cst) noexcept;
434
- bool compare_exchange_weak(integral&, integral,
 
 
435
  memory_order, memory_order) volatile noexcept;
436
- bool compare_exchange_weak(integral&, integral,
437
  memory_order, memory_order) noexcept;
438
- bool compare_exchange_strong(integral&, integral,
439
  memory_order, memory_order) volatile noexcept;
440
- bool compare_exchange_strong(integral&, integral,
441
  memory_order, memory_order) noexcept;
442
- bool compare_exchange_weak(integral&, integral,
443
  memory_order = memory_order::seq_cst) volatile noexcept;
444
- bool compare_exchange_weak(integral&, integral,
445
  memory_order = memory_order::seq_cst) noexcept;
446
- bool compare_exchange_strong(integral&, integral,
447
  memory_order = memory_order::seq_cst) volatile noexcept;
448
- bool compare_exchange_strong(integral&, integral,
449
  memory_order = memory_order::seq_cst) noexcept;
450
 
451
- integral fetch_add(integral, memory_order = memory_order::seq_cst) volatile noexcept;
452
- integral fetch_add(integral, memory_order = memory_order::seq_cst) noexcept;
453
- integral fetch_sub(integral, memory_order = memory_order::seq_cst) volatile noexcept;
454
- integral fetch_sub(integral, memory_order = memory_order::seq_cst) noexcept;
455
- integral fetch_and(integral, memory_order = memory_order::seq_cst) volatile noexcept;
456
- integral fetch_and(integral, memory_order = memory_order::seq_cst) noexcept;
457
- integral fetch_or(integral, memory_order = memory_order::seq_cst) volatile noexcept;
458
- integral fetch_or(integral, memory_order = memory_order::seq_cst) noexcept;
459
- integral fetch_xor(integral, memory_order = memory_order::seq_cst) volatile noexcept;
460
- integral fetch_xor(integral, memory_order = memory_order::seq_cst) noexcept;
 
 
 
 
 
 
 
 
 
 
461
 
462
- integral operator++(int) volatile noexcept;
463
- integral operator++(int) noexcept;
464
- integral operator--(int) volatile noexcept;
465
- integral operator--(int) noexcept;
466
- integral operator++() volatile noexcept;
467
- integral operator++() noexcept;
468
- integral operator--() volatile noexcept;
469
- integral operator--() noexcept;
470
- integral operator+=(integral) volatile noexcept;
471
- integral operator+=(integral) noexcept;
472
- integral operator-=(integral) volatile noexcept;
473
- integral operator-=(integral) noexcept;
474
- integral operator&=(integral) volatile noexcept;
475
- integral operator&=(integral) noexcept;
476
- integral operator|=(integral) volatile noexcept;
477
- integral operator|=(integral) noexcept;
478
- integral operator^=(integral) volatile noexcept;
479
- integral operator^=(integral) noexcept;
480
 
481
- void wait(integral, memory_order = memory_order::seq_cst) const volatile noexcept;
482
- void wait(integral, memory_order = memory_order::seq_cst) const noexcept;
483
  void notify_one() volatile noexcept;
484
  void notify_one() noexcept;
485
  void notify_all() volatile noexcept;
486
  void notify_all() noexcept;
487
  };
@@ -492,12 +506,13 @@ The atomic integral specializations are standard-layout structs. They
492
  each have a trivial destructor.
493
 
494
  Descriptions are provided below only for members that differ from the
495
  primary template.
496
 
497
- The following operations perform arithmetic computations. The key,
498
- operator, and computation correspondence is:
 
499
 
500
  **Table: Atomic arithmetic computations** <a id="atomic.types.int.comp">[atomic.types.int.comp]</a>
501
 
502
  | | | | | | |
503
  | ----- | --- | -------------------- | ----- | --- | -------------------- |
@@ -539,80 +554,80 @@ T operator op=(T operand) noexcept;
539
  `is_always_lock_free` is `true`.
540
 
541
  *Effects:* Equivalent to:
542
  `return fetch_`*`key`*`(operand) `*`op`*` operand;`
543
 
544
- ### Specializations for floating-point types <a id="atomics.types.float">[[atomics.types.float]]</a>
545
 
546
- There are specializations of the `atomic` class template for the
547
- floating-point types `float`, `double`, and `long double`. For each such
548
- type `floating-point`, the specialization `atomic<floating-point>`
549
  provides additional atomic operations appropriate to floating-point
550
  types.
551
 
552
  ``` cpp
553
  namespace std {
554
- template<> struct atomic<floating-point> {
555
- using value_type = floating-point;
556
  using difference_type = value_type;
557
 
558
  static constexpr bool is_always_lock_free = implementation-defined // whether a given atomic type's operations are always lock free;
559
  bool is_lock_free() const volatile noexcept;
560
  bool is_lock_free() const noexcept;
561
 
562
  constexpr atomic() noexcept;
563
- constexpr atomic(floating-point) noexcept;
564
  atomic(const atomic&) = delete;
565
  atomic& operator=(const atomic&) = delete;
566
  atomic& operator=(const atomic&) volatile = delete;
567
 
568
- void store(floating-point, memory_order = memory_order::seq_cst) volatile noexcept;
569
- void store(floating-point, memory_order = memory_order::seq_cst) noexcept;
570
- floating-point operator=(floating-point) volatile noexcept;
571
- floating-point operator=(floating-point) noexcept;
572
- floating-point load(memory_order = memory_order::seq_cst) volatile noexcept;
573
- floating-point load(memory_order = memory_order::seq_cst) noexcept;
574
- operator floating-point() volatile noexcept;
575
- operator floating-point() noexcept;
576
 
577
- floating-point exchange(floating-point,
578
  memory_order = memory_order::seq_cst) volatile noexcept;
579
- floating-point exchange(floating-point,
580
  memory_order = memory_order::seq_cst) noexcept;
581
- bool compare_exchange_weak(floating-point&, floating-point,
582
  memory_order, memory_order) volatile noexcept;
583
- bool compare_exchange_weak(floating-point&, floating-point,
584
  memory_order, memory_order) noexcept;
585
- bool compare_exchange_strong(floating-point&, floating-point,
586
  memory_order, memory_order) volatile noexcept;
587
- bool compare_exchange_strong(floating-point&, floating-point,
588
  memory_order, memory_order) noexcept;
589
- bool compare_exchange_weak(floating-point&, floating-point,
590
  memory_order = memory_order::seq_cst) volatile noexcept;
591
- bool compare_exchange_weak(floating-point&, floating-point,
592
  memory_order = memory_order::seq_cst) noexcept;
593
- bool compare_exchange_strong(floating-point&, floating-point,
594
  memory_order = memory_order::seq_cst) volatile noexcept;
595
- bool compare_exchange_strong(floating-point&, floating-point,
596
  memory_order = memory_order::seq_cst) noexcept;
597
 
598
- floating-point fetch_add(floating-point,
599
  memory_order = memory_order::seq_cst) volatile noexcept;
600
- floating-point fetch_add(floating-point,
601
  memory_order = memory_order::seq_cst) noexcept;
602
- floating-point fetch_sub(floating-point,
603
  memory_order = memory_order::seq_cst) volatile noexcept;
604
- floating-point fetch_sub(floating-point,
605
  memory_order = memory_order::seq_cst) noexcept;
606
 
607
- floating-point operator+=(floating-point) volatile noexcept;
608
- floating-point operator+=(floating-point) noexcept;
609
- floating-point operator-=(floating-point) volatile noexcept;
610
- floating-point operator-=(floating-point) noexcept;
611
 
612
- void wait(floating-point, memory_order = memory_order::seq_cst) const volatile noexcept;
613
- void wait(floating-point, memory_order = memory_order::seq_cst) const noexcept;
614
  void notify_one() volatile noexcept;
615
  void notify_one() noexcept;
616
  void notify_all() volatile noexcept;
617
  void notify_all() noexcept;
618
  };
@@ -624,12 +639,12 @@ They each have a trivial destructor.
624
 
625
  Descriptions are provided below only for members that differ from the
626
  primary template.
627
 
628
  The following operations perform arithmetic addition and subtraction
629
- computations. The key, operator, and computation correspondence are
630
- identified in [[atomic.types.int.comp]].
631
 
632
  ``` cpp
633
  T fetch_key(T operand, memory_order order = memory_order::seq_cst) volatile noexcept;
634
  T fetch_key(T operand, memory_order order = memory_order::seq_cst) noexcept;
635
  ```
@@ -647,15 +662,15 @@ operations [[intro.multithread]].
647
  the effects.
648
 
649
  *Remarks:* If the result is not a representable value for its
650
  type [[expr.pre]] the result is unspecified, but the operations
651
  otherwise have no undefined behavior. Atomic arithmetic operations on
652
- *`floating-point`* should conform to the
653
- `std::numeric_limits<`*`floating-point`*`>` traits associated with the
654
- floating-point type [[limits.syn]]. The floating-point
655
  environment [[cfenv]] for atomic arithmetic operations on
656
- *`floating-point`* may be different than the calling thread’s
657
  floating-point environment.
658
 
659
  ``` cpp
660
  T operator op=(T operand) volatile noexcept;
661
  T operator op=(T operand) noexcept;
@@ -668,18 +683,18 @@ T operator op=(T operand) noexcept;
668
  `return fetch_`*`key`*`(operand) `*`op`*` operand;`
669
 
670
  *Remarks:* If the result is not a representable value for its
671
  type [[expr.pre]] the result is unspecified, but the operations
672
  otherwise have no undefined behavior. Atomic arithmetic operations on
673
- *`floating-point`* should conform to the
674
- `std::numeric_limits<`*`floating-point`*`>` traits associated with the
675
- floating-point type [[limits.syn]]. The floating-point
676
  environment [[cfenv]] for atomic arithmetic operations on
677
- *`floating-point`* may be different than the calling thread’s
678
  floating-point environment.
679
 
680
- ### Partial specialization for pointers <a id="atomics.types.pointer">[[atomics.types.pointer]]</a>
681
 
682
  ``` cpp
683
  namespace std {
684
  template<class T> struct atomic<T*> {
685
  using value_type = T*;
@@ -752,12 +767,13 @@ pointers. Specializations of this partial specialization are
752
  standard-layout structs. They each have a trivial destructor.
753
 
754
  Descriptions are provided below only for members that differ from the
755
  primary template.
756
 
757
- The following operations perform pointer arithmetic. The key, operator,
758
- and computation correspondence is:
 
759
 
760
  **Table: Atomic pointer computations** <a id="atomic.types.pointer.comp">[atomic.types.pointer.comp]</a>
761
 
762
  | | | | | | |
763
  | ----- | --- | -------- | ----- | --- | ----------- |
@@ -797,11 +813,11 @@ T* operator op=(ptrdiff_t operand) noexcept;
797
  `is_always_lock_free` is `true`.
798
 
799
  *Effects:* Equivalent to:
800
  `return fetch_`*`key`*`(operand) `*`op`*` operand;`
801
 
802
- ### Member operators common to integers and pointers to objects <a id="atomics.types.memop">[[atomics.types.memop]]</a>
803
 
804
  ``` cpp
805
  value_type operator++(int) volatile noexcept;
806
  value_type operator++(int) noexcept;
807
  ```
@@ -839,26 +855,33 @@ value_type operator--() noexcept;
839
  *Constraints:* For the `volatile` overload of this function,
840
  `is_always_lock_free` is `true`.
841
 
842
  *Effects:* Equivalent to: `return fetch_sub(1) - 1;`
843
 
844
- ### Partial specializations for smart pointers <a id="util.smartptr.atomic">[[util.smartptr.atomic]]</a>
 
 
845
 
846
  The library provides partial specializations of the `atomic` template
847
- for shared-ownership smart pointers [[smartptr]]. The behavior of all
848
- operations is as specified in [[atomics.types.generic]], unless
849
- specified otherwise. The template parameter `T` of these partial
850
- specializations may be an incomplete type.
851
 
852
- All changes to an atomic smart pointer in this subclause, and all
853
- associated `use_count` increments, are guaranteed to be performed
 
 
 
 
 
 
 
 
854
  atomically. Associated `use_count` decrements are sequenced after the
855
  atomic operation, but are not required to be part of it. Any associated
856
  deletion and deallocation are sequenced after the atomic update step and
857
  are not part of the atomic operation.
858
 
859
- [*Note 1*: If the atomic operation uses locks, locks acquired by the
860
  implementation will be held when any `use_count` adjustments are
861
  performed, and will not be held when any destruction or deallocation
862
  resulting from this is performed. — *end note*]
863
 
864
  [*Example 1*:
@@ -870,16 +893,16 @@ template<typename T> class atomic_list {
870
  shared_ptr<node> next;
871
  };
872
  atomic<shared_ptr<node>> head;
873
 
874
  public:
875
- auto find(T t) const {
876
  auto p = head.load();
877
  while (p && p->t != t)
878
  p = p->next;
879
 
880
- return shared_ptr<node>(move(p));
881
  }
882
 
883
  void push_front(T t) {
884
  auto p = make_shared<node>();
885
  p->t = t;
@@ -889,21 +912,22 @@ public:
889
  };
890
  ```
891
 
892
  — *end example*]
893
 
894
- #### Partial specialization for `shared_ptr` <a id="util.smartptr.atomic.shared">[[util.smartptr.atomic.shared]]</a>
895
 
896
  ``` cpp
897
  namespace std {
898
  template<class T> struct atomic<shared_ptr<T>> {
899
  using value_type = shared_ptr<T>;
900
 
901
  static constexpr bool is_always_lock_free = implementation-defined // whether a given atomic type's operations are always lock free;
902
  bool is_lock_free() const noexcept;
903
 
904
  constexpr atomic() noexcept;
 
905
  atomic(shared_ptr<T> desired) noexcept;
906
  atomic(const atomic&) = delete;
907
  void operator=(const atomic&) = delete;
908
 
909
  shared_ptr<T> load(memory_order order = memory_order::seq_cst) const noexcept;
@@ -1098,11 +1122,11 @@ void notify_all() noexcept;
1098
  are eligible to be unblocked [[atomics.wait]] by this call.
1099
 
1100
  *Remarks:* This function is an atomic notifying
1101
  operation [[atomics.wait]].
1102
 
1103
- #### Partial specialization for `weak_ptr` <a id="util.smartptr.atomic.weak">[[util.smartptr.atomic.weak]]</a>
1104
 
1105
  ``` cpp
1106
  namespace std {
1107
  template<class T> struct atomic<weak_ptr<T>> {
1108
  using value_type = weak_ptr<T>;
@@ -1152,11 +1176,11 @@ atomic(weak_ptr<T> desired) noexcept;
1152
  ```
1153
 
1154
  *Effects:* Initializes the object with the value `desired`.
1155
  Initialization is not an atomic operation [[intro.multithread]].
1156
 
1157
- [*Note 1*: It is possible to have an access to an atomic object `A`
1158
  race with its construction, for example, by communicating the address of
1159
  the just-constructed object `A` to another thread via
1160
  `memory_order::relaxed` operations on a suitable atomic pointer
1161
  variable, and then immediately accessing `A` in the receiving thread.
1162
  This results in undefined behavior. — *end note*]
 
1
+ ### Class template `atomic` <a id="atomics.types.generic">[[atomics.types.generic]]</a>
2
+
3
+ #### General <a id="atomics.types.generic.general">[[atomics.types.generic.general]]</a>
4
 
5
  ``` cpp
6
  namespace std {
7
  template<class T> struct atomic {
8
  using value_type = T;
 
59
  - `is_move_assignable_v<T>`
60
 
61
  is `false`.
62
 
63
  [*Note 1*: Type arguments that are not also statically initializable
64
+ can be difficult to use. — *end note*]
65
 
66
  The specialization `atomic<bool>` is a standard-layout struct.
67
 
68
  [*Note 2*: The representation of an atomic specialization need not have
69
  the same size and alignment requirement as its corresponding argument
70
  type. — *end note*]
71
 
72
+ #### Operations on atomic types <a id="atomics.types.operations">[[atomics.types.operations]]</a>
73
 
74
  ``` cpp
75
  constexpr atomic() noexcept(is_nothrow_default_constructible_v<T>);
76
  ```
77
 
 
120
  ``` cpp
121
  void store(T desired, memory_order order = memory_order::seq_cst) volatile noexcept;
122
  void store(T desired, memory_order order = memory_order::seq_cst) noexcept;
123
  ```
124
 
125
+ *Constraints:* For the `volatile` overload of this function,
126
+ `is_always_lock_free` is `true`.
127
+
128
  *Preconditions:* The `order` argument is neither
129
  `memory_order::consume`, `memory_order::acquire`, nor
130
  `memory_order::acq_rel`.
131
 
 
 
 
132
  *Effects:* Atomically replaces the value pointed to by `this` with the
133
  value of `desired`. Memory is affected according to the value of
134
  `order`.
135
 
136
  ``` cpp
 
148
  ``` cpp
149
  T load(memory_order order = memory_order::seq_cst) const volatile noexcept;
150
  T load(memory_order order = memory_order::seq_cst) const noexcept;
151
  ```
152
 
153
+ *Constraints:* For the `volatile` overload of this function,
154
+ `is_always_lock_free` is `true`.
155
+
156
  *Preconditions:* The `order` argument is neither `memory_order::release`
157
  nor `memory_order::acq_rel`.
158
 
 
 
 
159
  *Effects:* Memory is affected according to the value of `order`.
160
 
161
  *Returns:* Atomically returns the value pointed to by `this`.
162
 
163
  ``` cpp
 
203
  memory_order order = memory_order::seq_cst) volatile noexcept;
204
  bool compare_exchange_strong(T& expected, T desired,
205
  memory_order order = memory_order::seq_cst) noexcept;
206
  ```
207
 
208
+ *Constraints:* For the `volatile` overload of this function,
209
+ `is_always_lock_free` is `true`.
210
+
211
  *Preconditions:* The `failure` argument is neither
212
  `memory_order::release` nor `memory_order::acq_rel`.
213
 
 
 
 
214
  *Effects:* Retrieves the value in `expected`. It then atomically
215
  compares the value representation of the value pointed to by `this` for
216
  equality with that previously retrieved from `expected`, and if true,
217
  replaces the value pointed to by `this` with that in `desired`. If and
218
  only if the comparison is `true`, memory is affected according to the
 
232
  *Returns:* The result of the comparison.
233
 
234
  [*Note 4*:
235
 
236
  For example, the effect of `compare_exchange_strong` on objects without
237
+ padding bits [[term.padding.bits]] is
238
 
239
  ``` cpp
240
  if (memcmp(this, &expected, sizeof(*this)) == 0)
241
  memcpy(this, &desired, sizeof(*this));
242
  else
243
+ memcpy(&expected, this, sizeof(*this));
244
  ```
245
 
246
  — *end note*]
247
 
248
  [*Example 1*:
 
293
  performance on some platforms. When a weak compare-and-exchange would
294
  require a loop and a strong one would not, the strong one is
295
  preferable. — *end note*]
296
 
297
  [*Note 6*: Under cases where the `memcpy` and `memcmp` semantics of the
298
+ compare-and-exchange operations apply, the comparisons can fail for
299
+ values that compare equal with `operator==` if the value representation
300
+ has trap bits or alternate representations of the same value. Notably,
301
+ on implementations conforming to ISO/IEC/IEEE 60559, floating-point
302
+ `-0.0` and `+0.0` will not compare equal with `memcmp` but will compare
303
+ equal with `operator==`, and NaNs with the same payload will compare
304
+ equal with `memcmp` but will not compare equal with
305
  `operator==`. — *end note*]
306
 
307
  [*Note 7*:
308
 
309
  Because compare-and-exchange acts on an object’s value representation,
 
390
  are eligible to be unblocked [[atomics.wait]] by this call.
391
 
392
  *Remarks:* This function is an atomic notifying
393
  operation [[atomics.wait]].
394
 
395
+ #### Specializations for integers <a id="atomics.types.int">[[atomics.types.int]]</a>
396
 
397
  There are specializations of the `atomic` class template for the
398
  integral types `char`, `signed char`, `unsigned char`, `short`,
399
  `unsigned short`, `int`, `unsigned int`, `long`, `unsigned long`,
400
  `long long`, `unsigned long long`, `char8_t`, `char16_t`, `char32_t`,
401
  `wchar_t`, and any other types needed by the typedefs in the header
402
+ `<cstdint>`. For each such type `integral-type`, the specialization
403
+ `atomic<integral-type>` provides additional atomic operations
404
+ appropriate to integral types.
405
 
406
  [*Note 1*: The specialization `atomic<bool>` uses the primary template
407
  [[atomics.types.generic]]. — *end note*]
408
 
409
  ``` cpp
410
  namespace std {
411
+ template<> struct atomic<integral-type> {
412
+ using value_type = integral-type;
413
  using difference_type = value_type;
414
 
415
  static constexpr bool is_always_lock_free = implementation-defined // whether a given atomic type's operations are always lock free;
416
  bool is_lock_free() const volatile noexcept;
417
  bool is_lock_free() const noexcept;
418
 
419
  constexpr atomic() noexcept;
420
+ constexpr atomic(integral-type) noexcept;
421
  atomic(const atomic&) = delete;
422
  atomic& operator=(const atomic&) = delete;
423
  atomic& operator=(const atomic&) volatile = delete;
424
 
425
+ void store(integral-type, memory_order = memory_order::seq_cst) volatile noexcept;
426
+ void store(integral-type, memory_order = memory_order::seq_cst) noexcept;
427
+ integral-type operator=(integral-type) volatile noexcept;
428
+ integral-type operator=(integral-type) noexcept;
429
+ integral-type load(memory_order = memory_order::seq_cst) const volatile noexcept;
430
+ integral-type load(memory_order = memory_order::seq_cst) const noexcept;
431
+ operator integral-type() const volatile noexcept;
432
+ operator integral-type() const noexcept;
433
 
434
+ integral-type exchange(integral-type,
435
+ memory_order = memory_order::seq_cst) volatile noexcept;
436
+ integral-type exchange(integral-type,
437
+ memory_order = memory_order::seq_cst) noexcept;
438
+ bool compare_exchange_weak(integral-type&, integral-type,
439
  memory_order, memory_order) volatile noexcept;
440
+ bool compare_exchange_weak(integral-type&, integral-type,
441
  memory_order, memory_order) noexcept;
442
+ bool compare_exchange_strong(integral-type&, integral-type,
443
  memory_order, memory_order) volatile noexcept;
444
+ bool compare_exchange_strong(integral-type&, integral-type,
445
  memory_order, memory_order) noexcept;
446
+ bool compare_exchange_weak(integral-type&, integral-type,
447
  memory_order = memory_order::seq_cst) volatile noexcept;
448
+ bool compare_exchange_weak(integral-type&, integral-type,
449
  memory_order = memory_order::seq_cst) noexcept;
450
+ bool compare_exchange_strong(integral-type&, integral-type,
451
  memory_order = memory_order::seq_cst) volatile noexcept;
452
+ bool compare_exchange_strong(integral-type&, integral-type,
453
  memory_order = memory_order::seq_cst) noexcept;
454
 
455
+ integral-type fetch_add(integral-type,
456
+ memory_order = memory_order::seq_cst) volatile noexcept;
457
+ integral-type fetch_add(integral-type,
458
+ memory_order = memory_order::seq_cst) noexcept;
459
+ integral-type fetch_sub(integral-type,
460
+ memory_order = memory_order::seq_cst) volatile noexcept;
461
+ integral-type fetch_sub(integral-type,
462
+ memory_order = memory_order::seq_cst) noexcept;
463
+ integral-type fetch_and(integral-type,
464
+ memory_order = memory_order::seq_cst) volatile noexcept;
465
+ integral-type fetch_and(integral-type,
466
+ memory_order = memory_order::seq_cst) noexcept;
467
+ integral-type fetch_or(integral-type,
468
+ memory_order = memory_order::seq_cst) volatile noexcept;
469
+ integral-type fetch_or(integral-type,
470
+ memory_order = memory_order::seq_cst) noexcept;
471
+ integral-type fetch_xor(integral-type,
472
+ memory_order = memory_order::seq_cst) volatile noexcept;
473
+ integral-type fetch_xor(integral-type,
474
+ memory_order = memory_order::seq_cst) noexcept;
475
 
476
+ integral-type operator++(int) volatile noexcept;
477
+ integral-type operator++(int) noexcept;
478
+ integral-type operator--(int) volatile noexcept;
479
+ integral-type operator--(int) noexcept;
480
+ integral-type operator++() volatile noexcept;
481
+ integral-type operator++() noexcept;
482
+ integral-type operator--() volatile noexcept;
483
+ integral-type operator--() noexcept;
484
+ integral-type operator+=(integral-type) volatile noexcept;
485
+ integral-type operator+=(integral-type) noexcept;
486
+ integral-type operator-=(integral-type) volatile noexcept;
487
+ integral-type operator-=(integral-type) noexcept;
488
+ integral-type operator&=(integral-type) volatile noexcept;
489
+ integral-type operator&=(integral-type) noexcept;
490
+ integral-type operator|=(integral-type) volatile noexcept;
491
+ integral-type operator|=(integral-type) noexcept;
492
+ integral-type operator^=(integral-type) volatile noexcept;
493
+ integral-type operator^=(integral-type) noexcept;
494
 
495
+ void wait(integral-type, memory_order = memory_order::seq_cst) const volatile noexcept;
496
+ void wait(integral-type, memory_order = memory_order::seq_cst) const noexcept;
497
  void notify_one() volatile noexcept;
498
  void notify_one() noexcept;
499
  void notify_all() volatile noexcept;
500
  void notify_all() noexcept;
501
  };
 
506
  each have a trivial destructor.
507
 
508
  Descriptions are provided below only for members that differ from the
509
  primary template.
510
 
511
+ The following operations perform arithmetic computations. The
512
+ correspondence among key, operator, and computation is specified in
513
+ [[atomic.types.int.comp]].
514
 
515
  **Table: Atomic arithmetic computations** <a id="atomic.types.int.comp">[atomic.types.int.comp]</a>
516
 
517
  | | | | | | |
518
  | ----- | --- | -------------------- | ----- | --- | -------------------- |
 
554
  `is_always_lock_free` is `true`.
555
 
556
  *Effects:* Equivalent to:
557
  `return fetch_`*`key`*`(operand) `*`op`*` operand;`
558
 
559
+ #### Specializations for floating-point types <a id="atomics.types.float">[[atomics.types.float]]</a>
560
 
561
+ There are specializations of the `atomic` class template for all
562
+ cv-unqualified floating-point types. For each such type
563
+ `floating-point-type`, the specialization `atomic<floating-point-type>`
564
  provides additional atomic operations appropriate to floating-point
565
  types.
566
 
567
  ``` cpp
568
  namespace std {
569
+ template<> struct atomic<floating-point-type> {
570
+ using value_type = floating-point-type;
571
  using difference_type = value_type;
572
 
573
  static constexpr bool is_always_lock_free = implementation-defined // whether a given atomic type's operations are always lock free;
574
  bool is_lock_free() const volatile noexcept;
575
  bool is_lock_free() const noexcept;
576
 
577
  constexpr atomic() noexcept;
578
+ constexpr atomic(floating-point-type) noexcept;
579
  atomic(const atomic&) = delete;
580
  atomic& operator=(const atomic&) = delete;
581
  atomic& operator=(const atomic&) volatile = delete;
582
 
583
+ void store(floating-point-type, memory_order = memory_order::seq_cst) volatile noexcept;
584
+ void store(floating-point-type, memory_order = memory_order::seq_cst) noexcept;
585
+ floating-point-type operator=(floating-point-type) volatile noexcept;
586
+ floating-point-type operator=(floating-point-type) noexcept;
587
+ floating-point-type load(memory_order = memory_order::seq_cst) volatile noexcept;
588
+ floating-point-type load(memory_order = memory_order::seq_cst) noexcept;
589
+ operator floating-point-type() volatile noexcept;
590
+ operator floating-point-type() noexcept;
591
 
592
+ floating-point-type exchange(floating-point-type,
593
  memory_order = memory_order::seq_cst) volatile noexcept;
594
+ floating-point-type exchange(floating-point-type,
595
  memory_order = memory_order::seq_cst) noexcept;
596
+ bool compare_exchange_weak(floating-point-type&, floating-point-type,
597
  memory_order, memory_order) volatile noexcept;
598
+ bool compare_exchange_weak(floating-point-type&, floating-point-type,
599
  memory_order, memory_order) noexcept;
600
+ bool compare_exchange_strong(floating-point-type&, floating-point-type,
601
  memory_order, memory_order) volatile noexcept;
602
+ bool compare_exchange_strong(floating-point-type&, floating-point-type,
603
  memory_order, memory_order) noexcept;
604
+ bool compare_exchange_weak(floating-point-type&, floating-point-type,
605
  memory_order = memory_order::seq_cst) volatile noexcept;
606
+ bool compare_exchange_weak(floating-point-type&, floating-point-type,
607
  memory_order = memory_order::seq_cst) noexcept;
608
+ bool compare_exchange_strong(floating-point-type&, floating-point-type,
609
  memory_order = memory_order::seq_cst) volatile noexcept;
610
+ bool compare_exchange_strong(floating-point-type&, floating-point-type,
611
  memory_order = memory_order::seq_cst) noexcept;
612
 
613
+ floating-point-type fetch_add(floating-point-type,
614
  memory_order = memory_order::seq_cst) volatile noexcept;
615
+ floating-point-type fetch_add(floating-point-type,
616
  memory_order = memory_order::seq_cst) noexcept;
617
+ floating-point-type fetch_sub(floating-point-type,
618
  memory_order = memory_order::seq_cst) volatile noexcept;
619
+ floating-point-type fetch_sub(floating-point-type,
620
  memory_order = memory_order::seq_cst) noexcept;
621
 
622
+ floating-point-type operator+=(floating-point-type) volatile noexcept;
623
+ floating-point-type operator+=(floating-point-type) noexcept;
624
+ floating-point-type operator-=(floating-point-type) volatile noexcept;
625
+ floating-point-type operator-=(floating-point-type) noexcept;
626
 
627
+ void wait(floating-point-type, memory_order = memory_order::seq_cst) const volatile noexcept;
628
+ void wait(floating-point-type, memory_order = memory_order::seq_cst) const noexcept;
629
  void notify_one() volatile noexcept;
630
  void notify_one() noexcept;
631
  void notify_all() volatile noexcept;
632
  void notify_all() noexcept;
633
  };
 
639
 
640
  Descriptions are provided below only for members that differ from the
641
  primary template.
642
 
643
  The following operations perform arithmetic addition and subtraction
644
+ computations. The correspondence among key, operator, and computation is
645
+ specified in [[atomic.types.int.comp]].
646
 
647
  ``` cpp
648
  T fetch_key(T operand, memory_order order = memory_order::seq_cst) volatile noexcept;
649
  T fetch_key(T operand, memory_order order = memory_order::seq_cst) noexcept;
650
  ```
 
662
  the effects.
663
 
664
  *Remarks:* If the result is not a representable value for its
665
  type [[expr.pre]] the result is unspecified, but the operations
666
  otherwise have no undefined behavior. Atomic arithmetic operations on
667
+ *`floating-point-type`* should conform to the
668
+ `std::numeric_limits<`*`floating-point-type`*`>` traits associated with
669
+ the floating-point type [[limits.syn]]. The floating-point
670
  environment [[cfenv]] for atomic arithmetic operations on
671
+ *`floating-point-type`* may be different than the calling thread’s
672
  floating-point environment.
673
 
674
  ``` cpp
675
  T operator op=(T operand) volatile noexcept;
676
  T operator op=(T operand) noexcept;
 
683
  `return fetch_`*`key`*`(operand) `*`op`*` operand;`
684
 
685
  *Remarks:* If the result is not a representable value for its
686
  type [[expr.pre]] the result is unspecified, but the operations
687
  otherwise have no undefined behavior. Atomic arithmetic operations on
688
+ *`floating-point-type`* should conform to the
689
+ `std::numeric_limits<`*`floating-point-type`*`>` traits associated with
690
+ the floating-point type [[limits.syn]]. The floating-point
691
  environment [[cfenv]] for atomic arithmetic operations on
692
+ *`floating-point-type`* may be different than the calling thread’s
693
  floating-point environment.
694
 
695
+ #### Partial specialization for pointers <a id="atomics.types.pointer">[[atomics.types.pointer]]</a>
696
 
697
  ``` cpp
698
  namespace std {
699
  template<class T> struct atomic<T*> {
700
  using value_type = T*;
 
767
  standard-layout structs. They each have a trivial destructor.
768
 
769
  Descriptions are provided below only for members that differ from the
770
  primary template.
771
 
772
+ The following operations perform pointer arithmetic. The correspondence
773
+ among key, operator, and computation is specified in
774
+ [[atomic.types.pointer.comp]].
775
 
776
  **Table: Atomic pointer computations** <a id="atomic.types.pointer.comp">[atomic.types.pointer.comp]</a>
777
 
778
  | | | | | | |
779
  | ----- | --- | -------- | ----- | --- | ----------- |
 
813
  `is_always_lock_free` is `true`.
814
 
815
  *Effects:* Equivalent to:
816
  `return fetch_`*`key`*`(operand) `*`op`*` operand;`
817
 
818
+ #### Member operators common to integers and pointers to objects <a id="atomics.types.memop">[[atomics.types.memop]]</a>
819
 
820
  ``` cpp
821
  value_type operator++(int) volatile noexcept;
822
  value_type operator++(int) noexcept;
823
  ```
 
855
  *Constraints:* For the `volatile` overload of this function,
856
  `is_always_lock_free` is `true`.
857
 
858
  *Effects:* Equivalent to: `return fetch_sub(1) - 1;`
859
 
860
+ #### Partial specializations for smart pointers <a id="util.smartptr.atomic">[[util.smartptr.atomic]]</a>
861
+
862
+ ##### General <a id="util.smartptr.atomic.general">[[util.smartptr.atomic.general]]</a>
863
 
864
  The library provides partial specializations of the `atomic` template
865
+ for shared-ownership smart pointers [[util.sharedptr]].
 
 
 
866
 
867
+ [*Note 1*: The partial specializations are declared in header
868
+ `<memory>`. *end note*]
869
+
870
+ The behavior of all operations is as specified in
871
+ [[atomics.types.generic]], unless specified otherwise. The template
872
+ parameter `T` of these partial specializations may be an incomplete
873
+ type.
874
+
875
+ All changes to an atomic smart pointer in [[util.smartptr.atomic]], and
876
+ all associated `use_count` increments, are guaranteed to be performed
877
  atomically. Associated `use_count` decrements are sequenced after the
878
  atomic operation, but are not required to be part of it. Any associated
879
  deletion and deallocation are sequenced after the atomic update step and
880
  are not part of the atomic operation.
881
 
882
+ [*Note 2*: If the atomic operation uses locks, locks acquired by the
883
  implementation will be held when any `use_count` adjustments are
884
  performed, and will not be held when any destruction or deallocation
885
  resulting from this is performed. — *end note*]
886
 
887
  [*Example 1*:
 
893
  shared_ptr<node> next;
894
  };
895
  atomic<shared_ptr<node>> head;
896
 
897
  public:
898
+ shared_ptr<node> find(T t) const {
899
  auto p = head.load();
900
  while (p && p->t != t)
901
  p = p->next;
902
 
903
+ return p;
904
  }
905
 
906
  void push_front(T t) {
907
  auto p = make_shared<node>();
908
  p->t = t;
 
912
  };
913
  ```
914
 
915
  — *end example*]
916
 
917
+ ##### Partial specialization for `shared_ptr` <a id="util.smartptr.atomic.shared">[[util.smartptr.atomic.shared]]</a>
918
 
919
  ``` cpp
920
  namespace std {
921
  template<class T> struct atomic<shared_ptr<T>> {
922
  using value_type = shared_ptr<T>;
923
 
924
  static constexpr bool is_always_lock_free = implementation-defined // whether a given atomic type's operations are always lock free;
925
  bool is_lock_free() const noexcept;
926
 
927
  constexpr atomic() noexcept;
928
+ constexpr atomic(nullptr_t) noexcept : atomic() { }
929
  atomic(shared_ptr<T> desired) noexcept;
930
  atomic(const atomic&) = delete;
931
  void operator=(const atomic&) = delete;
932
 
933
  shared_ptr<T> load(memory_order order = memory_order::seq_cst) const noexcept;
 
1122
  are eligible to be unblocked [[atomics.wait]] by this call.
1123
 
1124
  *Remarks:* This function is an atomic notifying
1125
  operation [[atomics.wait]].
1126
 
1127
+ ##### Partial specialization for `weak_ptr` <a id="util.smartptr.atomic.weak">[[util.smartptr.atomic.weak]]</a>
1128
 
1129
  ``` cpp
1130
  namespace std {
1131
  template<class T> struct atomic<weak_ptr<T>> {
1132
  using value_type = weak_ptr<T>;
 
1176
  ```
1177
 
1178
  *Effects:* Initializes the object with the value `desired`.
1179
  Initialization is not an atomic operation [[intro.multithread]].
1180
 
1181
+ [*Note 2*: It is possible to have an access to an atomic object `A`
1182
  race with its construction, for example, by communicating the address of
1183
  the just-constructed object `A` to another thread via
1184
  `memory_order::relaxed` operations on a suitable atomic pointer
1185
  variable, and then immediately accessing `A` in the receiving thread.
1186
  This results in undefined behavior. — *end note*]