From Jason Turner

[thread]

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

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmp4ul6xnb0/{from.md → to.md} +2448 -955
tmp/tmp4ul6xnb0/{from.md → to.md} RENAMED
@@ -16,12 +16,13 @@ conditions and values between threads, as summarized in
16
  | [[thread.threads]] | Threads | `<thread>` |
17
  | [[atomics]] | Atomic operations | `<atomic>`, `<stdatomic.h>` |
18
  | [[thread.mutex]] | Mutual exclusion | `<mutex>`, `<shared_mutex>` |
19
  | [[thread.condition]] | Condition variables | `<condition_variable>` |
20
  | [[thread.sema]] | Semaphores | `<semaphore>` |
21
- | [[thread.coord]] | Coordination types | `<latch>` `<barrier>` |
22
  | [[futures]] | Futures | `<future>` |
 
23
 
24
 
25
  ## Requirements <a id="thread.req">[[thread.req]]</a>
26
 
27
  ### Template parameter names <a id="thread.req.paramname">[[thread.req.paramname]]</a>
@@ -144,11 +145,11 @@ exceptions*.
144
  supplied by the implementation as specified in  [[time.clock]] do not
145
  throw exceptions. — *end note*]
146
 
147
  ### Requirements for *Cpp17Lockable* types <a id="thread.req.lockable">[[thread.req.lockable]]</a>
148
 
149
- #### In general <a id="thread.req.lockable.general">[[thread.req.lockable.general]]</a>
150
 
151
  An *execution agent* is an entity such as a thread that may perform work
152
  in parallel with other execution agents.
153
 
154
  [*Note 1*: Implementations or users can introduce other kinds of agents
@@ -188,13 +189,13 @@ A lock on an object `m` is said to be
188
  nature of any lock ownership is not part of these
189
  definitions. — *end note*]
190
 
191
  #### *Cpp17BasicLockable* requirements <a id="thread.req.lockable.basic">[[thread.req.lockable.basic]]</a>
192
 
193
- A type `L` meets the *Cpp17BasicLockable* requirements if the following
194
- expressions are well-formed and have the specified semantics (`m`
195
- denotes a value of type `L`).
196
 
197
  ``` cpp
198
  m.lock()
199
  ```
200
 
@@ -214,14 +215,13 @@ execution agent.
214
 
215
  *Throws:* Nothing.
216
 
217
  #### *Cpp17Lockable* requirements <a id="thread.req.lockable.req">[[thread.req.lockable.req]]</a>
218
 
219
- A type `L` meets the *Cpp17Lockable* requirements if it meets the
220
- *Cpp17BasicLockable* requirements and the following expressions are
221
- well-formed and have the specified semantics (`m` denotes a value of
222
- type `L`).
223
 
224
  ``` cpp
225
  m.try_lock()
226
  ```
227
 
@@ -233,16 +233,16 @@ been acquired for the current execution agent.
233
 
234
  *Returns:* `true` if the lock was acquired, otherwise `false`.
235
 
236
  #### *Cpp17TimedLockable* requirements <a id="thread.req.lockable.timed">[[thread.req.lockable.timed]]</a>
237
 
238
- A type `L` meets the *Cpp17TimedLockable* requirements if it meets the
239
- *Cpp17Lockable* requirements and the following expressions are
240
- well-formed and have the specified semantics (`m` denotes a value of
241
- type `L`, `rel_time` denotes a value of an instantiation of `duration`
242
- [[time.duration]], and `abs_time` denotes a value of an instantiation of
243
- `time_point` [[time.point]]).
244
 
245
  ``` cpp
246
  m.try_lock_for(rel_time)
247
  ```
248
 
@@ -272,14 +272,13 @@ acquired for the current execution agent.
272
 
273
  *Returns:* `true` if the lock was acquired, otherwise `false`.
274
 
275
  #### *Cpp17SharedLockable* requirements <a id="thread.req.lockable.shared">[[thread.req.lockable.shared]]</a>
276
 
277
- A type `L` meets the *Cpp17SharedLockable* requirements if the following
278
- expressions are well-formed, have the specified semantics, and the
279
- expression `m.try_lock_shared()` has type `bool` (`m` denotes a value of
280
- type `L`):
281
 
282
  ``` cpp
283
  m.lock_shared()
284
  ```
285
 
@@ -308,16 +307,16 @@ agent.
308
 
309
  *Throws:* Nothing.
310
 
311
  #### *Cpp17SharedTimedLockable* requirements <a id="thread.req.lockable.shared.timed">[[thread.req.lockable.shared.timed]]</a>
312
 
313
- A type `L` meets the *Cpp17SharedTimedLockable* requirements if it meets
314
- the *Cpp17SharedLockable* requirements, and the following expressions
315
- are well-formed, have type `bool`, and have the specified semantics (`m`
316
- denotes a value of type `L`, `rel_time` denotes a value of a
317
- specialization of `chrono::duration`, and `abs_time` denotes a value of
318
- a specialization of `chrono::time_point`).
319
 
320
  ``` cpp
321
  m.try_lock_shared_for(rel_time)
322
  ```
323
 
@@ -350,42 +349,64 @@ acquired for the current execution agent.
350
  Subclause [[thread.stoptoken]] describes components that can be used to
351
  asynchronously request that an operation stops execution in a timely
352
  manner, typically because the result is no longer required. Such a
353
  request is called a *stop request*.
354
 
355
- `stop_source`, `stop_token`, and `stop_callback` implement semantics of
356
- shared ownership of a *stop state*. Any `stop_source`, `stop_token`, or
357
- `stop_callback` that shares ownership of the same stop state is an
358
- *associated* `stop_source`, `stop_token`, or `stop_callback`,
359
- respectively. The last remaining owner of the stop state automatically
360
- releases the resources associated with the stop state.
361
 
362
- A `stop_token` can be passed to an operation which can either
 
363
 
364
  - actively poll the token to check if there has been a stop request, or
365
- - register a callback using the `stop_callback` class template which
366
- will be called in the event that a stop request is made.
367
 
368
- A stop request made via a `stop_source` will be visible to all
369
- associated `stop_token` and `stop_source` objects. Once a stop request
370
- has been made it cannot be withdrawn (a subsequent stop request has no
371
- effect).
372
 
373
- Callbacks registered via a `stop_callback` object are called when a stop
374
- request is first made by any associated `stop_source` object.
 
375
 
376
- Calls to the functions `request_stop`, `stop_requested`, and
377
- `stop_possible` do not introduce data races. A call to `request_stop`
378
- that returns `true` synchronizes with a call to `stop_requested` on an
379
- associated `stop_token` or `stop_source` object that returns `true`.
380
- Registration of a callback synchronizes with the invocation of that
381
- callback.
 
 
 
 
 
 
 
382
 
383
  ### Header `<stop_token>` synopsis <a id="thread.stoptoken.syn">[[thread.stoptoken.syn]]</a>
384
 
385
  ``` cpp
386
  namespace std {
 
 
 
 
 
 
 
 
 
 
 
 
 
387
  // [stoptoken], class stop_token
388
  class stop_token;
389
 
390
  // [stopsource], class stop_source
391
  class stop_source;
@@ -397,399 +418,662 @@ namespace std {
397
  inline constexpr nostopstate_t nostopstate{};
398
 
399
  // [stopcallback], class template stop_callback
400
  template<class Callback>
401
  class stop_callback;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
402
  }
403
  ```
404
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
405
  ### Class `stop_token` <a id="stoptoken">[[stoptoken]]</a>
406
 
407
  #### General <a id="stoptoken.general">[[stoptoken.general]]</a>
408
 
409
- The class `stop_token` provides an interface for querying whether a stop
410
- request has been made (`stop_requested`) or can ever be made
411
- (`stop_possible`) using an associated `stop_source` object
412
- [[stopsource]]. A `stop_token` can also be passed to a `stop_callback`
413
- [[stopcallback]] constructor to register a callback to be called when a
414
- stop request has been made from an associated `stop_source`.
415
 
416
  ``` cpp
417
  namespace std {
418
  class stop_token {
419
  public:
420
- // [stoptoken.cons], constructors, copy, and assignment
421
- stop_token() noexcept;
422
 
423
- stop_token(const stop_token&) noexcept;
424
- stop_token(stop_token&&) noexcept;
425
- stop_token& operator=(const stop_token&) noexcept;
426
- stop_token& operator=(stop_token&&) noexcept;
427
- ~stop_token();
428
  void swap(stop_token&) noexcept;
429
 
430
- // [stoptoken.mem], stop handling
431
- [[nodiscard]] bool stop_requested() const noexcept;
432
- [[nodiscard]] bool stop_possible() const noexcept;
433
 
434
- [[nodiscard]] friend bool operator==(const stop_token& lhs, const stop_token& rhs) noexcept;
435
- friend void swap(stop_token& lhs, stop_token& rhs) noexcept;
 
 
436
  };
437
  }
438
  ```
439
 
440
- #### Constructors, copy, and assignment <a id="stoptoken.cons">[[stoptoken.cons]]</a>
 
441
 
442
- ``` cpp
443
- stop_token() noexcept;
444
- ```
445
-
446
- *Ensures:* `stop_possible()` is `false` and `stop_requested()` is
447
- `false`.
448
-
449
- [*Note 1*: Because the created `stop_token` object can never receive a
450
- stop request, no resources are allocated for a stop
451
- state. — *end note*]
452
-
453
- ``` cpp
454
- stop_token(const stop_token& rhs) noexcept;
455
- ```
456
-
457
- *Ensures:* `*this == rhs` is `true`.
458
-
459
- [*Note 2*: `*this` and `rhs` share the ownership of the same stop
460
- state, if any. — *end note*]
461
-
462
- ``` cpp
463
- stop_token(stop_token&& rhs) noexcept;
464
- ```
465
-
466
- *Ensures:* `*this` contains the value of `rhs` prior to the start of
467
- construction and `rhs.stop_possible()` is `false`.
468
-
469
- ``` cpp
470
- ~stop_token();
471
- ```
472
-
473
- *Effects:* Releases ownership of the stop state, if any.
474
-
475
- ``` cpp
476
- stop_token& operator=(const stop_token& rhs) noexcept;
477
- ```
478
-
479
- *Effects:* Equivalent to: `stop_token(rhs).swap(*this)`.
480
-
481
- *Returns:* `*this`.
482
-
483
- ``` cpp
484
- stop_token& operator=(stop_token&& rhs) noexcept;
485
- ```
486
-
487
- *Effects:* Equivalent to: `stop_token(std::move(rhs)).swap(*this)`.
488
-
489
- *Returns:* `*this`.
490
 
491
  ``` cpp
492
  void swap(stop_token& rhs) noexcept;
493
  ```
494
 
495
- *Effects:* Exchanges the values of `*this` and `rhs`.
496
 
497
- #### Members <a id="stoptoken.mem">[[stoptoken.mem]]</a>
 
 
498
 
499
  ``` cpp
500
- [[nodiscard]] bool stop_requested() const noexcept;
501
  ```
502
 
503
- *Returns:* `true` if `*this` has ownership of a stop state that has
504
  received a stop request; otherwise, `false`.
505
 
506
  ``` cpp
507
- [[nodiscard]] bool stop_possible() const noexcept;
508
  ```
509
 
510
- *Returns:* `false` if:
511
 
512
- - `*this` does not have ownership of a stop state, or
513
  - a stop request was not made and there are no associated `stop_source`
514
  objects;
515
 
516
  otherwise, `true`.
517
 
518
- #### Non-member functions <a id="stoptoken.nonmembers">[[stoptoken.nonmembers]]</a>
519
-
520
- ``` cpp
521
- [[nodiscard]] bool operator==(const stop_token& lhs, const stop_token& rhs) noexcept;
522
- ```
523
-
524
- *Returns:* `true` if `lhs` and `rhs` have ownership of the same stop
525
- state or if both `lhs` and `rhs` do not have ownership of a stop state;
526
- otherwise `false`.
527
-
528
- ``` cpp
529
- friend void swap(stop_token& x, stop_token& y) noexcept;
530
- ```
531
-
532
- *Effects:* Equivalent to: `x.swap(y)`.
533
-
534
  ### Class `stop_source` <a id="stopsource">[[stopsource]]</a>
535
 
536
  #### General <a id="stopsource.general">[[stopsource.general]]</a>
537
 
538
- The class `stop_source` implements the semantics of making a stop
539
- request. A stop request made on a `stop_source` object is visible to all
540
- associated `stop_source` and `stop_token` [[stoptoken]] objects. Once a
541
- stop request has been made it cannot be withdrawn (a subsequent stop
542
- request has no effect).
543
-
544
  ``` cpp
545
  namespace std {
546
- // no-shared-stop-state indicator
547
- struct nostopstate_t {
548
- explicit nostopstate_t() = default;
549
- };
550
- inline constexpr nostopstate_t nostopstate{};
551
-
552
  class stop_source {
553
  public:
554
  // [stopsource.cons], constructors, copy, and assignment
555
  stop_source();
556
- explicit stop_source(nostopstate_t) noexcept;
557
 
558
- stop_source(const stop_source&) noexcept;
559
- stop_source(stop_source&&) noexcept;
560
- stop_source& operator=(const stop_source&) noexcept;
561
- stop_source& operator=(stop_source&&) noexcept;
562
- ~stop_source();
563
  void swap(stop_source&) noexcept;
564
 
565
- // [stopsource.mem], stop handling
566
- [[nodiscard]] stop_token get_token() const noexcept;
567
- [[nodiscard]] bool stop_possible() const noexcept;
568
- [[nodiscard]] bool stop_requested() const noexcept;
569
  bool request_stop() noexcept;
570
 
571
- [[nodiscard]] friend bool
572
- operator==(const stop_source& lhs, const stop_source& rhs) noexcept;
573
- friend void swap(stop_source& lhs, stop_source& rhs) noexcept;
 
574
  };
575
  }
576
  ```
577
 
 
 
 
 
 
 
578
  #### Constructors, copy, and assignment <a id="stopsource.cons">[[stopsource.cons]]</a>
579
 
580
  ``` cpp
581
  stop_source();
582
  ```
583
 
584
- *Effects:* Initialises `*this` to have ownership of a new stop state.
585
 
586
  *Ensures:* `stop_possible()` is `true` and `stop_requested()` is
587
  `false`.
588
 
589
  *Throws:* `bad_alloc` if memory cannot be allocated for the stop state.
590
 
591
- ``` cpp
592
- explicit stop_source(nostopstate_t) noexcept;
593
- ```
594
-
595
- *Ensures:* `stop_possible()` is `false` and `stop_requested()` is
596
- `false`.
597
-
598
- [*Note 1*: No resources are allocated for the state. — *end note*]
599
-
600
- ``` cpp
601
- stop_source(const stop_source& rhs) noexcept;
602
- ```
603
-
604
- *Ensures:* `*this == rhs` is `true`.
605
-
606
- [*Note 2*: `*this` and `rhs` share the ownership of the same stop
607
- state, if any. — *end note*]
608
-
609
- ``` cpp
610
- stop_source(stop_source&& rhs) noexcept;
611
- ```
612
-
613
- *Ensures:* `*this` contains the value of `rhs` prior to the start of
614
- construction and `rhs.stop_possible()` is `false`.
615
-
616
- ``` cpp
617
- ~stop_source();
618
- ```
619
-
620
- *Effects:* Releases ownership of the stop state, if any.
621
-
622
- ``` cpp
623
- stop_source& operator=(const stop_source& rhs) noexcept;
624
- ```
625
-
626
- *Effects:* Equivalent to: `stop_source(rhs).swap(*this)`.
627
-
628
- *Returns:* `*this`.
629
-
630
- ``` cpp
631
- stop_source& operator=(stop_source&& rhs) noexcept;
632
- ```
633
-
634
- *Effects:* Equivalent to: `stop_source(std::move(rhs)).swap(*this)`.
635
-
636
- *Returns:* `*this`.
637
 
638
  ``` cpp
639
  void swap(stop_source& rhs) noexcept;
640
  ```
641
 
642
- *Effects:* Exchanges the values of `*this` and `rhs`.
643
 
644
- #### Members <a id="stopsource.mem">[[stopsource.mem]]</a>
 
 
645
 
646
  ``` cpp
647
- [[nodiscard]] stop_token get_token() const noexcept;
648
  ```
649
 
650
  *Returns:* `stop_token()` if `stop_possible()` is `false`; otherwise a
651
- new associated `stop_token` object.
 
652
 
653
  ``` cpp
654
- [[nodiscard]] bool stop_possible() const noexcept;
655
  ```
656
 
657
- *Returns:* `true` if `*this` has ownership of a stop state; otherwise,
658
- `false`.
659
 
660
  ``` cpp
661
- [[nodiscard]] bool stop_requested() const noexcept;
662
  ```
663
 
664
- *Returns:* `true` if `*this` has ownership of a stop state that has
665
  received a stop request; otherwise, `false`.
666
 
667
  ``` cpp
668
  bool request_stop() noexcept;
669
  ```
670
 
671
- *Effects:* If `*this` does not have ownership of a stop state, returns
672
- `false`. Otherwise, atomically determines whether the owned stop state
673
- has received a stop request, and if not, makes a stop request. The
674
- determination and making of the stop request are an atomic
675
- read-modify-write operation [[intro.races]]. If the request was made,
676
- the callbacks registered by associated `stop_callback` objects are
677
- synchronously called. If an invocation of a callback exits via an
678
- exception then `terminate` is invoked [[except.terminate]].
679
-
680
- [*Note 1*: A stop request includes notifying all condition variables of
681
- type `condition_variable_any` temporarily registered during an
682
- interruptible wait [[thread.condvarany.intwait]]. — *end note*]
683
-
684
- *Ensures:* `stop_possible()` is `false` or `stop_requested()` is `true`.
685
-
686
- *Returns:* `true` if this call made a stop request; otherwise `false`.
687
-
688
- #### Non-member functions <a id="stopsource.nonmembers">[[stopsource.nonmembers]]</a>
689
-
690
- ``` cpp
691
- [[nodiscard]] friend bool
692
- operator==(const stop_source& lhs, const stop_source& rhs) noexcept;
693
- ```
694
-
695
- *Returns:* `true` if `lhs` and `rhs` have ownership of the same stop
696
- state or if both `lhs` and `rhs` do not have ownership of a stop state;
697
- otherwise `false`.
698
-
699
- ``` cpp
700
- friend void swap(stop_source& x, stop_source& y) noexcept;
701
- ```
702
-
703
- *Effects:* Equivalent to: `x.swap(y)`.
704
 
705
  ### Class template `stop_callback` <a id="stopcallback">[[stopcallback]]</a>
706
 
707
  #### General <a id="stopcallback.general">[[stopcallback.general]]</a>
708
 
709
  ``` cpp
710
  namespace std {
711
- template<class Callback>
712
  class stop_callback {
713
  public:
714
- using callback_type = Callback;
715
 
716
  // [stopcallback.cons], constructors and destructor
717
- template<class C>
718
- explicit stop_callback(const stop_token& st, C&& cb)
719
- noexcept(is_nothrow_constructible_v<Callback, C>);
720
- template<class C>
721
- explicit stop_callback(stop_token&& st, C&& cb)
722
- noexcept(is_nothrow_constructible_v<Callback, C>);
723
  ~stop_callback();
724
 
725
  stop_callback(const stop_callback&) = delete;
726
  stop_callback(stop_callback&&) = delete;
727
  stop_callback& operator=(const stop_callback&) = delete;
728
  stop_callback& operator=(stop_callback&&) = delete;
729
 
730
  private:
731
- Callback callback; // exposition only
732
  };
733
 
734
- template<class Callback>
735
- stop_callback(stop_token, Callback) -> stop_callback<Callback>;
736
  }
737
  ```
738
 
739
  *Mandates:* `stop_callback` is instantiated with an argument for the
740
- template parameter `Callback` that satisfies both `invocable` and
741
  `destructible`.
742
 
743
- *Preconditions:* `stop_callback` is instantiated with an argument for
744
- the template parameter `Callback` that models both `invocable` and
745
- `destructible`.
 
 
 
 
746
 
747
  #### Constructors and destructor <a id="stopcallback.cons">[[stopcallback.cons]]</a>
748
 
749
  ``` cpp
750
- template<class C>
751
- explicit stop_callback(const stop_token& st, C&& cb)
752
- noexcept(is_nothrow_constructible_v<Callback, C>);
753
- template<class C>
754
- explicit stop_callback(stop_token&& st, C&& cb)
755
- noexcept(is_nothrow_constructible_v<Callback, C>);
 
756
  ```
757
 
758
- *Constraints:* `Callback` and `C` satisfy
759
- `constructible_from<Callback, C>`.
760
-
761
- *Preconditions:* `Callback` and `C` model
762
- `constructible_from<Callback, C>`.
763
-
764
- *Effects:* Initializes `callback` with `std::forward<C>(cb)`. If
765
- `st.stop_requested()` is `true`, then
766
- `std::forward<Callback>(callback)()` is evaluated in the current thread
767
- before the constructor returns. Otherwise, if `st` has ownership of a
768
- stop state, acquires shared ownership of that stop state and registers
769
- the callback with that stop state such that
770
- `std::forward<Callback>(callback)()` is evaluated by the first call to
771
- `request_stop()` on an associated `stop_source`.
772
-
773
- *Throws:* Any exception thrown by the initialization of `callback`.
774
-
775
- *Remarks:* If evaluating `std::forward<Callback>(callback)()` exits via
776
- an exception, then `terminate` is invoked [[except.terminate]].
777
 
778
  ``` cpp
779
  ~stop_callback();
780
  ```
781
 
782
- *Effects:* Unregisters the callback from the owned stop state, if any.
783
- The destructor does not block waiting for the execution of another
784
- callback registered by an associated `stop_callback`. If `callback` is
785
- concurrently executing on another thread, then the return from the
786
- invocation of `callback` strongly happens before [[intro.races]]
787
- `callback` is destroyed. If `callback` is executing on the current
788
- thread, then the destructor does not block [[defns.block]] waiting for
789
- the return from the invocation of `callback`. Releases ownership of the
790
- stop state, if any.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
791
 
792
  ## Threads <a id="thread.threads">[[thread.threads]]</a>
793
 
794
  ### General <a id="thread.threads.general">[[thread.threads.general]]</a>
795
 
@@ -1193,26 +1477,26 @@ namespace std {
1193
  jthread& operator=(const jthread&) = delete;
1194
  jthread& operator=(jthread&&) noexcept;
1195
 
1196
  // [thread.jthread.mem], members
1197
  void swap(jthread&) noexcept;
1198
- [[nodiscard]] bool joinable() const noexcept;
1199
  void join();
1200
  void detach();
1201
- [[nodiscard]] id get_id() const noexcept;
1202
- [[nodiscard]] native_handle_type native_handle(); // see~[thread.req.native]
1203
 
1204
  // [thread.jthread.stop], stop token handling
1205
- [[nodiscard]] stop_source get_stop_source() noexcept;
1206
- [[nodiscard]] stop_token get_stop_token() const noexcept;
1207
  bool request_stop() noexcept;
1208
 
1209
  // [thread.jthread.special], specialized algorithms
1210
  friend void swap(jthread& lhs, jthread& rhs) noexcept;
1211
 
1212
  // [thread.jthread.static], static members
1213
- [[nodiscard]] static unsigned int hardware_concurrency() noexcept;
1214
 
1215
  private:
1216
  stop_source ssource; // exposition only
1217
  };
1218
  }
@@ -1324,11 +1608,11 @@ void swap(jthread& x) noexcept;
1324
  ```
1325
 
1326
  *Effects:* Exchanges the values of `*this` and `x`.
1327
 
1328
  ``` cpp
1329
- [[nodiscard]] bool joinable() const noexcept;
1330
  ```
1331
 
1332
  *Returns:* `get_id() != id()`.
1333
 
1334
  ``` cpp
@@ -1385,17 +1669,17 @@ represent a thread, otherwise `this_thread::get_id()` for the thread of
1385
  execution represented by `*this`.
1386
 
1387
  #### Stop token handling <a id="thread.jthread.stop">[[thread.jthread.stop]]</a>
1388
 
1389
  ``` cpp
1390
- [[nodiscard]] stop_source get_stop_source() noexcept;
1391
  ```
1392
 
1393
  *Effects:* Equivalent to: `return ssource;`
1394
 
1395
  ``` cpp
1396
- [[nodiscard]] stop_token get_stop_token() const noexcept;
1397
  ```
1398
 
1399
  *Effects:* Equivalent to: `return ssource.get_token();`
1400
 
1401
  ``` cpp
@@ -1413,11 +1697,11 @@ friend void swap(jthread& x, jthread& y) noexcept;
1413
  *Effects:* Equivalent to: `x.swap(y)`.
1414
 
1415
  #### Static members <a id="thread.jthread.static">[[thread.jthread.static]]</a>
1416
 
1417
  ``` cpp
1418
- [[nodiscard]] static unsigned int hardware_concurrency() noexcept;
1419
  ```
1420
 
1421
  *Returns:* `thread::hardware_concurrency()`.
1422
 
1423
  ### Namespace `this_thread` <a id="thread.thread.this">[[thread.thread.this]]</a>
@@ -1483,292 +1767,358 @@ Subclause [[atomics]] describes components for fine-grained atomic
1483
  access. This access is provided via operations on atomic objects.
1484
 
1485
  ### Header `<atomic>` synopsis <a id="atomics.syn">[[atomics.syn]]</a>
1486
 
1487
  ``` cpp
 
1488
  namespace std {
1489
  // [atomics.order], order and consistency
1490
- enum class memory_order : unspecified; // freestanding
1491
- inline constexpr memory_order memory_order_relaxed = memory_order::relaxed; // freestanding
1492
- inline constexpr memory_order memory_order_consume = memory_order::consume; // freestanding
1493
- inline constexpr memory_order memory_order_acquire = memory_order::acquire; // freestanding
1494
- inline constexpr memory_order memory_order_release = memory_order::release; // freestanding
1495
- inline constexpr memory_order memory_order_acq_rel = memory_order::acq_rel; // freestanding
1496
- inline constexpr memory_order memory_order_seq_cst = memory_order::seq_cst; // freestanding
1497
-
1498
- template<class T>
1499
- T kill_dependency(T y) noexcept; // freestanding
1500
  }
1501
 
1502
  // [atomics.lockfree], lock-free property
1503
- #define ATOMIC_BOOL_LOCK_FREE unspecified // freestanding
1504
- #define ATOMIC_CHAR_LOCK_FREE unspecified // freestanding
1505
- #define ATOMIC_CHAR8_T_LOCK_FREE unspecified // freestanding
1506
- #define ATOMIC_CHAR16_T_LOCK_FREE unspecified // freestanding
1507
- #define ATOMIC_CHAR32_T_LOCK_FREE unspecified // freestanding
1508
- #define ATOMIC_WCHAR_T_LOCK_FREE unspecified // freestanding
1509
- #define ATOMIC_SHORT_LOCK_FREE unspecified // freestanding
1510
- #define ATOMIC_INT_LOCK_FREE unspecified // freestanding
1511
- #define ATOMIC_LONG_LOCK_FREE unspecified // freestanding
1512
- #define ATOMIC_LLONG_LOCK_FREE unspecified // freestanding
1513
- #define ATOMIC_POINTER_LOCK_FREE unspecified // freestanding
1514
 
1515
  namespace std {
1516
  // [atomics.ref.generic], class template atomic_ref
1517
- template<class T> struct atomic_ref; // freestanding
1518
- // [atomics.ref.pointer], partial specialization for pointers
1519
- template<class T> struct atomic_ref<T*>; // freestanding
1520
 
1521
  // [atomics.types.generic], class template atomic
1522
- template<class T> struct atomic; // freestanding
1523
  // [atomics.types.pointer], partial specialization for pointers
1524
- template<class T> struct atomic<T*>; // freestanding
1525
 
1526
  // [atomics.nonmembers], non-member functions
1527
  template<class T>
1528
- bool atomic_is_lock_free(const volatile atomic<T>*) noexcept; // freestanding
1529
  template<class T>
1530
- bool atomic_is_lock_free(const atomic<T>*) noexcept; // freestanding
1531
  template<class T>
1532
- void atomic_store(volatile atomic<T>*, // freestanding
1533
- typename atomic<T>::value_type) noexcept;
1534
  template<class T>
1535
- void atomic_store(atomic<T>*, typename atomic<T>::value_type) noexcept; // freestanding
1536
  template<class T>
1537
- void atomic_store_explicit(volatile atomic<T>*, // freestanding
1538
- typename atomic<T>::value_type,
1539
  memory_order) noexcept;
1540
  template<class T>
1541
- void atomic_store_explicit(atomic<T>*, typename atomic<T>::value_type, // freestanding
1542
  memory_order) noexcept;
1543
  template<class T>
1544
- T atomic_load(const volatile atomic<T>*) noexcept; // freestanding
1545
  template<class T>
1546
- T atomic_load(const atomic<T>*) noexcept; // freestanding
1547
  template<class T>
1548
- T atomic_load_explicit(const volatile atomic<T>*, memory_order) noexcept; // freestanding
1549
  template<class T>
1550
- T atomic_load_explicit(const atomic<T>*, memory_order) noexcept; // freestanding
1551
  template<class T>
1552
- T atomic_exchange(volatile atomic<T>*, // freestanding
1553
- typename atomic<T>::value_type) noexcept;
1554
  template<class T>
1555
- T atomic_exchange(atomic<T>*, typename atomic<T>::value_type) noexcept; // freestanding
1556
  template<class T>
1557
- T atomic_exchange_explicit(volatile atomic<T>*, // freestanding
1558
- typename atomic<T>::value_type,
1559
  memory_order) noexcept;
1560
  template<class T>
1561
- T atomic_exchange_explicit(atomic<T>*, typename atomic<T>::value_type, // freestanding
1562
  memory_order) noexcept;
1563
  template<class T>
1564
- bool atomic_compare_exchange_weak(volatile atomic<T>*, // freestanding
1565
  typename atomic<T>::value_type*,
1566
  typename atomic<T>::value_type) noexcept;
1567
  template<class T>
1568
- bool atomic_compare_exchange_weak(atomic<T>*, // freestanding
1569
  typename atomic<T>::value_type*,
1570
  typename atomic<T>::value_type) noexcept;
1571
  template<class T>
1572
- bool atomic_compare_exchange_strong(volatile atomic<T>*, // freestanding
1573
  typename atomic<T>::value_type*,
1574
  typename atomic<T>::value_type) noexcept;
1575
  template<class T>
1576
- bool atomic_compare_exchange_strong(atomic<T>*, // freestanding
1577
  typename atomic<T>::value_type*,
1578
  typename atomic<T>::value_type) noexcept;
1579
  template<class T>
1580
- bool atomic_compare_exchange_weak_explicit(volatile atomic<T>*, // freestanding
1581
  typename atomic<T>::value_type*,
1582
  typename atomic<T>::value_type,
1583
  memory_order, memory_order) noexcept;
1584
  template<class T>
1585
- bool atomic_compare_exchange_weak_explicit(atomic<T>*, // freestanding
1586
  typename atomic<T>::value_type*,
1587
  typename atomic<T>::value_type,
1588
  memory_order, memory_order) noexcept;
1589
  template<class T>
1590
- bool atomic_compare_exchange_strong_explicit(volatile atomic<T>*, // freestanding
1591
  typename atomic<T>::value_type*,
1592
  typename atomic<T>::value_type,
1593
  memory_order, memory_order) noexcept;
1594
  template<class T>
1595
- bool atomic_compare_exchange_strong_explicit(atomic<T>*, // freestanding
1596
  typename atomic<T>::value_type*,
1597
  typename atomic<T>::value_type,
1598
  memory_order, memory_order) noexcept;
1599
 
1600
  template<class T>
1601
- T atomic_fetch_add(volatile atomic<T>*, // freestanding
1602
- typename atomic<T>::difference_type) noexcept;
1603
  template<class T>
1604
- T atomic_fetch_add(atomic<T>*, typename atomic<T>::difference_type) noexcept; // freestanding
1605
  template<class T>
1606
- T atomic_fetch_add_explicit(volatile atomic<T>*, // freestanding
1607
- typename atomic<T>::difference_type,
1608
  memory_order) noexcept;
1609
  template<class T>
1610
- T atomic_fetch_add_explicit(atomic<T>*, typename atomic<T>::difference_type, // freestanding
1611
  memory_order) noexcept;
1612
  template<class T>
1613
- T atomic_fetch_sub(volatile atomic<T>*, // freestanding
1614
- typename atomic<T>::difference_type) noexcept;
1615
  template<class T>
1616
- T atomic_fetch_sub(atomic<T>*, typename atomic<T>::difference_type) noexcept; // freestanding
1617
  template<class T>
1618
- T atomic_fetch_sub_explicit(volatile atomic<T>*, // freestanding
1619
- typename atomic<T>::difference_type,
1620
  memory_order) noexcept;
1621
  template<class T>
1622
- T atomic_fetch_sub_explicit(atomic<T>*, typename atomic<T>::difference_type, // freestanding
1623
  memory_order) noexcept;
1624
  template<class T>
1625
- T atomic_fetch_and(volatile atomic<T>*, // freestanding
1626
- typename atomic<T>::value_type) noexcept;
1627
  template<class T>
1628
- T atomic_fetch_and(atomic<T>*, typename atomic<T>::value_type) noexcept; // freestanding
1629
  template<class T>
1630
- T atomic_fetch_and_explicit(volatile atomic<T>*, // freestanding
1631
- typename atomic<T>::value_type,
1632
  memory_order) noexcept;
1633
  template<class T>
1634
- T atomic_fetch_and_explicit(atomic<T>*, typename atomic<T>::value_type, // freestanding
1635
  memory_order) noexcept;
1636
  template<class T>
1637
- T atomic_fetch_or(volatile atomic<T>*, // freestanding
1638
- typename atomic<T>::value_type) noexcept;
1639
  template<class T>
1640
- T atomic_fetch_or(atomic<T>*, typename atomic<T>::value_type) noexcept; // freestanding
1641
  template<class T>
1642
- T atomic_fetch_or_explicit(volatile atomic<T>*, // freestanding
1643
- typename atomic<T>::value_type,
1644
  memory_order) noexcept;
1645
  template<class T>
1646
- T atomic_fetch_or_explicit(atomic<T>*, typename atomic<T>::value_type, // freestanding
1647
  memory_order) noexcept;
1648
  template<class T>
1649
- T atomic_fetch_xor(volatile atomic<T>*, // freestanding
1650
- typename atomic<T>::value_type) noexcept;
1651
  template<class T>
1652
- T atomic_fetch_xor(atomic<T>*, typename atomic<T>::value_type) noexcept; // freestanding
1653
  template<class T>
1654
- T atomic_fetch_xor_explicit(volatile atomic<T>*, // freestanding
1655
- typename atomic<T>::value_type,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1656
  memory_order) noexcept;
1657
  template<class T>
1658
- T atomic_fetch_xor_explicit(atomic<T>*, typename atomic<T>::value_type, // freestanding
1659
  memory_order) noexcept;
1660
 
1661
  template<class T>
1662
- void atomic_wait(const volatile atomic<T>*, // freestanding
1663
- typename atomic<T>::value_type) noexcept;
1664
  template<class T>
1665
- void atomic_wait(const atomic<T>*, typename atomic<T>::value_type) noexcept; // freestanding
1666
  template<class T>
1667
- void atomic_wait_explicit(const volatile atomic<T>*, // freestanding
1668
- typename atomic<T>::value_type,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1669
  memory_order) noexcept;
1670
  template<class T>
1671
- void atomic_wait_explicit(const atomic<T>*, typename atomic<T>::value_type, // freestanding
1672
  memory_order) noexcept;
1673
  template<class T>
1674
- void atomic_notify_one(volatile atomic<T>*) noexcept; // freestanding
1675
  template<class T>
1676
- void atomic_notify_one(atomic<T>*) noexcept; // freestanding
1677
  template<class T>
1678
- void atomic_notify_all(volatile atomic<T>*) noexcept; // freestanding
1679
  template<class T>
1680
- void atomic_notify_all(atomic<T>*) noexcept; // freestanding
1681
 
1682
  // [atomics.alias], type aliases
1683
- using atomic_bool = atomic<bool>; // freestanding
1684
- using atomic_char = atomic<char>; // freestanding
1685
- using atomic_schar = atomic<signed char>; // freestanding
1686
- using atomic_uchar = atomic<unsigned char>; // freestanding
1687
- using atomic_short = atomic<short>; // freestanding
1688
- using atomic_ushort = atomic<unsigned short>; // freestanding
1689
- using atomic_int = atomic<int>; // freestanding
1690
- using atomic_uint = atomic<unsigned int>; // freestanding
1691
- using atomic_long = atomic<long>; // freestanding
1692
- using atomic_ulong = atomic<unsigned long>; // freestanding
1693
- using atomic_llong = atomic<long long>; // freestanding
1694
- using atomic_ullong = atomic<unsigned long long>; // freestanding
1695
- using atomic_char8_t = atomic<char8_t>; // freestanding
1696
- using atomic_char16_t = atomic<char16_t>; // freestanding
1697
- using atomic_char32_t = atomic<char32_t>; // freestanding
1698
- using atomic_wchar_t = atomic<wchar_t>; // freestanding
1699
 
1700
- using atomic_int8_t = atomic<int8_t>; // freestanding
1701
- using atomic_uint8_t = atomic<uint8_t>; // freestanding
1702
- using atomic_int16_t = atomic<int16_t>; // freestanding
1703
- using atomic_uint16_t = atomic<uint16_t>; // freestanding
1704
- using atomic_int32_t = atomic<int32_t>; // freestanding
1705
- using atomic_uint32_t = atomic<uint32_t>; // freestanding
1706
- using atomic_int64_t = atomic<int64_t>; // freestanding
1707
- using atomic_uint64_t = atomic<uint64_t>; // freestanding
1708
 
1709
- using atomic_int_least8_t = atomic<int_least8_t>; // freestanding
1710
- using atomic_uint_least8_t = atomic<uint_least8_t>; // freestanding
1711
- using atomic_int_least16_t = atomic<int_least16_t>; // freestanding
1712
- using atomic_uint_least16_t = atomic<uint_least16_t>; // freestanding
1713
- using atomic_int_least32_t = atomic<int_least32_t>; // freestanding
1714
- using atomic_uint_least32_t = atomic<uint_least32_t>; // freestanding
1715
- using atomic_int_least64_t = atomic<int_least64_t>; // freestanding
1716
- using atomic_uint_least64_t = atomic<uint_least64_t>; // freestanding
1717
 
1718
- using atomic_int_fast8_t = atomic<int_fast8_t>; // freestanding
1719
- using atomic_uint_fast8_t = atomic<uint_fast8_t>; // freestanding
1720
- using atomic_int_fast16_t = atomic<int_fast16_t>; // freestanding
1721
- using atomic_uint_fast16_t = atomic<uint_fast16_t>; // freestanding
1722
- using atomic_int_fast32_t = atomic<int_fast32_t>; // freestanding
1723
- using atomic_uint_fast32_t = atomic<uint_fast32_t>; // freestanding
1724
- using atomic_int_fast64_t = atomic<int_fast64_t>; // freestanding
1725
- using atomic_uint_fast64_t = atomic<uint_fast64_t>; // freestanding
1726
 
1727
- using atomic_intptr_t = atomic<intptr_t>; // freestanding
1728
- using atomic_uintptr_t = atomic<uintptr_t>; // freestanding
1729
- using atomic_size_t = atomic<size_t>; // freestanding
1730
- using atomic_ptrdiff_t = atomic<ptrdiff_t>; // freestanding
1731
- using atomic_intmax_t = atomic<intmax_t>; // freestanding
1732
- using atomic_uintmax_t = atomic<uintmax_t>; // freestanding
1733
 
1734
- using atomic_signed_lock_free = see below;
1735
- using atomic_unsigned_lock_free = see below;
1736
 
1737
  // [atomics.flag], flag type and operations
1738
- struct atomic_flag; // freestanding
1739
 
1740
- bool atomic_flag_test(const volatile atomic_flag*) noexcept; // freestanding
1741
- bool atomic_flag_test(const atomic_flag*) noexcept; // freestanding
1742
- bool atomic_flag_test_explicit(const volatile atomic_flag*, // freestanding
1743
- memory_order) noexcept;
1744
- bool atomic_flag_test_explicit(const atomic_flag*, memory_order) noexcept; // freestanding
1745
- bool atomic_flag_test_and_set(volatile atomic_flag*) noexcept; // freestanding
1746
- bool atomic_flag_test_and_set(atomic_flag*) noexcept; // freestanding
1747
- bool atomic_flag_test_and_set_explicit(volatile atomic_flag*, // freestanding
1748
- memory_order) noexcept;
1749
- bool atomic_flag_test_and_set_explicit(atomic_flag*, memory_order) noexcept; // freestanding
1750
- void atomic_flag_clear(volatile atomic_flag*) noexcept; // freestanding
1751
- void atomic_flag_clear(atomic_flag*) noexcept; // freestanding
1752
- void atomic_flag_clear_explicit(volatile atomic_flag*, memory_order) noexcept; // freestanding
1753
- void atomic_flag_clear_explicit(atomic_flag*, memory_order) noexcept; // freestanding
1754
 
1755
- void atomic_flag_wait(const volatile atomic_flag*, bool) noexcept; // freestanding
1756
- void atomic_flag_wait(const atomic_flag*, bool) noexcept; // freestanding
1757
- void atomic_flag_wait_explicit(const volatile atomic_flag*, // freestanding
1758
- bool, memory_order) noexcept;
1759
- void atomic_flag_wait_explicit(const atomic_flag*, // freestanding
1760
- bool, memory_order) noexcept;
1761
- void atomic_flag_notify_one(volatile atomic_flag*) noexcept; // freestanding
1762
- void atomic_flag_notify_one(atomic_flag*) noexcept; // freestanding
1763
- void atomic_flag_notify_all(volatile atomic_flag*) noexcept; // freestanding
1764
- void atomic_flag_notify_all(atomic_flag*) noexcept; // freestanding
1765
- #define ATOMIC_FLAG_INIT see belownc // freestanding
1766
 
1767
  // [atomics.fences], fences
1768
- extern "C" void atomic_thread_fence(memory_order) noexcept; // freestanding
1769
- extern "C" void atomic_signal_fence(memory_order) noexcept; // freestanding
1770
  }
1771
  ```
1772
 
1773
  ### Type aliases <a id="atomics.alias">[[atomics.alias]]</a>
1774
 
@@ -1791,11 +2141,11 @@ operations [[atomics.wait]] are most efficient.
1791
  ### Order and consistency <a id="atomics.order">[[atomics.order]]</a>
1792
 
1793
  ``` cpp
1794
  namespace std {
1795
  enum class memory_order : unspecified {
1796
- relaxed, consume, acquire, release, acq_rel, seq_cst
1797
  };
1798
  }
1799
  ```
1800
 
1801
  The enumeration `memory_order` specifies the detailed regular
@@ -1805,21 +2155,15 @@ enumerated values and their meanings are as follows:
1805
 
1806
  - `memory_order::relaxed`: no operation orders memory.
1807
  - `memory_order::release`, `memory_order::acq_rel`, and
1808
  `memory_order::seq_cst`: a store operation performs a release
1809
  operation on the affected memory location.
1810
- - `memory_order::consume`: a load operation performs a consume operation
1811
- on the affected memory location. \[*Note 1*: Prefer
1812
- `memory_order::acquire`, which provides stronger guarantees than
1813
- `memory_order::consume`. Implementations have found it infeasible to
1814
- provide performance better than that of `memory_order::acquire`.
1815
- Specification revisions are under consideration. — *end note*]
1816
  - `memory_order::acquire`, `memory_order::acq_rel`, and
1817
  `memory_order::seq_cst`: a load operation performs an acquire
1818
  operation on the affected memory location.
1819
 
1820
- [*Note 2*: Atomic operations specifying `memory_order::relaxed` are
1821
  relaxed with respect to memory ordering. Implementations must still
1822
  guarantee that any given atomic access to a particular atomic object be
1823
  indivisible with respect to all other atomic accesses to that
1824
  object. — *end note*]
1825
 
@@ -1854,35 +2198,35 @@ S:
1854
  - if a `memory_order::seq_cst` fence X happens before A and B is a
1855
  `memory_order::seq_cst` operation, then X precedes B in S; and
1856
  - if a `memory_order::seq_cst` fence X happens before A and B happens
1857
  before a `memory_order::seq_cst` fence Y, then X precedes Y in S.
1858
 
1859
- [*Note 3*: This definition ensures that S is consistent with the
1860
  modification order of any atomic object M. It also ensures that a
1861
  `memory_order::seq_cst` load A of M gets its value either from the last
1862
  modification of M that precedes A in S or from some
1863
  non-`memory_order::seq_cst` modification of M that does not happen
1864
  before any modification of M that precedes A in S. — *end note*]
1865
 
1866
- [*Note 4*: We do not require that S be consistent with “happens before”
1867
  [[intro.races]]. This allows more efficient implementation of
1868
  `memory_order::acquire` and `memory_order::release` on some machine
1869
  architectures. It can produce surprising results when these are mixed
1870
  with `memory_order::seq_cst` accesses. — *end note*]
1871
 
1872
- [*Note 5*: `memory_order::seq_cst` ensures sequential consistency only
1873
  for a program that is free of data races and uses exclusively
1874
  `memory_order::seq_cst` atomic operations. Any use of weaker ordering
1875
  will invalidate this guarantee unless extreme care is used. In many
1876
  cases, `memory_order::seq_cst` atomic operations are reorderable with
1877
  respect to other atomic operations performed by the same
1878
  thread. — *end note*]
1879
 
1880
  Implementations should ensure that no “out-of-thin-air” values are
1881
  computed that circularly depend on their own computation.
1882
 
1883
- [*Note 6*:
1884
 
1885
  For example, with `x` and `y` initially zero,
1886
 
1887
  ``` cpp
1888
  // Thread 1:
@@ -1901,11 +2245,11 @@ store of 42 to `y` is only possible if the store to `x` stores `42`,
1901
  which circularly depends on the store to `y` storing `42`. Note that
1902
  without this restriction, such an execution is possible.
1903
 
1904
  — *end note*]
1905
 
1906
- [*Note 7*:
1907
 
1908
  The recommendation similarly disallows `r1 == r2 == 42` in the following
1909
  example, with `x` and `y` again initially zero:
1910
 
1911
  ``` cpp
@@ -1924,22 +2268,23 @@ if (r2 == 42) x.store(42, memory_order::relaxed);
1924
 
1925
  Atomic read-modify-write operations shall always read the last value (in
1926
  the modification order) written before the write associated with the
1927
  read-modify-write operation.
1928
 
1929
- Implementations should make atomic stores visible to atomic loads within
1930
- a reasonable amount of time.
 
1931
 
1932
- ``` cpp
1933
- template<class T>
1934
- T kill_dependency(T y) noexcept;
1935
- ```
 
1936
 
1937
- *Effects:* The argument does not carry a dependency to the return
1938
- value [[intro.multithread]].
1939
-
1940
- *Returns:* `y`.
1941
 
1942
  ### Lock-free property <a id="atomics.lockfree">[[atomics.lockfree]]</a>
1943
 
1944
  ``` cpp
1945
  #define ATOMIC_BOOL_LOCK_FREE unspecified
@@ -2040,38 +2385,40 @@ namespace std {
2040
  template<class T> struct atomic_ref {
2041
  private:
2042
  T* ptr; // exposition only
2043
 
2044
  public:
2045
- using value_type = T;
2046
  static constexpr size_t required_alignment = implementation-defined // required alignment for atomic_ref type's operations;
2047
 
2048
  static constexpr bool is_always_lock_free = implementation-defined // whether a given atomic_ref type's operations are always lock free;
2049
  bool is_lock_free() const noexcept;
2050
 
2051
- explicit atomic_ref(T&);
2052
- atomic_ref(const atomic_ref&) noexcept;
2053
  atomic_ref& operator=(const atomic_ref&) = delete;
2054
 
2055
- void store(T, memory_order = memory_order::seq_cst) const noexcept;
2056
- T operator=(T) const noexcept;
2057
- T load(memory_order = memory_order::seq_cst) const noexcept;
2058
- operator T() const noexcept;
2059
 
2060
- T exchange(T, memory_order = memory_order::seq_cst) const noexcept;
2061
- bool compare_exchange_weak(T&, T,
 
2062
  memory_order, memory_order) const noexcept;
2063
- bool compare_exchange_strong(T&, T,
2064
  memory_order, memory_order) const noexcept;
2065
- bool compare_exchange_weak(T&, T,
2066
  memory_order = memory_order::seq_cst) const noexcept;
2067
- bool compare_exchange_strong(T&, T,
2068
  memory_order = memory_order::seq_cst) const noexcept;
2069
 
2070
- void wait(T, memory_order = memory_order::seq_cst) const noexcept;
2071
- void notify_one() const noexcept;
2072
- void notify_all() const noexcept;
 
2073
  };
2074
  }
2075
  ```
2076
 
2077
  An `atomic_ref` object applies atomic operations [[atomics.general]] to
@@ -2096,10 +2443,13 @@ through any other `atomic_ref` referencing the same object.
2096
  [*Note 1*: Atomic operations or the `atomic_ref` constructor can
2097
  acquire a shared resource, such as a lock associated with the referenced
2098
  object, to enable atomic operations to be applied to the referenced
2099
  object. — *end note*]
2100
 
 
 
 
2101
  #### Operations <a id="atomics.ref.ops">[[atomics.ref.ops]]</a>
2102
 
2103
  ``` cpp
2104
  static constexpr size_t required_alignment;
2105
  ```
@@ -2128,94 +2478,103 @@ bool is_lock_free() const noexcept;
2128
 
2129
  *Returns:* `true` if operations on all objects of the type
2130
  `atomic_ref<T>` are lock-free, `false` otherwise.
2131
 
2132
  ``` cpp
2133
- atomic_ref(T& obj);
2134
  ```
2135
 
2136
  *Preconditions:* The referenced object is aligned to
2137
  `required_alignment`.
2138
 
2139
  *Ensures:* `*this` references `obj`.
2140
 
2141
  *Throws:* Nothing.
2142
 
2143
  ``` cpp
2144
- atomic_ref(const atomic_ref& ref) noexcept;
2145
  ```
2146
 
2147
  *Ensures:* `*this` references the object referenced by `ref`.
2148
 
2149
  ``` cpp
2150
- void store(T desired, memory_order order = memory_order::seq_cst) const noexcept;
 
2151
  ```
2152
 
2153
- *Preconditions:* The `order` argument is neither
2154
- `memory_order::consume`, `memory_order::acquire`, nor
2155
- `memory_order::acq_rel`.
 
2156
 
2157
  *Effects:* Atomically replaces the value referenced by `*ptr` with the
2158
  value of `desired`. Memory is affected according to the value of
2159
  `order`.
2160
 
2161
  ``` cpp
2162
- T operator=(T desired) const noexcept;
2163
  ```
2164
 
 
 
2165
  *Effects:* Equivalent to:
2166
 
2167
  ``` cpp
2168
  store(desired);
2169
  return desired;
2170
  ```
2171
 
2172
  ``` cpp
2173
- T load(memory_order order = memory_order::seq_cst) const noexcept;
2174
  ```
2175
 
2176
- *Preconditions:* The `order` argument is neither `memory_order::release`
2177
- nor `memory_order::acq_rel`.
2178
 
2179
  *Effects:* Memory is affected according to the value of `order`.
2180
 
2181
  *Returns:* Atomically returns the value referenced by `*ptr`.
2182
 
2183
  ``` cpp
2184
- operator T() const noexcept;
2185
  ```
2186
 
2187
  *Effects:* Equivalent to: `return load();`
2188
 
2189
  ``` cpp
2190
- T exchange(T desired, memory_order order = memory_order::seq_cst) const noexcept;
 
2191
  ```
2192
 
 
 
2193
  *Effects:* Atomically replaces the value referenced by `*ptr` with
2194
  `desired`. Memory is affected according to the value of `order`. This
2195
  operation is an atomic read-modify-write
2196
  operation [[intro.multithread]].
2197
 
2198
  *Returns:* Atomically returns the value referenced by `*ptr` immediately
2199
  before the effects.
2200
 
2201
  ``` cpp
2202
- bool compare_exchange_weak(T& expected, T desired,
2203
  memory_order success, memory_order failure) const noexcept;
2204
 
2205
- bool compare_exchange_strong(T& expected, T desired,
2206
  memory_order success, memory_order failure) const noexcept;
2207
 
2208
- bool compare_exchange_weak(T& expected, T desired,
2209
  memory_order order = memory_order::seq_cst) const noexcept;
2210
 
2211
- bool compare_exchange_strong(T& expected, T desired,
2212
  memory_order order = memory_order::seq_cst) const noexcept;
2213
  ```
2214
 
2215
- *Preconditions:* The `failure` argument is neither
2216
- `memory_order::release` nor `memory_order::acq_rel`.
 
 
2217
 
2218
  *Effects:* Retrieves the value in `expected`. It then atomically
2219
  compares the value representation of the value referenced by `*ptr` for
2220
  equality with that previously retrieved from `expected`, and if `true`,
2221
  replaces the value referenced by `*ptr` with that in `desired`. If and
@@ -2249,15 +2608,15 @@ compare-and-exchange is in a loop, the weak version will yield better
2249
  performance on some platforms. When a weak compare-and-exchange would
2250
  require a loop and a strong one would not, the strong one is
2251
  preferable. — *end note*]
2252
 
2253
  ``` cpp
2254
- void wait(T old, memory_order order = memory_order::seq_cst) const noexcept;
2255
  ```
2256
 
2257
- *Preconditions:* `order` is neither `memory_order::release` nor
2258
- `memory_order::acq_rel`.
2259
 
2260
  *Effects:* Repeatedly performs the following steps, in order:
2261
 
2262
  - Evaluates `load(order)` and compares its value representation for
2263
  equality against that of `old`.
@@ -2267,102 +2626,131 @@ void wait(T old, memory_order order = memory_order::seq_cst) const noexcept;
2267
 
2268
  *Remarks:* This function is an atomic waiting operation [[atomics.wait]]
2269
  on atomic object `*ptr`.
2270
 
2271
  ``` cpp
2272
- void notify_one() const noexcept;
2273
  ```
2274
 
 
 
2275
  *Effects:* Unblocks the execution of at least one atomic waiting
2276
  operation on `*ptr` that is eligible to be unblocked [[atomics.wait]] by
2277
  this call, if any such atomic waiting operations exist.
2278
 
2279
  *Remarks:* This function is an atomic notifying
2280
  operation [[atomics.wait]] on atomic object `*ptr`.
2281
 
2282
  ``` cpp
2283
- void notify_all() const noexcept;
2284
  ```
2285
 
 
 
2286
  *Effects:* Unblocks the execution of all atomic waiting operations on
2287
  `*ptr` that are eligible to be unblocked [[atomics.wait]] by this call.
2288
 
2289
  *Remarks:* This function is an atomic notifying
2290
  operation [[atomics.wait]] on atomic object `*ptr`.
2291
 
 
 
 
 
 
 
2292
  #### Specializations for integral types <a id="atomics.ref.int">[[atomics.ref.int]]</a>
2293
 
2294
- There are specializations of the `atomic_ref` class template for the
2295
- integral types `char`, `signed char`, `unsigned char`, `short`,
2296
- `unsigned short`, `int`, `unsigned int`, `long`, `unsigned long`,
2297
- `long long`, `unsigned long long`, `char8_t`, `char16_t`, `char32_t`,
2298
- `wchar_t`, and any other types needed by the typedefs in the header
2299
- `<cstdint>`. For each such type `integral-type`, the specialization
2300
- `atomic_ref<integral-type>` provides additional atomic operations
2301
- appropriate to integral types.
2302
 
2303
  [*Note 1*: The specialization `atomic_ref<bool>` uses the primary
2304
  template [[atomics.ref.generic]]. — *end note*]
2305
 
 
 
 
2306
  ``` cpp
2307
  namespace std {
2308
  template<> struct atomic_ref<integral-type> {
2309
  private:
2310
  integral-type* ptr; // exposition only
2311
 
2312
  public:
2313
- using value_type = integral-type;
2314
  using difference_type = value_type;
2315
  static constexpr size_t required_alignment = implementation-defined // required alignment for atomic_ref type's operations;
2316
 
2317
  static constexpr bool is_always_lock_free = implementation-defined // whether a given atomic_ref type's operations are always lock free;
2318
  bool is_lock_free() const noexcept;
2319
 
2320
- explicit atomic_ref(integral-type&);
2321
- atomic_ref(const atomic_ref&) noexcept;
2322
  atomic_ref& operator=(const atomic_ref&) = delete;
2323
 
2324
- void store(integral-type, memory_order = memory_order::seq_cst) const noexcept;
2325
- integral-type operator=(integral-type) const noexcept;
2326
- integral-type load(memory_order = memory_order::seq_cst) const noexcept;
2327
- operator integral-type() const noexcept;
2328
 
2329
- integral-type exchange(integral-type,
2330
  memory_order = memory_order::seq_cst) const noexcept;
2331
- bool compare_exchange_weak(integral-type&, integral-type,
2332
  memory_order, memory_order) const noexcept;
2333
- bool compare_exchange_strong(integral-type&, integral-type,
2334
  memory_order, memory_order) const noexcept;
2335
- bool compare_exchange_weak(integral-type&, integral-type,
2336
  memory_order = memory_order::seq_cst) const noexcept;
2337
- bool compare_exchange_strong(integral-type&, integral-type,
2338
  memory_order = memory_order::seq_cst) const noexcept;
2339
 
2340
- integral-type fetch_add(integral-type,
2341
  memory_order = memory_order::seq_cst) const noexcept;
2342
- integral-type fetch_sub(integral-type,
2343
  memory_order = memory_order::seq_cst) const noexcept;
2344
- integral-type fetch_and(integral-type,
2345
  memory_order = memory_order::seq_cst) const noexcept;
2346
- integral-type fetch_or(integral-type,
2347
  memory_order = memory_order::seq_cst) const noexcept;
2348
- integral-type fetch_xor(integral-type,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2349
  memory_order = memory_order::seq_cst) const noexcept;
2350
 
2351
- integral-type operator++(int) const noexcept;
2352
- integral-type operator--(int) const noexcept;
2353
- integral-type operator++() const noexcept;
2354
- integral-type operator--() const noexcept;
2355
- integral-type operator+=(integral-type) const noexcept;
2356
- integral-type operator-=(integral-type) const noexcept;
2357
- integral-type operator&=(integral-type) const noexcept;
2358
- integral-type operator|=(integral-type) const noexcept;
2359
- integral-type operator^=(integral-type) const noexcept;
2360
 
2361
- void wait(integral-type, memory_order = memory_order::seq_cst) const noexcept;
2362
- void notify_one() const noexcept;
2363
- void notify_all() const noexcept;
 
2364
  };
2365
  }
2366
  ```
2367
 
2368
  Descriptions are provided below only for members that differ from the
@@ -2371,107 +2759,177 @@ primary template.
2371
  The following operations perform arithmetic computations. The
2372
  correspondence among key, operator, and computation is specified in
2373
  [[atomic.types.int.comp]].
2374
 
2375
  ``` cpp
2376
- integral-type fetch_key(integral-type operand,
2377
  memory_order order = memory_order::seq_cst) const noexcept;
2378
  ```
2379
 
 
 
2380
  *Effects:* Atomically replaces the value referenced by `*ptr` with the
2381
  result of the computation applied to the value referenced by `*ptr` and
2382
  the given operand. Memory is affected according to the value of `order`.
2383
  These operations are atomic read-modify-write
2384
  operations [[intro.races]].
2385
 
2386
  *Returns:* Atomically, the value referenced by `*ptr` immediately before
2387
  the effects.
2388
 
2389
- *Remarks:* For signed integer types, the result is as if the object
2390
- value and parameters were converted to their corresponding unsigned
2391
- types, the computation performed on those types, and the result
2392
- converted back to the signed type.
2393
 
2394
  [*Note 1*: There are no undefined results arising from the
2395
  computation. — *end note*]
2396
 
 
 
 
 
 
2397
  ``` cpp
2398
- integral-type operator op=(integral-type operand) const noexcept;
 
2399
  ```
2400
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2401
  *Effects:* Equivalent to:
2402
  `return fetch_`*`key`*`(operand) `*`op`*` operand;`
2403
 
2404
  #### Specializations for floating-point types <a id="atomics.ref.float">[[atomics.ref.float]]</a>
2405
 
2406
  There are specializations of the `atomic_ref` class template for all
2407
- cv-unqualified floating-point types. For each such type
2408
- `floating-point-type`, the specialization `atomic_ref<floating-point>`
2409
- provides additional atomic operations appropriate to floating-point
2410
- types.
 
 
2411
 
2412
  ``` cpp
2413
  namespace std {
2414
  template<> struct atomic_ref<floating-point-type> {
2415
  private:
2416
  floating-point-type* ptr; // exposition only
2417
 
2418
  public:
2419
- using value_type = floating-point-type;
2420
  using difference_type = value_type;
2421
  static constexpr size_t required_alignment = implementation-defined // required alignment for atomic_ref type's operations;
2422
 
2423
  static constexpr bool is_always_lock_free = implementation-defined // whether a given atomic_ref type's operations are always lock free;
2424
  bool is_lock_free() const noexcept;
2425
 
2426
- explicit atomic_ref(floating-point-type&);
2427
- atomic_ref(const atomic_ref&) noexcept;
2428
  atomic_ref& operator=(const atomic_ref&) = delete;
2429
 
2430
- void store(floating-point-type, memory_order = memory_order::seq_cst) const noexcept;
2431
- floating-point-type operator=(floating-point-type) const noexcept;
2432
- floating-point-type load(memory_order = memory_order::seq_cst) const noexcept;
2433
- operator floating-point-type() const noexcept;
 
2434
 
2435
- floating-point-type exchange(floating-point-type,
2436
  memory_order = memory_order::seq_cst) const noexcept;
2437
- bool compare_exchange_weak(floating-point-type&, floating-point-type,
2438
  memory_order, memory_order) const noexcept;
2439
- bool compare_exchange_strong(floating-point-type&, floating-point-type,
2440
  memory_order, memory_order) const noexcept;
2441
- bool compare_exchange_weak(floating-point-type&, floating-point-type,
 
 
 
 
 
 
 
 
 
 
2442
  memory_order = memory_order::seq_cst) const noexcept;
2443
- bool compare_exchange_strong(floating-point-type&, floating-point-type,
 
 
 
 
 
 
 
 
2444
  memory_order = memory_order::seq_cst) const noexcept;
2445
 
2446
- floating-point-type fetch_add(floating-point-type,
 
 
 
 
2447
  memory_order = memory_order::seq_cst) const noexcept;
2448
- floating-point-type fetch_sub(floating-point-type,
 
 
 
 
2449
  memory_order = memory_order::seq_cst) const noexcept;
2450
 
2451
- floating-point-type operator+=(floating-point-type) const noexcept;
2452
- floating-point-type operator-=(floating-point-type) const noexcept;
2453
 
2454
- void wait(floating-point-type, memory_order = memory_order::seq_cst) const noexcept;
2455
- void notify_one() const noexcept;
2456
- void notify_all() const noexcept;
 
 
2457
  };
2458
  }
2459
  ```
2460
 
2461
  Descriptions are provided below only for members that differ from the
2462
  primary template.
2463
 
2464
  The following operations perform arithmetic computations. The
2465
  correspondence among key, operator, and computation is specified in
2466
- [[atomic.types.int.comp]].
 
 
2467
 
2468
  ``` cpp
2469
- floating-point-type fetch_key(floating-point-type operand,
2470
  memory_order order = memory_order::seq_cst) const noexcept;
2471
  ```
2472
 
 
 
2473
  *Effects:* Atomically replaces the value referenced by `*ptr` with the
2474
  result of the computation applied to the value referenced by `*ptr` and
2475
  the given operand. Memory is affected according to the value of `order`.
2476
  These operations are atomic read-modify-write
2477
  operations [[intro.races]].
@@ -2481,71 +2939,167 @@ the effects.
2481
 
2482
  *Remarks:* If the result is not a representable value for its
2483
  type [[expr.pre]], the result is unspecified, but the operations
2484
  otherwise have no undefined behavior. Atomic arithmetic operations on
2485
  *`floating-point-type`* should conform to the
2486
- `std::numeric_limits<`*`floating-point-type`*`>` traits associated with
2487
- the floating-point type [[limits.syn]]. The floating-point
2488
  environment [[cfenv]] for atomic arithmetic operations on
2489
  *`floating-point-type`* may be different than the calling thread’s
2490
  floating-point environment.
2491
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2492
  ``` cpp
2493
- floating-point-type operator op=(floating-point-type operand) const noexcept;
 
2494
  ```
2495
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2496
  *Effects:* Equivalent to:
2497
  `return fetch_`*`key`*`(operand) `*`op`*` operand;`
2498
 
2499
- #### Partial specialization for pointers <a id="atomics.ref.pointer">[[atomics.ref.pointer]]</a>
 
 
 
 
 
 
 
 
2500
 
2501
  ``` cpp
2502
  namespace std {
2503
- template<class T> struct atomic_ref<T*> {
2504
  private:
2505
- T** ptr; // exposition only
2506
 
2507
  public:
2508
- using value_type = T*;
2509
  using difference_type = ptrdiff_t;
2510
  static constexpr size_t required_alignment = implementation-defined // required alignment for atomic_ref type's operations;
2511
 
2512
  static constexpr bool is_always_lock_free = implementation-defined // whether a given atomic_ref type's operations are always lock free;
2513
  bool is_lock_free() const noexcept;
2514
 
2515
- explicit atomic_ref(T*&);
2516
- atomic_ref(const atomic_ref&) noexcept;
2517
  atomic_ref& operator=(const atomic_ref&) = delete;
2518
 
2519
- void store(T*, memory_order = memory_order::seq_cst) const noexcept;
2520
- T* operator=(T*) const noexcept;
2521
- T* load(memory_order = memory_order::seq_cst) const noexcept;
2522
- operator T*() const noexcept;
2523
 
2524
- T* exchange(T*, memory_order = memory_order::seq_cst) const noexcept;
2525
- bool compare_exchange_weak(T*&, T*,
 
2526
  memory_order, memory_order) const noexcept;
2527
- bool compare_exchange_strong(T*&, T*,
2528
  memory_order, memory_order) const noexcept;
2529
- bool compare_exchange_weak(T*&, T*,
 
 
 
 
 
 
 
2530
  memory_order = memory_order::seq_cst) const noexcept;
2531
- bool compare_exchange_strong(T*&, T*,
 
 
2532
  memory_order = memory_order::seq_cst) const noexcept;
2533
 
2534
- T* fetch_add(difference_type, memory_order = memory_order::seq_cst) const noexcept;
2535
- T* fetch_sub(difference_type, memory_order = memory_order::seq_cst) const noexcept;
 
 
 
 
 
 
2536
 
2537
- T* operator++(int) const noexcept;
2538
- T* operator--(int) const noexcept;
2539
- T* operator++() const noexcept;
2540
- T* operator--() const noexcept;
2541
- T* operator+=(difference_type) const noexcept;
2542
- T* operator-=(difference_type) const noexcept;
2543
 
2544
- void wait(T*, memory_order = memory_order::seq_cst) const noexcept;
2545
- void notify_one() const noexcept;
2546
- void notify_all() const noexcept;
 
2547
  };
2548
  }
2549
  ```
2550
 
2551
  Descriptions are provided below only for members that differ from the
@@ -2554,14 +3108,18 @@ primary template.
2554
  The following operations perform arithmetic computations. The
2555
  correspondence among key, operator, and computation is specified in
2556
  [[atomic.types.pointer.comp]].
2557
 
2558
  ``` cpp
2559
- T* fetch_key(difference_type operand, memory_order order = memory_order::seq_cst) const noexcept;
 
2560
  ```
2561
 
2562
- *Mandates:* `T` is a complete object type.
 
 
 
2563
 
2564
  *Effects:* Atomically replaces the value referenced by `*ptr` with the
2565
  result of the computation applied to the value referenced by `*ptr` and
2566
  the given operand. Memory is affected according to the value of `order`.
2567
  These operations are atomic read-modify-write
@@ -2571,41 +3129,91 @@ operations [[intro.races]].
2571
  the effects.
2572
 
2573
  *Remarks:* The result may be an undefined address, but the operations
2574
  otherwise have no undefined behavior.
2575
 
 
 
 
 
 
 
 
 
 
2576
  ``` cpp
2577
- T* operator op=(difference_type operand) const noexcept;
 
2578
  ```
2579
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2580
  *Effects:* Equivalent to:
2581
  `return fetch_`*`key`*`(operand) `*`op`*` operand;`
2582
 
2583
  #### Member operators common to integers and pointers to objects <a id="atomics.ref.memop">[[atomics.ref.memop]]</a>
2584
 
 
 
 
 
2585
  ``` cpp
2586
- value_type operator++(int) const noexcept;
2587
  ```
2588
 
 
 
2589
  *Effects:* Equivalent to: `return fetch_add(1);`
2590
 
2591
  ``` cpp
2592
- value_type operator--(int) const noexcept;
2593
  ```
2594
 
 
 
2595
  *Effects:* Equivalent to: `return fetch_sub(1);`
2596
 
2597
  ``` cpp
2598
- value_type operator++() const noexcept;
2599
  ```
2600
 
 
 
2601
  *Effects:* Equivalent to: `return fetch_add(1) + 1;`
2602
 
2603
  ``` cpp
2604
- value_type operator--() const noexcept;
2605
  ```
2606
 
 
 
2607
  *Effects:* Equivalent to: `return fetch_sub(1) - 1;`
2608
 
2609
  ### Class template `atomic` <a id="atomics.types.generic">[[atomics.types.generic]]</a>
2610
 
2611
  #### General <a id="atomics.types.generic.general">[[atomics.types.generic.general]]</a>
@@ -2625,35 +3233,35 @@ namespace std {
2625
  atomic(const atomic&) = delete;
2626
  atomic& operator=(const atomic&) = delete;
2627
  atomic& operator=(const atomic&) volatile = delete;
2628
 
2629
  T load(memory_order = memory_order::seq_cst) const volatile noexcept;
2630
- T load(memory_order = memory_order::seq_cst) const noexcept;
2631
  operator T() const volatile noexcept;
2632
- operator T() const noexcept;
2633
  void store(T, memory_order = memory_order::seq_cst) volatile noexcept;
2634
- void store(T, memory_order = memory_order::seq_cst) noexcept;
2635
  T operator=(T) volatile noexcept;
2636
- T operator=(T) noexcept;
2637
 
2638
  T exchange(T, memory_order = memory_order::seq_cst) volatile noexcept;
2639
- T exchange(T, memory_order = memory_order::seq_cst) noexcept;
2640
  bool compare_exchange_weak(T&, T, memory_order, memory_order) volatile noexcept;
2641
- bool compare_exchange_weak(T&, T, memory_order, memory_order) noexcept;
2642
  bool compare_exchange_strong(T&, T, memory_order, memory_order) volatile noexcept;
2643
- bool compare_exchange_strong(T&, T, memory_order, memory_order) noexcept;
2644
  bool compare_exchange_weak(T&, T, memory_order = memory_order::seq_cst) volatile noexcept;
2645
- bool compare_exchange_weak(T&, T, memory_order = memory_order::seq_cst) noexcept;
2646
  bool compare_exchange_strong(T&, T, memory_order = memory_order::seq_cst) volatile noexcept;
2647
- bool compare_exchange_strong(T&, T, memory_order = memory_order::seq_cst) noexcept;
2648
 
2649
  void wait(T, memory_order = memory_order::seq_cst) const volatile noexcept;
2650
- void wait(T, memory_order = memory_order::seq_cst) const noexcept;
2651
  void notify_one() volatile noexcept;
2652
- void notify_one() noexcept;
2653
  void notify_all() volatile noexcept;
2654
- void notify_all() noexcept;
2655
  };
2656
  }
2657
  ```
2658
 
2659
  The template argument for `T` shall meet the *Cpp17CopyConstructible*
@@ -2661,19 +3269,21 @@ and *Cpp17CopyAssignable* requirements. The program is ill-formed if any
2661
  of
2662
 
2663
  - `is_trivially_copyable_v<T>`,
2664
  - `is_copy_constructible_v<T>`,
2665
  - `is_move_constructible_v<T>`,
2666
- - `is_copy_assignable_v<T>`, or
2667
- - `is_move_assignable_v<T>`
 
2668
 
2669
  is `false`.
2670
 
2671
  [*Note 1*: Type arguments that are not also statically initializable
2672
  can be difficult to use. — *end note*]
2673
 
2674
- The specialization `atomic<bool>` is a standard-layout struct.
 
2675
 
2676
  [*Note 2*: The representation of an atomic specialization need not have
2677
  the same size and alignment requirement as its corresponding argument
2678
  type. — *end note*]
2679
 
@@ -2681,11 +3291,11 @@ type. — *end note*]
2681
 
2682
  ``` cpp
2683
  constexpr atomic() noexcept(is_nothrow_default_constructible_v<T>);
2684
  ```
2685
 
2686
- *Mandates:* `is_default_constructible_v<T>` is `true`.
2687
 
2688
  *Effects:* Initializes the atomic object with the value of `T()`.
2689
  Initialization is not an atomic operation [[intro.multithread]].
2690
 
2691
  ``` cpp
@@ -2725,27 +3335,26 @@ otherwise.
2725
  consistent with the value of `is_always_lock_free` for the same
2726
  type. — *end note*]
2727
 
2728
  ``` cpp
2729
  void store(T desired, memory_order order = memory_order::seq_cst) volatile noexcept;
2730
- void store(T desired, memory_order order = memory_order::seq_cst) noexcept;
2731
  ```
2732
 
2733
  *Constraints:* For the `volatile` overload of this function,
2734
  `is_always_lock_free` is `true`.
2735
 
2736
- *Preconditions:* The `order` argument is neither
2737
- `memory_order::consume`, `memory_order::acquire`, nor
2738
- `memory_order::acq_rel`.
2739
 
2740
  *Effects:* Atomically replaces the value pointed to by `this` with the
2741
  value of `desired`. Memory is affected according to the value of
2742
  `order`.
2743
 
2744
  ``` cpp
2745
  T operator=(T desired) volatile noexcept;
2746
- T operator=(T desired) noexcept;
2747
  ```
2748
 
2749
  *Constraints:* For the `volatile` overload of this function,
2750
  `is_always_lock_free` is `true`.
2751
 
@@ -2753,36 +3362,36 @@ T operator=(T desired) noexcept;
2753
 
2754
  *Returns:* `desired`.
2755
 
2756
  ``` cpp
2757
  T load(memory_order order = memory_order::seq_cst) const volatile noexcept;
2758
- T load(memory_order order = memory_order::seq_cst) const noexcept;
2759
  ```
2760
 
2761
  *Constraints:* For the `volatile` overload of this function,
2762
  `is_always_lock_free` is `true`.
2763
 
2764
- *Preconditions:* The `order` argument is neither `memory_order::release`
2765
- nor `memory_order::acq_rel`.
2766
 
2767
  *Effects:* Memory is affected according to the value of `order`.
2768
 
2769
  *Returns:* Atomically returns the value pointed to by `this`.
2770
 
2771
  ``` cpp
2772
  operator T() const volatile noexcept;
2773
- operator T() const noexcept;
2774
  ```
2775
 
2776
  *Constraints:* For the `volatile` overload of this function,
2777
  `is_always_lock_free` is `true`.
2778
 
2779
  *Effects:* Equivalent to: `return load();`
2780
 
2781
  ``` cpp
2782
  T exchange(T desired, memory_order order = memory_order::seq_cst) volatile noexcept;
2783
- T exchange(T desired, memory_order order = memory_order::seq_cst) noexcept;
2784
  ```
2785
 
2786
  *Constraints:* For the `volatile` overload of this function,
2787
  `is_always_lock_free` is `true`.
2788
 
@@ -2795,31 +3404,31 @@ operations [[intro.multithread]].
2795
  before the effects.
2796
 
2797
  ``` cpp
2798
  bool compare_exchange_weak(T& expected, T desired,
2799
  memory_order success, memory_order failure) volatile noexcept;
2800
- bool compare_exchange_weak(T& expected, T desired,
2801
  memory_order success, memory_order failure) noexcept;
2802
  bool compare_exchange_strong(T& expected, T desired,
2803
  memory_order success, memory_order failure) volatile noexcept;
2804
- bool compare_exchange_strong(T& expected, T desired,
2805
  memory_order success, memory_order failure) noexcept;
2806
  bool compare_exchange_weak(T& expected, T desired,
2807
  memory_order order = memory_order::seq_cst) volatile noexcept;
2808
- bool compare_exchange_weak(T& expected, T desired,
2809
  memory_order order = memory_order::seq_cst) noexcept;
2810
  bool compare_exchange_strong(T& expected, T desired,
2811
  memory_order order = memory_order::seq_cst) volatile noexcept;
2812
- bool compare_exchange_strong(T& expected, T desired,
2813
  memory_order order = memory_order::seq_cst) noexcept;
2814
  ```
2815
 
2816
  *Constraints:* For the `volatile` overload of this function,
2817
  `is_always_lock_free` is `true`.
2818
 
2819
- *Preconditions:* The `failure` argument is neither
2820
- `memory_order::release` nor `memory_order::acq_rel`.
2821
 
2822
  *Effects:* Retrieves the value in `expected`. It then atomically
2823
  compares the value representation of the value pointed to by `this` for
2824
  equality with that previously retrieved from `expected`, and if true,
2825
  replaces the value pointed to by `this` with that in `desired`. If and
@@ -2904,14 +3513,14 @@ preferable. — *end note*]
2904
 
2905
  [*Note 6*: Under cases where the `memcpy` and `memcmp` semantics of the
2906
  compare-and-exchange operations apply, the comparisons can fail for
2907
  values that compare equal with `operator==` if the value representation
2908
  has trap bits or alternate representations of the same value. Notably,
2909
- on implementations conforming to ISO/IEC/IEEE 60559, floating-point
2910
- `-0.0` and `+0.0` will not compare equal with `memcmp` but will compare
2911
- equal with `operator==`, and NaNs with the same payload will compare
2912
- equal with `memcmp` but will not compare equal with
2913
  `operator==`. — *end note*]
2914
 
2915
  [*Note 7*:
2916
 
2917
  Because compare-and-exchange acts on an object’s value representation,
@@ -2958,15 +3567,15 @@ bool party(pony desired) {
2958
 
2959
  — *end note*]
2960
 
2961
  ``` cpp
2962
  void wait(T old, memory_order order = memory_order::seq_cst) const volatile noexcept;
2963
- void wait(T old, memory_order order = memory_order::seq_cst) const noexcept;
2964
  ```
2965
 
2966
- *Preconditions:* `order` is neither `memory_order::release` nor
2967
- `memory_order::acq_rel`.
2968
 
2969
  *Effects:* Repeatedly performs the following steps, in order:
2970
 
2971
  - Evaluates `load(order)` and compares its value representation for
2972
  equality against that of `old`.
@@ -2977,11 +3586,11 @@ void wait(T old, memory_order order = memory_order::seq_cst) const noexcept;
2977
  *Remarks:* This function is an atomic waiting
2978
  operation [[atomics.wait]].
2979
 
2980
  ``` cpp
2981
  void notify_one() volatile noexcept;
2982
- void notify_one() noexcept;
2983
  ```
2984
 
2985
  *Effects:* Unblocks the execution of at least one atomic waiting
2986
  operation that is eligible to be unblocked [[atomics.wait]] by this
2987
  call, if any such atomic waiting operations exist.
@@ -2989,11 +3598,11 @@ call, if any such atomic waiting operations exist.
2989
  *Remarks:* This function is an atomic notifying
2990
  operation [[atomics.wait]].
2991
 
2992
  ``` cpp
2993
  void notify_all() volatile noexcept;
2994
- void notify_all() noexcept;
2995
  ```
2996
 
2997
  *Effects:* Unblocks the execution of all atomic waiting operations that
2998
  are eligible to be unblocked [[atomics.wait]] by this call.
2999
 
@@ -3029,85 +3638,122 @@ namespace std {
3029
  atomic(const atomic&) = delete;
3030
  atomic& operator=(const atomic&) = delete;
3031
  atomic& operator=(const atomic&) volatile = delete;
3032
 
3033
  void store(integral-type, memory_order = memory_order::seq_cst) volatile noexcept;
3034
- void store(integral-type, memory_order = memory_order::seq_cst) noexcept;
3035
  integral-type operator=(integral-type) volatile noexcept;
3036
- integral-type operator=(integral-type) noexcept;
3037
  integral-type load(memory_order = memory_order::seq_cst) const volatile noexcept;
3038
- integral-type load(memory_order = memory_order::seq_cst) const noexcept;
3039
  operator integral-type() const volatile noexcept;
3040
- operator integral-type() const noexcept;
3041
 
3042
  integral-type exchange(integral-type,
3043
  memory_order = memory_order::seq_cst) volatile noexcept;
3044
- integral-type exchange(integral-type,
3045
  memory_order = memory_order::seq_cst) noexcept;
3046
  bool compare_exchange_weak(integral-type&, integral-type,
3047
  memory_order, memory_order) volatile noexcept;
3048
- bool compare_exchange_weak(integral-type&, integral-type,
3049
  memory_order, memory_order) noexcept;
3050
  bool compare_exchange_strong(integral-type&, integral-type,
3051
  memory_order, memory_order) volatile noexcept;
3052
- bool compare_exchange_strong(integral-type&, integral-type,
3053
  memory_order, memory_order) noexcept;
3054
  bool compare_exchange_weak(integral-type&, integral-type,
3055
  memory_order = memory_order::seq_cst) volatile noexcept;
3056
- bool compare_exchange_weak(integral-type&, integral-type,
3057
  memory_order = memory_order::seq_cst) noexcept;
3058
  bool compare_exchange_strong(integral-type&, integral-type,
3059
  memory_order = memory_order::seq_cst) volatile noexcept;
3060
- bool compare_exchange_strong(integral-type&, integral-type,
3061
  memory_order = memory_order::seq_cst) noexcept;
3062
 
3063
  integral-type fetch_add(integral-type,
3064
  memory_order = memory_order::seq_cst) volatile noexcept;
3065
- integral-type fetch_add(integral-type,
3066
  memory_order = memory_order::seq_cst) noexcept;
3067
  integral-type fetch_sub(integral-type,
3068
  memory_order = memory_order::seq_cst) volatile noexcept;
3069
- integral-type fetch_sub(integral-type,
3070
  memory_order = memory_order::seq_cst) noexcept;
3071
  integral-type fetch_and(integral-type,
3072
  memory_order = memory_order::seq_cst) volatile noexcept;
3073
- integral-type fetch_and(integral-type,
3074
  memory_order = memory_order::seq_cst) noexcept;
3075
  integral-type fetch_or(integral-type,
3076
  memory_order = memory_order::seq_cst) volatile noexcept;
3077
- integral-type fetch_or(integral-type,
3078
  memory_order = memory_order::seq_cst) noexcept;
3079
  integral-type fetch_xor(integral-type,
3080
  memory_order = memory_order::seq_cst) volatile noexcept;
3081
- integral-type fetch_xor(integral-type,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3082
  memory_order = memory_order::seq_cst) noexcept;
3083
 
3084
  integral-type operator++(int) volatile noexcept;
3085
- integral-type operator++(int) noexcept;
3086
  integral-type operator--(int) volatile noexcept;
3087
- integral-type operator--(int) noexcept;
3088
  integral-type operator++() volatile noexcept;
3089
- integral-type operator++() noexcept;
3090
  integral-type operator--() volatile noexcept;
3091
- integral-type operator--() noexcept;
3092
  integral-type operator+=(integral-type) volatile noexcept;
3093
- integral-type operator+=(integral-type) noexcept;
3094
  integral-type operator-=(integral-type) volatile noexcept;
3095
- integral-type operator-=(integral-type) noexcept;
3096
  integral-type operator&=(integral-type) volatile noexcept;
3097
- integral-type operator&=(integral-type) noexcept;
3098
  integral-type operator|=(integral-type) volatile noexcept;
3099
- integral-type operator|=(integral-type) noexcept;
3100
  integral-type operator^=(integral-type) volatile noexcept;
3101
- integral-type operator^=(integral-type) noexcept;
3102
 
3103
  void wait(integral-type, memory_order = memory_order::seq_cst) const volatile noexcept;
3104
- void wait(integral-type, memory_order = memory_order::seq_cst) const noexcept;
3105
  void notify_one() volatile noexcept;
3106
- void notify_one() noexcept;
3107
  void notify_all() volatile noexcept;
3108
- void notify_all() noexcept;
3109
  };
3110
  }
3111
  ```
3112
 
3113
  The atomic integral specializations are standard-layout structs. They
@@ -3121,18 +3767,21 @@ correspondence among key, operator, and computation is specified in
3121
  [[atomic.types.int.comp]].
3122
 
3123
  **Table: Atomic arithmetic computations** <a id="atomic.types.int.comp">[atomic.types.int.comp]</a>
3124
 
3125
  | | | | | | |
3126
- | ----- | --- | -------------------- | ----- | --- | -------------------- |
3127
- | `add` | `+` | addition | `sub` | `-` | subtraction |
3128
- | `or` | `|` | bitwise inclusive or | `xor` | `^` | bitwise exclusive or |
3129
- | `and` | `&` | bitwise and | | | |
 
3130
 
3131
  ``` cpp
3132
- T fetch_key(T operand, memory_order order = memory_order::seq_cst) volatile noexcept;
3133
- T fetch_key(T operand, memory_order order = memory_order::seq_cst) noexcept;
 
 
3134
  ```
3135
 
3136
  *Constraints:* For the `volatile` overload of this function,
3137
  `is_always_lock_free` is `true`.
3138
 
@@ -3143,21 +3792,59 @@ the given `operand`. Memory is affected according to the value of
3143
  operations [[intro.multithread]].
3144
 
3145
  *Returns:* Atomically, the value pointed to by `this` immediately before
3146
  the effects.
3147
 
3148
- *Remarks:* For signed integer types, the result is as if the object
3149
- value and parameters were converted to their corresponding unsigned
3150
- types, the computation performed on those types, and the result
3151
- converted back to the signed type.
3152
 
3153
  [*Note 1*: There are no undefined results arising from the
3154
  computation. — *end note*]
3155
 
 
 
 
 
 
3156
  ``` cpp
3157
- T operator op=(T operand) volatile noexcept;
3158
- T operator op=(T operand) noexcept;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3159
  ```
3160
 
3161
  *Constraints:* For the `volatile` overload of this function,
3162
  `is_always_lock_free` is `true`.
3163
 
@@ -3187,59 +3874,117 @@ namespace std {
3187
  atomic(const atomic&) = delete;
3188
  atomic& operator=(const atomic&) = delete;
3189
  atomic& operator=(const atomic&) volatile = delete;
3190
 
3191
  void store(floating-point-type, memory_order = memory_order::seq_cst) volatile noexcept;
3192
- void store(floating-point-type, memory_order = memory_order::seq_cst) noexcept;
3193
  floating-point-type operator=(floating-point-type) volatile noexcept;
3194
- floating-point-type operator=(floating-point-type) noexcept;
3195
  floating-point-type load(memory_order = memory_order::seq_cst) volatile noexcept;
3196
- floating-point-type load(memory_order = memory_order::seq_cst) noexcept;
3197
  operator floating-point-type() volatile noexcept;
3198
- operator floating-point-type() noexcept;
3199
 
3200
  floating-point-type exchange(floating-point-type,
3201
  memory_order = memory_order::seq_cst) volatile noexcept;
3202
- floating-point-type exchange(floating-point-type,
3203
  memory_order = memory_order::seq_cst) noexcept;
3204
  bool compare_exchange_weak(floating-point-type&, floating-point-type,
3205
  memory_order, memory_order) volatile noexcept;
3206
- bool compare_exchange_weak(floating-point-type&, floating-point-type,
3207
  memory_order, memory_order) noexcept;
3208
  bool compare_exchange_strong(floating-point-type&, floating-point-type,
3209
  memory_order, memory_order) volatile noexcept;
3210
- bool compare_exchange_strong(floating-point-type&, floating-point-type,
3211
  memory_order, memory_order) noexcept;
3212
  bool compare_exchange_weak(floating-point-type&, floating-point-type,
3213
  memory_order = memory_order::seq_cst) volatile noexcept;
3214
- bool compare_exchange_weak(floating-point-type&, floating-point-type,
3215
  memory_order = memory_order::seq_cst) noexcept;
3216
  bool compare_exchange_strong(floating-point-type&, floating-point-type,
3217
  memory_order = memory_order::seq_cst) volatile noexcept;
3218
- bool compare_exchange_strong(floating-point-type&, floating-point-type,
3219
  memory_order = memory_order::seq_cst) noexcept;
3220
 
3221
  floating-point-type fetch_add(floating-point-type,
3222
  memory_order = memory_order::seq_cst) volatile noexcept;
3223
- floating-point-type fetch_add(floating-point-type,
3224
  memory_order = memory_order::seq_cst) noexcept;
3225
  floating-point-type fetch_sub(floating-point-type,
3226
  memory_order = memory_order::seq_cst) volatile noexcept;
3227
- floating-point-type fetch_sub(floating-point-type,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3228
  memory_order = memory_order::seq_cst) noexcept;
3229
 
3230
  floating-point-type operator+=(floating-point-type) volatile noexcept;
3231
- floating-point-type operator+=(floating-point-type) noexcept;
3232
  floating-point-type operator-=(floating-point-type) volatile noexcept;
3233
- floating-point-type operator-=(floating-point-type) noexcept;
3234
 
3235
  void wait(floating-point-type, memory_order = memory_order::seq_cst) const volatile noexcept;
3236
- void wait(floating-point-type, memory_order = memory_order::seq_cst) const noexcept;
 
3237
  void notify_one() volatile noexcept;
3238
- void notify_one() noexcept;
3239
  void notify_all() volatile noexcept;
3240
- void notify_all() noexcept;
3241
  };
3242
  }
3243
  ```
3244
 
3245
  The atomic floating-point specializations are standard-layout structs.
@@ -3248,15 +3993,19 @@ They each have a trivial destructor.
3248
  Descriptions are provided below only for members that differ from the
3249
  primary template.
3250
 
3251
  The following operations perform arithmetic addition and subtraction
3252
  computations. The correspondence among key, operator, and computation is
3253
- specified in [[atomic.types.int.comp]].
 
 
3254
 
3255
  ``` cpp
3256
- T fetch_key(T operand, memory_order order = memory_order::seq_cst) volatile noexcept;
3257
- T fetch_key(T operand, memory_order order = memory_order::seq_cst) noexcept;
 
 
3258
  ```
3259
 
3260
  *Constraints:* For the `volatile` overload of this function,
3261
  `is_always_lock_free` is `true`.
3262
 
@@ -3277,13 +4026,92 @@ otherwise have no undefined behavior. Atomic arithmetic operations on
3277
  the floating-point type [[limits.syn]]. The floating-point
3278
  environment [[cfenv]] for atomic arithmetic operations on
3279
  *`floating-point-type`* may be different than the calling thread’s
3280
  floating-point environment.
3281
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3282
  ``` cpp
3283
- T operator op=(T operand) volatile noexcept;
3284
- T operator op=(T operand) noexcept;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3285
  ```
3286
 
3287
  *Constraints:* For the `volatile` overload of this function,
3288
  `is_always_lock_free` is `true`.
3289
 
@@ -3317,57 +4145,70 @@ namespace std {
3317
  atomic(const atomic&) = delete;
3318
  atomic& operator=(const atomic&) = delete;
3319
  atomic& operator=(const atomic&) volatile = delete;
3320
 
3321
  void store(T*, memory_order = memory_order::seq_cst) volatile noexcept;
3322
- void store(T*, memory_order = memory_order::seq_cst) noexcept;
3323
  T* operator=(T*) volatile noexcept;
3324
- T* operator=(T*) noexcept;
3325
  T* load(memory_order = memory_order::seq_cst) const volatile noexcept;
3326
- T* load(memory_order = memory_order::seq_cst) const noexcept;
3327
  operator T*() const volatile noexcept;
3328
- operator T*() const noexcept;
3329
 
3330
  T* exchange(T*, memory_order = memory_order::seq_cst) volatile noexcept;
3331
- T* exchange(T*, memory_order = memory_order::seq_cst) noexcept;
3332
  bool compare_exchange_weak(T*&, T*, memory_order, memory_order) volatile noexcept;
3333
- bool compare_exchange_weak(T*&, T*, memory_order, memory_order) noexcept;
3334
  bool compare_exchange_strong(T*&, T*, memory_order, memory_order) volatile noexcept;
3335
- bool compare_exchange_strong(T*&, T*, memory_order, memory_order) noexcept;
3336
  bool compare_exchange_weak(T*&, T*,
3337
  memory_order = memory_order::seq_cst) volatile noexcept;
3338
- bool compare_exchange_weak(T*&, T*,
3339
  memory_order = memory_order::seq_cst) noexcept;
3340
  bool compare_exchange_strong(T*&, T*,
3341
  memory_order = memory_order::seq_cst) volatile noexcept;
3342
- bool compare_exchange_strong(T*&, T*,
3343
  memory_order = memory_order::seq_cst) noexcept;
3344
 
3345
  T* fetch_add(ptrdiff_t, memory_order = memory_order::seq_cst) volatile noexcept;
3346
- T* fetch_add(ptrdiff_t, memory_order = memory_order::seq_cst) noexcept;
3347
  T* fetch_sub(ptrdiff_t, memory_order = memory_order::seq_cst) volatile noexcept;
3348
- T* fetch_sub(ptrdiff_t, memory_order = memory_order::seq_cst) noexcept;
 
 
 
 
 
 
 
 
 
 
 
 
 
3349
 
3350
  T* operator++(int) volatile noexcept;
3351
- T* operator++(int) noexcept;
3352
  T* operator--(int) volatile noexcept;
3353
- T* operator--(int) noexcept;
3354
  T* operator++() volatile noexcept;
3355
- T* operator++() noexcept;
3356
  T* operator--() volatile noexcept;
3357
- T* operator--() noexcept;
3358
  T* operator+=(ptrdiff_t) volatile noexcept;
3359
- T* operator+=(ptrdiff_t) noexcept;
3360
  T* operator-=(ptrdiff_t) volatile noexcept;
3361
- T* operator-=(ptrdiff_t) noexcept;
3362
 
3363
  void wait(T*, memory_order = memory_order::seq_cst) const volatile noexcept;
3364
- void wait(T*, memory_order = memory_order::seq_cst) const noexcept;
3365
  void notify_one() volatile noexcept;
3366
- void notify_one() noexcept;
3367
  void notify_all() volatile noexcept;
3368
- void notify_all() noexcept;
3369
  };
3370
  }
3371
  ```
3372
 
3373
  There is a partial specialization of the `atomic` class template for
@@ -3384,14 +4225,15 @@ among key, operator, and computation is specified in
3384
  **Table: Atomic pointer computations** <a id="atomic.types.pointer.comp">[atomic.types.pointer.comp]</a>
3385
 
3386
  | | | | | | |
3387
  | ----- | --- | -------- | ----- | --- | ----------- |
3388
  | `add` | `+` | addition | `sub` | `-` | subtraction |
 
3389
 
3390
  ``` cpp
3391
- T* fetch_key(ptrdiff_t operand, memory_order order = memory_order::seq_cst) volatile noexcept;
3392
- T* fetch_key(ptrdiff_t operand, memory_order order = memory_order::seq_cst) noexcept;
3393
  ```
3394
 
3395
  *Constraints:* For the `volatile` overload of this function,
3396
  `is_always_lock_free` is `true`.
3397
 
@@ -3410,13 +4252,51 @@ operations [[intro.multithread]].
3410
  the effects.
3411
 
3412
  *Remarks:* The result may be an undefined address, but the operations
3413
  otherwise have no undefined behavior.
3414
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3415
  ``` cpp
3416
  T* operator op=(ptrdiff_t operand) volatile noexcept;
3417
- T* operator op=(ptrdiff_t operand) noexcept;
3418
  ```
3419
 
3420
  *Constraints:* For the `volatile` overload of this function,
3421
  `is_always_lock_free` is `true`.
3422
 
@@ -3425,41 +4305,41 @@ T* operator op=(ptrdiff_t operand) noexcept;
3425
 
3426
  #### Member operators common to integers and pointers to objects <a id="atomics.types.memop">[[atomics.types.memop]]</a>
3427
 
3428
  ``` cpp
3429
  value_type operator++(int) volatile noexcept;
3430
- value_type operator++(int) noexcept;
3431
  ```
3432
 
3433
  *Constraints:* For the `volatile` overload of this function,
3434
  `is_always_lock_free` is `true`.
3435
 
3436
  *Effects:* Equivalent to: `return fetch_add(1);`
3437
 
3438
  ``` cpp
3439
  value_type operator--(int) volatile noexcept;
3440
- value_type operator--(int) noexcept;
3441
  ```
3442
 
3443
  *Constraints:* For the `volatile` overload of this function,
3444
  `is_always_lock_free` is `true`.
3445
 
3446
  *Effects:* Equivalent to: `return fetch_sub(1);`
3447
 
3448
  ``` cpp
3449
  value_type operator++() volatile noexcept;
3450
- value_type operator++() noexcept;
3451
  ```
3452
 
3453
  *Constraints:* For the `volatile` overload of this function,
3454
  `is_always_lock_free` is `true`.
3455
 
3456
  *Effects:* Equivalent to: `return fetch_add(1) + 1;`
3457
 
3458
  ``` cpp
3459
  value_type operator--() volatile noexcept;
3460
- value_type operator--() noexcept;
3461
  ```
3462
 
3463
  *Constraints:* For the `volatile` overload of this function,
3464
  `is_always_lock_free` is `true`.
3465
 
@@ -3532,33 +4412,36 @@ namespace std {
3532
  static constexpr bool is_always_lock_free = implementation-defined // whether a given atomic type's operations are always lock free;
3533
  bool is_lock_free() const noexcept;
3534
 
3535
  constexpr atomic() noexcept;
3536
  constexpr atomic(nullptr_t) noexcept : atomic() { }
3537
- atomic(shared_ptr<T> desired) noexcept;
3538
  atomic(const atomic&) = delete;
3539
  void operator=(const atomic&) = delete;
3540
 
3541
- shared_ptr<T> load(memory_order order = memory_order::seq_cst) const noexcept;
3542
- operator shared_ptr<T>() const noexcept;
3543
- void store(shared_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept;
3544
- void operator=(shared_ptr<T> desired) noexcept;
 
 
3545
 
3546
- shared_ptr<T> exchange(shared_ptr<T> desired,
3547
  memory_order order = memory_order::seq_cst) noexcept;
3548
- bool compare_exchange_weak(shared_ptr<T>& expected, shared_ptr<T> desired,
3549
  memory_order success, memory_order failure) noexcept;
3550
- bool compare_exchange_strong(shared_ptr<T>& expected, shared_ptr<T> desired,
3551
  memory_order success, memory_order failure) noexcept;
3552
- bool compare_exchange_weak(shared_ptr<T>& expected, shared_ptr<T> desired,
3553
  memory_order order = memory_order::seq_cst) noexcept;
3554
- bool compare_exchange_strong(shared_ptr<T>& expected, shared_ptr<T> desired,
3555
  memory_order order = memory_order::seq_cst) noexcept;
3556
 
3557
- void wait(shared_ptr<T> old, memory_order order = memory_order::seq_cst) const noexcept;
3558
- void notify_one() noexcept;
3559
- void notify_all() noexcept;
 
3560
 
3561
  private:
3562
  shared_ptr<T> p; // exposition only
3563
  };
3564
  }
@@ -3566,14 +4449,14 @@ namespace std {
3566
 
3567
  ``` cpp
3568
  constexpr atomic() noexcept;
3569
  ```
3570
 
3571
- *Effects:* Initializes `p{}`.
3572
 
3573
  ``` cpp
3574
- atomic(shared_ptr<T> desired) noexcept;
3575
  ```
3576
 
3577
  *Effects:* Initializes the object with the value `desired`.
3578
  Initialization is not an atomic operation [[intro.multithread]].
3579
 
@@ -3583,63 +4466,70 @@ the just-constructed object `A` to another thread via
3583
  `memory_order::relaxed` operations on a suitable atomic pointer
3584
  variable, and then immediately accessing `A` in the receiving thread.
3585
  This results in undefined behavior. — *end note*]
3586
 
3587
  ``` cpp
3588
- void store(shared_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept;
3589
  ```
3590
 
3591
- *Preconditions:* `order` is neither `memory_order::consume`,
3592
- `memory_order::acquire`, nor `memory_order::acq_rel`.
3593
 
3594
  *Effects:* Atomically replaces the value pointed to by `this` with the
3595
  value of `desired` as if by `p.swap(desired)`. Memory is affected
3596
  according to the value of `order`.
3597
 
3598
  ``` cpp
3599
- void operator=(shared_ptr<T> desired) noexcept;
3600
  ```
3601
 
3602
  *Effects:* Equivalent to `store(desired)`.
3603
 
3604
  ``` cpp
3605
- shared_ptr<T> load(memory_order order = memory_order::seq_cst) const noexcept;
3606
  ```
3607
 
3608
- *Preconditions:* `order` is neither `memory_order::release` nor
3609
- `memory_order::acq_rel`.
 
 
 
 
 
 
3610
 
3611
  *Effects:* Memory is affected according to the value of `order`.
3612
 
3613
  *Returns:* Atomically returns `p`.
3614
 
3615
  ``` cpp
3616
- operator shared_ptr<T>() const noexcept;
3617
  ```
3618
 
3619
  *Effects:* Equivalent to: `return load();`
3620
 
3621
  ``` cpp
3622
- shared_ptr<T> exchange(shared_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept;
 
3623
  ```
3624
 
3625
  *Effects:* Atomically replaces `p` with `desired` as if by
3626
  `p.swap(desired)`. Memory is affected according to the value of `order`.
3627
  This is an atomic read-modify-write operation [[intro.races]].
3628
 
3629
  *Returns:* Atomically returns the value of `p` immediately before the
3630
  effects.
3631
 
3632
  ``` cpp
3633
- bool compare_exchange_weak(shared_ptr<T>& expected, shared_ptr<T> desired,
3634
  memory_order success, memory_order failure) noexcept;
3635
- bool compare_exchange_strong(shared_ptr<T>& expected, shared_ptr<T> desired,
3636
  memory_order success, memory_order failure) noexcept;
3637
  ```
3638
 
3639
- *Preconditions:* `failure` is neither `memory_order::release` nor
3640
- `memory_order::acq_rel`.
3641
 
3642
  *Effects:* If `p` is equivalent to `expected`, assigns `desired` to `p`
3643
  and has synchronization semantics corresponding to the value of
3644
  `success`, otherwise assigns `p` to `expected` and has synchronization
3645
  semantics corresponding to the value of `failure`.
@@ -3660,11 +4550,11 @@ object in the attempted atomic update. The `use_count` update
3660
  corresponding to the write to `expected` is part of the atomic
3661
  operation. The write to `expected` itself is not required to be part of
3662
  the atomic operation.
3663
 
3664
  ``` cpp
3665
- bool compare_exchange_weak(shared_ptr<T>& expected, shared_ptr<T> desired,
3666
  memory_order order = memory_order::seq_cst) noexcept;
3667
  ```
3668
 
3669
  *Effects:* Equivalent to:
3670
 
@@ -3676,11 +4566,11 @@ where `fail_order` is the same as `order` except that a value of
3676
  `memory_order::acq_rel` shall be replaced by the value
3677
  `memory_order::acquire` and a value of `memory_order::release` shall be
3678
  replaced by the value `memory_order::relaxed`.
3679
 
3680
  ``` cpp
3681
- bool compare_exchange_strong(shared_ptr<T>& expected, shared_ptr<T> desired,
3682
  memory_order order = memory_order::seq_cst) noexcept;
3683
  ```
3684
 
3685
  *Effects:* Equivalent to:
3686
 
@@ -3692,15 +4582,15 @@ where `fail_order` is the same as `order` except that a value of
3692
  `memory_order::acq_rel` shall be replaced by the value
3693
  `memory_order::acquire` and a value of `memory_order::release` shall be
3694
  replaced by the value `memory_order::relaxed`.
3695
 
3696
  ``` cpp
3697
- void wait(shared_ptr<T> old, memory_order order = memory_order::seq_cst) const noexcept;
3698
  ```
3699
 
3700
- *Preconditions:* `order` is neither `memory_order::release` nor
3701
- `memory_order::acq_rel`.
3702
 
3703
  *Effects:* Repeatedly performs the following steps, in order:
3704
 
3705
  - Evaluates `load(order)` and compares it to `old`.
3706
  - If the two are not equivalent, returns.
@@ -3710,22 +4600,22 @@ void wait(shared_ptr<T> old, memory_order order = memory_order::seq_cst) const n
3710
  *Remarks:* Two `shared_ptr` objects are equivalent if they store the
3711
  same pointer and either share ownership or are both empty. This function
3712
  is an atomic waiting operation [[atomics.wait]].
3713
 
3714
  ``` cpp
3715
- void notify_one() noexcept;
3716
  ```
3717
 
3718
  *Effects:* Unblocks the execution of at least one atomic waiting
3719
  operation that is eligible to be unblocked [[atomics.wait]] by this
3720
  call, if any such atomic waiting operations exist.
3721
 
3722
  *Remarks:* This function is an atomic notifying
3723
  operation [[atomics.wait]].
3724
 
3725
  ``` cpp
3726
- void notify_all() noexcept;
3727
  ```
3728
 
3729
  *Effects:* Unblocks the execution of all atomic waiting operations that
3730
  are eligible to be unblocked [[atomics.wait]] by this call.
3731
 
@@ -3741,33 +4631,35 @@ namespace std {
3741
 
3742
  static constexpr bool is_always_lock_free = implementation-defined // whether a given atomic type's operations are always lock free;
3743
  bool is_lock_free() const noexcept;
3744
 
3745
  constexpr atomic() noexcept;
3746
- atomic(weak_ptr<T> desired) noexcept;
3747
  atomic(const atomic&) = delete;
3748
  void operator=(const atomic&) = delete;
3749
 
3750
- weak_ptr<T> load(memory_order order = memory_order::seq_cst) const noexcept;
3751
- operator weak_ptr<T>() const noexcept;
3752
- void store(weak_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept;
3753
- void operator=(weak_ptr<T> desired) noexcept;
 
3754
 
3755
- weak_ptr<T> exchange(weak_ptr<T> desired,
3756
  memory_order order = memory_order::seq_cst) noexcept;
3757
- bool compare_exchange_weak(weak_ptr<T>& expected, weak_ptr<T> desired,
3758
  memory_order success, memory_order failure) noexcept;
3759
- bool compare_exchange_strong(weak_ptr<T>& expected, weak_ptr<T> desired,
3760
  memory_order success, memory_order failure) noexcept;
3761
- bool compare_exchange_weak(weak_ptr<T>& expected, weak_ptr<T> desired,
3762
  memory_order order = memory_order::seq_cst) noexcept;
3763
- bool compare_exchange_strong(weak_ptr<T>& expected, weak_ptr<T> desired,
3764
  memory_order order = memory_order::seq_cst) noexcept;
3765
 
3766
- void wait(weak_ptr<T> old, memory_order order = memory_order::seq_cst) const noexcept;
3767
- void notify_one() noexcept;
3768
- void notify_all() noexcept;
 
3769
 
3770
  private:
3771
  weak_ptr<T> p; // exposition only
3772
  };
3773
  }
@@ -3775,14 +4667,14 @@ namespace std {
3775
 
3776
  ``` cpp
3777
  constexpr atomic() noexcept;
3778
  ```
3779
 
3780
- *Effects:* Initializes `p{}`.
3781
 
3782
  ``` cpp
3783
- atomic(weak_ptr<T> desired) noexcept;
3784
  ```
3785
 
3786
  *Effects:* Initializes the object with the value `desired`.
3787
  Initialization is not an atomic operation [[intro.multithread]].
3788
 
@@ -3792,63 +4684,64 @@ the just-constructed object `A` to another thread via
3792
  `memory_order::relaxed` operations on a suitable atomic pointer
3793
  variable, and then immediately accessing `A` in the receiving thread.
3794
  This results in undefined behavior. — *end note*]
3795
 
3796
  ``` cpp
3797
- void store(weak_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept;
3798
  ```
3799
 
3800
- *Preconditions:* `order` is neither `memory_order::consume`,
3801
- `memory_order::acquire`, nor `memory_order::acq_rel`.
3802
 
3803
  *Effects:* Atomically replaces the value pointed to by `this` with the
3804
  value of `desired` as if by `p.swap(desired)`. Memory is affected
3805
  according to the value of `order`.
3806
 
3807
  ``` cpp
3808
- void operator=(weak_ptr<T> desired) noexcept;
3809
  ```
3810
 
3811
  *Effects:* Equivalent to `store(desired)`.
3812
 
3813
  ``` cpp
3814
- weak_ptr<T> load(memory_order order = memory_order::seq_cst) const noexcept;
3815
  ```
3816
 
3817
- *Preconditions:* `order` is neither `memory_order::release` nor
3818
- `memory_order::acq_rel`.
3819
 
3820
  *Effects:* Memory is affected according to the value of `order`.
3821
 
3822
  *Returns:* Atomically returns `p`.
3823
 
3824
  ``` cpp
3825
- operator weak_ptr<T>() const noexcept;
3826
  ```
3827
 
3828
  *Effects:* Equivalent to: `return load();`
3829
 
3830
  ``` cpp
3831
- weak_ptr<T> exchange(weak_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept;
 
3832
  ```
3833
 
3834
  *Effects:* Atomically replaces `p` with `desired` as if by
3835
  `p.swap(desired)`. Memory is affected according to the value of `order`.
3836
  This is an atomic read-modify-write operation [[intro.races]].
3837
 
3838
  *Returns:* Atomically returns the value of `p` immediately before the
3839
  effects.
3840
 
3841
  ``` cpp
3842
- bool compare_exchange_weak(weak_ptr<T>& expected, weak_ptr<T> desired,
3843
  memory_order success, memory_order failure) noexcept;
3844
- bool compare_exchange_strong(weak_ptr<T>& expected, weak_ptr<T> desired,
3845
  memory_order success, memory_order failure) noexcept;
3846
  ```
3847
 
3848
- *Preconditions:* `failure` is neither `memory_order::release` nor
3849
- `memory_order::acq_rel`.
3850
 
3851
  *Effects:* If `p` is equivalent to `expected`, assigns `desired` to `p`
3852
  and has synchronization semantics corresponding to the value of
3853
  `success`, otherwise assigns `p` to `expected` and has synchronization
3854
  semantics corresponding to the value of `failure`.
@@ -3869,11 +4762,11 @@ object in the attempted atomic update. The `use_count` update
3869
  corresponding to the write to `expected` is part of the atomic
3870
  operation. The write to `expected` itself is not required to be part of
3871
  the atomic operation.
3872
 
3873
  ``` cpp
3874
- bool compare_exchange_weak(weak_ptr<T>& expected, weak_ptr<T> desired,
3875
  memory_order order = memory_order::seq_cst) noexcept;
3876
  ```
3877
 
3878
  *Effects:* Equivalent to:
3879
 
@@ -3885,11 +4778,11 @@ where `fail_order` is the same as `order` except that a value of
3885
  `memory_order::acq_rel` shall be replaced by the value
3886
  `memory_order::acquire` and a value of `memory_order::release` shall be
3887
  replaced by the value `memory_order::relaxed`.
3888
 
3889
  ``` cpp
3890
- bool compare_exchange_strong(weak_ptr<T>& expected, weak_ptr<T> desired,
3891
  memory_order order = memory_order::seq_cst) noexcept;
3892
  ```
3893
 
3894
  *Effects:* Equivalent to:
3895
 
@@ -3901,15 +4794,15 @@ where `fail_order` is the same as `order` except that a value of
3901
  `memory_order::acq_rel` shall be replaced by the value
3902
  `memory_order::acquire` and a value of `memory_order::release` shall be
3903
  replaced by the value `memory_order::relaxed`.
3904
 
3905
  ``` cpp
3906
- void wait(weak_ptr<T> old, memory_order order = memory_order::seq_cst) const noexcept;
3907
  ```
3908
 
3909
- *Preconditions:* `order` is neither `memory_order::release` nor
3910
- `memory_order::acq_rel`.
3911
 
3912
  *Effects:* Repeatedly performs the following steps, in order:
3913
 
3914
  - Evaluates `load(order)` and compares it to `old`.
3915
  - If the two are not equivalent, returns.
@@ -3919,22 +4812,22 @@ void wait(weak_ptr<T> old, memory_order order = memory_order::seq_cst) const noe
3919
  *Remarks:* Two `weak_ptr` objects are equivalent if they store the same
3920
  pointer and either share ownership or are both empty. This function is
3921
  an atomic waiting operation [[atomics.wait]].
3922
 
3923
  ``` cpp
3924
- void notify_one() noexcept;
3925
  ```
3926
 
3927
  *Effects:* Unblocks the execution of at least one atomic waiting
3928
  operation that is eligible to be unblocked [[atomics.wait]] by this
3929
  call, if any such atomic waiting operations exist.
3930
 
3931
  *Remarks:* This function is an atomic notifying
3932
  operation [[atomics.wait]].
3933
 
3934
  ``` cpp
3935
- void notify_all() noexcept;
3936
  ```
3937
 
3938
  *Effects:* Unblocks the execution of all atomic waiting operations that
3939
  are eligible to be unblocked [[atomics.wait]] by this call.
3940
 
@@ -3965,22 +4858,22 @@ namespace std {
3965
  atomic_flag(const atomic_flag&) = delete;
3966
  atomic_flag& operator=(const atomic_flag&) = delete;
3967
  atomic_flag& operator=(const atomic_flag&) volatile = delete;
3968
 
3969
  bool test(memory_order = memory_order::seq_cst) const volatile noexcept;
3970
- bool test(memory_order = memory_order::seq_cst) const noexcept;
3971
  bool test_and_set(memory_order = memory_order::seq_cst) volatile noexcept;
3972
- bool test_and_set(memory_order = memory_order::seq_cst) noexcept;
3973
  void clear(memory_order = memory_order::seq_cst) volatile noexcept;
3974
- void clear(memory_order = memory_order::seq_cst) noexcept;
3975
 
3976
  void wait(bool, memory_order = memory_order::seq_cst) const volatile noexcept;
3977
- void wait(bool, memory_order = memory_order::seq_cst) const noexcept;
3978
  void notify_one() volatile noexcept;
3979
- void notify_one() noexcept;
3980
  void notify_all() volatile noexcept;
3981
- void notify_all() noexcept;
3982
  };
3983
  }
3984
  ```
3985
 
3986
  The `atomic_flag` type provides the classic test-and-set functionality.
@@ -3998,36 +4891,36 @@ constexpr atomic_flag::atomic_flag() noexcept;
3998
 
3999
  *Effects:* Initializes `*this` to the clear state.
4000
 
4001
  ``` cpp
4002
  bool atomic_flag_test(const volatile atomic_flag* object) noexcept;
4003
- bool atomic_flag_test(const atomic_flag* object) noexcept;
4004
  bool atomic_flag_test_explicit(const volatile atomic_flag* object,
4005
  memory_order order) noexcept;
4006
- bool atomic_flag_test_explicit(const atomic_flag* object,
4007
  memory_order order) noexcept;
4008
  bool atomic_flag::test(memory_order order = memory_order::seq_cst) const volatile noexcept;
4009
- bool atomic_flag::test(memory_order order = memory_order::seq_cst) const noexcept;
4010
  ```
4011
 
4012
  For `atomic_flag_test`, let `order` be `memory_order::seq_cst`.
4013
 
4014
- *Preconditions:* `order` is neither `memory_order::release` nor
4015
- `memory_order::acq_rel`.
4016
 
4017
  *Effects:* Memory is affected according to the value of `order`.
4018
 
4019
  *Returns:* Atomically returns the value pointed to by `object` or
4020
  `this`.
4021
 
4022
  ``` cpp
4023
  bool atomic_flag_test_and_set(volatile atomic_flag* object) noexcept;
4024
- bool atomic_flag_test_and_set(atomic_flag* object) noexcept;
4025
  bool atomic_flag_test_and_set_explicit(volatile atomic_flag* object, memory_order order) noexcept;
4026
- bool atomic_flag_test_and_set_explicit(atomic_flag* object, memory_order order) noexcept;
4027
  bool atomic_flag::test_and_set(memory_order order = memory_order::seq_cst) volatile noexcept;
4028
- bool atomic_flag::test_and_set(memory_order order = memory_order::seq_cst) noexcept;
4029
  ```
4030
 
4031
  *Effects:* Atomically sets the value pointed to by `object` or by `this`
4032
  to `true`. Memory is affected according to the value of `order`. These
4033
  operations are atomic read-modify-write
@@ -4036,43 +4929,42 @@ operations [[intro.multithread]].
4036
  *Returns:* Atomically, the value of the object immediately before the
4037
  effects.
4038
 
4039
  ``` cpp
4040
  void atomic_flag_clear(volatile atomic_flag* object) noexcept;
4041
- void atomic_flag_clear(atomic_flag* object) noexcept;
4042
  void atomic_flag_clear_explicit(volatile atomic_flag* object, memory_order order) noexcept;
4043
- void atomic_flag_clear_explicit(atomic_flag* object, memory_order order) noexcept;
4044
  void atomic_flag::clear(memory_order order = memory_order::seq_cst) volatile noexcept;
4045
- void atomic_flag::clear(memory_order order = memory_order::seq_cst) noexcept;
4046
  ```
4047
 
4048
- *Preconditions:* The `order` argument is neither
4049
- `memory_order::consume`, `memory_order::acquire`, nor
4050
- `memory_order::acq_rel`.
4051
 
4052
  *Effects:* Atomically sets the value pointed to by `object` or by `this`
4053
  to `false`. Memory is affected according to the value of `order`.
4054
 
4055
  ``` cpp
4056
  void atomic_flag_wait(const volatile atomic_flag* object, bool old) noexcept;
4057
- void atomic_flag_wait(const atomic_flag* object, bool old) noexcept;
4058
  void atomic_flag_wait_explicit(const volatile atomic_flag* object,
4059
  bool old, memory_order order) noexcept;
4060
- void atomic_flag_wait_explicit(const atomic_flag* object,
4061
  bool old, memory_order order) noexcept;
4062
  void atomic_flag::wait(bool old, memory_order order =
4063
  memory_order::seq_cst) const volatile noexcept;
4064
- void atomic_flag::wait(bool old, memory_order order =
4065
  memory_order::seq_cst) const noexcept;
4066
  ```
4067
 
4068
  For `atomic_flag_wait`, let `order` be `memory_order::seq_cst`. Let
4069
  `flag` be `object` for the non-member functions and `this` for the
4070
  member functions.
4071
 
4072
- *Preconditions:* `order` is neither `memory_order::release` nor
4073
- `memory_order::acq_rel`.
4074
 
4075
  *Effects:* Repeatedly performs the following steps, in order:
4076
 
4077
  - Evaluates `flag->test(order) != old`.
4078
  - If the result of that evaluation is `true`, returns.
@@ -4082,13 +4974,13 @@ member functions.
4082
  *Remarks:* This function is an atomic waiting
4083
  operation [[atomics.wait]].
4084
 
4085
  ``` cpp
4086
  void atomic_flag_notify_one(volatile atomic_flag* object) noexcept;
4087
- void atomic_flag_notify_one(atomic_flag* object) noexcept;
4088
  void atomic_flag::notify_one() volatile noexcept;
4089
- void atomic_flag::notify_one() noexcept;
4090
  ```
4091
 
4092
  *Effects:* Unblocks the execution of at least one atomic waiting
4093
  operation that is eligible to be unblocked [[atomics.wait]] by this
4094
  call, if any such atomic waiting operations exist.
@@ -4096,13 +4988,13 @@ call, if any such atomic waiting operations exist.
4096
  *Remarks:* This function is an atomic notifying
4097
  operation [[atomics.wait]].
4098
 
4099
  ``` cpp
4100
  void atomic_flag_notify_all(volatile atomic_flag* object) noexcept;
4101
- void atomic_flag_notify_all(atomic_flag* object) noexcept;
4102
  void atomic_flag::notify_all() volatile noexcept;
4103
- void atomic_flag::notify_all() noexcept;
4104
  ```
4105
 
4106
  *Effects:* Unblocks the execution of all atomic waiting operations that
4107
  are eligible to be unblocked [[atomics.wait]] by this call.
4108
 
@@ -4131,15 +5023,16 @@ This subclause introduces synchronization primitives called *fences*.
4131
  Fences can have acquire semantics, release semantics, or both. A fence
4132
  with acquire semantics is called an *acquire fence*. A fence with
4133
  release semantics is called a *release fence*.
4134
 
4135
  A release fence A synchronizes with an acquire fence B if there exist
4136
- atomic operations X and Y, both operating on some atomic object M, such
4137
- that A is sequenced before X, X modifies M, Y is sequenced before B, and
4138
- Y reads the value written by X or a value written by any side effect in
4139
- the hypothetical release sequence X would head if it were a release
4140
- operation.
 
4141
 
4142
  A release fence A synchronizes with an atomic operation B that performs
4143
  an acquire operation on an atomic object M if there exists an atomic
4144
  operation X such that A is sequenced before X, X modifies M, and B reads
4145
  the value written by X or a value written by any side effect in the
@@ -4151,26 +5044,25 @@ synchronizes with an acquire fence B if there exists some atomic
4151
  operation X on M such that X is sequenced before B and reads the value
4152
  written by A or a value written by any side effect in the release
4153
  sequence headed by A.
4154
 
4155
  ``` cpp
4156
- extern "C" void atomic_thread_fence(memory_order order) noexcept;
4157
  ```
4158
 
4159
  *Effects:* Depending on the value of `order`, this operation:
4160
 
4161
  - has no effects, if `order == memory_order::relaxed`;
4162
- - is an acquire fence, if `order == memory_order::acquire` or
4163
- `order == memory_order::consume`;
4164
  - is a release fence, if `order == memory_order::release`;
4165
  - is both an acquire fence and a release fence, if
4166
  `order == memory_order::acq_rel`;
4167
  - is a sequentially consistent acquire and release fence, if
4168
  `order == memory_order::seq_cst`.
4169
 
4170
  ``` cpp
4171
- extern "C" void atomic_signal_fence(memory_order order) noexcept;
4172
  ```
4173
 
4174
  *Effects:* Equivalent to `atomic_thread_fence(order)`, except that the
4175
  resulting ordering constraints are established only between a thread and
4176
  a signal handler executed in the same thread.
@@ -4327,11 +5219,11 @@ race-free programs [[intro.multithread]].
4327
  namespace std {
4328
  // [thread.mutex.class], class mutex
4329
  class mutex;
4330
  // [thread.mutex.recursive], class recursive_mutex
4331
  class recursive_mutex;
4332
- // [thread.timedmutex.class] class timed_mutex
4333
  class timed_mutex;
4334
  // [thread.timedmutex.recursive], class recursive_timed_mutex
4335
  class recursive_timed_mutex;
4336
 
4337
  struct defer_lock_t { explicit defer_lock_t() = default; };
@@ -4376,11 +5268,11 @@ namespace std {
4376
  }
4377
  ```
4378
 
4379
  ### Mutex requirements <a id="thread.mutex.requirements">[[thread.mutex.requirements]]</a>
4380
 
4381
- #### In general <a id="thread.mutex.requirements.general">[[thread.mutex.requirements.general]]</a>
4382
 
4383
  A mutex object facilitates protection against data races and allows safe
4384
  synchronization of data between execution agents
4385
  [[thread.req.lockable]]. An execution agent *owns* a mutex from the time
4386
  it successfully calls one of the lock functions until it calls unlock.
@@ -4534,13 +5426,13 @@ another thread to acquire ownership of that object will fail (for
4534
  released ownership with a call to `unlock()`.
4535
 
4536
  [*Note 4*: After a thread `A` has called `unlock()`, releasing a mutex,
4537
  it is possible for another thread `B` to lock the same mutex, observe
4538
  that it is no longer in use, unlock it, and destroy it, before thread
4539
- `A` appears to have returned from its unlock call. Implementations are
4540
- required to handle such scenarios correctly, as long as thread `A`
4541
- doesn’t access the mutex after the unlock call returns. These cases
4542
  typically occur when a reference-counted object contains a mutex that is
4543
  used to protect the reference count. — *end note*]
4544
 
4545
  The class `mutex` meets all of the mutex requirements
4546
  [[thread.mutex.requirements]]. It is a standard-layout class
@@ -4596,11 +5488,11 @@ ownership for a `recursive_mutex` object, additional calls to
4596
  of type `system_error`. A thread shall call `unlock()` once for each
4597
  level of ownership acquired by calls to `lock()` and `try_lock()`. Only
4598
  when all levels of ownership have been released may ownership be
4599
  acquired by another thread.
4600
 
4601
- The behavior of a program is undefined if:
4602
 
4603
  - it destroys a `recursive_mutex` object owned by any thread or
4604
  - a thread terminates while owning a `recursive_mutex` object.
4605
 
4606
  #### Timed mutex types <a id="thread.timedmutex.requirements">[[thread.timedmutex.requirements]]</a>
@@ -4707,11 +5599,11 @@ a call to `unlock()` or the call to `try_lock_for()` or
4707
 
4708
  The class `timed_mutex` meets all of the timed mutex requirements
4709
  [[thread.timedmutex.requirements]]. It is a standard-layout class
4710
  [[class.prop]].
4711
 
4712
- The behavior of a program is undefined if:
4713
 
4714
  - it destroys a `timed_mutex` object owned by any thread,
4715
  - a thread that owns a `timed_mutex` object calls `lock()`,
4716
  `try_lock()`, `try_lock_for()`, or `try_lock_until()` on that object,
4717
  or
@@ -4766,11 +5658,11 @@ for a `recursive_timed_mutex` object, additional calls to `try_lock()`,
4766
  `unlock()` once for each level of ownership acquired by calls to
4767
  `lock()`, `try_lock()`, `try_lock_for()`, and `try_lock_until()`. Only
4768
  when all levels of ownership have been released may ownership of the
4769
  object be acquired by another thread.
4770
 
4771
- The behavior of a program is undefined if:
4772
 
4773
  - it destroys a `recursive_timed_mutex` object owned by any thread, or
4774
  - a thread terminates while owning a `recursive_timed_mutex` object.
4775
 
4776
  #### Shared mutex types <a id="thread.sharedmutex.requirements">[[thread.sharedmutex.requirements]]</a>
@@ -4895,11 +5787,11 @@ ownership semantics.
4895
 
4896
  The class `shared_mutex` meets all of the shared mutex requirements
4897
  [[thread.sharedmutex.requirements]]. It is a standard-layout class
4898
  [[class.prop]].
4899
 
4900
- The behavior of a program is undefined if:
4901
 
4902
  - it destroys a `shared_mutex` object owned by any thread,
4903
  - a thread attempts to recursively gain any ownership of a
4904
  `shared_mutex`, or
4905
  - a thread terminates while possessing any ownership of a
@@ -5021,11 +5913,11 @@ shared ownership semantics.
5021
 
5022
  The class `shared_timed_mutex` meets all of the shared timed mutex
5023
  requirements [[thread.sharedtimedmutex.requirements]]. It is a
5024
  standard-layout class [[class.prop]].
5025
 
5026
- The behavior of a program is undefined if:
5027
 
5028
  - it destroys a `shared_timed_mutex` object owned by any thread,
5029
  - a thread attempts to recursively gain any ownership of a
5030
  `shared_timed_mutex`, or
5031
  - a thread terminates while possessing any ownership of a
@@ -5205,11 +6097,11 @@ namespace std {
5205
 
5206
  unique_lock(const unique_lock&) = delete;
5207
  unique_lock& operator=(const unique_lock&) = delete;
5208
 
5209
  unique_lock(unique_lock&& u) noexcept;
5210
- unique_lock& operator=(unique_lock&& u);
5211
 
5212
  // [thread.lock.unique.locking], locking
5213
  void lock();
5214
  bool try_lock();
5215
 
@@ -5331,24 +6223,16 @@ unique_lock(unique_lock&& u) noexcept;
5331
  *Ensures:* `pm == u_p.pm` and `owns == u_p.owns` (where `u_p` is the
5332
  state of `u` just prior to this construction), `u.pm == 0` and
5333
  `u.owns == false`.
5334
 
5335
  ``` cpp
5336
- unique_lock& operator=(unique_lock&& u);
5337
  ```
5338
 
5339
- *Effects:* If `owns` calls `pm->unlock()`.
5340
 
5341
- *Ensures:* `pm == u_p.pm` and `owns == u_p.owns` (where `u_p` is the
5342
- state of `u` just prior to this construction), `u.pm == 0` and
5343
- `u.owns == false`.
5344
-
5345
- [*Note 1*: With a recursive mutex it is possible for both `*this` and
5346
- `u` to own the same mutex before the assignment. In this case, `*this`
5347
- will own the mutex after the assignment and `u` will not. — *end note*]
5348
-
5349
- *Throws:* Nothing.
5350
 
5351
  ``` cpp
5352
  ~unique_lock();
5353
  ```
5354
 
@@ -5653,15 +6537,13 @@ state of `sl` just prior to this construction), `sl.pm == nullptr` and
5653
 
5654
  ``` cpp
5655
  shared_lock& operator=(shared_lock&& sl) noexcept;
5656
  ```
5657
 
5658
- *Effects:* If `owns` calls `pm->unlock_shared()`.
5659
 
5660
- *Ensures:* `pm == sl_p.pm` and `owns == sl_p.owns` (where `sl_p` is the
5661
- state of `sl` just prior to this assignment), `sl.pm == nullptr` and
5662
- `sl.owns == false`.
5663
 
5664
  ##### Locking <a id="thread.lock.shared.locking">[[thread.lock.shared.locking]]</a>
5665
 
5666
  ``` cpp
5667
  void lock();
@@ -5886,11 +6768,11 @@ template<class Callable, class... Args>
5886
 
5887
  *Mandates:* `is_invocable_v<Callable, Args...>` is `true`.
5888
 
5889
  *Effects:* An execution of `call_once` that does not call its `func` is
5890
  a *passive* execution. An execution of `call_once` that calls its `func`
5891
- is an *active* execution. An active execution calls *INVOKE*(
5892
  std::forward\<Callable\>(func),
5893
  std::forward\<Args\>(args)...) [[func.require]]. If such a call to
5894
  `func` throws an exception the execution is *exceptional*, otherwise it
5895
  is *returning*. An exceptional execution propagates the exception to the
5896
  caller of `call_once`. Among all executions of `call_once` for any given
@@ -6003,11 +6885,11 @@ void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk);
6003
  supplied by all concurrently waiting (via `wait`, `wait_for`, or
6004
  `wait_until`) threads.
6005
 
6006
  *Effects:* Transfers ownership of the lock associated with `lk` into
6007
  internal storage and schedules `cond` to be notified when the current
6008
- thread exits, after all objects of thread storage duration associated
6009
  with the current thread have been destroyed. This notification is
6010
  equivalent to:
6011
 
6012
  ``` cpp
6013
  lk.unlock();
@@ -6020,11 +6902,11 @@ the current thread.
6020
 
6021
  [*Note 1*: The supplied lock is held until the thread exits, which
6022
  might cause deadlock due to lock ordering issues. — *end note*]
6023
 
6024
  [*Note 2*: It is the user’s responsibility to ensure that waiting
6025
- threads do not erroneously assume that the thread has finished if they
6026
  experience spurious wakeups. This typically requires that the condition
6027
  being waited for is satisfied while holding the lock on `lk`, and that
6028
  this lock is not released and reacquired prior to calling
6029
  `notify_all_at_thread_exit`. — *end note*]
6030
 
@@ -6329,13 +7211,13 @@ exception. — *end note*]
6329
 
6330
  ### Class `condition_variable_any` <a id="thread.condition.condvarany">[[thread.condition.condvarany]]</a>
6331
 
6332
  #### General <a id="thread.condition.condvarany.general">[[thread.condition.condvarany.general]]</a>
6333
 
6334
- In this subclause [[thread.condition.condvarany]], template arguments
6335
- for template parameters named `Lock` shall meet the *Cpp17BasicLockable*
6336
- requirements [[thread.req.lockable.basic]].
6337
 
6338
  [*Note 1*: All of the standard mutex types meet this requirement. If a
6339
  type other than one of the standard mutex types or a `unique_lock`
6340
  wrapper for a standard mutex type is used with `condition_variable_any`,
6341
  any necessary synchronization is assumed to be in place with respect to
@@ -6967,11 +7849,11 @@ namespace std {
6967
  ~barrier();
6968
 
6969
  barrier(const barrier&) = delete;
6970
  barrier& operator=(const barrier&) = delete;
6971
 
6972
- [[nodiscard]] arrival_token arrive(ptrdiff_t update = 1);
6973
  void wait(arrival_token&& arrival) const;
6974
 
6975
  void arrive_and_wait();
6976
  void arrive_and_drop();
6977
 
@@ -7055,11 +7937,11 @@ destroyed. — *end note*]
7055
 
7056
  *Throws:* Any exception thrown by `CompletionFunction`’s move
7057
  constructor.
7058
 
7059
  ``` cpp
7060
- [[nodiscard]] arrival_token arrive(ptrdiff_t update = 1);
7061
  ```
7062
 
7063
  *Preconditions:* `update > 0` is `true`, and `update` is less than or
7064
  equal to the expected count for the current barrier phase.
7065
 
@@ -7182,13 +8064,10 @@ namespace std {
7182
  template<> class promise<void>;
7183
 
7184
  template<class R>
7185
  void swap(promise<R>& x, promise<R>& y) noexcept;
7186
 
7187
- template<class R, class Alloc>
7188
- struct uses_allocator<promise<R>, Alloc>;
7189
-
7190
  // [futures.unique.future], class template future
7191
  template<class R> class future;
7192
  template<class R> class future<R&>;
7193
  template<> class future<void>;
7194
 
@@ -7205,14 +8084,14 @@ namespace std {
7205
  template<class R, class... ArgTypes>
7206
  void swap(packaged_task<R(ArgTypes...)>&, packaged_task<R(ArgTypes...)>&) noexcept;
7207
 
7208
  // [futures.async], function template async
7209
  template<class F, class... Args>
7210
- [[nodiscard]] future<invoke_result_t<decay_t<F>, decay_t<Args>...>>
7211
  async(F&& f, Args&&... args);
7212
  template<class F, class... Args>
7213
- [[nodiscard]] future<invoke_result_t<decay_t<F>, decay_t<Args>...>>
7214
  async(launch policy, F&& f, Args&&... args);
7215
  }
7216
  ```
7217
 
7218
  The `enum` type `launch` is a bitmask type [[bitmask.types]] with
@@ -7310,11 +8189,12 @@ waiting function*, otherwise it is a *non-timed waiting function*.
7310
 
7311
  An *asynchronous provider* is an object that provides a result to a
7312
  shared state. The result of a shared state is set by respective
7313
  functions on the asynchronous provider.
7314
 
7315
- [*Note 3*: Such as promises or tasks. *end note*]
 
7316
 
7317
  The means of setting the result of a shared state is specified in the
7318
  description of those classes and functions that create such a state
7319
  object.
7320
 
@@ -7364,11 +8244,11 @@ of each of that thread’s objects with thread storage duration
7364
  [[basic.stc.thread]] is sequenced before making that shared state ready.
7365
 
7366
  Access to the result of the same shared state may conflict
7367
  [[intro.multithread]].
7368
 
7369
- [*Note 4*: This explicitly specifies that the result of the shared
7370
  state is visible in the objects that reference this state in the sense
7371
  of data race avoidance [[res.on.data.races]]. For example, concurrent
7372
  accesses through references returned by `shared_future::get()`
7373
  [[futures.shared.future]] must either use read-only operations or
7374
  provide additional synchronization. — *end note*]
@@ -7401,13 +8281,10 @@ namespace std {
7401
 
7402
  // setting the result with deferred notification
7403
  void set_value_at_thread_exit(see below);
7404
  void set_exception_at_thread_exit(exception_ptr p);
7405
  };
7406
-
7407
- template<class R, class Alloc>
7408
- struct uses_allocator<promise<R>, Alloc>;
7409
  }
7410
  ```
7411
 
7412
  For the primary template, `R` shall be an object type that meets the
7413
  *Cpp17Destructible* requirements.
@@ -7420,19 +8297,10 @@ in the argument type of the member functions `set_value` and
7420
  The `set_value`, `set_exception`, `set_value_at_thread_exit`, and
7421
  `set_exception_at_thread_exit` member functions behave as though they
7422
  acquire a single mutex associated with the promise object while updating
7423
  the promise object.
7424
 
7425
- ``` cpp
7426
- template<class R, class Alloc>
7427
- struct uses_allocator<promise<R>, Alloc>
7428
- : true_type { };
7429
- ```
7430
-
7431
- *Preconditions:* `Alloc` meets the *Cpp17Allocator*
7432
- requirements [[allocator.requirements.general]].
7433
-
7434
  ``` cpp
7435
  promise();
7436
  template<class Allocator>
7437
  promise(allocator_arg_t, const Allocator& a);
7438
  ```
@@ -7547,11 +8415,11 @@ void promise<R&>::set_value_at_thread_exit(R& r);
7547
  void promise<void>::set_value_at_thread_exit();
7548
  ```
7549
 
7550
  *Effects:* Stores the value `r` in the shared state without making that
7551
  state ready immediately. Schedules that state to be made ready when the
7552
- current thread exits, after all objects of thread storage duration
7553
  associated with the current thread have been destroyed.
7554
 
7555
  *Throws:*
7556
 
7557
  - `future_error` if its shared state already has a stored value or
@@ -7573,12 +8441,12 @@ void set_exception_at_thread_exit(exception_ptr p);
7573
 
7574
  *Preconditions:* `p` is not null.
7575
 
7576
  *Effects:* Stores the exception pointer `p` in the shared state without
7577
  making that state ready immediately. Schedules that state to be made
7578
- ready when the current thread exits, after all objects of thread storage
7579
- duration associated with the current thread have been destroyed.
7580
 
7581
  *Throws:* `future_error` if an error condition occurs.
7582
 
7583
  *Error conditions:*
7584
 
@@ -7606,11 +8474,11 @@ respective function on an object that shares the same shared state.
7606
 
7607
  [*Note 1*: Member functions of `future` do not synchronize with
7608
  themselves or with member functions of `shared_future`. — *end note*]
7609
 
7610
  The effect of calling any member function other than the destructor, the
7611
- move-assignment operator, `share`, or `valid` on a `future` object for
7612
  which `valid() == false` is undefined.
7613
 
7614
  [*Note 2*: It is valid to move from a future object for which
7615
  `valid() == false`. — *end note*]
7616
 
@@ -7805,11 +8673,11 @@ object that shares the same shared state.
7805
 
7806
  [*Note 1*: Member functions of `shared_future` do not synchronize with
7807
  themselves, but they synchronize with the shared state. — *end note*]
7808
 
7809
  The effect of calling any member function other than the destructor, the
7810
- move-assignment operator, the copy-assignment operator, or `valid()` on
7811
  a `shared_future` object for which `valid() == false` is undefined.
7812
 
7813
  [*Note 2*: It is valid to copy or move from a `shared_future` object
7814
  for which `valid()` is `false`. — *end note*]
7815
 
@@ -8014,14 +8882,14 @@ The function template `async` provides a mechanism to launch a function
8014
  potentially in a new thread and provides the result of the function in a
8015
  `future` object with which it shares a shared state.
8016
 
8017
  ``` cpp
8018
  template<class F, class... Args>
8019
- [[nodiscard]] future<invoke_result_t<decay_t<F>, decay_t<Args>...>>
8020
  async(F&& f, Args&&... args);
8021
  template<class F, class... Args>
8022
- [[nodiscard]] future<invoke_result_t<decay_t<F>, decay_t<Args>...>>
8023
  async(launch policy, F&& f, Args&&... args);
8024
  ```
8025
 
8026
  *Mandates:* The following are all `true`:
8027
 
@@ -8138,10 +9006,12 @@ namespace std {
8138
  public:
8139
  // construction and destruction
8140
  packaged_task() noexcept;
8141
  template<class F>
8142
  explicit packaged_task(F&& f);
 
 
8143
  ~packaged_task();
8144
 
8145
  // no copy
8146
  packaged_task(const packaged_task&) = delete;
8147
  packaged_task& operator=(const packaged_task&) = delete;
@@ -8181,24 +9051,37 @@ packaged_task() noexcept;
8181
  ``` cpp
8182
  template<class F>
8183
  explicit packaged_task(F&& f);
8184
  ```
8185
 
 
 
 
 
 
 
 
 
8186
  *Constraints:* `remove_cvref_t<F>` is not the same type as
8187
  `packaged_task<R(ArgTypes...)>`.
8188
 
8189
- *Mandates:* `is_invocable_r_v<R, F&, ArgTypes...>` is `true`.
8190
 
8191
- *Preconditions:* Invoking a copy of `f` behaves the same as invoking
8192
- `f`.
8193
 
8194
- *Effects:* Constructs a new `packaged_task` object with a shared state
8195
- and initializes the object’s stored task with `std::forward<F>(f)`.
 
 
 
 
 
8196
 
8197
- *Throws:* Any exceptions thrown by the copy or move constructor of `f`,
8198
- or `bad_alloc` if memory for the internal data structures cannot be
8199
- allocated.
8200
 
8201
  ``` cpp
8202
  template<class F> packaged_task(F) -> packaged_task<see below>;
8203
  ```
8204
 
@@ -8308,11 +9191,11 @@ where `f` is the stored task and `t`₁`, t`₂`, `…`, t`$_N$ are the values
8308
  in `args...`. If the task returns normally, the return value is stored
8309
  as the asynchronous result in the shared state of `*this`, otherwise the
8310
  exception thrown by the task is stored. In either case, this is done
8311
  without making that state ready [[futures.state]] immediately. Schedules
8312
  the shared state to be made ready when the current thread exits, after
8313
- all objects of thread storage duration associated with the current
8314
  thread have been destroyed.
8315
 
8316
  *Throws:* `future_error` if an error condition occurs.
8317
 
8318
  *Error conditions:*
@@ -8323,21 +9206,28 @@ thread have been destroyed.
8323
 
8324
  ``` cpp
8325
  void reset();
8326
  ```
8327
 
8328
- *Effects:* As if `*this = packaged_task(std::move(f))`, where `f` is the
8329
- task stored in `*this`.
 
 
 
 
 
 
 
 
 
8330
 
8331
  [*Note 2*: This constructs a new shared state for `*this`. The old
8332
  state is abandoned [[futures.state]]. — *end note*]
8333
 
8334
  *Throws:*
8335
 
8336
- - `bad_alloc` if memory for the new shared state cannot be allocated.
8337
- - Any exception thrown by the move constructor of the task stored in the
8338
- shared state.
8339
  - `future_error` with an error condition of `no_state` if `*this` has no
8340
  shared state.
8341
 
8342
  #### Globals <a id="futures.task.nonmembers">[[futures.task.nonmembers]]</a>
8343
 
@@ -8346,11 +9236,583 @@ template<class R, class... ArgTypes>
8346
  void swap(packaged_task<R(ArgTypes...)>& x, packaged_task<R(ArgTypes...)>& y) noexcept;
8347
  ```
8348
 
8349
  *Effects:* As if by `x.swap(y)`.
8350
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8351
  <!-- Link reference definitions -->
 
8352
  [alg.sorting]: algorithms.md#alg.sorting
8353
  [allocator.requirements.general]: library.md#allocator.requirements.general
8354
  [atomic.types.int.comp]: #atomic.types.int.comp
8355
  [atomic.types.pointer.comp]: #atomic.types.pointer.comp
8356
  [atomics]: #atomics
@@ -8379,26 +9841,29 @@ template<class R, class... ArgTypes>
8379
  [atomics.wait]: #atomics.wait
8380
  [barrier.syn]: #barrier.syn
8381
  [basic.align]: basic.md#basic.align
8382
  [basic.fundamental]: basic.md#basic.fundamental
8383
  [basic.life]: basic.md#basic.life
 
8384
  [basic.stc.thread]: basic.md#basic.stc.thread
8385
  [bitmask.types]: library.md#bitmask.types
8386
  [cfenv]: numerics.md#cfenv
8387
  [class.prop]: class.md#class.prop
8388
  [compliance]: library.md#compliance
8389
  [concept.booleantestable]: concepts.md#concept.booleantestable
8390
  [condition.variable.syn]: #condition.variable.syn
8391
  [conv.rval]: expr.md#conv.rval
8392
  [cpp17.defaultconstructible]: #cpp17.defaultconstructible
8393
  [cpp17.destructible]: #cpp17.destructible
 
8394
  [cpp17.moveassignable]: #cpp17.moveassignable
8395
  [cpp17.moveconstructible]: #cpp17.moveconstructible
8396
  [defns.block]: intro.md#defns.block
8397
  [except.terminate]: except.md#except.terminate
8398
  [expr.pre]: expr.md#expr.pre
8399
- [format.string.std]: utilities.md#format.string.std
 
8400
  [func.invoke]: utilities.md#func.invoke
8401
  [func.require]: utilities.md#func.require
8402
  [function.objects]: utilities.md#function.objects
8403
  [future.syn]: #future.syn
8404
  [futures]: #futures
@@ -8412,34 +9877,62 @@ template<class R, class... ArgTypes>
8412
  [futures.task]: #futures.task
8413
  [futures.task.general]: #futures.task.general
8414
  [futures.task.members]: #futures.task.members
8415
  [futures.task.nonmembers]: #futures.task.nonmembers
8416
  [futures.unique.future]: #futures.unique.future
 
8417
  [intro.multithread]: basic.md#intro.multithread
8418
  [intro.progress]: basic.md#intro.progress
8419
  [intro.races]: basic.md#intro.races
8420
  [latch.syn]: #latch.syn
8421
  [limits.syn]: support.md#limits.syn
8422
  [mutex.syn]: #mutex.syn
 
8423
  [res.on.data.races]: library.md#res.on.data.races
8424
  [res.on.exception.handling]: library.md#res.on.exception.handling
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8425
  [semaphore.syn]: #semaphore.syn
8426
  [shared.mutex.syn]: #shared.mutex.syn
8427
  [stdatomic.h.syn]: #stdatomic.h.syn
8428
  [stopcallback]: #stopcallback
8429
  [stopcallback.cons]: #stopcallback.cons
8430
  [stopcallback.general]: #stopcallback.general
 
 
 
8431
  [stopsource]: #stopsource
8432
  [stopsource.cons]: #stopsource.cons
8433
  [stopsource.general]: #stopsource.general
 
 
 
 
8434
  [stopsource.mem]: #stopsource.mem
8435
- [stopsource.nonmembers]: #stopsource.nonmembers
8436
  [stoptoken]: #stoptoken
8437
- [stoptoken.cons]: #stoptoken.cons
8438
  [stoptoken.general]: #stoptoken.general
 
 
 
8439
  [stoptoken.mem]: #stoptoken.mem
8440
- [stoptoken.nonmembers]: #stoptoken.nonmembers
8441
  [syserr]: diagnostics.md#syserr
8442
  [syserr.syserr]: diagnostics.md#syserr.syserr
8443
  [term.padding.bits]: basic.md#term.padding.bits
8444
  [term.unevaluated.operand]: expr.md#term.unevaluated.operand
8445
  [thread]: #thread
 
16
  | [[thread.threads]] | Threads | `<thread>` |
17
  | [[atomics]] | Atomic operations | `<atomic>`, `<stdatomic.h>` |
18
  | [[thread.mutex]] | Mutual exclusion | `<mutex>`, `<shared_mutex>` |
19
  | [[thread.condition]] | Condition variables | `<condition_variable>` |
20
  | [[thread.sema]] | Semaphores | `<semaphore>` |
21
+ | [[thread.coord]] | Coordination types | `<latch>`, `<barrier>` |
22
  | [[futures]] | Futures | `<future>` |
23
+ | [[saferecl]] | Safe reclamation | `<rcu>`, `<hazard_pointer>` |
24
 
25
 
26
  ## Requirements <a id="thread.req">[[thread.req]]</a>
27
 
28
  ### Template parameter names <a id="thread.req.paramname">[[thread.req.paramname]]</a>
 
145
  supplied by the implementation as specified in  [[time.clock]] do not
146
  throw exceptions. — *end note*]
147
 
148
  ### Requirements for *Cpp17Lockable* types <a id="thread.req.lockable">[[thread.req.lockable]]</a>
149
 
150
+ #### General <a id="thread.req.lockable.general">[[thread.req.lockable.general]]</a>
151
 
152
  An *execution agent* is an entity such as a thread that may perform work
153
  in parallel with other execution agents.
154
 
155
  [*Note 1*: Implementations or users can introduce other kinds of agents
 
189
  nature of any lock ownership is not part of these
190
  definitions. — *end note*]
191
 
192
  #### *Cpp17BasicLockable* requirements <a id="thread.req.lockable.basic">[[thread.req.lockable.basic]]</a>
193
 
194
+ A type `L` meets the requirements if the following expressions are
195
+ well-formed and have the specified semantics (`m` denotes a value of
196
+ type `L`).
197
 
198
  ``` cpp
199
  m.lock()
200
  ```
201
 
 
215
 
216
  *Throws:* Nothing.
217
 
218
  #### *Cpp17Lockable* requirements <a id="thread.req.lockable.req">[[thread.req.lockable.req]]</a>
219
 
220
+ A type `L` meets the requirements if it meets the *Cpp17BasicLockable*
221
+ requirements and the following expressions are well-formed and have the
222
+ specified semantics (`m` denotes a value of type `L`).
 
223
 
224
  ``` cpp
225
  m.try_lock()
226
  ```
227
 
 
233
 
234
  *Returns:* `true` if the lock was acquired, otherwise `false`.
235
 
236
  #### *Cpp17TimedLockable* requirements <a id="thread.req.lockable.timed">[[thread.req.lockable.timed]]</a>
237
 
238
+ A type `L` meets the requirements if it meets the *Cpp17Lockable*
239
+ requirements and the following expressions are well-formed and have the
240
+ specified semantics (`m` denotes a value of type `L`, `rel_time` denotes
241
+ a value of an instantiation of `duration` [[time.duration]], and
242
+ `abs_time` denotes a value of an instantiation of `time_point`
243
+ [[time.point]]).
244
 
245
  ``` cpp
246
  m.try_lock_for(rel_time)
247
  ```
248
 
 
272
 
273
  *Returns:* `true` if the lock was acquired, otherwise `false`.
274
 
275
  #### *Cpp17SharedLockable* requirements <a id="thread.req.lockable.shared">[[thread.req.lockable.shared]]</a>
276
 
277
+ A type `L` meets the requirements if the following expressions are
278
+ well-formed, have the specified semantics, and the expression
279
+ `m.try_lock_shared()` has type `bool` (`m` denotes a value of type `L`):
 
280
 
281
  ``` cpp
282
  m.lock_shared()
283
  ```
284
 
 
307
 
308
  *Throws:* Nothing.
309
 
310
  #### *Cpp17SharedTimedLockable* requirements <a id="thread.req.lockable.shared.timed">[[thread.req.lockable.shared.timed]]</a>
311
 
312
+ A type `L` meets the requirements if it meets the *Cpp17SharedLockable*
313
+ requirements, and the following expressions are well-formed, have type
314
+ `bool`, and have the specified semantics (`m` denotes a value of type
315
+ `L`, `rel_time` denotes a value of a specialization of
316
+ `chrono::duration`, and `abs_time` denotes a value of a specialization
317
+ of `chrono::time_point`).
318
 
319
  ``` cpp
320
  m.try_lock_shared_for(rel_time)
321
  ```
322
 
 
349
  Subclause [[thread.stoptoken]] describes components that can be used to
350
  asynchronously request that an operation stops execution in a timely
351
  manner, typically because the result is no longer required. Such a
352
  request is called a *stop request*.
353
 
354
+ The concepts `stoppable-source`, `stoppable_token`, and
355
+ `stoppable-callback-for` specify the required syntax and semantics of
356
+ shared access to a *stop state*. Any object modeling `stoppable-source`,
357
+ `stoppable_token`, or `stoppable-callback-for` that refers to the same
358
+ stop state is an *associated* `stoppable-source`, `stoppable_token`, or
359
+ `stoppable-callback-for`, respectively.
360
 
361
+ An object of a type that models `stoppable_token` can be passed to an
362
+ operation that can either
363
 
364
  - actively poll the token to check if there has been a stop request, or
365
+ - register a callback that will be called in the event that a stop
366
+ request is made.
367
 
368
+ A stop request made via an object whose type models `stoppable-source`
369
+ will be visible to all associated `stoppable_token` and
370
+ `stoppable-source` objects. Once a stop request has been made it cannot
371
+ be withdrawn (a subsequent stop request has no effect).
372
 
373
+ Callbacks registered via an object whose type models
374
+ `stoppable-callback-for` are called when a stop request is first made by
375
+ any associated `stoppable-source` object.
376
 
377
+ The types `stop_source` and `stop_token` and the class template
378
+ `stop_callback` implement the semantics of shared ownership of a stop
379
+ state. The last remaining owner of the stop state automatically releases
380
+ the resources associated with the stop state.
381
+
382
+ An object of type `inplace_stop_source` is the sole owner of its stop
383
+ state. An object of type `inplace_stop_token` or of a specialization of
384
+ the class template `inplace_stop_callback` does not participate in
385
+ ownership of its associated stop state.
386
+
387
+ [*Note 1*: They are for use when all uses of the associated token and
388
+ callback objects are known to nest within the lifetime of the
389
+ `inplace_stop_source` object. — *end note*]
390
 
391
  ### Header `<stop_token>` synopsis <a id="thread.stoptoken.syn">[[thread.stoptoken.syn]]</a>
392
 
393
  ``` cpp
394
  namespace std {
395
+ // [stoptoken.concepts], stop token concepts
396
+ template<class CallbackFn, class Token, class Initializer = CallbackFn>
397
+ concept stoppable-callback-for = see below; // exposition only
398
+
399
+ template<class Token>
400
+ concept stoppable_token = see below;
401
+
402
+ template<class Token>
403
+ concept unstoppable_token = see below;
404
+
405
+ template<class Source>
406
+ concept stoppable-source = see below; // exposition only
407
+
408
  // [stoptoken], class stop_token
409
  class stop_token;
410
 
411
  // [stopsource], class stop_source
412
  class stop_source;
 
418
  inline constexpr nostopstate_t nostopstate{};
419
 
420
  // [stopcallback], class template stop_callback
421
  template<class Callback>
422
  class stop_callback;
423
+
424
+ // [stoptoken.never], class never_stop_token
425
+ class never_stop_token;
426
+
427
+ // [stoptoken.inplace], class inplace_stop_token
428
+ class inplace_stop_token;
429
+
430
+ // [stopsource.inplace], class inplace_stop_source
431
+ class inplace_stop_source;
432
+
433
+ // [stopcallback.inplace], class template inplace_stop_callback
434
+ template<class CallbackFn>
435
+ class inplace_stop_callback;
436
+
437
+ template<class T, class CallbackFn>
438
+ using stop_callback_for_t = T::template callback_type<CallbackFn>;
439
  }
440
  ```
441
 
442
+ ### Stop token concepts <a id="stoptoken.concepts">[[stoptoken.concepts]]</a>
443
+
444
+ The exposition-only `stoppable-callback-for` concept checks for a
445
+ callback compatible with a given `Token` type.
446
+
447
+ ``` cpp
448
+ template<class CallbackFn, class Token, class Initializer = CallbackFn>
449
+ concept stoppable-callback-for = // exposition only
450
+ invocable<CallbackFn> &&
451
+ constructible_from<CallbackFn, Initializer> &&
452
+ requires { typename stop_callback_for_t<Token, CallbackFn>; } &&
453
+ constructible_from<stop_callback_for_t<Token, CallbackFn>, const Token&, Initializer>;
454
+ ```
455
+
456
+ Let `t` and `u` be distinct, valid objects of type `Token` that
457
+ reference the same logical stop state; let `init` be an expression such
458
+ that `same_as<decltype(init), Initializer>` is `true`; and let `SCB`
459
+ denote the type `stop_callback_for_t<Token, CallbackFn>`.
460
+
461
+ The concept `stoppable-callback-for<CallbackFn, Token, Initializer>` is
462
+ modeled only if:
463
+
464
+ - The following concepts are modeled:
465
+ - `\texttt{constructible_from}<SCB, Token, Initializer>`
466
+ - `\texttt{constructible_from}<SCB, Token&, Initializer>`
467
+ - `\texttt{constructible_from}<SCB, const Token, Initializer>`
468
+ - An object of type `SCB` has an associated callback function of type
469
+ `CallbackFn`. Let `scb` be an object of type `SCB` and let
470
+ `callback_fn` denote `scb`’s associated callback function.
471
+ Direct-non-list-initializing `scb` from arguments `t` and `init` shall
472
+ execute a *stoppable callback registration* as follows:
473
+ - If `t.stop_possible()` is `true`:
474
+ - `callback_fn` shall be direct-initialized with `init`.
475
+ - Construction of `scb` shall only throw exceptions thrown by the
476
+ initialization of `callback_fn` from `init`.
477
+ - The callback invocation `std::forward<CallbackFn>(callback_fn)()`
478
+ shall be registered with `t`’s associated stop state as follows:
479
+ - If `t.stop_requested()` evaluates to `false` at the time of
480
+ registration, the callback invocation is added to the stop
481
+ state’s list of callbacks such that
482
+ `std::forward<CallbackFn>( callback_fn)()` is evaluated if a
483
+ stop request is made on the stop state.
484
+ - Otherwise, `std::forward<CallbackFn>(callback_fn)()` shall be
485
+ immediately evaluated on the thread executing `scb`’s
486
+ constructor, and the callback invocation shall not be added to
487
+ the list of callback invocations.
488
+
489
+ If the callback invocation was added to stop state’s list of
490
+ callbacks, `scb` shall be associated with the stop state.
491
+ - \[*Note 1*: If `t.stop_possible()` is `false`, there is no
492
+ requirement that the initialization of `scb` causes the
493
+ initialization of `callback_fn`. — *end note*]
494
+ - Destruction of `scb` shall execute a
495
+ *stoppable callback deregistration* as follows (in order):
496
+ - If the constructor of `scb` did not register a callback invocation
497
+ with `t`’s stop state, then the stoppable callback deregistration
498
+ shall have no effect other than destroying `callback_fn` if it was
499
+ constructed.
500
+ - Otherwise, the invocation of `callback_fn` shall be removed from the
501
+ associated stop state.
502
+ - If `callback_fn` is concurrently executing on another thread, then
503
+ the stoppable callback deregistration shall block [[defns.block]]
504
+ until the invocation of `callback_fn` returns such that the return
505
+ from the invocation of `callback_fn` strongly happens before
506
+ [[intro.races]] the destruction of `callback_fn`.
507
+ - If `callback_fn` is executing on the current thread, then the
508
+ destructor shall not block waiting for the return from the
509
+ invocation of `callback_fn`.
510
+ - A stoppable callback deregistration shall not block on the
511
+ completion of the invocation of some other callback registered with
512
+ the same logical stop state.
513
+ - The stoppable callback deregistration shall destroy `callback_fn`.
514
+
515
+ The `stoppable_token` concept checks for the basic interface of a stop
516
+ token that is copyable and allows polling to see if stop has been
517
+ requested and also whether a stop request is possible. The
518
+ `unstoppable_token` concept checks for a `stoppable_token` type that
519
+ does not allow stopping.
520
+
521
+ ``` cpp
522
+ template<template<class> class>
523
+ struct check-type-alias-exists; // exposition only
524
+
525
+ template<class Token>
526
+ concept stoppable_token =
527
+ requires (const Token tok) {
528
+ typename check-type-alias-exists<Token::template callback_type>;
529
+ { tok.stop_requested() } noexcept -> same_as<bool>;
530
+ { tok.stop_possible() } noexcept -> same_as<bool>;
531
+ { Token(tok) } noexcept; // see implicit expression variations[concepts.equality]
532
+ } &&
533
+ copyable<Token> &&
534
+ equality_comparable<Token>;
535
+
536
+ template<class Token>
537
+ concept unstoppable_token =
538
+ stoppable_token<Token> &&
539
+ requires (const Token tok) {
540
+ requires bool_constant<(!tok.stop_possible())>::value;
541
+ };
542
+ ```
543
+
544
+ An object whose type models `stoppable_token` has at most one associated
545
+ logical stop state. A `stoppable_token` object with no associated stop
546
+ state is said to be *disengaged*.
547
+
548
+ Let `SP` be an evaluation of `t.stop_possible()` that is `false`, and
549
+ let SR be an evaluation of `t.stop_requested()` that is `true`.
550
+
551
+ The type `Token` models `stoppable_token` only if:
552
+
553
+ - Any evaluation of `u.stop_possible()` or `u.stop_requested()` that
554
+ happens after [[intro.races]] `SP` is `false`.
555
+ - Any evaluation of `u.stop_possible()` or `u.stop_requested()` that
556
+ happens after `SR` is `true`.
557
+ - For any types `CallbackFn` and `Initializer` such that
558
+ `stoppable-callback-for<CallbackFn, Token, Initializer>` is satisfied,
559
+ `stoppable-callback-for<CallbackFn, Token, Initializer>` is modeled.
560
+ - If `t` is disengaged, evaluations of `t.stop_possible()` and
561
+ `t.stop_requested()` are `false`.
562
+ - If `t` and `u` reference the same stop state, or if both `t` and `u`
563
+ are disengaged, `t == u` is `true`; otherwise, it is `false`.
564
+
565
+ An object whose type models the exposition-only `stoppable-source`
566
+ concept can be queried whether stop has been requested
567
+ (`stop_requested`) and whether stop is possible (`stop_possible`). It is
568
+ a factory for associated stop tokens (`get_token`), and a stop request
569
+ can be made on it (`request_stop`). It maintains a list of registered
570
+ stop callback invocations that it executes when a stop request is first
571
+ made.
572
+
573
+ ``` cpp
574
+ template<class Source>
575
+ concept stoppable-source = // exposition only
576
+ requires (Source& src, const Source csrc) { // see implicit expression variations[concepts.equality]
577
+ { csrc.get_token() } -> stoppable_token;
578
+ { csrc.stop_possible() } noexcept -> same_as<bool>;
579
+ { csrc.stop_requested() } noexcept -> same_as<bool>;
580
+ { src.request_stop() } -> same_as<bool>;
581
+ };
582
+ ```
583
+
584
+ An object whose type models `stoppable-source` has at most one
585
+ associated logical stop state. If it has no associated stop state, it is
586
+ said to be disengaged. Let `s` be an object whose type models
587
+ `stoppable-source` and that is disengaged. `s.stop_possible()` and
588
+ `s.stop_requested()` shall be `false`.
589
+
590
+ Let `t` be an object whose type models `stoppable-source`. If `t` is
591
+ disengaged, `t.get_token()` shall return a disengaged stop token;
592
+ otherwise, it shall return a stop token that is associated with the stop
593
+ state of `t`.
594
+
595
+ Calls to the member functions `request_stop`, `stop_requested`, and
596
+ `stop_possible` and similarly named member functions on associated
597
+ `stoppable_token` objects do not introduce data races. A call to
598
+ `request_stop` that returns `true` synchronizes with a call to
599
+ `stop_requested` on an associated `stoppable_token` or
600
+ `stoppable-source` object that returns `true`. Registration of a
601
+ callback synchronizes with the invocation of that callback.
602
+
603
+ If the `stoppable-source` is disengaged, `request_stop` shall have no
604
+ effect and return `false`. Otherwise, it shall execute a
605
+ *stop request operation* on the associated stop state. A stop request
606
+ operation determines whether the stop state has received a stop request,
607
+ and if not, makes a stop request. The determination and making of the
608
+ stop request shall happen atomically, as-if by a read-modify-write
609
+ operation [[intro.races]]. If the request was made, the stop state’s
610
+ registered callback invocations shall be synchronously executed. If an
611
+ invocation of a callback exits via an exception then `terminate` shall
612
+ be invoked [[except.terminate]].
613
+
614
+ [*Note 2*: No constraint is placed on the order in which the callback
615
+ invocations are executed. — *end note*]
616
+
617
+ `request_stop` shall return `true` if a stop request was made, and
618
+ `false` otherwise. After a call to `request_stop` either a call to
619
+ `stop_possible` shall return `false` or a call to `stop_requested` shall
620
+ return `true`.
621
+
622
+ [*Note 3*: A stop request includes notifying all condition variables of
623
+ type `condition_variable_any` temporarily registered during an
624
+ interruptible wait [[thread.condvarany.intwait]]. — *end note*]
625
+
626
  ### Class `stop_token` <a id="stoptoken">[[stoptoken]]</a>
627
 
628
  #### General <a id="stoptoken.general">[[stoptoken.general]]</a>
629
 
630
+ The class `stop_token` models the concept `stoppable_token`. It shares
631
+ ownership of its stop state, if any, with its associated `stop_source`
632
+ object [[stopsource]] and any `stop_token` objects to which it compares
633
+ equal.
 
 
634
 
635
  ``` cpp
636
  namespace std {
637
  class stop_token {
638
  public:
639
+ template<class CallbackFn>
640
+ using callback_type = stop_callback<CallbackFn>;
641
 
642
+ stop_token() noexcept = default;
643
+
644
+ // [stoptoken.mem], member functions
 
 
645
  void swap(stop_token&) noexcept;
646
 
647
+ bool stop_requested() const noexcept;
648
+ bool stop_possible() const noexcept;
 
649
 
650
+ bool operator==(const stop_token& rhs) noexcept = default;
651
+
652
+ private:
653
+ shared_ptr<unspecified> stop-state; // exposition only
654
  };
655
  }
656
  ```
657
 
658
+ *`stop-state`* refers to the `stop_token`’s associated stop state. A
659
+ `stop_token` object is disengaged when *`stop-state`* is empty.
660
 
661
+ #### Member functions <a id="stoptoken.mem">[[stoptoken.mem]]</a>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
662
 
663
  ``` cpp
664
  void swap(stop_token& rhs) noexcept;
665
  ```
666
 
667
+ *Effects:* Equivalent to:
668
 
669
+ ``` cpp
670
+ stop-state.swap(rhs.stop-state);
671
+ ```
672
 
673
  ``` cpp
674
+ bool stop_requested() const noexcept;
675
  ```
676
 
677
+ *Returns:* `true` if *stop-state* refers to a stop state that has
678
  received a stop request; otherwise, `false`.
679
 
680
  ``` cpp
681
+ bool stop_possible() const noexcept;
682
  ```
683
 
684
+ *Returns:* `false` if
685
 
686
+ - `*this` is disengaged, or
687
  - a stop request was not made and there are no associated `stop_source`
688
  objects;
689
 
690
  otherwise, `true`.
691
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
692
  ### Class `stop_source` <a id="stopsource">[[stopsource]]</a>
693
 
694
  #### General <a id="stopsource.general">[[stopsource.general]]</a>
695
 
 
 
 
 
 
 
696
  ``` cpp
697
  namespace std {
 
 
 
 
 
 
698
  class stop_source {
699
  public:
700
  // [stopsource.cons], constructors, copy, and assignment
701
  stop_source();
702
+ explicit stop_source(nostopstate_t) noexcept {}
703
 
704
+ // [stopsource.mem], member functions
 
 
 
 
705
  void swap(stop_source&) noexcept;
706
 
707
+ stop_token get_token() const noexcept;
708
+ bool stop_possible() const noexcept;
709
+ bool stop_requested() const noexcept;
 
710
  bool request_stop() noexcept;
711
 
712
+ bool operator==(const stop_source& rhs) noexcept = default;
713
+
714
+ private:
715
+ shared_ptr<unspecified> stop-state; // exposition only
716
  };
717
  }
718
  ```
719
 
720
+ *`stop-state`* refers to the `stop_source`’s associated stop state. A
721
+ `stop_source` object is disengaged when *`stop-state`* is empty.
722
+
723
+ `stop_source` models `stoppable-source`, `copyable`,
724
+ `equality_comparable`, and `swappable`.
725
+
726
  #### Constructors, copy, and assignment <a id="stopsource.cons">[[stopsource.cons]]</a>
727
 
728
  ``` cpp
729
  stop_source();
730
  ```
731
 
732
+ *Effects:* Initializes *stop-state* with a pointer to a new stop state.
733
 
734
  *Ensures:* `stop_possible()` is `true` and `stop_requested()` is
735
  `false`.
736
 
737
  *Throws:* `bad_alloc` if memory cannot be allocated for the stop state.
738
 
739
+ #### Member functions <a id="stopsource.mem">[[stopsource.mem]]</a>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
740
 
741
  ``` cpp
742
  void swap(stop_source& rhs) noexcept;
743
  ```
744
 
745
+ *Effects:* Equivalent to:
746
 
747
+ ``` cpp
748
+ stop-state.swap(rhs.stop-state);
749
+ ```
750
 
751
  ``` cpp
752
+ stop_token get_token() const noexcept;
753
  ```
754
 
755
  *Returns:* `stop_token()` if `stop_possible()` is `false`; otherwise a
756
+ new associated `stop_token` object; i.e., its *stop-state* member is
757
+ equal to the *stop-state* member of `*this`.
758
 
759
  ``` cpp
760
+ bool stop_possible() const noexcept;
761
  ```
762
 
763
+ *Returns:* *`stop-state`*` != nullptr`.
 
764
 
765
  ``` cpp
766
+ bool stop_requested() const noexcept;
767
  ```
768
 
769
+ *Returns:* `true` if *stop-state* refers to a stop state that has
770
  received a stop request; otherwise, `false`.
771
 
772
  ``` cpp
773
  bool request_stop() noexcept;
774
  ```
775
 
776
+ *Effects:* Executes a stop request operation [[stoptoken.concepts]] on
777
+ the associated stop state, if any.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
778
 
779
  ### Class template `stop_callback` <a id="stopcallback">[[stopcallback]]</a>
780
 
781
  #### General <a id="stopcallback.general">[[stopcallback.general]]</a>
782
 
783
  ``` cpp
784
  namespace std {
785
+ template<class CallbackFn>
786
  class stop_callback {
787
  public:
788
+ using callback_type = CallbackFn;
789
 
790
  // [stopcallback.cons], constructors and destructor
791
+ template<class Initializer>
792
+ explicit stop_callback(const stop_token& st, Initializer&& init)
793
+ noexcept(is_nothrow_constructible_v<CallbackFn, Initializer>);
794
+ template<class Initializer>
795
+ explicit stop_callback(stop_token&& st, Initializer&& init)
796
+ noexcept(is_nothrow_constructible_v<CallbackFn, Initializer>);
797
  ~stop_callback();
798
 
799
  stop_callback(const stop_callback&) = delete;
800
  stop_callback(stop_callback&&) = delete;
801
  stop_callback& operator=(const stop_callback&) = delete;
802
  stop_callback& operator=(stop_callback&&) = delete;
803
 
804
  private:
805
+ CallbackFn callback-fn; // exposition only
806
  };
807
 
808
+ template<class CallbackFn>
809
+ stop_callback(stop_token, CallbackFn) -> stop_callback<CallbackFn>;
810
  }
811
  ```
812
 
813
  *Mandates:* `stop_callback` is instantiated with an argument for the
814
+ template parameter `CallbackFn` that satisfies both `invocable` and
815
  `destructible`.
816
 
817
+ *Remarks:* For a type `Initializer`, if
818
+ `stoppable-callback-for<CallbackFn, stop_token, Initializer>` is
819
+ satisfied, then
820
+ `stoppable-callback-for<CallbackFn, stop_token, Initializer>` is
821
+ modeled. The exposition-only *`callback-fn`* member is the associated
822
+ callback function [[stoptoken.concepts]] of `stop_callback< CallbackFn>`
823
+ objects.
824
 
825
  #### Constructors and destructor <a id="stopcallback.cons">[[stopcallback.cons]]</a>
826
 
827
  ``` cpp
828
+ template<class Initializer>
829
+ explicit stop_callback(const stop_token& st, Initializer&& init)
830
+ noexcept(is_nothrow_constructible_v<CallbackFn, Initializer>);
831
+
832
+ template<class Initializer>
833
+ explicit stop_callback(stop_token&& st, Initializer&& init)
834
+ noexcept(is_nothrow_constructible_v<CallbackFn, Initializer>);
835
  ```
836
 
837
+ *Constraints:* `CallbackFn` and `Initializer` satisfy
838
+ `constructible_from<CallbackFn, Initializer>`.
839
+
840
+ *Effects:* Initializes *callback-fn* with
841
+ `std::forward<Initializer>(init)` and executes a stoppable callback
842
+ registration [[stoptoken.concepts]]. If a callback is registered with
843
+ `st`’s shared stop state, then `*this` acquires shared ownership of that
844
+ stop state.
 
 
 
 
 
 
 
 
 
 
 
845
 
846
  ``` cpp
847
  ~stop_callback();
848
  ```
849
 
850
+ *Effects:* Executes a stoppable callback
851
+ deregistration [[stoptoken.concepts]] and releases ownership of the stop
852
+ state, if any.
853
+
854
+ ### Class `never_stop_token` <a id="stoptoken.never">[[stoptoken.never]]</a>
855
+
856
+ The class `never_stop_token` models the `unstoppable_token` concept. It
857
+ provides a stop token interface, but also provides static information
858
+ that a stop is never possible nor requested.
859
+
860
+ ``` cpp
861
+ namespace std {
862
+ class never_stop_token {
863
+ struct callback-type { // exposition only
864
+ explicit callback-type(never_stop_token, auto&&) noexcept {}
865
+ };
866
+ public:
867
+ template<class>
868
+ using callback_type = callback-type;
869
+
870
+ static constexpr bool stop_requested() noexcept { return false; }
871
+ static constexpr bool stop_possible() noexcept { return false; }
872
+
873
+ bool operator==(const never_stop_token&) const = default;
874
+ };
875
+ }
876
+ ```
877
+
878
+ ### Class `inplace_stop_token` <a id="stoptoken.inplace">[[stoptoken.inplace]]</a>
879
+
880
+ #### General <a id="stoptoken.inplace.general">[[stoptoken.inplace.general]]</a>
881
+
882
+ The class `inplace_stop_token` models the concept `stoppable_token`. It
883
+ references the stop state of its associated `inplace_stop_source` object
884
+ [[stopsource.inplace]], if any.
885
+
886
+ ``` cpp
887
+ namespace std {
888
+ class inplace_stop_token {
889
+ public:
890
+ template<class CallbackFn>
891
+ using callback_type = inplace_stop_callback<CallbackFn>;
892
+
893
+ inplace_stop_token() = default;
894
+ bool operator==(const inplace_stop_token&) const = default;
895
+
896
+ // [stoptoken.inplace.mem], member functions
897
+ bool stop_requested() const noexcept;
898
+ bool stop_possible() const noexcept;
899
+ void swap(inplace_stop_token&) noexcept;
900
+
901
+ private:
902
+ const inplace_stop_source* stop-source = nullptr; // exposition only
903
+ };
904
+ }
905
+ ```
906
+
907
+ #### Member functions <a id="stoptoken.inplace.mem">[[stoptoken.inplace.mem]]</a>
908
+
909
+ ``` cpp
910
+ void swap(inplace_stop_token& rhs) noexcept;
911
+ ```
912
+
913
+ *Effects:* Exchanges the values of *stop-source* and
914
+ `rhs.`*`stop-source`*.
915
+
916
+ ``` cpp
917
+ bool stop_requested() const noexcept;
918
+ ```
919
+
920
+ *Effects:* Equivalent to:
921
+
922
+ ``` cpp
923
+ return stop-source != nullptr && stop-source->stop_requested();
924
+ ```
925
+
926
+ [*Note 1*: As specified in [[basic.life]], the behavior of
927
+ `stop_requested` is undefined unless the call strongly happens before
928
+ the start of the destructor of the associated `inplace_stop_source`
929
+ object, if any. — *end note*]
930
+
931
+ ``` cpp
932
+ stop_possible() const noexcept;
933
+ ```
934
+
935
+ *Returns:* *`stop-source`*` != nullptr`.
936
+
937
+ [*Note 2*: As specified in [[basic.stc.general]], the behavior of
938
+ `stop_possible` is implementation-defined unless the call strongly
939
+ happens before the end of the storage duration of the associated
940
+ `inplace_stop_source` object, if any. — *end note*]
941
+
942
+ ### Class `inplace_stop_source` <a id="stopsource.inplace">[[stopsource.inplace]]</a>
943
+
944
+ #### General <a id="stopsource.inplace.general">[[stopsource.inplace.general]]</a>
945
+
946
+ The class `inplace_stop_source` models `stoppable-source`.
947
+
948
+ ``` cpp
949
+ namespace std {
950
+ class inplace_stop_source {
951
+ public:
952
+ // [stopsource.inplace.cons], constructors
953
+ constexpr inplace_stop_source() noexcept;
954
+
955
+ inplace_stop_source(inplace_stop_source&&) = delete;
956
+ inplace_stop_source(const inplace_stop_source&) = delete;
957
+ inplace_stop_source& operator=(inplace_stop_source&&) = delete;
958
+ inplace_stop_source& operator=(const inplace_stop_source&) = delete;
959
+ ~inplace_stop_source();
960
+
961
+ // [stopsource.inplace.mem], stop handling
962
+ constexpr inplace_stop_token get_token() const noexcept;
963
+ static constexpr bool stop_possible() noexcept { return true; }
964
+ bool stop_requested() const noexcept;
965
+ bool request_stop() noexcept;
966
+ };
967
+ }
968
+ ```
969
+
970
+ #### Constructors <a id="stopsource.inplace.cons">[[stopsource.inplace.cons]]</a>
971
+
972
+ ``` cpp
973
+ constexpr inplace_stop_source() noexcept;
974
+ ```
975
+
976
+ *Effects:* Initializes a new stop state inside `*this`.
977
+
978
+ *Ensures:* `stop_requested()` is `false`.
979
+
980
+ #### Member functions <a id="stopsource.inplace.mem">[[stopsource.inplace.mem]]</a>
981
+
982
+ ``` cpp
983
+ constexpr inplace_stop_token get_token() const noexcept;
984
+ ```
985
+
986
+ *Returns:* A new associated `inplace_stop_token` object whose
987
+ *stop-source* member is equal to `this`.
988
+
989
+ ``` cpp
990
+ bool stop_requested() const noexcept;
991
+ ```
992
+
993
+ *Returns:* `true` if the stop state inside `*this` has received a stop
994
+ request; otherwise, `false`.
995
+
996
+ ``` cpp
997
+ bool request_stop() noexcept;
998
+ ```
999
+
1000
+ *Effects:* Executes a stop request operation [[stoptoken.concepts]].
1001
+
1002
+ *Ensures:* `stop_requested()` is `true`.
1003
+
1004
+ ### Class template `inplace_stop_callback` <a id="stopcallback.inplace">[[stopcallback.inplace]]</a>
1005
+
1006
+ #### General <a id="stopcallback.inplace.general">[[stopcallback.inplace.general]]</a>
1007
+
1008
+ ``` cpp
1009
+ namespace std {
1010
+ template<class CallbackFn>
1011
+ class inplace_stop_callback {
1012
+ public:
1013
+ using callback_type = CallbackFn;
1014
+
1015
+ // [stopcallback.inplace.cons], constructors and destructor
1016
+ template<class Initializer>
1017
+ explicit inplace_stop_callback(inplace_stop_token st, Initializer&& init)
1018
+ noexcept(is_nothrow_constructible_v<CallbackFn, Initializer>);
1019
+ ~inplace_stop_callback();
1020
+
1021
+ inplace_stop_callback(inplace_stop_callback&&) = delete;
1022
+ inplace_stop_callback(const inplace_stop_callback&) = delete;
1023
+ inplace_stop_callback& operator=(inplace_stop_callback&&) = delete;
1024
+ inplace_stop_callback& operator=(const inplace_stop_callback&) = delete;
1025
+
1026
+ private:
1027
+ CallbackFn callback-fn; // exposition only
1028
+ };
1029
+
1030
+ template<class CallbackFn>
1031
+ inplace_stop_callback(inplace_stop_token, CallbackFn)
1032
+ -> inplace_stop_callback<CallbackFn>;
1033
+ }
1034
+ ```
1035
+
1036
+ *Mandates:* `CallbackFn` satisfies both `invocable` and `destructible`.
1037
+
1038
+ *Remarks:* For a type `Initializer`, if
1039
+
1040
+ ``` cpp
1041
+ stoppable-callback-for<CallbackFn, inplace_stop_token, Initializer>
1042
+ ```
1043
+
1044
+ is satisfied, then
1045
+
1046
+ ``` cpp
1047
+ stoppable-callback-for<CallbackFn, inplace_stop_token, Initializer>
1048
+ ```
1049
+
1050
+ is modeled. For an `inplace_stop_callback<CallbackFn>` object, the
1051
+ exposition-only *`callback-fn`* member is its associated callback
1052
+ function [[stoptoken.concepts]].
1053
+
1054
+ #### Constructors and destructor <a id="stopcallback.inplace.cons">[[stopcallback.inplace.cons]]</a>
1055
+
1056
+ ``` cpp
1057
+ template<class Initializer>
1058
+ explicit inplace_stop_callback(inplace_stop_token st, Initializer&& init)
1059
+ noexcept(is_nothrow_constructible_v<CallbackFn, Initializer>);
1060
+ ```
1061
+
1062
+ *Constraints:* `constructible_from<CallbackFn, Initializer>` is
1063
+ satisfied.
1064
+
1065
+ *Effects:* Initializes *callback-fn* with
1066
+ `std::forward<Initializer>(init)` and executes a stoppable callback
1067
+ registration [[stoptoken.concepts]].
1068
+
1069
+ ``` cpp
1070
+ ~inplace_stop_callback();
1071
+ ```
1072
+
1073
+ *Effects:* Executes a stoppable callback
1074
+ deregistration [[stoptoken.concepts]].
1075
 
1076
  ## Threads <a id="thread.threads">[[thread.threads]]</a>
1077
 
1078
  ### General <a id="thread.threads.general">[[thread.threads.general]]</a>
1079
 
 
1477
  jthread& operator=(const jthread&) = delete;
1478
  jthread& operator=(jthread&&) noexcept;
1479
 
1480
  // [thread.jthread.mem], members
1481
  void swap(jthread&) noexcept;
1482
+ bool joinable() const noexcept;
1483
  void join();
1484
  void detach();
1485
+ id get_id() const noexcept;
1486
+ native_handle_type native_handle(); // see~[thread.req.native]
1487
 
1488
  // [thread.jthread.stop], stop token handling
1489
+ stop_source get_stop_source() noexcept;
1490
+ stop_token get_stop_token() const noexcept;
1491
  bool request_stop() noexcept;
1492
 
1493
  // [thread.jthread.special], specialized algorithms
1494
  friend void swap(jthread& lhs, jthread& rhs) noexcept;
1495
 
1496
  // [thread.jthread.static], static members
1497
+ static unsigned int hardware_concurrency() noexcept;
1498
 
1499
  private:
1500
  stop_source ssource; // exposition only
1501
  };
1502
  }
 
1608
  ```
1609
 
1610
  *Effects:* Exchanges the values of `*this` and `x`.
1611
 
1612
  ``` cpp
1613
+ bool joinable() const noexcept;
1614
  ```
1615
 
1616
  *Returns:* `get_id() != id()`.
1617
 
1618
  ``` cpp
 
1669
  execution represented by `*this`.
1670
 
1671
  #### Stop token handling <a id="thread.jthread.stop">[[thread.jthread.stop]]</a>
1672
 
1673
  ``` cpp
1674
+ stop_source get_stop_source() noexcept;
1675
  ```
1676
 
1677
  *Effects:* Equivalent to: `return ssource;`
1678
 
1679
  ``` cpp
1680
+ stop_token get_stop_token() const noexcept;
1681
  ```
1682
 
1683
  *Effects:* Equivalent to: `return ssource.get_token();`
1684
 
1685
  ``` cpp
 
1697
  *Effects:* Equivalent to: `x.swap(y)`.
1698
 
1699
  #### Static members <a id="thread.jthread.static">[[thread.jthread.static]]</a>
1700
 
1701
  ``` cpp
1702
+ static unsigned int hardware_concurrency() noexcept;
1703
  ```
1704
 
1705
  *Returns:* `thread::hardware_concurrency()`.
1706
 
1707
  ### Namespace `this_thread` <a id="thread.thread.this">[[thread.thread.this]]</a>
 
1767
  access. This access is provided via operations on atomic objects.
1768
 
1769
  ### Header `<atomic>` synopsis <a id="atomics.syn">[[atomics.syn]]</a>
1770
 
1771
  ``` cpp
1772
+ // mostly freestanding
1773
  namespace std {
1774
  // [atomics.order], order and consistency
1775
+ enum class memory_order : unspecified;
1776
+ inline constexpr memory_order memory_order_relaxed = memory_order::relaxed;
1777
+ inline constexpr memory_order memory_order_acquire = memory_order::acquire;
1778
+ inline constexpr memory_order memory_order_release = memory_order::release;
1779
+ inline constexpr memory_order memory_order_acq_rel = memory_order::acq_rel;
1780
+ inline constexpr memory_order memory_order_seq_cst = memory_order::seq_cst;
 
 
 
 
1781
  }
1782
 
1783
  // [atomics.lockfree], lock-free property
1784
+ #define ATOMIC_BOOL_LOCK_FREE unspecified
1785
+ #define ATOMIC_CHAR_LOCK_FREE unspecified
1786
+ #define ATOMIC_CHAR8_T_LOCK_FREE unspecified
1787
+ #define ATOMIC_CHAR16_T_LOCK_FREE unspecified
1788
+ #define ATOMIC_CHAR32_T_LOCK_FREE unspecified
1789
+ #define ATOMIC_WCHAR_T_LOCK_FREE unspecified
1790
+ #define ATOMIC_SHORT_LOCK_FREE unspecified
1791
+ #define ATOMIC_INT_LOCK_FREE unspecified
1792
+ #define ATOMIC_LONG_LOCK_FREE unspecified
1793
+ #define ATOMIC_LLONG_LOCK_FREE unspecified
1794
+ #define ATOMIC_POINTER_LOCK_FREE unspecified
1795
 
1796
  namespace std {
1797
  // [atomics.ref.generic], class template atomic_ref
1798
+ template<class T> struct atomic_ref;
 
 
1799
 
1800
  // [atomics.types.generic], class template atomic
1801
+ template<class T> struct atomic;
1802
  // [atomics.types.pointer], partial specialization for pointers
1803
+ template<class T> struct atomic<T*>;
1804
 
1805
  // [atomics.nonmembers], non-member functions
1806
  template<class T>
1807
+ bool atomic_is_lock_free(const volatile atomic<T>*) noexcept;
1808
  template<class T>
1809
+ bool atomic_is_lock_free(const atomic<T>*) noexcept;
1810
  template<class T>
1811
+ void atomic_store(volatile atomic<T>*, typename atomic<T>::value_type) noexcept;
 
1812
  template<class T>
1813
+ constexpr void atomic_store(atomic<T>*, typename atomic<T>::value_type) noexcept;
1814
  template<class T>
1815
+ void atomic_store_explicit(volatile atomic<T>*, typename atomic<T>::value_type,
 
1816
  memory_order) noexcept;
1817
  template<class T>
1818
+ constexpr void atomic_store_explicit(atomic<T>*, typename atomic<T>::value_type,
1819
  memory_order) noexcept;
1820
  template<class T>
1821
+ T atomic_load(const volatile atomic<T>*) noexcept;
1822
  template<class T>
1823
+ constexpr T atomic_load(const atomic<T>*) noexcept;
1824
  template<class T>
1825
+ T atomic_load_explicit(const volatile atomic<T>*, memory_order) noexcept;
1826
  template<class T>
1827
+ constexpr T atomic_load_explicit(const atomic<T>*, memory_order) noexcept;
1828
  template<class T>
1829
+ T atomic_exchange(volatile atomic<T>*, typename atomic<T>::value_type) noexcept;
 
1830
  template<class T>
1831
+ constexpr T atomic_exchange(atomic<T>*, typename atomic<T>::value_type) noexcept;
1832
  template<class T>
1833
+ T atomic_exchange_explicit(volatile atomic<T>*, typename atomic<T>::value_type,
 
1834
  memory_order) noexcept;
1835
  template<class T>
1836
+ constexpr T atomic_exchange_explicit(atomic<T>*, typename atomic<T>::value_type,
1837
  memory_order) noexcept;
1838
  template<class T>
1839
+ bool atomic_compare_exchange_weak(volatile atomic<T>*,
1840
  typename atomic<T>::value_type*,
1841
  typename atomic<T>::value_type) noexcept;
1842
  template<class T>
1843
+ constexpr bool atomic_compare_exchange_weak(atomic<T>*,
1844
  typename atomic<T>::value_type*,
1845
  typename atomic<T>::value_type) noexcept;
1846
  template<class T>
1847
+ bool atomic_compare_exchange_strong(volatile atomic<T>*,
1848
  typename atomic<T>::value_type*,
1849
  typename atomic<T>::value_type) noexcept;
1850
  template<class T>
1851
+ constexpr bool atomic_compare_exchange_strong(atomic<T>*,
1852
  typename atomic<T>::value_type*,
1853
  typename atomic<T>::value_type) noexcept;
1854
  template<class T>
1855
+ bool atomic_compare_exchange_weak_explicit(volatile atomic<T>*,
1856
  typename atomic<T>::value_type*,
1857
  typename atomic<T>::value_type,
1858
  memory_order, memory_order) noexcept;
1859
  template<class T>
1860
+ constexpr bool atomic_compare_exchange_weak_explicit(atomic<T>*,
1861
  typename atomic<T>::value_type*,
1862
  typename atomic<T>::value_type,
1863
  memory_order, memory_order) noexcept;
1864
  template<class T>
1865
+ bool atomic_compare_exchange_strong_explicit(volatile atomic<T>*,
1866
  typename atomic<T>::value_type*,
1867
  typename atomic<T>::value_type,
1868
  memory_order, memory_order) noexcept;
1869
  template<class T>
1870
+ constexpr bool atomic_compare_exchange_strong_explicit(atomic<T>*,
1871
  typename atomic<T>::value_type*,
1872
  typename atomic<T>::value_type,
1873
  memory_order, memory_order) noexcept;
1874
 
1875
  template<class T>
1876
+ T atomic_fetch_add(volatile atomic<T>*, typename atomic<T>::difference_type) noexcept;
 
1877
  template<class T>
1878
+ constexpr T atomic_fetch_add(atomic<T>*, typename atomic<T>::difference_type) noexcept;
1879
  template<class T>
1880
+ T atomic_fetch_add_explicit(volatile atomic<T>*, typename atomic<T>::difference_type,
 
1881
  memory_order) noexcept;
1882
  template<class T>
1883
+ constexpr T atomic_fetch_add_explicit(atomic<T>*, typename atomic<T>::difference_type,
1884
  memory_order) noexcept;
1885
  template<class T>
1886
+ T atomic_fetch_sub(volatile atomic<T>*, typename atomic<T>::difference_type) noexcept;
 
1887
  template<class T>
1888
+ constexpr T atomic_fetch_sub(atomic<T>*, typename atomic<T>::difference_type) noexcept;
1889
  template<class T>
1890
+ T atomic_fetch_sub_explicit(volatile atomic<T>*, typename atomic<T>::difference_type,
 
1891
  memory_order) noexcept;
1892
  template<class T>
1893
+ constexpr T atomic_fetch_sub_explicit(atomic<T>*, typename atomic<T>::difference_type,
1894
  memory_order) noexcept;
1895
  template<class T>
1896
+ T atomic_fetch_and(volatile atomic<T>*, typename atomic<T>::value_type) noexcept;
 
1897
  template<class T>
1898
+ constexpr T atomic_fetch_and(atomic<T>*, typename atomic<T>::value_type) noexcept;
1899
  template<class T>
1900
+ T atomic_fetch_and_explicit(volatile atomic<T>*, typename atomic<T>::value_type,
 
1901
  memory_order) noexcept;
1902
  template<class T>
1903
+ constexpr T atomic_fetch_and_explicit(atomic<T>*, typename atomic<T>::value_type,
1904
  memory_order) noexcept;
1905
  template<class T>
1906
+ T atomic_fetch_or(volatile atomic<T>*, typename atomic<T>::value_type) noexcept;
 
1907
  template<class T>
1908
+ constexpr T atomic_fetch_or(atomic<T>*, typename atomic<T>::value_type) noexcept;
1909
  template<class T>
1910
+ T atomic_fetch_or_explicit(volatile atomic<T>*, typename atomic<T>::value_type,
 
1911
  memory_order) noexcept;
1912
  template<class T>
1913
+ constexpr T atomic_fetch_or_explicit(atomic<T>*, typename atomic<T>::value_type,
1914
  memory_order) noexcept;
1915
  template<class T>
1916
+ T atomic_fetch_xor(volatile atomic<T>*, typename atomic<T>::value_type) noexcept;
 
1917
  template<class T>
1918
+ constexpr T atomic_fetch_xor(atomic<T>*, typename atomic<T>::value_type) noexcept;
1919
  template<class T>
1920
+ T atomic_fetch_xor_explicit(volatile atomic<T>*, typename atomic<T>::value_type,
1921
+ memory_order) noexcept;
1922
+ template<class T>
1923
+ constexpr T atomic_fetch_xor_explicit(atomic<T>*, typename atomic<T>::value_type,
1924
+ memory_order) noexcept;
1925
+ template<class T>
1926
+ T atomic_fetch_max(volatile atomic<T>*, typename atomic<T>::value_type) noexcept;
1927
+ template<class T>
1928
+ constexpr T atomic_fetch_max(atomic<T>*, typename atomic<T>::value_type) noexcept;
1929
+ template<class T>
1930
+ T atomic_fetch_max_explicit(volatile atomic<T>*, typename atomic<T>::value_type,
1931
+ memory_order) noexcept;
1932
+ template<class T>
1933
+ constexpr T atomic_fetch_max_explicit(atomic<T>*, typename atomic<T>::value_type,
1934
+ memory_order) noexcept;
1935
+ template<class T>
1936
+ T atomic_fetch_min(volatile atomic<T>*, typename atomic<T>::value_type) noexcept;
1937
+ template<class T>
1938
+ constexpr T atomic_fetch_min(atomic<T>*, typename atomic<T>::value_type) noexcept;
1939
+ template<class T>
1940
+ T atomic_fetch_min_explicit(volatile atomic<T>*, typename atomic<T>::value_type,
1941
  memory_order) noexcept;
1942
  template<class T>
1943
+ constexpr T atomic_fetch_min_explicit(atomic<T>*, typename atomic<T>::value_type,
1944
  memory_order) noexcept;
1945
 
1946
  template<class T>
1947
+ void atomic_store_add(volatile atomic<T>*, typename atomic<T>::difference_type) noexcept;
 
1948
  template<class T>
1949
+ constexpr void atomic_store_add(atomic<T>*, typename atomic<T>::difference_type) noexcept;
1950
  template<class T>
1951
+ void atomic_store_add_explicit(volatile atomic<T>*, typename atomic<T>::difference_type,
1952
+ memory_order) noexcept;
1953
+ template<class T>
1954
+ constexpr void atomic_store_add_explicit(atomic<T>*, typename atomic<T>::difference_type,
1955
+ memory_order) noexcept;
1956
+ template<class T>
1957
+ void atomic_store_sub(volatile atomic<T>*, typename atomic<T>::difference_type) noexcept;
1958
+ template<class T>
1959
+ constexpr void atomic_store_sub(atomic<T>*, typename atomic<T>::difference_type) noexcept;
1960
+ template<class T>
1961
+ void atomic_store_sub_explicit(volatile atomic<T>*, typename atomic<T>::difference_type,
1962
+ memory_order) noexcept;
1963
+ template<class T>
1964
+ constexpr void atomic_store_sub_explicit(atomic<T>*, typename atomic<T>::difference_type,
1965
+ memory_order) noexcept;
1966
+ template<class T>
1967
+ void atomic_store_and(volatile atomic<T>*, typename atomic<T>::value_type) noexcept;
1968
+ template<class T>
1969
+ constexpr void atomic_store_and(atomic<T>*, typename atomic<T>::value_type) noexcept;
1970
+ template<class T>
1971
+ void atomic_store_and_explicit(volatile atomic<T>*, typename atomic<T>::value_type,
1972
+ memory_order) noexcept;
1973
+ template<class T>
1974
+ constexpr void atomic_store_and_explicit(atomic<T>*, typename atomic<T>::value_type,
1975
+ memory_order) noexcept;
1976
+ template<class T>
1977
+ void atomic_store_or(volatile atomic<T>*, typename atomic<T>::value_type) noexcept;
1978
+ template<class T>
1979
+ constexpr void atomic_store_or(atomic<T>*, typename atomic<T>::value_type) noexcept;
1980
+ template<class T>
1981
+ void atomic_store_or_explicit(volatile atomic<T>*, typename atomic<T>::value_type,
1982
+ memory_order) noexcept;
1983
+ template<class T>
1984
+ constexpr void atomic_store_or_explicit(atomic<T>*, typename atomic<T>::value_type,
1985
+ memory_order) noexcept;
1986
+ template<class T>
1987
+ void atomic_store_xor(volatile atomic<T>*, typename atomic<T>::value_type) noexcept;
1988
+ template<class T>
1989
+ constexpr void atomic_store_xor(atomic<T>*, typename atomic<T>::value_type) noexcept;
1990
+ template<class T>
1991
+ void atomic_store_xor_explicit(volatile atomic<T>*, typename atomic<T>::value_type,
1992
+ memory_order) noexcept;
1993
+ template<class T>
1994
+ constexpr void atomic_store_xor_explicit(atomic<T>*, typename atomic<T>::value_type,
1995
+ memory_order) noexcept;
1996
+ template<class T>
1997
+ void atomic_store_max(volatile atomic<T>*, typename atomic<T>::value_type) noexcept;
1998
+ template<class T>
1999
+ constexpr void atomic_store_max(atomic<T>*, typename atomic<T>::value_type) noexcept;
2000
+ template<class T>
2001
+ void atomic_store_max_explicit(volatile atomic<T>*, typename atomic<T>::value_type,
2002
+ memory_order) noexcept;
2003
+ template<class T>
2004
+ constexpr void atomic_store_max_explicit(atomic<T>*, typename atomic<T>::value_type,
2005
+ memory_order) noexcept;
2006
+ template<class T>
2007
+ void atomic_store_min(volatile atomic<T>*, typename atomic<T>::value_type) noexcept;
2008
+ template<class T>
2009
+ constexpr void atomic_store_min(atomic<T>*, typename atomic<T>::value_type) noexcept;
2010
+ template<class T>
2011
+ void atomic_store_min_explicit(volatile atomic<T>*, typename atomic<T>::value_type,
2012
+ memory_order) noexcept;
2013
+ template<class T>
2014
+ constexpr void atomic_store_min_explicit(atomic<T>*, typename atomic<T>::value_type,
2015
+ memory_order) noexcept;
2016
+
2017
+ template<class T>
2018
+ void atomic_wait(const volatile atomic<T>*, typename atomic<T>::value_type) noexcept;
2019
+ template<class T>
2020
+ constexpr void atomic_wait(const atomic<T>*, typename atomic<T>::value_type) noexcept;
2021
+ template<class T>
2022
+ void atomic_wait_explicit(const volatile atomic<T>*, typename atomic<T>::value_type,
2023
  memory_order) noexcept;
2024
  template<class T>
2025
+ constexpr void atomic_wait_explicit(const atomic<T>*, typename atomic<T>::value_type,
2026
  memory_order) noexcept;
2027
  template<class T>
2028
+ void atomic_notify_one(volatile atomic<T>*) noexcept;
2029
  template<class T>
2030
+ constexpr void atomic_notify_one(atomic<T>*) noexcept;
2031
  template<class T>
2032
+ void atomic_notify_all(volatile atomic<T>*) noexcept;
2033
  template<class T>
2034
+ constexpr void atomic_notify_all(atomic<T>*) noexcept;
2035
 
2036
  // [atomics.alias], type aliases
2037
+ using atomic_bool = atomic<bool>;
2038
+ using atomic_char = atomic<char>;
2039
+ using atomic_schar = atomic<signed char>;
2040
+ using atomic_uchar = atomic<unsigned char>;
2041
+ using atomic_short = atomic<short>;
2042
+ using atomic_ushort = atomic<unsigned short>;
2043
+ using atomic_int = atomic<int>;
2044
+ using atomic_uint = atomic<unsigned int>;
2045
+ using atomic_long = atomic<long>;
2046
+ using atomic_ulong = atomic<unsigned long>;
2047
+ using atomic_llong = atomic<long long>;
2048
+ using atomic_ullong = atomic<unsigned long long>;
2049
+ using atomic_char8_t = atomic<char8_t>;
2050
+ using atomic_char16_t = atomic<char16_t>;
2051
+ using atomic_char32_t = atomic<char32_t>;
2052
+ using atomic_wchar_t = atomic<wchar_t>;
2053
 
2054
+ using atomic_int8_t = atomic<int8_t>;
2055
+ using atomic_uint8_t = atomic<uint8_t>;
2056
+ using atomic_int16_t = atomic<int16_t>;
2057
+ using atomic_uint16_t = atomic<uint16_t>;
2058
+ using atomic_int32_t = atomic<int32_t>;
2059
+ using atomic_uint32_t = atomic<uint32_t>;
2060
+ using atomic_int64_t = atomic<int64_t>;
2061
+ using atomic_uint64_t = atomic<uint64_t>;
2062
 
2063
+ using atomic_int_least8_t = atomic<int_least8_t>;
2064
+ using atomic_uint_least8_t = atomic<uint_least8_t>;
2065
+ using atomic_int_least16_t = atomic<int_least16_t>;
2066
+ using atomic_uint_least16_t = atomic<uint_least16_t>;
2067
+ using atomic_int_least32_t = atomic<int_least32_t>;
2068
+ using atomic_uint_least32_t = atomic<uint_least32_t>;
2069
+ using atomic_int_least64_t = atomic<int_least64_t>;
2070
+ using atomic_uint_least64_t = atomic<uint_least64_t>;
2071
 
2072
+ using atomic_int_fast8_t = atomic<int_fast8_t>;
2073
+ using atomic_uint_fast8_t = atomic<uint_fast8_t>;
2074
+ using atomic_int_fast16_t = atomic<int_fast16_t>;
2075
+ using atomic_uint_fast16_t = atomic<uint_fast16_t>;
2076
+ using atomic_int_fast32_t = atomic<int_fast32_t>;
2077
+ using atomic_uint_fast32_t = atomic<uint_fast32_t>;
2078
+ using atomic_int_fast64_t = atomic<int_fast64_t>;
2079
+ using atomic_uint_fast64_t = atomic<uint_fast64_t>;
2080
 
2081
+ using atomic_intptr_t = atomic<intptr_t>;
2082
+ using atomic_uintptr_t = atomic<uintptr_t>;
2083
+ using atomic_size_t = atomic<size_t>;
2084
+ using atomic_ptrdiff_t = atomic<ptrdiff_t>;
2085
+ using atomic_intmax_t = atomic<intmax_t>;
2086
+ using atomic_uintmax_t = atomic<uintmax_t>;
2087
 
2088
+ using atomic_signed_lock_free = see below; // hosted
2089
+ using atomic_unsigned_lock_free = see below; // hosted
2090
 
2091
  // [atomics.flag], flag type and operations
2092
+ struct atomic_flag;
2093
 
2094
+ bool atomic_flag_test(const volatile atomic_flag*) noexcept;
2095
+ constexpr bool atomic_flag_test(const atomic_flag*) noexcept;
2096
+ bool atomic_flag_test_explicit(const volatile atomic_flag*, memory_order) noexcept;
2097
+ constexpr bool atomic_flag_test_explicit(const atomic_flag*, memory_order) noexcept;
2098
+ bool atomic_flag_test_and_set(volatile atomic_flag*) noexcept;
2099
+ constexpr bool atomic_flag_test_and_set(atomic_flag*) noexcept;
2100
+ bool atomic_flag_test_and_set_explicit(volatile atomic_flag*, memory_order) noexcept;
2101
+ constexpr bool atomic_flag_test_and_set_explicit(atomic_flag*, memory_order) noexcept;
2102
+ void atomic_flag_clear(volatile atomic_flag*) noexcept;
2103
+ constexpr void atomic_flag_clear(atomic_flag*) noexcept;
2104
+ void atomic_flag_clear_explicit(volatile atomic_flag*, memory_order) noexcept;
2105
+ constexpr void atomic_flag_clear_explicit(atomic_flag*, memory_order) noexcept;
 
 
2106
 
2107
+ void atomic_flag_wait(const volatile atomic_flag*, bool) noexcept;
2108
+ constexpr void atomic_flag_wait(const atomic_flag*, bool) noexcept;
2109
+ void atomic_flag_wait_explicit(const volatile atomic_flag*, bool, memory_order) noexcept;
2110
+ constexpr void atomic_flag_wait_explicit(const atomic_flag*, bool, memory_order) noexcept;
2111
+ void atomic_flag_notify_one(volatile atomic_flag*) noexcept;
2112
+ constexpr void atomic_flag_notify_one(atomic_flag*) noexcept;
2113
+ void atomic_flag_notify_all(volatile atomic_flag*) noexcept;
2114
+ constexpr void atomic_flag_notify_all(atomic_flag*) noexcept;
2115
+ #define ATOMIC_FLAG_INIT see belownc
 
 
2116
 
2117
  // [atomics.fences], fences
2118
+ extern "C" constexpr void atomic_thread_fence(memory_order) noexcept;
2119
+ extern "C" constexpr void atomic_signal_fence(memory_order) noexcept;
2120
  }
2121
  ```
2122
 
2123
  ### Type aliases <a id="atomics.alias">[[atomics.alias]]</a>
2124
 
 
2141
  ### Order and consistency <a id="atomics.order">[[atomics.order]]</a>
2142
 
2143
  ``` cpp
2144
  namespace std {
2145
  enum class memory_order : unspecified {
2146
+ relaxed = 0, acquire = 2, release = 3, acq_rel = 4, seq_cst = 5
2147
  };
2148
  }
2149
  ```
2150
 
2151
  The enumeration `memory_order` specifies the detailed regular
 
2155
 
2156
  - `memory_order::relaxed`: no operation orders memory.
2157
  - `memory_order::release`, `memory_order::acq_rel`, and
2158
  `memory_order::seq_cst`: a store operation performs a release
2159
  operation on the affected memory location.
 
 
 
 
 
 
2160
  - `memory_order::acquire`, `memory_order::acq_rel`, and
2161
  `memory_order::seq_cst`: a load operation performs an acquire
2162
  operation on the affected memory location.
2163
 
2164
+ [*Note 1*: Atomic operations specifying `memory_order::relaxed` are
2165
  relaxed with respect to memory ordering. Implementations must still
2166
  guarantee that any given atomic access to a particular atomic object be
2167
  indivisible with respect to all other atomic accesses to that
2168
  object. — *end note*]
2169
 
 
2198
  - if a `memory_order::seq_cst` fence X happens before A and B is a
2199
  `memory_order::seq_cst` operation, then X precedes B in S; and
2200
  - if a `memory_order::seq_cst` fence X happens before A and B happens
2201
  before a `memory_order::seq_cst` fence Y, then X precedes Y in S.
2202
 
2203
+ [*Note 2*: This definition ensures that S is consistent with the
2204
  modification order of any atomic object M. It also ensures that a
2205
  `memory_order::seq_cst` load A of M gets its value either from the last
2206
  modification of M that precedes A in S or from some
2207
  non-`memory_order::seq_cst` modification of M that does not happen
2208
  before any modification of M that precedes A in S. — *end note*]
2209
 
2210
+ [*Note 3*: We do not require that S be consistent with “happens before”
2211
  [[intro.races]]. This allows more efficient implementation of
2212
  `memory_order::acquire` and `memory_order::release` on some machine
2213
  architectures. It can produce surprising results when these are mixed
2214
  with `memory_order::seq_cst` accesses. — *end note*]
2215
 
2216
+ [*Note 4*: `memory_order::seq_cst` ensures sequential consistency only
2217
  for a program that is free of data races and uses exclusively
2218
  `memory_order::seq_cst` atomic operations. Any use of weaker ordering
2219
  will invalidate this guarantee unless extreme care is used. In many
2220
  cases, `memory_order::seq_cst` atomic operations are reorderable with
2221
  respect to other atomic operations performed by the same
2222
  thread. — *end note*]
2223
 
2224
  Implementations should ensure that no “out-of-thin-air” values are
2225
  computed that circularly depend on their own computation.
2226
 
2227
+ [*Note 5*:
2228
 
2229
  For example, with `x` and `y` initially zero,
2230
 
2231
  ``` cpp
2232
  // Thread 1:
 
2245
  which circularly depends on the store to `y` storing `42`. Note that
2246
  without this restriction, such an execution is possible.
2247
 
2248
  — *end note*]
2249
 
2250
+ [*Note 6*:
2251
 
2252
  The recommendation similarly disallows `r1 == r2 == 42` in the following
2253
  example, with `x` and `y` again initially zero:
2254
 
2255
  ``` cpp
 
2268
 
2269
  Atomic read-modify-write operations shall always read the last value (in
2270
  the modification order) written before the write associated with the
2271
  read-modify-write operation.
2272
 
2273
+ An *atomic modify-write operation* is an atomic read-modify-write
2274
+ operation with weaker synchronization requirements as specified in 
2275
+ [[atomics.fences]].
2276
 
2277
+ [*Note 7*: The intent is for atomic modify-write operations to be
2278
+ implemented using mechanisms that are not ordered, in hardware, by the
2279
+ implementation of acquire fences. No other semantic or hardware property
2280
+ (e.g., that the mechanism is a far atomic operation) is
2281
+ implied. — *end note*]
2282
 
2283
+ *Recommended practice:* The implementation should make atomic stores
2284
+ visible to atomic loads, and atomic loads should observe atomic stores,
2285
+ within a reasonable amount of time.
 
2286
 
2287
  ### Lock-free property <a id="atomics.lockfree">[[atomics.lockfree]]</a>
2288
 
2289
  ``` cpp
2290
  #define ATOMIC_BOOL_LOCK_FREE unspecified
 
2385
  template<class T> struct atomic_ref {
2386
  private:
2387
  T* ptr; // exposition only
2388
 
2389
  public:
2390
+ using value_type = remove_cv_t<T>;
2391
  static constexpr size_t required_alignment = implementation-defined // required alignment for atomic_ref type's operations;
2392
 
2393
  static constexpr bool is_always_lock_free = implementation-defined // whether a given atomic_ref type's operations are always lock free;
2394
  bool is_lock_free() const noexcept;
2395
 
2396
+ constexpr explicit atomic_ref(T&);
2397
+ constexpr atomic_ref(const atomic_ref&) noexcept;
2398
  atomic_ref& operator=(const atomic_ref&) = delete;
2399
 
2400
+ constexpr void store(value_type, memory_order = memory_order::seq_cst) const noexcept;
2401
+ constexpr value_type operator=(value_type) const noexcept;
2402
+ constexpr value_type load(memory_order = memory_order::seq_cst) const noexcept;
2403
+ constexpr operator value_type() const noexcept;
2404
 
2405
+ constexpr value_type exchange(value_type,
2406
+ memory_order = memory_order::seq_cst) const noexcept;
2407
+ constexpr bool compare_exchange_weak(value_type&, value_type,
2408
  memory_order, memory_order) const noexcept;
2409
+ constexpr bool compare_exchange_strong(value_type&, value_type,
2410
  memory_order, memory_order) const noexcept;
2411
+ constexpr bool compare_exchange_weak(value_type&, value_type,
2412
  memory_order = memory_order::seq_cst) const noexcept;
2413
+ constexpr bool compare_exchange_strong(value_type&, value_type,
2414
  memory_order = memory_order::seq_cst) const noexcept;
2415
 
2416
+ constexpr void wait(value_type, memory_order = memory_order::seq_cst) const noexcept;
2417
+ constexpr void notify_one() const noexcept;
2418
+ constexpr void notify_all() const noexcept;
2419
+ constexpr T* address() const noexcept;
2420
  };
2421
  }
2422
  ```
2423
 
2424
  An `atomic_ref` object applies atomic operations [[atomics.general]] to
 
2443
  [*Note 1*: Atomic operations or the `atomic_ref` constructor can
2444
  acquire a shared resource, such as a lock associated with the referenced
2445
  object, to enable atomic operations to be applied to the referenced
2446
  object. — *end note*]
2447
 
2448
+ The program is ill-formed if `is_always_lock_free` is `false` and
2449
+ `is_volatile_v<T>` is `true`.
2450
+
2451
  #### Operations <a id="atomics.ref.ops">[[atomics.ref.ops]]</a>
2452
 
2453
  ``` cpp
2454
  static constexpr size_t required_alignment;
2455
  ```
 
2478
 
2479
  *Returns:* `true` if operations on all objects of the type
2480
  `atomic_ref<T>` are lock-free, `false` otherwise.
2481
 
2482
  ``` cpp
2483
+ constexpr atomic_ref(T& obj);
2484
  ```
2485
 
2486
  *Preconditions:* The referenced object is aligned to
2487
  `required_alignment`.
2488
 
2489
  *Ensures:* `*this` references `obj`.
2490
 
2491
  *Throws:* Nothing.
2492
 
2493
  ``` cpp
2494
+ constexpr atomic_ref(const atomic_ref& ref) noexcept;
2495
  ```
2496
 
2497
  *Ensures:* `*this` references the object referenced by `ref`.
2498
 
2499
  ``` cpp
2500
+ constexpr void store(value_type desired,
2501
+ memory_order order = memory_order::seq_cst) const noexcept;
2502
  ```
2503
 
2504
+ *Constraints:* `is_const_v<T>` is `false`.
2505
+
2506
+ *Preconditions:* `order` is `memory_order::relaxed`,
2507
+ `memory_order::release`, or `memory_order::seq_cst`.
2508
 
2509
  *Effects:* Atomically replaces the value referenced by `*ptr` with the
2510
  value of `desired`. Memory is affected according to the value of
2511
  `order`.
2512
 
2513
  ``` cpp
2514
+ constexpr value_type operator=(value_type desired) const noexcept;
2515
  ```
2516
 
2517
+ *Constraints:* `is_const_v<T>` is `false`.
2518
+
2519
  *Effects:* Equivalent to:
2520
 
2521
  ``` cpp
2522
  store(desired);
2523
  return desired;
2524
  ```
2525
 
2526
  ``` cpp
2527
+ constexpr value_type load(memory_order order = memory_order::seq_cst) const noexcept;
2528
  ```
2529
 
2530
+ *Preconditions:* `order` is `memory_order::relaxed`,
2531
+ `memory_order::acquire`, or `memory_order::seq_cst`.
2532
 
2533
  *Effects:* Memory is affected according to the value of `order`.
2534
 
2535
  *Returns:* Atomically returns the value referenced by `*ptr`.
2536
 
2537
  ``` cpp
2538
+ constexpr operator value_type() const noexcept;
2539
  ```
2540
 
2541
  *Effects:* Equivalent to: `return load();`
2542
 
2543
  ``` cpp
2544
+ constexpr value_type exchange(value_type desired,
2545
+ memory_order order = memory_order::seq_cst) const noexcept;
2546
  ```
2547
 
2548
+ *Constraints:* `is_const_v<T>` is `false`.
2549
+
2550
  *Effects:* Atomically replaces the value referenced by `*ptr` with
2551
  `desired`. Memory is affected according to the value of `order`. This
2552
  operation is an atomic read-modify-write
2553
  operation [[intro.multithread]].
2554
 
2555
  *Returns:* Atomically returns the value referenced by `*ptr` immediately
2556
  before the effects.
2557
 
2558
  ``` cpp
2559
+ constexpr bool compare_exchange_weak(value_type& expected, value_type desired,
2560
  memory_order success, memory_order failure) const noexcept;
2561
 
2562
+ constexpr bool compare_exchange_strong(value_type& expected, value_type desired,
2563
  memory_order success, memory_order failure) const noexcept;
2564
 
2565
+ constexpr bool compare_exchange_weak(value_type& expected, value_type desired,
2566
  memory_order order = memory_order::seq_cst) const noexcept;
2567
 
2568
+ constexpr bool compare_exchange_strong(value_type& expected, value_type desired,
2569
  memory_order order = memory_order::seq_cst) const noexcept;
2570
  ```
2571
 
2572
+ *Constraints:* `is_const_v<T>` is `false`.
2573
+
2574
+ *Preconditions:* `failure` is `memory_order::relaxed`,
2575
+ `memory_order::acquire`, or `memory_order::seq_cst`.
2576
 
2577
  *Effects:* Retrieves the value in `expected`. It then atomically
2578
  compares the value representation of the value referenced by `*ptr` for
2579
  equality with that previously retrieved from `expected`, and if `true`,
2580
  replaces the value referenced by `*ptr` with that in `desired`. If and
 
2608
  performance on some platforms. When a weak compare-and-exchange would
2609
  require a loop and a strong one would not, the strong one is
2610
  preferable. — *end note*]
2611
 
2612
  ``` cpp
2613
+ constexpr void wait(value_type old, memory_order order = memory_order::seq_cst) const noexcept;
2614
  ```
2615
 
2616
+ *Preconditions:* `order` is `memory_order::relaxed`,
2617
+ `memory_order::acquire`, or `memory_order::seq_cst`.
2618
 
2619
  *Effects:* Repeatedly performs the following steps, in order:
2620
 
2621
  - Evaluates `load(order)` and compares its value representation for
2622
  equality against that of `old`.
 
2626
 
2627
  *Remarks:* This function is an atomic waiting operation [[atomics.wait]]
2628
  on atomic object `*ptr`.
2629
 
2630
  ``` cpp
2631
+ constexpr void notify_one() const noexcept;
2632
  ```
2633
 
2634
+ *Constraints:* `is_const_v<T>` is `false`.
2635
+
2636
  *Effects:* Unblocks the execution of at least one atomic waiting
2637
  operation on `*ptr` that is eligible to be unblocked [[atomics.wait]] by
2638
  this call, if any such atomic waiting operations exist.
2639
 
2640
  *Remarks:* This function is an atomic notifying
2641
  operation [[atomics.wait]] on atomic object `*ptr`.
2642
 
2643
  ``` cpp
2644
+ constexpr void notify_all() const noexcept;
2645
  ```
2646
 
2647
+ *Constraints:* `is_const_v<T>` is `false`.
2648
+
2649
  *Effects:* Unblocks the execution of all atomic waiting operations on
2650
  `*ptr` that are eligible to be unblocked [[atomics.wait]] by this call.
2651
 
2652
  *Remarks:* This function is an atomic notifying
2653
  operation [[atomics.wait]] on atomic object `*ptr`.
2654
 
2655
+ ``` cpp
2656
+ constexpr T* address() const noexcept;
2657
+ ```
2658
+
2659
+ *Returns:* `ptr`.
2660
+
2661
  #### Specializations for integral types <a id="atomics.ref.int">[[atomics.ref.int]]</a>
2662
 
2663
+ There are specializations of the `atomic_ref` class template for all
2664
+ integral types except cv `bool`. For each such type `integral-type`, the
2665
+ specialization `atomic_ref<integral-type>` provides additional atomic
2666
+ operations appropriate to integral types.
 
 
 
 
2667
 
2668
  [*Note 1*: The specialization `atomic_ref<bool>` uses the primary
2669
  template [[atomics.ref.generic]]. — *end note*]
2670
 
2671
+ The program is ill-formed if `is_always_lock_free` is `false` and
2672
+ `is_volatile_v<integral-type>` is `true`.
2673
+
2674
  ``` cpp
2675
  namespace std {
2676
  template<> struct atomic_ref<integral-type> {
2677
  private:
2678
  integral-type* ptr; // exposition only
2679
 
2680
  public:
2681
+ using value_type = remove_cv_t<integral-type>;
2682
  using difference_type = value_type;
2683
  static constexpr size_t required_alignment = implementation-defined // required alignment for atomic_ref type's operations;
2684
 
2685
  static constexpr bool is_always_lock_free = implementation-defined // whether a given atomic_ref type's operations are always lock free;
2686
  bool is_lock_free() const noexcept;
2687
 
2688
+ constexpr explicit atomic_ref(integral-type&);
2689
+ constexpr atomic_ref(const atomic_ref&) noexcept;
2690
  atomic_ref& operator=(const atomic_ref&) = delete;
2691
 
2692
+ constexpr void store(value_type, memory_order = memory_order::seq_cst) const noexcept;
2693
+ constexpr value_type operator=(value_type) const noexcept;
2694
+ constexpr value_type load(memory_order = memory_order::seq_cst) const noexcept;
2695
+ constexpr operator value_type() const noexcept;
2696
 
2697
+ constexpr value_type exchange(value_type,
2698
  memory_order = memory_order::seq_cst) const noexcept;
2699
+ constexpr bool compare_exchange_weak(value_type&, value_type,
2700
  memory_order, memory_order) const noexcept;
2701
+ constexpr bool compare_exchange_strong(value_type&, value_type,
2702
  memory_order, memory_order) const noexcept;
2703
+ constexpr bool compare_exchange_weak(value_type&, value_type,
2704
  memory_order = memory_order::seq_cst) const noexcept;
2705
+ constexpr bool compare_exchange_strong(value_type&, value_type,
2706
  memory_order = memory_order::seq_cst) const noexcept;
2707
 
2708
+ constexpr value_type fetch_add(value_type,
2709
  memory_order = memory_order::seq_cst) const noexcept;
2710
+ constexpr value_type fetch_sub(value_type,
2711
  memory_order = memory_order::seq_cst) const noexcept;
2712
+ constexpr value_type fetch_and(value_type,
2713
  memory_order = memory_order::seq_cst) const noexcept;
2714
+ constexpr value_type fetch_or(value_type,
2715
  memory_order = memory_order::seq_cst) const noexcept;
2716
+ constexpr value_type fetch_xor(value_type,
2717
+ memory_order = memory_order::seq_cst) const noexcept;
2718
+ constexpr value_type fetch_max(value_type,
2719
+ memory_order = memory_order::seq_cst) const noexcept;
2720
+ constexpr value_type fetch_min(value_type,
2721
+ memory_order = memory_order::seq_cst) const noexcept;
2722
+
2723
+ constexpr void store_add(value_type,
2724
+ memory_order = memory_order::seq_cst) const noexcept;
2725
+ constexpr void store_sub(value_type,
2726
+ memory_order = memory_order::seq_cst) const noexcept;
2727
+ constexpr void store_and(value_type,
2728
+ memory_order = memory_order::seq_cst) const noexcept;
2729
+ constexpr void store_or(value_type,
2730
+ memory_order = memory_order::seq_cst) const noexcept;
2731
+ constexpr void store_xor(value_type,
2732
+ memory_order = memory_order::seq_cst) const noexcept;
2733
+ constexpr void store_max(value_type,
2734
+ memory_order = memory_order::seq_cst) const noexcept;
2735
+ constexpr void store_min(value_type,
2736
  memory_order = memory_order::seq_cst) const noexcept;
2737
 
2738
+ constexpr value_type operator++(int) const noexcept;
2739
+ constexpr value_type operator--(int) const noexcept;
2740
+ constexpr value_type operator++() const noexcept;
2741
+ constexpr value_type operator--() const noexcept;
2742
+ constexpr value_type operator+=(value_type) const noexcept;
2743
+ constexpr value_type operator-=(value_type) const noexcept;
2744
+ constexpr value_type operator&=(value_type) const noexcept;
2745
+ constexpr value_type operator|=(value_type) const noexcept;
2746
+ constexpr value_type operator^=(value_type) const noexcept;
2747
 
2748
+ constexpr void wait(value_type, memory_order = memory_order::seq_cst) const noexcept;
2749
+ constexpr void notify_one() const noexcept;
2750
+ constexpr void notify_all() const noexcept;
2751
+ constexpr integral-type* address() const noexcept;
2752
  };
2753
  }
2754
  ```
2755
 
2756
  Descriptions are provided below only for members that differ from the
 
2759
  The following operations perform arithmetic computations. The
2760
  correspondence among key, operator, and computation is specified in
2761
  [[atomic.types.int.comp]].
2762
 
2763
  ``` cpp
2764
+ constexpr value_type fetch_key(value_type operand,
2765
  memory_order order = memory_order::seq_cst) const noexcept;
2766
  ```
2767
 
2768
+ *Constraints:* `is_const_v<`*`integral-type`*`>` is `false`.
2769
+
2770
  *Effects:* Atomically replaces the value referenced by `*ptr` with the
2771
  result of the computation applied to the value referenced by `*ptr` and
2772
  the given operand. Memory is affected according to the value of `order`.
2773
  These operations are atomic read-modify-write
2774
  operations [[intro.races]].
2775
 
2776
  *Returns:* Atomically, the value referenced by `*ptr` immediately before
2777
  the effects.
2778
 
2779
+ *Remarks:* Except for `fetch_max` and `fetch_min`, for signed integer
2780
+ types the result is as if the object value and parameters were converted
2781
+ to their corresponding unsigned types, the computation performed on
2782
+ those types, and the result converted back to the signed type.
2783
 
2784
  [*Note 1*: There are no undefined results arising from the
2785
  computation. — *end note*]
2786
 
2787
+ For `fetch_max` and `fetch_min`, the maximum and minimum computation is
2788
+ performed as if by `max` and `min` algorithms [[alg.min.max]],
2789
+ respectively, with the object value and the first parameter as the
2790
+ arguments.
2791
+
2792
  ``` cpp
2793
+ constexpr void store_key(value_type operand,
2794
+ memory_order order = memory_order::seq_cst) const noexcept;
2795
  ```
2796
 
2797
+ *Preconditions:* `order` is `memory_order::relaxed`,
2798
+ `memory_order::release`, or `memory_order::seq_cst`.
2799
+
2800
+ *Effects:* Atomically replaces the value referenced by `*ptr` with the
2801
+ result of the computation applied to the value referenced by `*ptr` and
2802
+ the given `operand`. Memory is affected according to the value of
2803
+ `order`. These operations are atomic modify-write
2804
+ operations [[atomics.order]].
2805
+
2806
+ *Remarks:* Except for `store_max` and `store_min`, for signed integer
2807
+ types, the result is as if `*ptr` and parameters were converted to their
2808
+ corresponding unsigned types, the computation performed on those types,
2809
+ and the result converted back to the signed type.
2810
+
2811
+ [*Note 2*: There are no undefined results arising from the
2812
+ computation. — *end note*]
2813
+
2814
+ For `store_max` and `store_min`, the maximum and minimum computation is
2815
+ performed as if by `max` and `min` algorithms [[alg.min.max]],
2816
+ respectively, with `*ptr` and the first parameter as the arguments.
2817
+
2818
+ ``` cpp
2819
+ constexpr value_type operator op=(value_type operand) const noexcept;
2820
+ ```
2821
+
2822
+ *Constraints:* `is_const_v<`*`integral-type`*`>` is `false`.
2823
+
2824
  *Effects:* Equivalent to:
2825
  `return fetch_`*`key`*`(operand) `*`op`*` operand;`
2826
 
2827
  #### Specializations for floating-point types <a id="atomics.ref.float">[[atomics.ref.float]]</a>
2828
 
2829
  There are specializations of the `atomic_ref` class template for all
2830
+ floating-point types. For each such type `floating-point-type`, the
2831
+ specialization `atomic_ref<floating-point-type>` provides additional
2832
+ atomic operations appropriate to floating-point types.
2833
+
2834
+ The program is ill-formed if `is_always_lock_free` is `false` and
2835
+ `is_volatile_v<floating-point-type>` is `true`.
2836
 
2837
  ``` cpp
2838
  namespace std {
2839
  template<> struct atomic_ref<floating-point-type> {
2840
  private:
2841
  floating-point-type* ptr; // exposition only
2842
 
2843
  public:
2844
+ using value_type = remove_cv_t<floating-point-type>;
2845
  using difference_type = value_type;
2846
  static constexpr size_t required_alignment = implementation-defined // required alignment for atomic_ref type's operations;
2847
 
2848
  static constexpr bool is_always_lock_free = implementation-defined // whether a given atomic_ref type's operations are always lock free;
2849
  bool is_lock_free() const noexcept;
2850
 
2851
+ constexpr explicit atomic_ref(floating-point-type&);
2852
+ constexpr atomic_ref(const atomic_ref&) noexcept;
2853
  atomic_ref& operator=(const atomic_ref&) = delete;
2854
 
2855
+ constexpr void store(value_type,
2856
+ memory_order = memory_order::seq_cst) const noexcept;
2857
+ constexpr value_type operator=(value_type) const noexcept;
2858
+ constexpr value_type load(memory_order = memory_order::seq_cst) const noexcept;
2859
+ constexpr operator value_type() const noexcept;
2860
 
2861
+ constexpr value_type exchange(value_type,
2862
  memory_order = memory_order::seq_cst) const noexcept;
2863
+ constexpr bool compare_exchange_weak(value_type&, value_type,
2864
  memory_order, memory_order) const noexcept;
2865
+ constexpr bool compare_exchange_strong(value_type&, value_type,
2866
  memory_order, memory_order) const noexcept;
2867
+ constexpr bool compare_exchange_weak(value_type&, value_type,
2868
+ memory_order = memory_order::seq_cst) const noexcept;
2869
+ constexpr bool compare_exchange_strong(value_type&, value_type,
2870
+ memory_order = memory_order::seq_cst) const noexcept;
2871
+
2872
+ constexpr value_type fetch_add(value_type,
2873
+ memory_order = memory_order::seq_cst) const noexcept;
2874
+ constexpr value_type fetch_sub(value_type,
2875
+ memory_order = memory_order::seq_cst) const noexcept;
2876
+
2877
+ constexpr value_type fetch_max(value_type,
2878
  memory_order = memory_order::seq_cst) const noexcept;
2879
+ constexpr value_type fetch_min(value_type,
2880
+ memory_order = memory_order::seq_cst) const noexcept;
2881
+ constexpr value_type fetch_fmaximum(value_type,
2882
+ memory_order = memory_order::seq_cst) const noexcept;
2883
+ constexpr value_type fetch_fminimum(value_type,
2884
+ memory_order = memory_order::seq_cst) const noexcept;
2885
+ constexpr value_type fetch_fmaximum_num(value_type,
2886
+ memory_order = memory_order::seq_cst) const noexcept;
2887
+ constexpr value_type fetch_fminimum_num(value_type,
2888
  memory_order = memory_order::seq_cst) const noexcept;
2889
 
2890
+ constexpr void store_add(value_type, memory_order = memory_order::seq_cst) const noexcept;
2891
+ constexpr void store_sub(value_type, memory_order = memory_order::seq_cst) const noexcept;
2892
+ constexpr void store_max(value_type, memory_order = memory_order::seq_cst) const noexcept;
2893
+ constexpr void store_min(value_type, memory_order = memory_order::seq_cst) const noexcept;
2894
+ constexpr void store_fmaximum(value_type,
2895
  memory_order = memory_order::seq_cst) const noexcept;
2896
+ constexpr void store_fminimum(value_type,
2897
+ memory_order = memory_order::seq_cst) const noexcept;
2898
+ constexpr void store_fmaximum_num(value_type,
2899
+ memory_order = memory_order::seq_cst) const noexcept;
2900
+ constexpr void store_fminimum_num(value_type,
2901
  memory_order = memory_order::seq_cst) const noexcept;
2902
 
2903
+ constexpr value_type operator+=(value_type) const noexcept;
2904
+ constexpr value_type operator-=(value_type) const noexcept;
2905
 
2906
+ constexpr void wait(value_type,
2907
+ memory_order = memory_order::seq_cst) const noexcept;
2908
+ constexpr void notify_one() const noexcept;
2909
+ constexpr void notify_all() const noexcept;
2910
+ constexpr floating-point-type* address() const noexcept;
2911
  };
2912
  }
2913
  ```
2914
 
2915
  Descriptions are provided below only for members that differ from the
2916
  primary template.
2917
 
2918
  The following operations perform arithmetic computations. The
2919
  correspondence among key, operator, and computation is specified in
2920
+ [[atomic.types.int.comp]], except for the keys `max`, `min`, `fmaximum`,
2921
+ `fminimum`, `fmaximum_num`, and `fminimum_num`, which are specified
2922
+ below.
2923
 
2924
  ``` cpp
2925
+ constexpr value_type fetch_key(value_type operand,
2926
  memory_order order = memory_order::seq_cst) const noexcept;
2927
  ```
2928
 
2929
+ *Constraints:* `is_const_v<`*`floating-point-type`*`>` is `false`.
2930
+
2931
  *Effects:* Atomically replaces the value referenced by `*ptr` with the
2932
  result of the computation applied to the value referenced by `*ptr` and
2933
  the given operand. Memory is affected according to the value of `order`.
2934
  These operations are atomic read-modify-write
2935
  operations [[intro.races]].
 
2939
 
2940
  *Remarks:* If the result is not a representable value for its
2941
  type [[expr.pre]], the result is unspecified, but the operations
2942
  otherwise have no undefined behavior. Atomic arithmetic operations on
2943
  *`floating-point-type`* should conform to the
2944
+ `std::numeric_limits<value_type>` traits associated with the
2945
+ floating-point type [[limits.syn]]. The floating-point
2946
  environment [[cfenv]] for atomic arithmetic operations on
2947
  *`floating-point-type`* may be different than the calling thread’s
2948
  floating-point environment.
2949
 
2950
+ - For `fetch_fmaximum` and `fetch_fminimum`, the maximum and minimum
2951
+ computation is performed as if by `fmaximum` and `fminimum`,
2952
+ respectively, with `*ptr` and the first parameter as the arguments.
2953
+ - For `fetch_fmaximum_num` and `fetch_fminimum_num`, the maximum and
2954
+ minimum computation is performed as if by `fmaximum_num` and
2955
+ `fminimum_num`, respectively, with `*ptr` and the first parameter as
2956
+ the arguments.
2957
+ - For `fetch_max` and `fetch_min`, the maximum and minimum computation
2958
+ is performed as if by `fmaximum_num` and `fminimum_num`, respectively,
2959
+ with `*ptr` and the first parameter as the arguments, except that:
2960
+ - If both arguments are NaN, an unspecified NaN value is stored at
2961
+ `*ptr`.
2962
+ - If exactly one argument is a NaN, either the other argument or an
2963
+ unspecified NaN value is stored at `*ptr`; it is unspecified which.
2964
+ - If the arguments are differently signed zeros, which of these values
2965
+ is stored at `*ptr` is unspecified.
2966
+
2967
+ *Recommended practice:* The implementation of `fetch_max` and
2968
+ `fetch_min` should treat negative zero as smaller than positive zero.
2969
+
2970
  ``` cpp
2971
+ constexpr void store_key(value_type operand,
2972
+ memory_order order = memory_order::seq_cst) const noexcept;
2973
  ```
2974
 
2975
+ *Preconditions:* `order` is `memory_order::relaxed`,
2976
+ `memory_order::release`, or `memory_order::seq_cst`.
2977
+
2978
+ *Effects:* Atomically replaces the value referenced by `*ptr` with the
2979
+ result of the computation applied to the value referenced by `*ptr` and
2980
+ the given `operand`. Memory is affected according to the value of
2981
+ `order`. These operations are atomic modify-write
2982
+ operations [[atomics.order]].
2983
+
2984
+ *Remarks:* If the result is not a representable value for its
2985
+ type [[expr.pre]], the result is unspecified, but the operations
2986
+ otherwise have no undefined behavior. Atomic arithmetic operations on
2987
+ *`floating-point-type`* should conform to the
2988
+ `numeric_limits<`*`floating-point-type`*`>` traits associated with the
2989
+ floating-point type [[limits.syn]]. The floating-point
2990
+ environment [[cfenv]] for atomic arithmetic operations on
2991
+ *`floating-point-type`* may be different than the calling thread’s
2992
+ floating-point environment. The arithmetic rules of floating-point
2993
+ atomic modify-write operations may be different from operations on
2994
+ floating-point types or atomic floating-point types.
2995
+
2996
+ [*Note 1*: Tree reductions are permitted for atomic modify-write
2997
+ operations. — *end note*]
2998
+
2999
+ - For `store_fmaximum` and `store_fminimum`, the maximum and minimum
3000
+ computation is performed as if by `fmaximum` and `fminimum`,
3001
+ respectively, with `*ptr` and the first parameter as the arguments.
3002
+ - For `store_fmaximum_num` and `store_fminimum_num`, the maximum and
3003
+ minimum computation is performed as if by `fmaximum_num `and
3004
+ `fminimum_num`, respectively, with `*ptr` and the first parameter as
3005
+ the arguments.
3006
+ - For `store_max` and `store_min`, the maximum and minimum computation
3007
+ is performed as if by `fmaximum_num` and `fminimum_num`, respectively,
3008
+ with `*ptr` and the first parameter as the arguments, except that:
3009
+ - If both arguments are NaN, an unspecified NaN value is stored at
3010
+ `*ptr`.
3011
+ - If exactly one argument is a NaN, either the other argument or an
3012
+ unspecified NaN value is stored at `*ptr`, it is unspecified which.
3013
+ - If the arguments are differently signed zeros, which of these values
3014
+ is stored at `*ptr` is unspecified.
3015
+
3016
+ *Recommended practice:* The implementation of `store_max` and
3017
+ `store_min` should treat negative zero as smaller than positive zero.
3018
+
3019
+ ``` cpp
3020
+ constexpr value_type operator op=(value_type operand) const noexcept;
3021
+ ```
3022
+
3023
+ *Constraints:* `is_const_v<`*`floating-point-type`*`>` is `false`.
3024
+
3025
  *Effects:* Equivalent to:
3026
  `return fetch_`*`key`*`(operand) `*`op`*` operand;`
3027
 
3028
+ #### Specialization for pointers <a id="atomics.ref.pointer">[[atomics.ref.pointer]]</a>
3029
+
3030
+ There are specializations of the `atomic_ref` class template for all
3031
+ pointer-to-object types. For each such type `pointer-type`, the
3032
+ specialization `atomic_ref<pointer-type>` provides additional atomic
3033
+ operations appropriate to pointer types.
3034
+
3035
+ The program is ill-formed if `is_always_lock_free` is `false` and
3036
+ `is_volatile_v<pointer-type>` is `true`.
3037
 
3038
  ``` cpp
3039
  namespace std {
3040
+ template<> struct atomic_ref<pointer-type> {
3041
  private:
3042
+ pointer-type* ptr; // exposition only
3043
 
3044
  public:
3045
+ using value_type = remove_cv_t<pointer-type>;
3046
  using difference_type = ptrdiff_t;
3047
  static constexpr size_t required_alignment = implementation-defined // required alignment for atomic_ref type's operations;
3048
 
3049
  static constexpr bool is_always_lock_free = implementation-defined // whether a given atomic_ref type's operations are always lock free;
3050
  bool is_lock_free() const noexcept;
3051
 
3052
+ constexpr explicit atomic_ref(pointer-type&);
3053
+ constexpr atomic_ref(const atomic_ref&) noexcept;
3054
  atomic_ref& operator=(const atomic_ref&) = delete;
3055
 
3056
+ constexpr void store(value_type, memory_order = memory_order::seq_cst) const noexcept;
3057
+ constexpr value_type operator=(value_type) const noexcept;
3058
+ constexpr value_type load(memory_order = memory_order::seq_cst) const noexcept;
3059
+ constexpr operator value_type() const noexcept;
3060
 
3061
+ constexpr value_type exchange(value_type,
3062
+ memory_order = memory_order::seq_cst) const noexcept;
3063
+ constexpr bool compare_exchange_weak(value_type&, value_type,
3064
  memory_order, memory_order) const noexcept;
3065
+ constexpr bool compare_exchange_strong(value_type&, value_type,
3066
  memory_order, memory_order) const noexcept;
3067
+ constexpr bool compare_exchange_weak(value_type&, value_type,
3068
+ memory_order = memory_order::seq_cst) const noexcept;
3069
+ constexpr bool compare_exchange_strong(value_type&, value_type,
3070
+ memory_order = memory_order::seq_cst) const noexcept;
3071
+
3072
+ constexpr value_type fetch_add(difference_type,
3073
+ memory_order = memory_order::seq_cst) const noexcept;
3074
+ constexpr value_type fetch_sub(difference_type,
3075
  memory_order = memory_order::seq_cst) const noexcept;
3076
+ constexpr value_type fetch_max(value_type,
3077
+ memory_order = memory_order::seq_cst) const noexcept;
3078
+ constexpr value_type fetch_min(value_type,
3079
  memory_order = memory_order::seq_cst) const noexcept;
3080
 
3081
+ constexpr void store_add(difference_type,
3082
+ memory_order = memory_order::seq_cst) const noexcept;
3083
+ constexpr void store_sub(difference_type,
3084
+ memory_order = memory_order::seq_cst) const noexcept;
3085
+ constexpr void store_max(value_type,
3086
+ memory_order = memory_order::seq_cst) const noexcept;
3087
+ constexpr void store_min(value_type,
3088
+ memory_order = memory_order::seq_cst) const noexcept;
3089
 
3090
+ constexpr value_type operator++(int) const noexcept;
3091
+ constexpr value_type operator--(int) const noexcept;
3092
+ constexpr value_type operator++() const noexcept;
3093
+ constexpr value_type operator--() const noexcept;
3094
+ constexpr value_type operator+=(difference_type) const noexcept;
3095
+ constexpr value_type operator-=(difference_type) const noexcept;
3096
 
3097
+ constexpr void wait(value_type, memory_order = memory_order::seq_cst) const noexcept;
3098
+ constexpr void notify_one() const noexcept;
3099
+ constexpr void notify_all() const noexcept;
3100
+ constexpr pointer-type* address() const noexcept;
3101
  };
3102
  }
3103
  ```
3104
 
3105
  Descriptions are provided below only for members that differ from the
 
3108
  The following operations perform arithmetic computations. The
3109
  correspondence among key, operator, and computation is specified in
3110
  [[atomic.types.pointer.comp]].
3111
 
3112
  ``` cpp
3113
+ constexpr value_type fetch_key(\seeabovenc operand,
3114
+ memory_order order = memory_order::seq_cst) const noexcept;
3115
  ```
3116
 
3117
+ *Constraints:* `is_const_v<`*`pointer-type`*`>` is `false`.
3118
+
3119
+ *Mandates:* `remove_pointer_t<`*`pointer-type`*`>` is a complete object
3120
+ type.
3121
 
3122
  *Effects:* Atomically replaces the value referenced by `*ptr` with the
3123
  result of the computation applied to the value referenced by `*ptr` and
3124
  the given operand. Memory is affected according to the value of `order`.
3125
  These operations are atomic read-modify-write
 
3129
  the effects.
3130
 
3131
  *Remarks:* The result may be an undefined address, but the operations
3132
  otherwise have no undefined behavior.
3133
 
3134
+ For `fetch_max` and `fetch_min`, the maximum and minimum computation is
3135
+ performed as if by `max` and `min` algorithms [[alg.min.max]],
3136
+ respectively, with the object value and the first parameter as the
3137
+ arguments.
3138
+
3139
+ [*Note 1*: If the pointers point to different complete objects (or
3140
+ subobjects thereof), the `<` operator does not establish a strict weak
3141
+ ordering ([[cpp17.lessthancomparable]], [[expr.rel]]). — *end note*]
3142
+
3143
  ``` cpp
3144
+ constexpr void store_key(\seeabovenc operand,
3145
+ memory_order order = memory_order::seq_cst) const noexcept;
3146
  ```
3147
 
3148
+ *Mandates:* `remove_pointer_t<`*`pointer-type`*`>` is a complete object
3149
+ type.
3150
+
3151
+ *Preconditions:* `order` is `memory_order::relaxed`,
3152
+ `memory_order::release`, or `memory_order::seq_cst`.
3153
+
3154
+ *Effects:* Atomically replaces the value referenced by `*ptr` with the
3155
+ result of the computation applied to the value referenced by `*ptr` and
3156
+ the given `operand`. Memory is affected according to the value of
3157
+ `order`. These operations are atomic modify-write
3158
+ operations [[atomics.order]].
3159
+
3160
+ *Remarks:* The result may be an undefined address, but the operations
3161
+ otherwise have no undefined behavior. For `store_max` and `store_min`,
3162
+ the `maximum` and `minimum` computation is performed as if by `max` and
3163
+ `min` algorithms [[alg.min.max]], respectively, with `*ptr` and the
3164
+ first parameter as the arguments.
3165
+
3166
+ [*Note 2*: If the pointers point to different complete objects (or
3167
+ subobjects thereof), the `<` operator does not establish a strict weak
3168
+ ordering ([[cpp17.lessthancomparable]], [[expr.rel]]). — *end note*]
3169
+
3170
+ ``` cpp
3171
+ constexpr value_type operator op=(difference_type operand) const noexcept;
3172
+ ```
3173
+
3174
+ *Constraints:* `is_const_v<`*`pointer-type`*`>` is `false`.
3175
+
3176
  *Effects:* Equivalent to:
3177
  `return fetch_`*`key`*`(operand) `*`op`*` operand;`
3178
 
3179
  #### Member operators common to integers and pointers to objects <a id="atomics.ref.memop">[[atomics.ref.memop]]</a>
3180
 
3181
+ Let `referred-type` be `pointer-type` for the specializations in
3182
+ [[atomics.ref.pointer]] and be `integral-type` for the specializations
3183
+ in [[atomics.ref.int]].
3184
+
3185
  ``` cpp
3186
+ constexpr value_type operator++(int) const noexcept;
3187
  ```
3188
 
3189
+ *Constraints:* `is_const_v<`*`referred-type`*`>` is `false`.
3190
+
3191
  *Effects:* Equivalent to: `return fetch_add(1);`
3192
 
3193
  ``` cpp
3194
+ constexpr value_type operator--(int) const noexcept;
3195
  ```
3196
 
3197
+ *Constraints:* `is_const_v<`*`referred-type`*`>` is `false`.
3198
+
3199
  *Effects:* Equivalent to: `return fetch_sub(1);`
3200
 
3201
  ``` cpp
3202
+ constexpr value_type operator++() const noexcept;
3203
  ```
3204
 
3205
+ *Constraints:* `is_const_v<`*`referred-type`*`>` is `false`.
3206
+
3207
  *Effects:* Equivalent to: `return fetch_add(1) + 1;`
3208
 
3209
  ``` cpp
3210
+ constexpr value_type operator--() const noexcept;
3211
  ```
3212
 
3213
+ *Constraints:* `is_const_v<`*`referred-type`*`>` is `false`.
3214
+
3215
  *Effects:* Equivalent to: `return fetch_sub(1) - 1;`
3216
 
3217
  ### Class template `atomic` <a id="atomics.types.generic">[[atomics.types.generic]]</a>
3218
 
3219
  #### General <a id="atomics.types.generic.general">[[atomics.types.generic.general]]</a>
 
3233
  atomic(const atomic&) = delete;
3234
  atomic& operator=(const atomic&) = delete;
3235
  atomic& operator=(const atomic&) volatile = delete;
3236
 
3237
  T load(memory_order = memory_order::seq_cst) const volatile noexcept;
3238
+ constexpr T load(memory_order = memory_order::seq_cst) const noexcept;
3239
  operator T() const volatile noexcept;
3240
+ constexpr operator T() const noexcept;
3241
  void store(T, memory_order = memory_order::seq_cst) volatile noexcept;
3242
+ constexpr void store(T, memory_order = memory_order::seq_cst) noexcept;
3243
  T operator=(T) volatile noexcept;
3244
+ constexpr T operator=(T) noexcept;
3245
 
3246
  T exchange(T, memory_order = memory_order::seq_cst) volatile noexcept;
3247
+ constexpr T exchange(T, memory_order = memory_order::seq_cst) noexcept;
3248
  bool compare_exchange_weak(T&, T, memory_order, memory_order) volatile noexcept;
3249
+ constexpr bool compare_exchange_weak(T&, T, memory_order, memory_order) noexcept;
3250
  bool compare_exchange_strong(T&, T, memory_order, memory_order) volatile noexcept;
3251
+ constexpr bool compare_exchange_strong(T&, T, memory_order, memory_order) noexcept;
3252
  bool compare_exchange_weak(T&, T, memory_order = memory_order::seq_cst) volatile noexcept;
3253
+ constexpr bool compare_exchange_weak(T&, T, memory_order = memory_order::seq_cst) noexcept;
3254
  bool compare_exchange_strong(T&, T, memory_order = memory_order::seq_cst) volatile noexcept;
3255
+ constexpr bool compare_exchange_strong(T&, T, memory_order = memory_order::seq_cst) noexcept;
3256
 
3257
  void wait(T, memory_order = memory_order::seq_cst) const volatile noexcept;
3258
+ constexpr void wait(T, memory_order = memory_order::seq_cst) const noexcept;
3259
  void notify_one() volatile noexcept;
3260
+ constexpr void notify_one() noexcept;
3261
  void notify_all() volatile noexcept;
3262
+ constexpr void notify_all() noexcept;
3263
  };
3264
  }
3265
  ```
3266
 
3267
  The template argument for `T` shall meet the *Cpp17CopyConstructible*
 
3269
  of
3270
 
3271
  - `is_trivially_copyable_v<T>`,
3272
  - `is_copy_constructible_v<T>`,
3273
  - `is_move_constructible_v<T>`,
3274
+ - `is_copy_assignable_v<T>`,
3275
+ - `is_move_assignable_v<T>`, or
3276
+ - `is_same_v<T, remove_cv_t<T>>`,
3277
 
3278
  is `false`.
3279
 
3280
  [*Note 1*: Type arguments that are not also statically initializable
3281
  can be difficult to use. — *end note*]
3282
 
3283
+ The specialization `atomic<bool>` is a standard-layout struct. It has a
3284
+ trivial destructor.
3285
 
3286
  [*Note 2*: The representation of an atomic specialization need not have
3287
  the same size and alignment requirement as its corresponding argument
3288
  type. — *end note*]
3289
 
 
3291
 
3292
  ``` cpp
3293
  constexpr atomic() noexcept(is_nothrow_default_constructible_v<T>);
3294
  ```
3295
 
3296
+ *Constraints:* `is_default_constructible_v<T>` is `true`.
3297
 
3298
  *Effects:* Initializes the atomic object with the value of `T()`.
3299
  Initialization is not an atomic operation [[intro.multithread]].
3300
 
3301
  ``` cpp
 
3335
  consistent with the value of `is_always_lock_free` for the same
3336
  type. — *end note*]
3337
 
3338
  ``` cpp
3339
  void store(T desired, memory_order order = memory_order::seq_cst) volatile noexcept;
3340
+ constexpr void store(T desired, memory_order order = memory_order::seq_cst) noexcept;
3341
  ```
3342
 
3343
  *Constraints:* For the `volatile` overload of this function,
3344
  `is_always_lock_free` is `true`.
3345
 
3346
+ *Preconditions:* `order` is `memory_order::relaxed`,
3347
+ `memory_order::release`, or `memory_order::seq_cst`.
 
3348
 
3349
  *Effects:* Atomically replaces the value pointed to by `this` with the
3350
  value of `desired`. Memory is affected according to the value of
3351
  `order`.
3352
 
3353
  ``` cpp
3354
  T operator=(T desired) volatile noexcept;
3355
+ constexpr T operator=(T desired) noexcept;
3356
  ```
3357
 
3358
  *Constraints:* For the `volatile` overload of this function,
3359
  `is_always_lock_free` is `true`.
3360
 
 
3362
 
3363
  *Returns:* `desired`.
3364
 
3365
  ``` cpp
3366
  T load(memory_order order = memory_order::seq_cst) const volatile noexcept;
3367
+ constexpr T load(memory_order order = memory_order::seq_cst) const noexcept;
3368
  ```
3369
 
3370
  *Constraints:* For the `volatile` overload of this function,
3371
  `is_always_lock_free` is `true`.
3372
 
3373
+ *Preconditions:* `order` is `memory_order::relaxed`,
3374
+ `memory_order::acquire`, or `memory_order::seq_cst`.
3375
 
3376
  *Effects:* Memory is affected according to the value of `order`.
3377
 
3378
  *Returns:* Atomically returns the value pointed to by `this`.
3379
 
3380
  ``` cpp
3381
  operator T() const volatile noexcept;
3382
+ constexpr operator T() const noexcept;
3383
  ```
3384
 
3385
  *Constraints:* For the `volatile` overload of this function,
3386
  `is_always_lock_free` is `true`.
3387
 
3388
  *Effects:* Equivalent to: `return load();`
3389
 
3390
  ``` cpp
3391
  T exchange(T desired, memory_order order = memory_order::seq_cst) volatile noexcept;
3392
+ constexpr T exchange(T desired, memory_order order = memory_order::seq_cst) noexcept;
3393
  ```
3394
 
3395
  *Constraints:* For the `volatile` overload of this function,
3396
  `is_always_lock_free` is `true`.
3397
 
 
3404
  before the effects.
3405
 
3406
  ``` cpp
3407
  bool compare_exchange_weak(T& expected, T desired,
3408
  memory_order success, memory_order failure) volatile noexcept;
3409
+ constexpr bool compare_exchange_weak(T& expected, T desired,
3410
  memory_order success, memory_order failure) noexcept;
3411
  bool compare_exchange_strong(T& expected, T desired,
3412
  memory_order success, memory_order failure) volatile noexcept;
3413
+ constexpr bool compare_exchange_strong(T& expected, T desired,
3414
  memory_order success, memory_order failure) noexcept;
3415
  bool compare_exchange_weak(T& expected, T desired,
3416
  memory_order order = memory_order::seq_cst) volatile noexcept;
3417
+ constexpr bool compare_exchange_weak(T& expected, T desired,
3418
  memory_order order = memory_order::seq_cst) noexcept;
3419
  bool compare_exchange_strong(T& expected, T desired,
3420
  memory_order order = memory_order::seq_cst) volatile noexcept;
3421
+ constexpr bool compare_exchange_strong(T& expected, T desired,
3422
  memory_order order = memory_order::seq_cst) noexcept;
3423
  ```
3424
 
3425
  *Constraints:* For the `volatile` overload of this function,
3426
  `is_always_lock_free` is `true`.
3427
 
3428
+ *Preconditions:* `failure` is `memory_order::relaxed`,
3429
+ `memory_order::acquire`, or `memory_order::seq_cst`.
3430
 
3431
  *Effects:* Retrieves the value in `expected`. It then atomically
3432
  compares the value representation of the value pointed to by `this` for
3433
  equality with that previously retrieved from `expected`, and if true,
3434
  replaces the value pointed to by `this` with that in `desired`. If and
 
3513
 
3514
  [*Note 6*: Under cases where the `memcpy` and `memcmp` semantics of the
3515
  compare-and-exchange operations apply, the comparisons can fail for
3516
  values that compare equal with `operator==` if the value representation
3517
  has trap bits or alternate representations of the same value. Notably,
3518
+ on implementations conforming to ISO/IEC 60559, floating-point `-0.0`
3519
+ and `+0.0` will not compare equal with `memcmp` but will compare equal
3520
+ with `operator==`, and NaNs with the same payload will compare equal
3521
+ with `memcmp` but will not compare equal with
3522
  `operator==`. — *end note*]
3523
 
3524
  [*Note 7*:
3525
 
3526
  Because compare-and-exchange acts on an object’s value representation,
 
3567
 
3568
  — *end note*]
3569
 
3570
  ``` cpp
3571
  void wait(T old, memory_order order = memory_order::seq_cst) const volatile noexcept;
3572
+ constexpr void wait(T old, memory_order order = memory_order::seq_cst) const noexcept;
3573
  ```
3574
 
3575
+ *Preconditions:* `order` is `memory_order::relaxed`,
3576
+ `memory_order::acquire`, or `memory_order::seq_cst`.
3577
 
3578
  *Effects:* Repeatedly performs the following steps, in order:
3579
 
3580
  - Evaluates `load(order)` and compares its value representation for
3581
  equality against that of `old`.
 
3586
  *Remarks:* This function is an atomic waiting
3587
  operation [[atomics.wait]].
3588
 
3589
  ``` cpp
3590
  void notify_one() volatile noexcept;
3591
+ constexpr void notify_one() noexcept;
3592
  ```
3593
 
3594
  *Effects:* Unblocks the execution of at least one atomic waiting
3595
  operation that is eligible to be unblocked [[atomics.wait]] by this
3596
  call, if any such atomic waiting operations exist.
 
3598
  *Remarks:* This function is an atomic notifying
3599
  operation [[atomics.wait]].
3600
 
3601
  ``` cpp
3602
  void notify_all() volatile noexcept;
3603
+ constexpr void notify_all() noexcept;
3604
  ```
3605
 
3606
  *Effects:* Unblocks the execution of all atomic waiting operations that
3607
  are eligible to be unblocked [[atomics.wait]] by this call.
3608
 
 
3638
  atomic(const atomic&) = delete;
3639
  atomic& operator=(const atomic&) = delete;
3640
  atomic& operator=(const atomic&) volatile = delete;
3641
 
3642
  void store(integral-type, memory_order = memory_order::seq_cst) volatile noexcept;
3643
+ constexpr void store(integral-type, memory_order = memory_order::seq_cst) noexcept;
3644
  integral-type operator=(integral-type) volatile noexcept;
3645
+ constexpr integral-type operator=(integral-type) noexcept;
3646
  integral-type load(memory_order = memory_order::seq_cst) const volatile noexcept;
3647
+ constexpr integral-type load(memory_order = memory_order::seq_cst) const noexcept;
3648
  operator integral-type() const volatile noexcept;
3649
+ constexpr operator integral-type() const noexcept;
3650
 
3651
  integral-type exchange(integral-type,
3652
  memory_order = memory_order::seq_cst) volatile noexcept;
3653
+ constexpr integral-type exchange(integral-type,
3654
  memory_order = memory_order::seq_cst) noexcept;
3655
  bool compare_exchange_weak(integral-type&, integral-type,
3656
  memory_order, memory_order) volatile noexcept;
3657
+ constexpr bool compare_exchange_weak(integral-type&, integral-type,
3658
  memory_order, memory_order) noexcept;
3659
  bool compare_exchange_strong(integral-type&, integral-type,
3660
  memory_order, memory_order) volatile noexcept;
3661
+ constexpr bool compare_exchange_strong(integral-type&, integral-type,
3662
  memory_order, memory_order) noexcept;
3663
  bool compare_exchange_weak(integral-type&, integral-type,
3664
  memory_order = memory_order::seq_cst) volatile noexcept;
3665
+ constexpr bool compare_exchange_weak(integral-type&, integral-type,
3666
  memory_order = memory_order::seq_cst) noexcept;
3667
  bool compare_exchange_strong(integral-type&, integral-type,
3668
  memory_order = memory_order::seq_cst) volatile noexcept;
3669
+ constexpr bool compare_exchange_strong(integral-type&, integral-type,
3670
  memory_order = memory_order::seq_cst) noexcept;
3671
 
3672
  integral-type fetch_add(integral-type,
3673
  memory_order = memory_order::seq_cst) volatile noexcept;
3674
+ constexpr integral-type fetch_add(integral-type,
3675
  memory_order = memory_order::seq_cst) noexcept;
3676
  integral-type fetch_sub(integral-type,
3677
  memory_order = memory_order::seq_cst) volatile noexcept;
3678
+ constexpr integral-type fetch_sub(integral-type,
3679
  memory_order = memory_order::seq_cst) noexcept;
3680
  integral-type fetch_and(integral-type,
3681
  memory_order = memory_order::seq_cst) volatile noexcept;
3682
+ constexpr integral-type fetch_and(integral-type,
3683
  memory_order = memory_order::seq_cst) noexcept;
3684
  integral-type fetch_or(integral-type,
3685
  memory_order = memory_order::seq_cst) volatile noexcept;
3686
+ constexpr integral-type fetch_or(integral-type,
3687
  memory_order = memory_order::seq_cst) noexcept;
3688
  integral-type fetch_xor(integral-type,
3689
  memory_order = memory_order::seq_cst) volatile noexcept;
3690
+ constexpr integral-type fetch_xor(integral-type,
3691
+ memory_order = memory_order::seq_cst) noexcept;
3692
+ integral-type fetch_max(integral-type,
3693
+ memory_order = memory_order::seq_cst) volatile noexcept;
3694
+ constexpr integral-type fetch_max(integral-type,
3695
+ memory_order = memory_order::seq_cst) noexcept;
3696
+ integral-type fetch_min(integral-type,
3697
+ memory_order = memory_order::seq_cst) volatile noexcept;
3698
+ constexpr integral-type fetch_min(integral-type,
3699
+ memory_order = memory_order::seq_cst) noexcept;
3700
+
3701
+ void store_add(integral-type,
3702
+ memory_order = memory_order::seq_cst) volatile noexcept;
3703
+ constexpr void store_add(integral-type,
3704
+ memory_order = memory_order::seq_cst) noexcept;
3705
+ void store_sub(integral-type,
3706
+ memory_order = memory_order::seq_cst) volatile noexcept;
3707
+ constexpr void store_sub(integral-type,
3708
+ memory_order = memory_order::seq_cst) noexcept;
3709
+ void store_and(integral-type,
3710
+ memory_order = memory_order::seq_cst) volatile noexcept;
3711
+ constexpr void store_and(integral-type,
3712
+ memory_order = memory_order::seq_cst) noexcept;
3713
+ void store_or(integral-type,
3714
+ memory_order = memory_order::seq_cst) volatile noexcept;
3715
+ constexpr void store_or(integral-type,
3716
+ memory_order = memory_order::seq_cst) noexcept;
3717
+ void store_xor(integral-type,
3718
+ memory_order = memory_order::seq_cst) volatile noexcept;
3719
+ constexpr void store_xor(integral-type,
3720
+ memory_order = memory_order::seq_cst) noexcept;
3721
+ void store_max(integral-type,
3722
+ memory_order = memory_order::seq_cst) volatile noexcept;
3723
+ constexpr void store_max(integral-type,
3724
+ memory_order = memory_order::seq_cst) noexcept;
3725
+ void store_min(integral-type,
3726
+ memory_order = memory_order::seq_cst) volatile noexcept;
3727
+ constexpr void store_min(integral-type,
3728
  memory_order = memory_order::seq_cst) noexcept;
3729
 
3730
  integral-type operator++(int) volatile noexcept;
3731
+ constexpr integral-type operator++(int) noexcept;
3732
  integral-type operator--(int) volatile noexcept;
3733
+ constexpr integral-type operator--(int) noexcept;
3734
  integral-type operator++() volatile noexcept;
3735
+ constexpr integral-type operator++() noexcept;
3736
  integral-type operator--() volatile noexcept;
3737
+ constexpr integral-type operator--() noexcept;
3738
  integral-type operator+=(integral-type) volatile noexcept;
3739
+ constexpr integral-type operator+=(integral-type) noexcept;
3740
  integral-type operator-=(integral-type) volatile noexcept;
3741
+ constexpr integral-type operator-=(integral-type) noexcept;
3742
  integral-type operator&=(integral-type) volatile noexcept;
3743
+ constexpr integral-type operator&=(integral-type) noexcept;
3744
  integral-type operator|=(integral-type) volatile noexcept;
3745
+ constexpr integral-type operator|=(integral-type) noexcept;
3746
  integral-type operator^=(integral-type) volatile noexcept;
3747
+ constexpr integral-type operator^=(integral-type) noexcept;
3748
 
3749
  void wait(integral-type, memory_order = memory_order::seq_cst) const volatile noexcept;
3750
+ constexpr void wait(integral-type, memory_order = memory_order::seq_cst) const noexcept;
3751
  void notify_one() volatile noexcept;
3752
+ constexpr void notify_one() noexcept;
3753
  void notify_all() volatile noexcept;
3754
+ constexpr void notify_all() noexcept;
3755
  };
3756
  }
3757
  ```
3758
 
3759
  The atomic integral specializations are standard-layout structs. They
 
3767
  [[atomic.types.int.comp]].
3768
 
3769
  **Table: Atomic arithmetic computations** <a id="atomic.types.int.comp">[atomic.types.int.comp]</a>
3770
 
3771
  | | | | | | |
3772
+ | ----- | --- | ----------- | ----- | --- | -------------------- |
3773
+ | `add` | `+` | addition | `and` | `&` | bitwise and |
3774
+ | `sub` | `-` | subtraction | `or` | `|` | bitwise inclusive or |
3775
+ | `max` | | maximum | `xor` | `^` | bitwise exclusive or |
3776
+ | `min` | | minimum | | | |
3777
 
3778
  ``` cpp
3779
+ integral-type fetch_key(integral-type operand,
3780
+ memory_order order = memory_order::seq_cst) volatile noexcept;
3781
+ constexpr integral-type fetch_key(integral-type operand,
3782
+ memory_order order = memory_order::seq_cst) noexcept;
3783
  ```
3784
 
3785
  *Constraints:* For the `volatile` overload of this function,
3786
  `is_always_lock_free` is `true`.
3787
 
 
3792
  operations [[intro.multithread]].
3793
 
3794
  *Returns:* Atomically, the value pointed to by `this` immediately before
3795
  the effects.
3796
 
3797
+ *Remarks:* Except for `fetch_max` and `fetch_min`, for signed integer
3798
+ types the result is as if the object value and parameters were converted
3799
+ to their corresponding unsigned types, the computation performed on
3800
+ those types, and the result converted back to the signed type.
3801
 
3802
  [*Note 1*: There are no undefined results arising from the
3803
  computation. — *end note*]
3804
 
3805
+ For `fetch_max` and `fetch_min`, the maximum and minimum computation is
3806
+ performed as if by `max` and `min` algorithms [[alg.min.max]],
3807
+ respectively, with the object value and the first parameter as the
3808
+ arguments.
3809
+
3810
  ``` cpp
3811
+ void store_key(integral-type operand,
3812
+ memory_order order = memory_order::seq_cst) volatile noexcept;
3813
+ constexpr void store_key(integral-type operand,
3814
+ memory_order order = memory_order::seq_cst) noexcept;
3815
+ ```
3816
+
3817
+ *Constraints:* For the `volatile` overload of this function,
3818
+ `is_always_lock_free` is `true`.
3819
+
3820
+ *Preconditions:* `order` is `memory_order::relaxed`,
3821
+ `memory_order::release`, or `memory_order::seq_cst`.
3822
+
3823
+ *Effects:* Atomically replaces the value pointed to by `this` with the
3824
+ result of the computation applied to the value pointed to by `this` and
3825
+ the given `operand`. Memory is affected according to the value of
3826
+ `order`. These operations are atomic modify-write
3827
+ operations [[atomics.order]].
3828
+
3829
+ *Remarks:* Except for `store_max` and `store_min`, for signed integer
3830
+ types, the result is as if the value pointed to by `this` and parameters
3831
+ were converted to their corresponding unsigned types, the computation
3832
+ performed on those types, and the result converted back to the signed
3833
+ type.
3834
+
3835
+ [*Note 2*: There are no undefined results arising from the
3836
+ computation. — *end note*]
3837
+
3838
+ For `store_max` and `store_min`, the maximum and minimum computation is
3839
+ performed as if by `max` and `min` algorithms [[alg.min.max]],
3840
+ respectively, with the value pointed to by `this` and the first
3841
+ parameter as the arguments.
3842
+
3843
+ ``` cpp
3844
+ integral-type operator op=(integral-type operand) volatile noexcept;
3845
+ constexpr integral-type operator op=(integral-type operand) noexcept;
3846
  ```
3847
 
3848
  *Constraints:* For the `volatile` overload of this function,
3849
  `is_always_lock_free` is `true`.
3850
 
 
3874
  atomic(const atomic&) = delete;
3875
  atomic& operator=(const atomic&) = delete;
3876
  atomic& operator=(const atomic&) volatile = delete;
3877
 
3878
  void store(floating-point-type, memory_order = memory_order::seq_cst) volatile noexcept;
3879
+ constexpr void store(floating-point-type, memory_order = memory_order::seq_cst) noexcept;
3880
  floating-point-type operator=(floating-point-type) volatile noexcept;
3881
+ constexpr floating-point-type operator=(floating-point-type) noexcept;
3882
  floating-point-type load(memory_order = memory_order::seq_cst) volatile noexcept;
3883
+ constexpr floating-point-type load(memory_order = memory_order::seq_cst) noexcept;
3884
  operator floating-point-type() volatile noexcept;
3885
+ constexpr operator floating-point-type() noexcept;
3886
 
3887
  floating-point-type exchange(floating-point-type,
3888
  memory_order = memory_order::seq_cst) volatile noexcept;
3889
+ constexpr floating-point-type exchange(floating-point-type,
3890
  memory_order = memory_order::seq_cst) noexcept;
3891
  bool compare_exchange_weak(floating-point-type&, floating-point-type,
3892
  memory_order, memory_order) volatile noexcept;
3893
+ constexpr bool compare_exchange_weak(floating-point-type&, floating-point-type,
3894
  memory_order, memory_order) noexcept;
3895
  bool compare_exchange_strong(floating-point-type&, floating-point-type,
3896
  memory_order, memory_order) volatile noexcept;
3897
+ constexpr bool compare_exchange_strong(floating-point-type&, floating-point-type,
3898
  memory_order, memory_order) noexcept;
3899
  bool compare_exchange_weak(floating-point-type&, floating-point-type,
3900
  memory_order = memory_order::seq_cst) volatile noexcept;
3901
+ constexpr bool compare_exchange_weak(floating-point-type&, floating-point-type,
3902
  memory_order = memory_order::seq_cst) noexcept;
3903
  bool compare_exchange_strong(floating-point-type&, floating-point-type,
3904
  memory_order = memory_order::seq_cst) volatile noexcept;
3905
+ constexpr bool compare_exchange_strong(floating-point-type&, floating-point-type,
3906
  memory_order = memory_order::seq_cst) noexcept;
3907
 
3908
  floating-point-type fetch_add(floating-point-type,
3909
  memory_order = memory_order::seq_cst) volatile noexcept;
3910
+ constexpr floating-point-type fetch_add(floating-point-type,
3911
  memory_order = memory_order::seq_cst) noexcept;
3912
  floating-point-type fetch_sub(floating-point-type,
3913
  memory_order = memory_order::seq_cst) volatile noexcept;
3914
+ constexpr floating-point-type fetch_sub(floating-point-type,
3915
+ memory_order = memory_order::seq_cst) noexcept;
3916
+ floating-point-type fetch_max(floating-point-type,
3917
+ memory_order = memory_order::seq_cst) volatile noexcept;
3918
+ constexpr floating-point-type fetch_max(floating-point-type,
3919
+ memory_order = memory_order::seq_cst) noexcept;
3920
+ floating-point-type fetch_min(floating-point-type,
3921
+ memory_order = memory_order::seq_cst) volatile noexcept;
3922
+ constexpr floating-poin-typet fetch_min(floating-point-type,
3923
+ memory_order = memory_order::seq_cst) noexcept;
3924
+ floating-point-type fetch_fmaximum(floating-point-type,
3925
+ memory_order = memory_order::seq_cst) volatile noexcept;
3926
+ constexpr floating-point-type fetch_fmaximum(floating-point-type,
3927
+ memory_order = memory_order::seq_cst) noexcept;
3928
+ floating-point-type fetch_fminimum(floating-point-type,
3929
+ memory_order = memory_order::seq_cst) volatile noexcept;
3930
+ constexpr floating-point-type fetch_fminimum(floating-point-type,
3931
+ memory_order = memory_order::seq_cst) noexcept;
3932
+ floating-point-type fetch_fmaximum_num(
3933
+ floating-point-type, memory_order = memory_order::seq_cst) volatile noexcept;
3934
+ constexpr floating-point-type fetch_fmaximum_num(
3935
+ floating-point-type, memory_order = memory_order::seq_cst) noexcept;
3936
+ floating-point-type fetch_fminimum_num(
3937
+ floating-point-type, memory_order = memory_order::seq_cst) volatile noexcept;
3938
+ constexpr floating-point-type fetch_fminimum_num(
3939
+ floating-point-type, memory_order = memory_order::seq_cst) noexcept;
3940
+
3941
+ void store_add(floating-point-type,
3942
+ memory_order = memory_order::seq_cst) volatile noexcept;
3943
+ constexpr void store_add(floating-point-type,
3944
+ memory_order = memory_order::seq_cst) noexcept;
3945
+ void store_sub(floating-point-type,
3946
+ memory_order = memory_order::seq_cst) volatile noexcept;
3947
+ constexpr void store_sub(floating-point-type,
3948
+ memory_order = memory_order::seq_cst) noexcept;
3949
+ void store_max(floating-point-type,
3950
+ memory_order = memory_order::seq_cst) volatile noexcept;
3951
+ constexpr void store_max(floating-point-type,
3952
+ memory_order = memory_order::seq_cst) noexcept;
3953
+ void store_min(floating-point-type,
3954
+ memory_order = memory_order::seq_cst) volatile noexcept;
3955
+ constexpr void store_min(floating-point-type,
3956
+ memory_order = memory_order::seq_cst) noexcept;
3957
+ void store_fmaximum(floating-point-type,
3958
+ memory_order = memory_order::seq_cst) volatile noexcept;
3959
+ constexpr void store_fmaximum(floating-point-type,
3960
+ memory_order = memory_order::seq_cst) noexcept;
3961
+ void store_fminimum(floating-point-type,
3962
+ memory_order = memory_order::seq_cst) volatile noexcept;
3963
+ constexpr void store_fminimum(floating-point-type,
3964
+ memory_order = memory_order::seq_cst) noexcept;
3965
+ void store_fmaximum_num(floating-point-type,
3966
+ memory_order = memory_order::seq_cst) volatile noexcept;
3967
+ constexpr void store_fmaximum_num(floating-point-type,
3968
+ memory_order = memory_order::seq_cst) noexcept;
3969
+ void store_fminimum_num(floating-point-type,
3970
+ memory_order = memory_order::seq_cst) volatile noexcept;
3971
+ constexpr void store_fminimum_num(floating-point-type,
3972
  memory_order = memory_order::seq_cst) noexcept;
3973
 
3974
  floating-point-type operator+=(floating-point-type) volatile noexcept;
3975
+ constexpr floating-point-type operator+=(floating-point-type) noexcept;
3976
  floating-point-type operator-=(floating-point-type) volatile noexcept;
3977
+ constexpr floating-point-type operator-=(floating-point-type) noexcept;
3978
 
3979
  void wait(floating-point-type, memory_order = memory_order::seq_cst) const volatile noexcept;
3980
+ constexpr void wait(floating-point-type,
3981
+ memory_order = memory_order::seq_cst) const noexcept;
3982
  void notify_one() volatile noexcept;
3983
+ constexpr void notify_one() noexcept;
3984
  void notify_all() volatile noexcept;
3985
+ constexpr void notify_all() noexcept;
3986
  };
3987
  }
3988
  ```
3989
 
3990
  The atomic floating-point specializations are standard-layout structs.
 
3993
  Descriptions are provided below only for members that differ from the
3994
  primary template.
3995
 
3996
  The following operations perform arithmetic addition and subtraction
3997
  computations. The correspondence among key, operator, and computation is
3998
+ specified in [[atomic.types.int.comp]], except for the keys `max`,
3999
+ `min`, `fmaximum`, `fminimum`, `fmaximum_num`, and `fminimum_num`, which
4000
+ are specified below.
4001
 
4002
  ``` cpp
4003
+ floating-point-type fetch_key(floating-point-type operand,
4004
+ memory_order order = memory_order::seq_cst) volatile noexcept;
4005
+ constexpr floating-point-type fetch_key(floating-point-type operand,
4006
+ memory_order order = memory_order::seq_cst) noexcept;
4007
  ```
4008
 
4009
  *Constraints:* For the `volatile` overload of this function,
4010
  `is_always_lock_free` is `true`.
4011
 
 
4026
  the floating-point type [[limits.syn]]. The floating-point
4027
  environment [[cfenv]] for atomic arithmetic operations on
4028
  *`floating-point-type`* may be different than the calling thread’s
4029
  floating-point environment.
4030
 
4031
+ - For `fetch_fmaximum` and `fetch_fminimum`, the maximum and minimum
4032
+ computation is performed as if by `fmaximum` and `fminimum`,
4033
+ respectively, with the value pointed to by `this` and the first
4034
+ parameter as the arguments.
4035
+ - For `fetch_fmaximum_num` and `fetch_fminimum_num`, the maximum and
4036
+ minimum computation is performed as if by `fmaximum_num` and
4037
+ `fminimum_num`, respectively, with the value pointed to by `this` and
4038
+ the first parameter as the arguments.
4039
+ - For `fetch_max` and `fetch_min`, the maximum and minimum computation
4040
+ is performed as if by `fmaximum_num` and `fminimum_num`, respectively,
4041
+ with the value pointed to by `this` and the first parameter as the
4042
+ arguments, except that:
4043
+ - If both arguments are NaN, an unspecified NaN value replaces the
4044
+ value pointed to by `this`.
4045
+ - If exactly one argument is a NaN, either the other argument or an
4046
+ unspecified NaN value replaces the value pointed to by `this`; it is
4047
+ unspecified which.
4048
+ - If the arguments are differently signed zeros, which of these values
4049
+ replaces the value pointed to by this is unspecified.
4050
+
4051
+ *Recommended practice:* The implementation of `fetch_max` and
4052
+ `fetch_min` should treat negative zero as smaller than positive zero.
4053
+
4054
  ``` cpp
4055
+ void store_key(floating-point-type operand,
4056
+ memory_order order = memory_order::seq_cst) volatile noexcept;
4057
+ constexpr void store_key(floating-point-type operand,
4058
+ memory_order order = memory_order::seq_cst) noexcept;
4059
+ ```
4060
+
4061
+ *Constraints:* For the `volatile` overload of this function,
4062
+ `is_always_lock_free` is `true`.
4063
+
4064
+ *Preconditions:* `order` is `memory_order::relaxed`,
4065
+ `memory_order::release`, or `memory_order::seq_cst`.
4066
+
4067
+ *Effects:* Atomically replaces the value pointed to by `this` with the
4068
+ result of the computation applied to the value pointed to by `this` and
4069
+ the given operand. Memory is affected according to the value of `order`.
4070
+ These operations are atomic modify-write operations [[atomics.order]].
4071
+
4072
+ *Remarks:* If the result is not a representable value for its
4073
+ type [[expr.pre]] the result is unspecified, but the operations
4074
+ otherwise have no undefined behavior. Atomic arithmetic operations on
4075
+ *`floating-point-type`* should conform to the
4076
+ `numeric_limits<`*`floating-point-type`*`>` traits associated with the
4077
+ floating-point type [[limits.syn]]. The floating-point
4078
+ environment [[cfenv]] for atomic arithmetic operations on
4079
+ *`floating-point-type`* may be different than the calling thread’s
4080
+ floating-point environment. The arithmetic rules of floating-point
4081
+ atomic modify-write operations may be different from operations on
4082
+ floating-point types or atomic floating-point types.
4083
+
4084
+ [*Note 1*: Tree reductions are permitted for atomic modify-write
4085
+ operations. — *end note*]
4086
+
4087
+ - For `store_fmaximum` and `store_fminimum`, the maximum and minimum
4088
+ computation is performed as if by `fmaximum` and `fminimum`,
4089
+ respectively, with the value pointed to by `this` and the first
4090
+ parameter as the arguments.
4091
+ - For `store_fmaximum_num` and `store_fminimum_num`, the maximum and
4092
+ minimum computation is performed as if by `fmaximum_num` and
4093
+ `fminimum_num`, respectively, with the value pointed to by `this` and
4094
+ the first parameter as the arguments.
4095
+ - For `store_max` and `store_min`, the maximum and minimum computation
4096
+ is performed as if by `fmaximum_num` and `fminimum_num`, respectively,
4097
+ with the value pointed to by `this` and the first parameter as the
4098
+ arguments, except that:
4099
+ - If both arguments are NaN, an unspecified NaN value replaces the
4100
+ value pointed to by `this`.
4101
+ - If exactly one argument is a NaN, either the other argument or an
4102
+ unspecified NaN value replaces the value pointed to by `this`; it is
4103
+ unspecified which.
4104
+ - If the arguments are differently signed zeros, which of these values
4105
+ replaces the value pointed to by `this` is unspecified.
4106
+
4107
+ *Recommended practice:* The implementation of `store_max` and
4108
+ `store_min` should treat negative zero as smaller than positive zero.
4109
+
4110
+ ``` cpp
4111
+ floating-point-type operator op=(floating-point-type operand) volatile noexcept;
4112
+ constexpr floating-point-type operator op=(floating-point-type operand) noexcept;
4113
  ```
4114
 
4115
  *Constraints:* For the `volatile` overload of this function,
4116
  `is_always_lock_free` is `true`.
4117
 
 
4145
  atomic(const atomic&) = delete;
4146
  atomic& operator=(const atomic&) = delete;
4147
  atomic& operator=(const atomic&) volatile = delete;
4148
 
4149
  void store(T*, memory_order = memory_order::seq_cst) volatile noexcept;
4150
+ constexpr void store(T*, memory_order = memory_order::seq_cst) noexcept;
4151
  T* operator=(T*) volatile noexcept;
4152
+ constexpr T* operator=(T*) noexcept;
4153
  T* load(memory_order = memory_order::seq_cst) const volatile noexcept;
4154
+ constexpr T* load(memory_order = memory_order::seq_cst) const noexcept;
4155
  operator T*() const volatile noexcept;
4156
+ constexpr operator T*() const noexcept;
4157
 
4158
  T* exchange(T*, memory_order = memory_order::seq_cst) volatile noexcept;
4159
+ constexpr T* exchange(T*, memory_order = memory_order::seq_cst) noexcept;
4160
  bool compare_exchange_weak(T*&, T*, memory_order, memory_order) volatile noexcept;
4161
+ constexpr bool compare_exchange_weak(T*&, T*, memory_order, memory_order) noexcept;
4162
  bool compare_exchange_strong(T*&, T*, memory_order, memory_order) volatile noexcept;
4163
+ constexpr bool compare_exchange_strong(T*&, T*, memory_order, memory_order) noexcept;
4164
  bool compare_exchange_weak(T*&, T*,
4165
  memory_order = memory_order::seq_cst) volatile noexcept;
4166
+ constexpr bool compare_exchange_weak(T*&, T*,
4167
  memory_order = memory_order::seq_cst) noexcept;
4168
  bool compare_exchange_strong(T*&, T*,
4169
  memory_order = memory_order::seq_cst) volatile noexcept;
4170
+ constexpr bool compare_exchange_strong(T*&, T*,
4171
  memory_order = memory_order::seq_cst) noexcept;
4172
 
4173
  T* fetch_add(ptrdiff_t, memory_order = memory_order::seq_cst) volatile noexcept;
4174
+ constexpr T* fetch_add(ptrdiff_t, memory_order = memory_order::seq_cst) noexcept;
4175
  T* fetch_sub(ptrdiff_t, memory_order = memory_order::seq_cst) volatile noexcept;
4176
+ constexpr T* fetch_sub(ptrdiff_t, memory_order = memory_order::seq_cst) noexcept;
4177
+ T* fetch_max(T*, memory_order = memory_order::seq_cst) volatile noexcept;
4178
+ constexpr T* fetch_max(T*, memory_order = memory_order::seq_cst) noexcept;
4179
+ T* fetch_min(T*, memory_order = memory_order::seq_cst) volatile noexcept;
4180
+ constexpr T* fetch_min(T*, memory_order = memory_order::seq_cst) noexcept;
4181
+
4182
+ void store_add(ptrdiff_t, memory_order = memory_order::seq_cst) volatile noexcept;
4183
+ constexpr void store_add(ptrdiff_t, memory_order = memory_order::seq_cst) noexcept;
4184
+ void store_sub(ptrdiff_t, memory_order = memory_order::seq_cst) volatile noexcept;
4185
+ constexpr void store_sub(ptrdiff_t, memory_order = memory_order::seq_cst) noexcept;
4186
+ void store_max(T*, memory_order = memory_order::seq_cst) volatile noexcept;
4187
+ constexpr void store_max(T*, memory_order = memory_order::seq_cst) noexcept;
4188
+ void store_min(T*, memory_order = memory_order::seq_cst) volatile noexcept;
4189
+ constexpr void store_min(T*, memory_order = memory_order::seq_cst) noexcept;
4190
 
4191
  T* operator++(int) volatile noexcept;
4192
+ constexpr T* operator++(int) noexcept;
4193
  T* operator--(int) volatile noexcept;
4194
+ constexpr T* operator--(int) noexcept;
4195
  T* operator++() volatile noexcept;
4196
+ constexpr T* operator++() noexcept;
4197
  T* operator--() volatile noexcept;
4198
+ constexpr T* operator--() noexcept;
4199
  T* operator+=(ptrdiff_t) volatile noexcept;
4200
+ constexpr T* operator+=(ptrdiff_t) noexcept;
4201
  T* operator-=(ptrdiff_t) volatile noexcept;
4202
+ constexpr T* operator-=(ptrdiff_t) noexcept;
4203
 
4204
  void wait(T*, memory_order = memory_order::seq_cst) const volatile noexcept;
4205
+ constexpr void wait(T*, memory_order = memory_order::seq_cst) const noexcept;
4206
  void notify_one() volatile noexcept;
4207
+ constexpr void notify_one() noexcept;
4208
  void notify_all() volatile noexcept;
4209
+ constexpr void notify_all() noexcept;
4210
  };
4211
  }
4212
  ```
4213
 
4214
  There is a partial specialization of the `atomic` class template for
 
4225
  **Table: Atomic pointer computations** <a id="atomic.types.pointer.comp">[atomic.types.pointer.comp]</a>
4226
 
4227
  | | | | | | |
4228
  | ----- | --- | -------- | ----- | --- | ----------- |
4229
  | `add` | `+` | addition | `sub` | `-` | subtraction |
4230
+ | `max` | | maximum | `min` | | minimum |
4231
 
4232
  ``` cpp
4233
+ T* fetch_key(\seeabovenc operand, memory_order order = memory_order::seq_cst) volatile noexcept;
4234
+ constexpr T* fetch_key(\seeabovenc operand, memory_order order = memory_order::seq_cst) noexcept;
4235
  ```
4236
 
4237
  *Constraints:* For the `volatile` overload of this function,
4238
  `is_always_lock_free` is `true`.
4239
 
 
4252
  the effects.
4253
 
4254
  *Remarks:* The result may be an undefined address, but the operations
4255
  otherwise have no undefined behavior.
4256
 
4257
+ For `fetch_max` and `fetch_min`, the maximum and minimum computation is
4258
+ performed as if by `max` and `min` algorithms [[alg.min.max]],
4259
+ respectively, with the object value and the first parameter as the
4260
+ arguments.
4261
+
4262
+ [*Note 2*: If the pointers point to different complete objects (or
4263
+ subobjects thereof), the `<` operator does not establish a strict weak
4264
+ ordering ([[cpp17.lessthancomparable]], [[expr.rel]]). — *end note*]
4265
+
4266
+ ``` cpp
4267
+ void store_key(\seeabovenc operand, memory_order order = memory_order::seq_cst) volatile noexcept;
4268
+ constexpr void store_key(\seeabovenc operand, memory_order order = memory_order::seq_cst) noexcept;
4269
+ ```
4270
+
4271
+ *Constraints:* For the `volatile` overload of this function,
4272
+ `is_always_lock_free` is `true`.
4273
+
4274
+ *Mandates:* `T` is a complete object type.
4275
+
4276
+ [*Note 3*: Pointer arithmetic on `void*` or function pointers is
4277
+ ill-formed. — *end note*]
4278
+
4279
+ *Effects:* Atomically replaces the value pointed to by `this` with the
4280
+ result of the computation applied to the value pointed to by `this` and
4281
+ the given `operand`. Memory is affected according to the value of
4282
+ `order`. These operations are atomic modify-write
4283
+ operations [[atomics.order]].
4284
+
4285
+ *Remarks:* The result may be an undefined address, but the operations
4286
+ otherwise have no undefined behavior. For `store_max` and `store_min`,
4287
+ the maximum and minimum computation is performed as if by `max` and
4288
+ `min` algorithms [[alg.min.max]], respectively, with the value pointed
4289
+ to by `this` and the first parameter as the arguments.
4290
+
4291
+ [*Note 4*: If the pointers point to different complete objects (or
4292
+ subobjects thereof), the `<` operator does not establish a strict weak
4293
+ ordering ([[cpp17.lessthancomparable]], [[expr.rel]]). — *end note*]
4294
+
4295
  ``` cpp
4296
  T* operator op=(ptrdiff_t operand) volatile noexcept;
4297
+ constexpr T* operator op=(ptrdiff_t operand) noexcept;
4298
  ```
4299
 
4300
  *Constraints:* For the `volatile` overload of this function,
4301
  `is_always_lock_free` is `true`.
4302
 
 
4305
 
4306
  #### Member operators common to integers and pointers to objects <a id="atomics.types.memop">[[atomics.types.memop]]</a>
4307
 
4308
  ``` cpp
4309
  value_type operator++(int) volatile noexcept;
4310
+ constexpr value_type operator++(int) noexcept;
4311
  ```
4312
 
4313
  *Constraints:* For the `volatile` overload of this function,
4314
  `is_always_lock_free` is `true`.
4315
 
4316
  *Effects:* Equivalent to: `return fetch_add(1);`
4317
 
4318
  ``` cpp
4319
  value_type operator--(int) volatile noexcept;
4320
+ constexpr value_type operator--(int) noexcept;
4321
  ```
4322
 
4323
  *Constraints:* For the `volatile` overload of this function,
4324
  `is_always_lock_free` is `true`.
4325
 
4326
  *Effects:* Equivalent to: `return fetch_sub(1);`
4327
 
4328
  ``` cpp
4329
  value_type operator++() volatile noexcept;
4330
+ constexpr value_type operator++() noexcept;
4331
  ```
4332
 
4333
  *Constraints:* For the `volatile` overload of this function,
4334
  `is_always_lock_free` is `true`.
4335
 
4336
  *Effects:* Equivalent to: `return fetch_add(1) + 1;`
4337
 
4338
  ``` cpp
4339
  value_type operator--() volatile noexcept;
4340
+ constexpr value_type operator--() noexcept;
4341
  ```
4342
 
4343
  *Constraints:* For the `volatile` overload of this function,
4344
  `is_always_lock_free` is `true`.
4345
 
 
4412
  static constexpr bool is_always_lock_free = implementation-defined // whether a given atomic type's operations are always lock free;
4413
  bool is_lock_free() const noexcept;
4414
 
4415
  constexpr atomic() noexcept;
4416
  constexpr atomic(nullptr_t) noexcept : atomic() { }
4417
+ constexpr atomic(shared_ptr<T> desired) noexcept;
4418
  atomic(const atomic&) = delete;
4419
  void operator=(const atomic&) = delete;
4420
 
4421
+ constexpr shared_ptr<T> load(memory_order order = memory_order::seq_cst) const noexcept;
4422
+ constexpr operator shared_ptr<T>() const noexcept;
4423
+ constexpr void store(shared_ptr<T> desired,
4424
+ memory_order order = memory_order::seq_cst) noexcept;
4425
+ constexpr void operator=(shared_ptr<T> desired) noexcept;
4426
+ constexpr void operator=(nullptr_t) noexcept;
4427
 
4428
+ constexpr shared_ptr<T> exchange(shared_ptr<T> desired,
4429
  memory_order order = memory_order::seq_cst) noexcept;
4430
+ constexpr bool compare_exchange_weak(shared_ptr<T>& expected, shared_ptr<T> desired,
4431
  memory_order success, memory_order failure) noexcept;
4432
+ constexpr bool compare_exchange_strong(shared_ptr<T>& expected, shared_ptr<T> desired,
4433
  memory_order success, memory_order failure) noexcept;
4434
+ constexpr bool compare_exchange_weak(shared_ptr<T>& expected, shared_ptr<T> desired,
4435
  memory_order order = memory_order::seq_cst) noexcept;
4436
+ constexpr bool compare_exchange_strong(shared_ptr<T>& expected, shared_ptr<T> desired,
4437
  memory_order order = memory_order::seq_cst) noexcept;
4438
 
4439
+ constexpr void wait(shared_ptr<T> old,
4440
+ memory_order order = memory_order::seq_cst) const noexcept;
4441
+ constexpr void notify_one() noexcept;
4442
+ constexpr void notify_all() noexcept;
4443
 
4444
  private:
4445
  shared_ptr<T> p; // exposition only
4446
  };
4447
  }
 
4449
 
4450
  ``` cpp
4451
  constexpr atomic() noexcept;
4452
  ```
4453
 
4454
+ *Effects:* Value-initializes `p`.
4455
 
4456
  ``` cpp
4457
+ constexpr atomic(shared_ptr<T> desired) noexcept;
4458
  ```
4459
 
4460
  *Effects:* Initializes the object with the value `desired`.
4461
  Initialization is not an atomic operation [[intro.multithread]].
4462
 
 
4466
  `memory_order::relaxed` operations on a suitable atomic pointer
4467
  variable, and then immediately accessing `A` in the receiving thread.
4468
  This results in undefined behavior. — *end note*]
4469
 
4470
  ``` cpp
4471
+ constexpr void store(shared_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept;
4472
  ```
4473
 
4474
+ *Preconditions:* `order` is `memory_order::relaxed`,
4475
+ `memory_order::release`, or `memory_order::seq_cst`.
4476
 
4477
  *Effects:* Atomically replaces the value pointed to by `this` with the
4478
  value of `desired` as if by `p.swap(desired)`. Memory is affected
4479
  according to the value of `order`.
4480
 
4481
  ``` cpp
4482
+ constexpr void operator=(shared_ptr<T> desired) noexcept;
4483
  ```
4484
 
4485
  *Effects:* Equivalent to `store(desired)`.
4486
 
4487
  ``` cpp
4488
+ constexpr void operator=(nullptr_t) noexcept;
4489
  ```
4490
 
4491
+ *Effects:* Equivalent to `store(nullptr)`.
4492
+
4493
+ ``` cpp
4494
+ constexpr shared_ptr<T> load(memory_order order = memory_order::seq_cst) const noexcept;
4495
+ ```
4496
+
4497
+ *Preconditions:* `order` is `memory_order::relaxed`,
4498
+ `memory_order::acquire`, or `memory_order::seq_cst`.
4499
 
4500
  *Effects:* Memory is affected according to the value of `order`.
4501
 
4502
  *Returns:* Atomically returns `p`.
4503
 
4504
  ``` cpp
4505
+ constexpr operator shared_ptr<T>() const noexcept;
4506
  ```
4507
 
4508
  *Effects:* Equivalent to: `return load();`
4509
 
4510
  ``` cpp
4511
+ constexpr shared_ptr<T> exchange(shared_ptr<T> desired,
4512
+ memory_order order = memory_order::seq_cst) noexcept;
4513
  ```
4514
 
4515
  *Effects:* Atomically replaces `p` with `desired` as if by
4516
  `p.swap(desired)`. Memory is affected according to the value of `order`.
4517
  This is an atomic read-modify-write operation [[intro.races]].
4518
 
4519
  *Returns:* Atomically returns the value of `p` immediately before the
4520
  effects.
4521
 
4522
  ``` cpp
4523
+ constexpr bool compare_exchange_weak(shared_ptr<T>& expected, shared_ptr<T> desired,
4524
  memory_order success, memory_order failure) noexcept;
4525
+ constexpr bool compare_exchange_strong(shared_ptr<T>& expected, shared_ptr<T> desired,
4526
  memory_order success, memory_order failure) noexcept;
4527
  ```
4528
 
4529
+ *Preconditions:* `failure` is `memory_order::relaxed`,
4530
+ `memory_order::acquire`, or `memory_order::seq_cst`.
4531
 
4532
  *Effects:* If `p` is equivalent to `expected`, assigns `desired` to `p`
4533
  and has synchronization semantics corresponding to the value of
4534
  `success`, otherwise assigns `p` to `expected` and has synchronization
4535
  semantics corresponding to the value of `failure`.
 
4550
  corresponding to the write to `expected` is part of the atomic
4551
  operation. The write to `expected` itself is not required to be part of
4552
  the atomic operation.
4553
 
4554
  ``` cpp
4555
+ constexpr bool compare_exchange_weak(shared_ptr<T>& expected, shared_ptr<T> desired,
4556
  memory_order order = memory_order::seq_cst) noexcept;
4557
  ```
4558
 
4559
  *Effects:* Equivalent to:
4560
 
 
4566
  `memory_order::acq_rel` shall be replaced by the value
4567
  `memory_order::acquire` and a value of `memory_order::release` shall be
4568
  replaced by the value `memory_order::relaxed`.
4569
 
4570
  ``` cpp
4571
+ constexpr bool compare_exchange_strong(shared_ptr<T>& expected, shared_ptr<T> desired,
4572
  memory_order order = memory_order::seq_cst) noexcept;
4573
  ```
4574
 
4575
  *Effects:* Equivalent to:
4576
 
 
4582
  `memory_order::acq_rel` shall be replaced by the value
4583
  `memory_order::acquire` and a value of `memory_order::release` shall be
4584
  replaced by the value `memory_order::relaxed`.
4585
 
4586
  ``` cpp
4587
+ constexpr void wait(shared_ptr<T> old, memory_order order = memory_order::seq_cst) const noexcept;
4588
  ```
4589
 
4590
+ *Preconditions:* `order` is `memory_order::relaxed`,
4591
+ `memory_order::acquire`, or `memory_order::seq_cst`.
4592
 
4593
  *Effects:* Repeatedly performs the following steps, in order:
4594
 
4595
  - Evaluates `load(order)` and compares it to `old`.
4596
  - If the two are not equivalent, returns.
 
4600
  *Remarks:* Two `shared_ptr` objects are equivalent if they store the
4601
  same pointer and either share ownership or are both empty. This function
4602
  is an atomic waiting operation [[atomics.wait]].
4603
 
4604
  ``` cpp
4605
+ constexpr void notify_one() noexcept;
4606
  ```
4607
 
4608
  *Effects:* Unblocks the execution of at least one atomic waiting
4609
  operation that is eligible to be unblocked [[atomics.wait]] by this
4610
  call, if any such atomic waiting operations exist.
4611
 
4612
  *Remarks:* This function is an atomic notifying
4613
  operation [[atomics.wait]].
4614
 
4615
  ``` cpp
4616
+ constexpr void notify_all() noexcept;
4617
  ```
4618
 
4619
  *Effects:* Unblocks the execution of all atomic waiting operations that
4620
  are eligible to be unblocked [[atomics.wait]] by this call.
4621
 
 
4631
 
4632
  static constexpr bool is_always_lock_free = implementation-defined // whether a given atomic type's operations are always lock free;
4633
  bool is_lock_free() const noexcept;
4634
 
4635
  constexpr atomic() noexcept;
4636
+ constexpr atomic(weak_ptr<T> desired) noexcept;
4637
  atomic(const atomic&) = delete;
4638
  void operator=(const atomic&) = delete;
4639
 
4640
+ constexpr weak_ptr<T> load(memory_order order = memory_order::seq_cst) const noexcept;
4641
+ constexpr operator weak_ptr<T>() const noexcept;
4642
+ constexpr void store(weak_ptr<T> desired,
4643
+ memory_order order = memory_order::seq_cst) noexcept;
4644
+ constexpr void operator=(weak_ptr<T> desired) noexcept;
4645
 
4646
+ constexpr weak_ptr<T> exchange(weak_ptr<T> desired,
4647
  memory_order order = memory_order::seq_cst) noexcept;
4648
+ constexpr bool compare_exchange_weak(weak_ptr<T>& expected, weak_ptr<T> desired,
4649
  memory_order success, memory_order failure) noexcept;
4650
+ constexpr bool compare_exchange_strong(weak_ptr<T>& expected, weak_ptr<T> desired,
4651
  memory_order success, memory_order failure) noexcept;
4652
+ constexpr bool compare_exchange_weak(weak_ptr<T>& expected, weak_ptr<T> desired,
4653
  memory_order order = memory_order::seq_cst) noexcept;
4654
+ constexpr bool compare_exchange_strong(weak_ptr<T>& expected, weak_ptr<T> desired,
4655
  memory_order order = memory_order::seq_cst) noexcept;
4656
 
4657
+ constexpr void wait(weak_ptr<T> old,
4658
+ memory_order order = memory_order::seq_cst) const noexcept;
4659
+ constexpr void notify_one() noexcept;
4660
+ constexpr void notify_all() noexcept;
4661
 
4662
  private:
4663
  weak_ptr<T> p; // exposition only
4664
  };
4665
  }
 
4667
 
4668
  ``` cpp
4669
  constexpr atomic() noexcept;
4670
  ```
4671
 
4672
+ *Effects:* Value-initializes `p`.
4673
 
4674
  ``` cpp
4675
+ constexpr atomic(weak_ptr<T> desired) noexcept;
4676
  ```
4677
 
4678
  *Effects:* Initializes the object with the value `desired`.
4679
  Initialization is not an atomic operation [[intro.multithread]].
4680
 
 
4684
  `memory_order::relaxed` operations on a suitable atomic pointer
4685
  variable, and then immediately accessing `A` in the receiving thread.
4686
  This results in undefined behavior. — *end note*]
4687
 
4688
  ``` cpp
4689
+ constexpr void store(weak_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept;
4690
  ```
4691
 
4692
+ *Preconditions:* `order` is `memory_order::relaxed`,
4693
+ `memory_order::release`, or `memory_order::seq_cst`.
4694
 
4695
  *Effects:* Atomically replaces the value pointed to by `this` with the
4696
  value of `desired` as if by `p.swap(desired)`. Memory is affected
4697
  according to the value of `order`.
4698
 
4699
  ``` cpp
4700
+ constexpr void operator=(weak_ptr<T> desired) noexcept;
4701
  ```
4702
 
4703
  *Effects:* Equivalent to `store(desired)`.
4704
 
4705
  ``` cpp
4706
+ constexpr weak_ptr<T> load(memory_order order = memory_order::seq_cst) const noexcept;
4707
  ```
4708
 
4709
+ *Preconditions:* `order` is `memory_order::relaxed`,
4710
+ `memory_order::acquire`, or `memory_order::seq_cst`.
4711
 
4712
  *Effects:* Memory is affected according to the value of `order`.
4713
 
4714
  *Returns:* Atomically returns `p`.
4715
 
4716
  ``` cpp
4717
+ constexpr operator weak_ptr<T>() const noexcept;
4718
  ```
4719
 
4720
  *Effects:* Equivalent to: `return load();`
4721
 
4722
  ``` cpp
4723
+ constexpr weak_ptr<T> exchange(weak_ptr<T> desired,
4724
+ memory_order order = memory_order::seq_cst) noexcept;
4725
  ```
4726
 
4727
  *Effects:* Atomically replaces `p` with `desired` as if by
4728
  `p.swap(desired)`. Memory is affected according to the value of `order`.
4729
  This is an atomic read-modify-write operation [[intro.races]].
4730
 
4731
  *Returns:* Atomically returns the value of `p` immediately before the
4732
  effects.
4733
 
4734
  ``` cpp
4735
+ constexpr bool compare_exchange_weak(weak_ptr<T>& expected, weak_ptr<T> desired,
4736
  memory_order success, memory_order failure) noexcept;
4737
+ constexpr bool compare_exchange_strong(weak_ptr<T>& expected, weak_ptr<T> desired,
4738
  memory_order success, memory_order failure) noexcept;
4739
  ```
4740
 
4741
+ *Preconditions:* `failure` is `memory_order::relaxed`,
4742
+ `memory_order::acquire`, or `memory_order::seq_cst`.
4743
 
4744
  *Effects:* If `p` is equivalent to `expected`, assigns `desired` to `p`
4745
  and has synchronization semantics corresponding to the value of
4746
  `success`, otherwise assigns `p` to `expected` and has synchronization
4747
  semantics corresponding to the value of `failure`.
 
4762
  corresponding to the write to `expected` is part of the atomic
4763
  operation. The write to `expected` itself is not required to be part of
4764
  the atomic operation.
4765
 
4766
  ``` cpp
4767
+ constexpr bool compare_exchange_weak(weak_ptr<T>& expected, weak_ptr<T> desired,
4768
  memory_order order = memory_order::seq_cst) noexcept;
4769
  ```
4770
 
4771
  *Effects:* Equivalent to:
4772
 
 
4778
  `memory_order::acq_rel` shall be replaced by the value
4779
  `memory_order::acquire` and a value of `memory_order::release` shall be
4780
  replaced by the value `memory_order::relaxed`.
4781
 
4782
  ``` cpp
4783
+ constexpr bool compare_exchange_strong(weak_ptr<T>& expected, weak_ptr<T> desired,
4784
  memory_order order = memory_order::seq_cst) noexcept;
4785
  ```
4786
 
4787
  *Effects:* Equivalent to:
4788
 
 
4794
  `memory_order::acq_rel` shall be replaced by the value
4795
  `memory_order::acquire` and a value of `memory_order::release` shall be
4796
  replaced by the value `memory_order::relaxed`.
4797
 
4798
  ``` cpp
4799
+ constexpr void wait(weak_ptr<T> old, memory_order order = memory_order::seq_cst) const noexcept;
4800
  ```
4801
 
4802
+ *Preconditions:* `order` is `memory_order::relaxed`,
4803
+ `memory_order::acquire`, or `memory_order::seq_cst`.
4804
 
4805
  *Effects:* Repeatedly performs the following steps, in order:
4806
 
4807
  - Evaluates `load(order)` and compares it to `old`.
4808
  - If the two are not equivalent, returns.
 
4812
  *Remarks:* Two `weak_ptr` objects are equivalent if they store the same
4813
  pointer and either share ownership or are both empty. This function is
4814
  an atomic waiting operation [[atomics.wait]].
4815
 
4816
  ``` cpp
4817
+ constexpr void notify_one() noexcept;
4818
  ```
4819
 
4820
  *Effects:* Unblocks the execution of at least one atomic waiting
4821
  operation that is eligible to be unblocked [[atomics.wait]] by this
4822
  call, if any such atomic waiting operations exist.
4823
 
4824
  *Remarks:* This function is an atomic notifying
4825
  operation [[atomics.wait]].
4826
 
4827
  ``` cpp
4828
+ constexpr void notify_all() noexcept;
4829
  ```
4830
 
4831
  *Effects:* Unblocks the execution of all atomic waiting operations that
4832
  are eligible to be unblocked [[atomics.wait]] by this call.
4833
 
 
4858
  atomic_flag(const atomic_flag&) = delete;
4859
  atomic_flag& operator=(const atomic_flag&) = delete;
4860
  atomic_flag& operator=(const atomic_flag&) volatile = delete;
4861
 
4862
  bool test(memory_order = memory_order::seq_cst) const volatile noexcept;
4863
+ constexpr bool test(memory_order = memory_order::seq_cst) const noexcept;
4864
  bool test_and_set(memory_order = memory_order::seq_cst) volatile noexcept;
4865
+ constexpr bool test_and_set(memory_order = memory_order::seq_cst) noexcept;
4866
  void clear(memory_order = memory_order::seq_cst) volatile noexcept;
4867
+ constexpr void clear(memory_order = memory_order::seq_cst) noexcept;
4868
 
4869
  void wait(bool, memory_order = memory_order::seq_cst) const volatile noexcept;
4870
+ constexpr void wait(bool, memory_order = memory_order::seq_cst) const noexcept;
4871
  void notify_one() volatile noexcept;
4872
+ constexpr void notify_one() noexcept;
4873
  void notify_all() volatile noexcept;
4874
+ constexpr void notify_all() noexcept;
4875
  };
4876
  }
4877
  ```
4878
 
4879
  The `atomic_flag` type provides the classic test-and-set functionality.
 
4891
 
4892
  *Effects:* Initializes `*this` to the clear state.
4893
 
4894
  ``` cpp
4895
  bool atomic_flag_test(const volatile atomic_flag* object) noexcept;
4896
+ constexpr bool atomic_flag_test(const atomic_flag* object) noexcept;
4897
  bool atomic_flag_test_explicit(const volatile atomic_flag* object,
4898
  memory_order order) noexcept;
4899
+ constexpr bool atomic_flag_test_explicit(const atomic_flag* object,
4900
  memory_order order) noexcept;
4901
  bool atomic_flag::test(memory_order order = memory_order::seq_cst) const volatile noexcept;
4902
+ constexpr bool atomic_flag::test(memory_order order = memory_order::seq_cst) const noexcept;
4903
  ```
4904
 
4905
  For `atomic_flag_test`, let `order` be `memory_order::seq_cst`.
4906
 
4907
+ *Preconditions:* `order` is `memory_order::relaxed`,
4908
+ `memory_order::acquire`, or `memory_order::seq_cst`.
4909
 
4910
  *Effects:* Memory is affected according to the value of `order`.
4911
 
4912
  *Returns:* Atomically returns the value pointed to by `object` or
4913
  `this`.
4914
 
4915
  ``` cpp
4916
  bool atomic_flag_test_and_set(volatile atomic_flag* object) noexcept;
4917
+ constexpr bool atomic_flag_test_and_set(atomic_flag* object) noexcept;
4918
  bool atomic_flag_test_and_set_explicit(volatile atomic_flag* object, memory_order order) noexcept;
4919
+ constexpr bool atomic_flag_test_and_set_explicit(atomic_flag* object, memory_order order) noexcept;
4920
  bool atomic_flag::test_and_set(memory_order order = memory_order::seq_cst) volatile noexcept;
4921
+ constexpr bool atomic_flag::test_and_set(memory_order order = memory_order::seq_cst) noexcept;
4922
  ```
4923
 
4924
  *Effects:* Atomically sets the value pointed to by `object` or by `this`
4925
  to `true`. Memory is affected according to the value of `order`. These
4926
  operations are atomic read-modify-write
 
4929
  *Returns:* Atomically, the value of the object immediately before the
4930
  effects.
4931
 
4932
  ``` cpp
4933
  void atomic_flag_clear(volatile atomic_flag* object) noexcept;
4934
+ constexpr void atomic_flag_clear(atomic_flag* object) noexcept;
4935
  void atomic_flag_clear_explicit(volatile atomic_flag* object, memory_order order) noexcept;
4936
+ constexpr void atomic_flag_clear_explicit(atomic_flag* object, memory_order order) noexcept;
4937
  void atomic_flag::clear(memory_order order = memory_order::seq_cst) volatile noexcept;
4938
+ constexpr void atomic_flag::clear(memory_order order = memory_order::seq_cst) noexcept;
4939
  ```
4940
 
4941
+ *Preconditions:* `order` is `memory_order::relaxed`,
4942
+ `memory_order::release`, or `memory_order::seq_cst`.
 
4943
 
4944
  *Effects:* Atomically sets the value pointed to by `object` or by `this`
4945
  to `false`. Memory is affected according to the value of `order`.
4946
 
4947
  ``` cpp
4948
  void atomic_flag_wait(const volatile atomic_flag* object, bool old) noexcept;
4949
+ constexpr void atomic_flag_wait(const atomic_flag* object, bool old) noexcept;
4950
  void atomic_flag_wait_explicit(const volatile atomic_flag* object,
4951
  bool old, memory_order order) noexcept;
4952
+ constexpr void atomic_flag_wait_explicit(const atomic_flag* object,
4953
  bool old, memory_order order) noexcept;
4954
  void atomic_flag::wait(bool old, memory_order order =
4955
  memory_order::seq_cst) const volatile noexcept;
4956
+ constexpr void atomic_flag::wait(bool old, memory_order order =
4957
  memory_order::seq_cst) const noexcept;
4958
  ```
4959
 
4960
  For `atomic_flag_wait`, let `order` be `memory_order::seq_cst`. Let
4961
  `flag` be `object` for the non-member functions and `this` for the
4962
  member functions.
4963
 
4964
+ *Preconditions:* `order` is `memory_order::relaxed`,
4965
+ `memory_order::acquire`, or `memory_order::seq_cst`.
4966
 
4967
  *Effects:* Repeatedly performs the following steps, in order:
4968
 
4969
  - Evaluates `flag->test(order) != old`.
4970
  - If the result of that evaluation is `true`, returns.
 
4974
  *Remarks:* This function is an atomic waiting
4975
  operation [[atomics.wait]].
4976
 
4977
  ``` cpp
4978
  void atomic_flag_notify_one(volatile atomic_flag* object) noexcept;
4979
+ constexpr void atomic_flag_notify_one(atomic_flag* object) noexcept;
4980
  void atomic_flag::notify_one() volatile noexcept;
4981
+ constexpr void atomic_flag::notify_one() noexcept;
4982
  ```
4983
 
4984
  *Effects:* Unblocks the execution of at least one atomic waiting
4985
  operation that is eligible to be unblocked [[atomics.wait]] by this
4986
  call, if any such atomic waiting operations exist.
 
4988
  *Remarks:* This function is an atomic notifying
4989
  operation [[atomics.wait]].
4990
 
4991
  ``` cpp
4992
  void atomic_flag_notify_all(volatile atomic_flag* object) noexcept;
4993
+ constexpr void atomic_flag_notify_all(atomic_flag* object) noexcept;
4994
  void atomic_flag::notify_all() volatile noexcept;
4995
+ constexpr void atomic_flag::notify_all() noexcept;
4996
  ```
4997
 
4998
  *Effects:* Unblocks the execution of all atomic waiting operations that
4999
  are eligible to be unblocked [[atomics.wait]] by this call.
5000
 
 
5023
  Fences can have acquire semantics, release semantics, or both. A fence
5024
  with acquire semantics is called an *acquire fence*. A fence with
5025
  release semantics is called a *release fence*.
5026
 
5027
  A release fence A synchronizes with an acquire fence B if there exist
5028
+ atomic operations X and Y, where Y is not an atomic modify-write
5029
+ operation [[atomics.order]], both operating on some atomic object M,
5030
+ such that A is sequenced before X, X modifies M, Y is sequenced before
5031
+ B, and Y reads the value written by X or a value written by any side
5032
+ effect in the hypothetical release sequence X would head if it were a
5033
+ release operation.
5034
 
5035
  A release fence A synchronizes with an atomic operation B that performs
5036
  an acquire operation on an atomic object M if there exists an atomic
5037
  operation X such that A is sequenced before X, X modifies M, and B reads
5038
  the value written by X or a value written by any side effect in the
 
5044
  operation X on M such that X is sequenced before B and reads the value
5045
  written by A or a value written by any side effect in the release
5046
  sequence headed by A.
5047
 
5048
  ``` cpp
5049
+ extern "C" constexpr void atomic_thread_fence(memory_order order) noexcept;
5050
  ```
5051
 
5052
  *Effects:* Depending on the value of `order`, this operation:
5053
 
5054
  - has no effects, if `order == memory_order::relaxed`;
5055
+ - is an acquire fence, if `order == memory_order::acquire`;
 
5056
  - is a release fence, if `order == memory_order::release`;
5057
  - is both an acquire fence and a release fence, if
5058
  `order == memory_order::acq_rel`;
5059
  - is a sequentially consistent acquire and release fence, if
5060
  `order == memory_order::seq_cst`.
5061
 
5062
  ``` cpp
5063
+ extern "C" constexpr void atomic_signal_fence(memory_order order) noexcept;
5064
  ```
5065
 
5066
  *Effects:* Equivalent to `atomic_thread_fence(order)`, except that the
5067
  resulting ordering constraints are established only between a thread and
5068
  a signal handler executed in the same thread.
 
5219
  namespace std {
5220
  // [thread.mutex.class], class mutex
5221
  class mutex;
5222
  // [thread.mutex.recursive], class recursive_mutex
5223
  class recursive_mutex;
5224
+ // [thread.timedmutex.class], class timed_mutex
5225
  class timed_mutex;
5226
  // [thread.timedmutex.recursive], class recursive_timed_mutex
5227
  class recursive_timed_mutex;
5228
 
5229
  struct defer_lock_t { explicit defer_lock_t() = default; };
 
5268
  }
5269
  ```
5270
 
5271
  ### Mutex requirements <a id="thread.mutex.requirements">[[thread.mutex.requirements]]</a>
5272
 
5273
+ #### General <a id="thread.mutex.requirements.general">[[thread.mutex.requirements.general]]</a>
5274
 
5275
  A mutex object facilitates protection against data races and allows safe
5276
  synchronization of data between execution agents
5277
  [[thread.req.lockable]]. An execution agent *owns* a mutex from the time
5278
  it successfully calls one of the lock functions until it calls unlock.
 
5426
  released ownership with a call to `unlock()`.
5427
 
5428
  [*Note 4*: After a thread `A` has called `unlock()`, releasing a mutex,
5429
  it is possible for another thread `B` to lock the same mutex, observe
5430
  that it is no longer in use, unlock it, and destroy it, before thread
5431
+ `A` appears to have returned from its unlock call. Conforming
5432
+ implementations handle such scenarios correctly, as long as thread `A`
5433
+ does not access the mutex after the unlock call returns. These cases
5434
  typically occur when a reference-counted object contains a mutex that is
5435
  used to protect the reference count. — *end note*]
5436
 
5437
  The class `mutex` meets all of the mutex requirements
5438
  [[thread.mutex.requirements]]. It is a standard-layout class
 
5488
  of type `system_error`. A thread shall call `unlock()` once for each
5489
  level of ownership acquired by calls to `lock()` and `try_lock()`. Only
5490
  when all levels of ownership have been released may ownership be
5491
  acquired by another thread.
5492
 
5493
+ The behavior of a program is undefined if
5494
 
5495
  - it destroys a `recursive_mutex` object owned by any thread or
5496
  - a thread terminates while owning a `recursive_mutex` object.
5497
 
5498
  #### Timed mutex types <a id="thread.timedmutex.requirements">[[thread.timedmutex.requirements]]</a>
 
5599
 
5600
  The class `timed_mutex` meets all of the timed mutex requirements
5601
  [[thread.timedmutex.requirements]]. It is a standard-layout class
5602
  [[class.prop]].
5603
 
5604
+ The behavior of a program is undefined if
5605
 
5606
  - it destroys a `timed_mutex` object owned by any thread,
5607
  - a thread that owns a `timed_mutex` object calls `lock()`,
5608
  `try_lock()`, `try_lock_for()`, or `try_lock_until()` on that object,
5609
  or
 
5658
  `unlock()` once for each level of ownership acquired by calls to
5659
  `lock()`, `try_lock()`, `try_lock_for()`, and `try_lock_until()`. Only
5660
  when all levels of ownership have been released may ownership of the
5661
  object be acquired by another thread.
5662
 
5663
+ The behavior of a program is undefined if
5664
 
5665
  - it destroys a `recursive_timed_mutex` object owned by any thread, or
5666
  - a thread terminates while owning a `recursive_timed_mutex` object.
5667
 
5668
  #### Shared mutex types <a id="thread.sharedmutex.requirements">[[thread.sharedmutex.requirements]]</a>
 
5787
 
5788
  The class `shared_mutex` meets all of the shared mutex requirements
5789
  [[thread.sharedmutex.requirements]]. It is a standard-layout class
5790
  [[class.prop]].
5791
 
5792
+ The behavior of a program is undefined if
5793
 
5794
  - it destroys a `shared_mutex` object owned by any thread,
5795
  - a thread attempts to recursively gain any ownership of a
5796
  `shared_mutex`, or
5797
  - a thread terminates while possessing any ownership of a
 
5913
 
5914
  The class `shared_timed_mutex` meets all of the shared timed mutex
5915
  requirements [[thread.sharedtimedmutex.requirements]]. It is a
5916
  standard-layout class [[class.prop]].
5917
 
5918
+ The behavior of a program is undefined if
5919
 
5920
  - it destroys a `shared_timed_mutex` object owned by any thread,
5921
  - a thread attempts to recursively gain any ownership of a
5922
  `shared_timed_mutex`, or
5923
  - a thread terminates while possessing any ownership of a
 
6097
 
6098
  unique_lock(const unique_lock&) = delete;
6099
  unique_lock& operator=(const unique_lock&) = delete;
6100
 
6101
  unique_lock(unique_lock&& u) noexcept;
6102
+ unique_lock& operator=(unique_lock&& u) noexcept;
6103
 
6104
  // [thread.lock.unique.locking], locking
6105
  void lock();
6106
  bool try_lock();
6107
 
 
6223
  *Ensures:* `pm == u_p.pm` and `owns == u_p.owns` (where `u_p` is the
6224
  state of `u` just prior to this construction), `u.pm == 0` and
6225
  `u.owns == false`.
6226
 
6227
  ``` cpp
6228
+ unique_lock& operator=(unique_lock&& u) noexcept;
6229
  ```
6230
 
6231
+ *Effects:* Equivalent to: `unique_lock(std::move(u)).swap(*this)`
6232
 
6233
+ *Returns:* `*this`.
 
 
 
 
 
 
 
 
6234
 
6235
  ``` cpp
6236
  ~unique_lock();
6237
  ```
6238
 
 
6537
 
6538
  ``` cpp
6539
  shared_lock& operator=(shared_lock&& sl) noexcept;
6540
  ```
6541
 
6542
+ *Effects:* Equivalent to: `shared_lock(std::move(sl)).swap(*this)`
6543
 
6544
+ *Returns:* `*this`.
 
 
6545
 
6546
  ##### Locking <a id="thread.lock.shared.locking">[[thread.lock.shared.locking]]</a>
6547
 
6548
  ``` cpp
6549
  void lock();
 
6768
 
6769
  *Mandates:* `is_invocable_v<Callable, Args...>` is `true`.
6770
 
6771
  *Effects:* An execution of `call_once` that does not call its `func` is
6772
  a *passive* execution. An execution of `call_once` that calls its `func`
6773
+ is an *active* execution. An active execution evaluates *INVOKE*(
6774
  std::forward\<Callable\>(func),
6775
  std::forward\<Args\>(args)...) [[func.require]]. If such a call to
6776
  `func` throws an exception the execution is *exceptional*, otherwise it
6777
  is *returning*. An exceptional execution propagates the exception to the
6778
  caller of `call_once`. Among all executions of `call_once` for any given
 
6885
  supplied by all concurrently waiting (via `wait`, `wait_for`, or
6886
  `wait_until`) threads.
6887
 
6888
  *Effects:* Transfers ownership of the lock associated with `lk` into
6889
  internal storage and schedules `cond` to be notified when the current
6890
+ thread exits, after all objects with thread storage duration associated
6891
  with the current thread have been destroyed. This notification is
6892
  equivalent to:
6893
 
6894
  ``` cpp
6895
  lk.unlock();
 
6902
 
6903
  [*Note 1*: The supplied lock is held until the thread exits, which
6904
  might cause deadlock due to lock ordering issues. — *end note*]
6905
 
6906
  [*Note 2*: It is the user’s responsibility to ensure that waiting
6907
+ threads do not incorrectly assume that the thread has finished if they
6908
  experience spurious wakeups. This typically requires that the condition
6909
  being waited for is satisfied while holding the lock on `lk`, and that
6910
  this lock is not released and reacquired prior to calling
6911
  `notify_all_at_thread_exit`. — *end note*]
6912
 
 
7211
 
7212
  ### Class `condition_variable_any` <a id="thread.condition.condvarany">[[thread.condition.condvarany]]</a>
7213
 
7214
  #### General <a id="thread.condition.condvarany.general">[[thread.condition.condvarany.general]]</a>
7215
 
7216
+ In [[thread.condition.condvarany]], template arguments for template
7217
+ parameters named `Lock` shall meet the *Cpp17BasicLockable* requirements
7218
+ [[thread.req.lockable.basic]].
7219
 
7220
  [*Note 1*: All of the standard mutex types meet this requirement. If a
7221
  type other than one of the standard mutex types or a `unique_lock`
7222
  wrapper for a standard mutex type is used with `condition_variable_any`,
7223
  any necessary synchronization is assumed to be in place with respect to
 
7849
  ~barrier();
7850
 
7851
  barrier(const barrier&) = delete;
7852
  barrier& operator=(const barrier&) = delete;
7853
 
7854
+ arrival_token arrive(ptrdiff_t update = 1);
7855
  void wait(arrival_token&& arrival) const;
7856
 
7857
  void arrive_and_wait();
7858
  void arrive_and_drop();
7859
 
 
7937
 
7938
  *Throws:* Any exception thrown by `CompletionFunction`’s move
7939
  constructor.
7940
 
7941
  ``` cpp
7942
+ arrival_token arrive(ptrdiff_t update = 1);
7943
  ```
7944
 
7945
  *Preconditions:* `update > 0` is `true`, and `update` is less than or
7946
  equal to the expected count for the current barrier phase.
7947
 
 
8064
  template<> class promise<void>;
8065
 
8066
  template<class R>
8067
  void swap(promise<R>& x, promise<R>& y) noexcept;
8068
 
 
 
 
8069
  // [futures.unique.future], class template future
8070
  template<class R> class future;
8071
  template<class R> class future<R&>;
8072
  template<> class future<void>;
8073
 
 
8084
  template<class R, class... ArgTypes>
8085
  void swap(packaged_task<R(ArgTypes...)>&, packaged_task<R(ArgTypes...)>&) noexcept;
8086
 
8087
  // [futures.async], function template async
8088
  template<class F, class... Args>
8089
+ future<invoke_result_t<decay_t<F>, decay_t<Args>...>>
8090
  async(F&& f, Args&&... args);
8091
  template<class F, class... Args>
8092
+ future<invoke_result_t<decay_t<F>, decay_t<Args>...>>
8093
  async(launch policy, F&& f, Args&&... args);
8094
  }
8095
  ```
8096
 
8097
  The `enum` type `launch` is a bitmask type [[bitmask.types]] with
 
8189
 
8190
  An *asynchronous provider* is an object that provides a result to a
8191
  shared state. The result of a shared state is set by respective
8192
  functions on the asynchronous provider.
8193
 
8194
+ [*Example 1*: Promises and tasks are examples of asynchronous
8195
+ providers. — *end example*]
8196
 
8197
  The means of setting the result of a shared state is specified in the
8198
  description of those classes and functions that create such a state
8199
  object.
8200
 
 
8244
  [[basic.stc.thread]] is sequenced before making that shared state ready.
8245
 
8246
  Access to the result of the same shared state may conflict
8247
  [[intro.multithread]].
8248
 
8249
+ [*Note 3*: This explicitly specifies that the result of the shared
8250
  state is visible in the objects that reference this state in the sense
8251
  of data race avoidance [[res.on.data.races]]. For example, concurrent
8252
  accesses through references returned by `shared_future::get()`
8253
  [[futures.shared.future]] must either use read-only operations or
8254
  provide additional synchronization. — *end note*]
 
8281
 
8282
  // setting the result with deferred notification
8283
  void set_value_at_thread_exit(see below);
8284
  void set_exception_at_thread_exit(exception_ptr p);
8285
  };
 
 
 
8286
  }
8287
  ```
8288
 
8289
  For the primary template, `R` shall be an object type that meets the
8290
  *Cpp17Destructible* requirements.
 
8297
  The `set_value`, `set_exception`, `set_value_at_thread_exit`, and
8298
  `set_exception_at_thread_exit` member functions behave as though they
8299
  acquire a single mutex associated with the promise object while updating
8300
  the promise object.
8301
 
 
 
 
 
 
 
 
 
 
8302
  ``` cpp
8303
  promise();
8304
  template<class Allocator>
8305
  promise(allocator_arg_t, const Allocator& a);
8306
  ```
 
8415
  void promise<void>::set_value_at_thread_exit();
8416
  ```
8417
 
8418
  *Effects:* Stores the value `r` in the shared state without making that
8419
  state ready immediately. Schedules that state to be made ready when the
8420
+ current thread exits, after all objects with thread storage duration
8421
  associated with the current thread have been destroyed.
8422
 
8423
  *Throws:*
8424
 
8425
  - `future_error` if its shared state already has a stored value or
 
8441
 
8442
  *Preconditions:* `p` is not null.
8443
 
8444
  *Effects:* Stores the exception pointer `p` in the shared state without
8445
  making that state ready immediately. Schedules that state to be made
8446
+ ready when the current thread exits, after all objects with thread
8447
+ storage duration associated with the current thread have been destroyed.
8448
 
8449
  *Throws:* `future_error` if an error condition occurs.
8450
 
8451
  *Error conditions:*
8452
 
 
8474
 
8475
  [*Note 1*: Member functions of `future` do not synchronize with
8476
  themselves or with member functions of `shared_future`. — *end note*]
8477
 
8478
  The effect of calling any member function other than the destructor, the
8479
+ move assignment operator, `share`, or `valid` on a `future` object for
8480
  which `valid() == false` is undefined.
8481
 
8482
  [*Note 2*: It is valid to move from a future object for which
8483
  `valid() == false`. — *end note*]
8484
 
 
8673
 
8674
  [*Note 1*: Member functions of `shared_future` do not synchronize with
8675
  themselves, but they synchronize with the shared state. — *end note*]
8676
 
8677
  The effect of calling any member function other than the destructor, the
8678
+ move assignment operator, the copy assignment operator, or `valid()` on
8679
  a `shared_future` object for which `valid() == false` is undefined.
8680
 
8681
  [*Note 2*: It is valid to copy or move from a `shared_future` object
8682
  for which `valid()` is `false`. — *end note*]
8683
 
 
8882
  potentially in a new thread and provides the result of the function in a
8883
  `future` object with which it shares a shared state.
8884
 
8885
  ``` cpp
8886
  template<class F, class... Args>
8887
+ future<invoke_result_t<decay_t<F>, decay_t<Args>...>>
8888
  async(F&& f, Args&&... args);
8889
  template<class F, class... Args>
8890
+ future<invoke_result_t<decay_t<F>, decay_t<Args>...>>
8891
  async(launch policy, F&& f, Args&&... args);
8892
  ```
8893
 
8894
  *Mandates:* The following are all `true`:
8895
 
 
9006
  public:
9007
  // construction and destruction
9008
  packaged_task() noexcept;
9009
  template<class F>
9010
  explicit packaged_task(F&& f);
9011
+ template<class F, class Allocator>
9012
+ explicit packaged_task(allocator_arg_t, const Allocator& a, F&& f);
9013
  ~packaged_task();
9014
 
9015
  // no copy
9016
  packaged_task(const packaged_task&) = delete;
9017
  packaged_task& operator=(const packaged_task&) = delete;
 
9051
  ``` cpp
9052
  template<class F>
9053
  explicit packaged_task(F&& f);
9054
  ```
9055
 
9056
+ *Effects:* Equivalent to
9057
+ `packaged_task(allocator_arg, allocator<int>(), std::forward<F>(f))`.
9058
+
9059
+ ``` cpp
9060
+ template<class F, class Allocator>
9061
+ explicit packaged_task(allocator_arg_t, const Allocator& a, F&& f);
9062
+ ```
9063
+
9064
  *Constraints:* `remove_cvref_t<F>` is not the same type as
9065
  `packaged_task<R(ArgTypes...)>`.
9066
 
9067
+ *Mandates:* `is_invocable_r_v<R, decay_t<F>&, ArgTypes...>` is `true`.
9068
 
9069
+ *Preconditions:* `Allocator` meets the *Cpp17Allocator*
9070
+ requirements [[allocator.requirements.general]].
9071
 
9072
+ *Effects:* Let `A2` be
9073
+ `allocator_traits<Allocator>::rebind_alloc<`*`unspecified`*`>` and let
9074
+ `a2` be an object of type `A2` initialized with `A2(a)`. Constructs a
9075
+ new `packaged_task` object with a stored task of type `decay_t<F>` and a
9076
+ shared state. Initializes the object’s stored task with
9077
+ `std::forward<F>(f)`. Uses `a2` to allocate storage for the shared state
9078
+ and stores a copy of `a2` in the shared state.
9079
 
9080
+ *Throws:* Any exceptions thrown by the initialization of the stored
9081
+ task. If storage for the shared state cannot be allocated, any exception
9082
+ thrown by `A2::allocate`.
9083
 
9084
  ``` cpp
9085
  template<class F> packaged_task(F) -> packaged_task<see below>;
9086
  ```
9087
 
 
9191
  in `args...`. If the task returns normally, the return value is stored
9192
  as the asynchronous result in the shared state of `*this`, otherwise the
9193
  exception thrown by the task is stored. In either case, this is done
9194
  without making that state ready [[futures.state]] immediately. Schedules
9195
  the shared state to be made ready when the current thread exits, after
9196
+ all objects with thread storage duration associated with the current
9197
  thread have been destroyed.
9198
 
9199
  *Throws:* `future_error` if an error condition occurs.
9200
 
9201
  *Error conditions:*
 
9206
 
9207
  ``` cpp
9208
  void reset();
9209
  ```
9210
 
9211
+ *Effects:* Equivalent to:
9212
+
9213
+ ``` cpp
9214
+ if (!valid()) {
9215
+ throw future_error(future_errc::no_state);
9216
+ }
9217
+ *this = packaged_task(allocator_arg, a, std::move(f));
9218
+ ```
9219
+
9220
+ where `f` is the task stored in `*this` and `a` is the allocator stored
9221
+ in the shared state.
9222
 
9223
  [*Note 2*: This constructs a new shared state for `*this`. The old
9224
  state is abandoned [[futures.state]]. — *end note*]
9225
 
9226
  *Throws:*
9227
 
9228
+ - Any exception thrown by the `packaged_task` constructor.
 
 
9229
  - `future_error` with an error condition of `no_state` if `*this` has no
9230
  shared state.
9231
 
9232
  #### Globals <a id="futures.task.nonmembers">[[futures.task.nonmembers]]</a>
9233
 
 
9236
  void swap(packaged_task<R(ArgTypes...)>& x, packaged_task<R(ArgTypes...)>& y) noexcept;
9237
  ```
9238
 
9239
  *Effects:* As if by `x.swap(y)`.
9240
 
9241
+ ## Safe reclamation <a id="saferecl">[[saferecl]]</a>
9242
+
9243
+ ### General <a id="saferecl.general">[[saferecl.general]]</a>
9244
+
9245
+ Subclause [[saferecl]] contains safe-reclamation techniques, which are
9246
+ most frequently used to straightforwardly resolve access-deletion races.
9247
+
9248
+ ### Read-copy update (RCU) <a id="saferecl.rcu">[[saferecl.rcu]]</a>
9249
+
9250
+ #### General <a id="saferecl.rcu.general">[[saferecl.rcu.general]]</a>
9251
+
9252
+ RCU is a synchronization mechanism that can be used for linked data
9253
+ structures that are frequently read, but seldom updated. RCU does not
9254
+ provide mutual exclusion, but instead allows the user to schedule
9255
+ specified actions such as deletion at some later time.
9256
+
9257
+ A class type `T` is *rcu-protectable* if it has exactly one base class
9258
+ of type `rcu_obj_base<T, D>` for some `D`, and that base is public and
9259
+ non-virtual, and it has no base classes of type `rcu_obj_base<X, Y>` for
9260
+ any other combination `X`, `Y`. An object is rcu-protectable if it is of
9261
+ rcu-protectable type.
9262
+
9263
+ An invocation of `unlock` U on an `rcu_domain dom` corresponds to an
9264
+ invocation of `lock` L on `dom` if L is sequenced before U and either
9265
+
9266
+ - no other invocation of `lock` on `dom` is sequenced after L and before
9267
+ U, or
9268
+ - every invocation of `unlock` U2 on `dom` such that L is sequenced
9269
+ before U2 and U2 is sequenced before U corresponds to an invocation of
9270
+ `lock` L2 on `dom` such that L is sequenced before L2 and L2 is
9271
+ sequenced before U2.
9272
+
9273
+ [*Note 1*: This pairs nested locks and unlocks on a given domain in
9274
+ each thread. — *end note*]
9275
+
9276
+ A *region of RCU protection* on a domain `dom` starts with a `lock` L on
9277
+ `dom` and ends with its corresponding `unlock` U.
9278
+
9279
+ Given a region of RCU protection R on a domain `dom` and given an
9280
+ evaluation E that scheduled another evaluation F in `dom`, if E does not
9281
+ strongly happen before the start of R, the end of R strongly happens
9282
+ before evaluating F.
9283
+
9284
+ The evaluation of a scheduled evaluation is potentially concurrent with
9285
+ any other scheduled evaluation. Each scheduled evaluation is evaluated
9286
+ at most once.
9287
+
9288
+ #### Header `<rcu>` synopsis <a id="rcu.syn">[[rcu.syn]]</a>
9289
+
9290
+ ``` cpp
9291
+ namespace std {
9292
+ // [saferecl.rcu.base], class template rcu_obj_base
9293
+ template<class T, class D = default_delete<T>> class rcu_obj_base;
9294
+
9295
+ // [saferecl.rcu.domain], class rcu_domain
9296
+ class rcu_domain;
9297
+
9298
+ // [saferecl.rcu.domain.func], non-member functions
9299
+ rcu_domain& rcu_default_domain() noexcept;
9300
+ void rcu_synchronize(rcu_domain& dom = rcu_default_domain()) noexcept;
9301
+ void rcu_barrier(rcu_domain& dom = rcu_default_domain()) noexcept;
9302
+ template<class T, class D = default_delete<T>>
9303
+ void rcu_retire(T* p, D d = D(), rcu_domain& dom = rcu_default_domain());
9304
+ }
9305
+ ```
9306
+
9307
+ #### Class template `rcu_obj_base` <a id="saferecl.rcu.base">[[saferecl.rcu.base]]</a>
9308
+
9309
+ Objects of type `T` to be protected by RCU inherit from a specialization
9310
+ `rcu_obj_base<T, D>` for some `D`.
9311
+
9312
+ ``` cpp
9313
+ namespace std {
9314
+ template<class T, class D = default_delete<T>>
9315
+ class rcu_obj_base {
9316
+ public:
9317
+ void retire(D d = D(), rcu_domain& dom = rcu_default_domain()) noexcept;
9318
+ protected:
9319
+ rcu_obj_base() = default;
9320
+ rcu_obj_base(const rcu_obj_base&) = default;
9321
+ rcu_obj_base(rcu_obj_base&&) = default;
9322
+ rcu_obj_base& operator=(const rcu_obj_base&) = default;
9323
+ rcu_obj_base& operator=(rcu_obj_base&&) = default;
9324
+ ~rcu_obj_base() = default;
9325
+ private:
9326
+ D deleter; // exposition only
9327
+ };
9328
+ }
9329
+ ```
9330
+
9331
+ The behavior of a program that adds specializations for `rcu_obj_base`
9332
+ is undefined.
9333
+
9334
+ `T` may be an incomplete type. It shall be complete before any member of
9335
+ the resulting specialization of `rcu_obj_base` is referenced.
9336
+
9337
+ `D` shall be a function object type [[function.objects]] for which,
9338
+ given a value `d` of type `D` and a value `ptr` of type `T*`, the
9339
+ expression `d(ptr)` is valid.
9340
+
9341
+ `D` shall meet the requirements for *Cpp17DefaultConstructible* and
9342
+ *Cpp17MoveAssignable*.
9343
+
9344
+ If `D` is trivially copyable, all specializations of
9345
+ `rcu_obj_base<T, D>` are trivially copyable.
9346
+
9347
+ ``` cpp
9348
+ void retire(D d = D(), rcu_domain& dom = rcu_default_domain()) noexcept;
9349
+ ```
9350
+
9351
+ *Mandates:* `T` is an rcu-protectable type.
9352
+
9353
+ *Preconditions:* `*this` is a base class subobject of an object `x` of
9354
+ type `T`. The member function `rcu_obj_base<T, D>::retire` was not
9355
+ invoked on `x` before. The assignment to *deleter* does not exit via an
9356
+ exception.
9357
+
9358
+ *Effects:* Evaluates *`deleter`*` = std::move(d)` and schedules the
9359
+ evaluation of the expression *`deleter`*`( addressof(x))` in the domain
9360
+ `dom`; the behavior is undefined if that evaluation exits via an
9361
+ exception. May invoke scheduled evaluations in `dom`.
9362
+
9363
+ [*Note 1*: If such evaluations acquire resources held across any
9364
+ invocation of `retire` on `dom`, deadlock can occur. — *end note*]
9365
+
9366
+ #### Class `rcu_domain` <a id="saferecl.rcu.domain">[[saferecl.rcu.domain]]</a>
9367
+
9368
+ ##### General <a id="saferecl.rcu.domain.general">[[saferecl.rcu.domain.general]]</a>
9369
+
9370
+ ``` cpp
9371
+ namespace std {
9372
+ class rcu_domain {
9373
+ public:
9374
+ rcu_domain(const rcu_domain&) = delete;
9375
+ rcu_domain& operator=(const rcu_domain&) = delete;
9376
+
9377
+ void lock() noexcept;
9378
+ bool try_lock() noexcept;
9379
+ void unlock() noexcept;
9380
+ };
9381
+ }
9382
+ ```
9383
+
9384
+ This class meets the requirements of *Cpp17Lockable*
9385
+ [[thread.req.lockable.req]] and provides regions of RCU protection.
9386
+
9387
+ [*Example 1*:
9388
+
9389
+ ``` cpp
9390
+ std::scoped_lock<rcu_domain> rlock(rcu_default_domain());
9391
+ ```
9392
+
9393
+ — *end example*]
9394
+
9395
+ The functions `lock` and `unlock` establish (possibly nested) regions of
9396
+ RCU protection.
9397
+
9398
+ ##### Member functions <a id="saferecl.rcu.domain.members">[[saferecl.rcu.domain.members]]</a>
9399
+
9400
+ ``` cpp
9401
+ void lock() noexcept;
9402
+ ```
9403
+
9404
+ *Effects:* Opens a region of RCU protection.
9405
+
9406
+ *Remarks:* Calls to `lock` do not introduce a data race [[intro.races]]
9407
+ involving `*this`.
9408
+
9409
+ ``` cpp
9410
+ bool try_lock() noexcept;
9411
+ ```
9412
+
9413
+ *Effects:* Equivalent to `lock()`.
9414
+
9415
+ *Returns:* `true`.
9416
+
9417
+ ``` cpp
9418
+ void unlock() noexcept;
9419
+ ```
9420
+
9421
+ *Preconditions:* A call to `lock` that opened an unclosed region of RCU
9422
+ protection is sequenced before the call to `unlock`.
9423
+
9424
+ *Effects:* Closes the unclosed region of RCU protection that was most
9425
+ recently opened. May invoke scheduled evaluations in `*this`.
9426
+
9427
+ [*Note 1*: If such evaluations acquire resources held across any
9428
+ invocation of `unlock` on `*this`, deadlock can occur. — *end note*]
9429
+
9430
+ *Remarks:* Calls to `unlock` do not introduce a data race involving
9431
+ `*this`.
9432
+
9433
+ [*Note 2*: Evaluation of scheduled evaluations can still cause a data
9434
+ race. — *end note*]
9435
+
9436
+ ##### Non-member functions <a id="saferecl.rcu.domain.func">[[saferecl.rcu.domain.func]]</a>
9437
+
9438
+ ``` cpp
9439
+ rcu_domain& rcu_default_domain() noexcept;
9440
+ ```
9441
+
9442
+ *Returns:* A reference to a static-duration object of type `rcu_domain`.
9443
+ A reference to the same object is returned every time this function is
9444
+ called.
9445
+
9446
+ ``` cpp
9447
+ void rcu_synchronize(rcu_domain& dom = rcu_default_domain()) noexcept;
9448
+ ```
9449
+
9450
+ *Effects:* If the call to `rcu_synchronize` does not strongly happen
9451
+ before the lock opening an RCU protection region `R` on `dom`, blocks
9452
+ until the `unlock` closing `R` happens.
9453
+
9454
+ *Synchronization:* The `unlock` closing `R` strongly happens before the
9455
+ return from `rcu_synchronize`.
9456
+
9457
+ ``` cpp
9458
+ void rcu_barrier(rcu_domain& dom = rcu_default_domain()) noexcept;
9459
+ ```
9460
+
9461
+ *Effects:* May evaluate any scheduled evaluations in `dom`. For any
9462
+ evaluation that happens before the call to `rcu_barrier` and that
9463
+ schedules an evaluation E in `dom`, blocks until E has been evaluated.
9464
+
9465
+ *Synchronization:* The evaluation of any such E strongly happens before
9466
+ the return from `rcu_barrier`.
9467
+
9468
+ [*Note 3*: A call to `rcu_barrier` does not imply a call to
9469
+ `rcu_synchronize` and vice versa. — *end note*]
9470
+
9471
+ ``` cpp
9472
+ template<class T, class D = default_delete<T>>
9473
+ void rcu_retire(T* p, D d = D(), rcu_domain& dom = rcu_default_domain());
9474
+ ```
9475
+
9476
+ *Mandates:* `is_move_constructible_v<D>` is `true` and the expression
9477
+ `d(p)` is well-formed.
9478
+
9479
+ *Preconditions:* `D` meets the *Cpp17MoveConstructible* and
9480
+ *Cpp17Destructible* requirements.
9481
+
9482
+ *Effects:* May allocate memory. It is unspecified whether the memory
9483
+ allocation is performed by invoking `operator new`. Initializes an
9484
+ object `d1` of type `D` from `std::move(d)`. Schedules the evaluation of
9485
+ `d1(p)` in the domain `dom`; the behavior is undefined if that
9486
+ evaluation exits via an exception. May invoke scheduled evaluations in
9487
+ `dom`.
9488
+
9489
+ [*Note 4*: If `rcu_retire` exits via an exception, no evaluation is
9490
+ scheduled. — *end note*]
9491
+
9492
+ *Throws:* `bad_alloc` or any exception thrown by the initialization of
9493
+ `d1`.
9494
+
9495
+ [*Note 5*: If scheduled evaluations acquire resources held across any
9496
+ invocation of `rcu_retire` on `dom`, deadlock can occur. — *end note*]
9497
+
9498
+ ### Hazard pointers <a id="saferecl.hp">[[saferecl.hp]]</a>
9499
+
9500
+ #### General <a id="saferecl.hp.general">[[saferecl.hp.general]]</a>
9501
+
9502
+ A hazard pointer is a single-writer multi-reader pointer that can be
9503
+ owned by at most one thread at any time. Only the owner of the hazard
9504
+ pointer can set its value, while any number of threads may read its
9505
+ value. The owner thread sets the value of a hazard pointer to point to
9506
+ an object in order to indicate to concurrent threads—which may delete
9507
+ such an object—that the object is not yet safe to delete.
9508
+
9509
+ A class type `T` is *hazard-protectable* if it has exactly one base
9510
+ class of type `hazard_pointer_obj_base<T, D>` for some `D`, that base is
9511
+ public and non-virtual, and it has no base classes of type
9512
+ `hazard_pointer_obj_base<T2, D2>` for any other combination `T2`, `D2`.
9513
+ An object is *hazard-protectable* if it is of hazard-protectable type.
9514
+
9515
+ The time span between creation and destruction of a hazard pointer h is
9516
+ partitioned into a series of *protection epochs*; in each protection
9517
+ epoch, h either is *associated with* a hazard-protectable object, or is
9518
+ *unassociated*. Upon creation, a hazard pointer is unassociated.
9519
+ Changing the association (possibly to the same object) initiates a new
9520
+ protection epoch and ends the preceding one.
9521
+
9522
+ An object `x` of hazard-protectable type `T` is *retired* with a deleter
9523
+ of type `D` when the member function
9524
+ `hazard_pointer_obj_base<T, D>::retire` is invoked on `x`. Any given
9525
+ object `x` shall be retired at most once.
9526
+
9527
+ A retired object `x` is *reclaimed* by invoking its deleter with a
9528
+ pointer to `x`; the behavior is undefined if that invocation exits via
9529
+ an exception.
9530
+
9531
+ A hazard-protectable object `x` is *possibly-reclaimable* with respect
9532
+ to an evaluation A if
9533
+
9534
+ - `x` is not reclaimed; and
9535
+ - `x` is retired in an evaluation R and A does not happen before R; and
9536
+ - for all hazard pointers h and for every protection epoch E of h during
9537
+ which h is associated with `x`:
9538
+ - if the beginning of E happens before R, the end of E strongly
9539
+ happens before A; and
9540
+ - if E began by an evaluation of `try_protect` with argument `src`,
9541
+ label its atomic load operation L. If there exists an atomic
9542
+ modification B on `src` such that L observes a modification that is
9543
+ modification-ordered before B, and B happens before `x` is retired,
9544
+ the end of E strongly happens before A. \[*Note 1*: In typical use,
9545
+ a store to `src` sequenced before retiring `x` will be such an
9546
+ atomic operation B. — *end note*]
9547
+
9548
+ \[*Note 2*: The latter two conditions convey the informal notion that
9549
+ a protection epoch that began before retiring `x`, as implied either
9550
+ by the happens-before relation or the coherence order of some source,
9551
+ delays the reclamation of `x`. — *end note*]
9552
+
9553
+ The number of possibly-reclaimable objects has an unspecified bound.
9554
+
9555
+ [*Note 3*: The bound can be a function of the number of hazard
9556
+ pointers, the number of threads that retire objects, and the number of
9557
+ threads that use hazard pointers. — *end note*]
9558
+
9559
+ [*Example 1*:
9560
+
9561
+ The following example shows how hazard pointers allow updates to be
9562
+ carried out in the presence of concurrent readers. The object of type
9563
+ `hazard_pointer` in `print_name` protects the object `*ptr` from being
9564
+ reclaimed by `ptr->retire` until the end of the protection epoch.
9565
+
9566
+ ``` cpp
9567
+ struct Name : public hazard_pointer_obj_base<Name> { /* details */ };
9568
+ atomic<Name*> name;
9569
+ // called often and in parallel!
9570
+ void print_name() {
9571
+ hazard_pointer h = make_hazard_pointer();
9572
+ Name* ptr = h.protect(name); // Protection epoch starts
9573
+ // ... safe to access *ptr
9574
+ } // Protection epoch ends.
9575
+
9576
+ // called rarely, but possibly concurrently with print_name
9577
+ void update_name(Name* new_name) {
9578
+ Name* ptr = name.exchange(new_name);
9579
+ ptr->retire();
9580
+ }
9581
+ ```
9582
+
9583
+ — *end example*]
9584
+
9585
+ #### Header `<hazard_pointer>` synopsis <a id="hazard.pointer.syn">[[hazard.pointer.syn]]</a>
9586
+
9587
+ ``` cpp
9588
+ namespace std {
9589
+ // [saferecl.hp.base], class template hazard_pointer_obj_base
9590
+ template<class T, class D = default_delete<T>> class hazard_pointer_obj_base;
9591
+
9592
+ // [saferecl.hp.holder], class hazard_pointer
9593
+ class hazard_pointer;
9594
+
9595
+ // [saferecl.hp.holder.nonmem], non-member functions
9596
+ hazard_pointer make_hazard_pointer();
9597
+ void swap(hazard_pointer&, hazard_pointer&) noexcept;
9598
+ }
9599
+ ```
9600
+
9601
+ #### Class template `hazard_pointer_obj_base` <a id="saferecl.hp.base">[[saferecl.hp.base]]</a>
9602
+
9603
+ ``` cpp
9604
+ namespace std {
9605
+ template<class T, class D = default_delete<T>>
9606
+ class hazard_pointer_obj_base {
9607
+ public:
9608
+ void retire(D d = D()) noexcept;
9609
+ protected:
9610
+ hazard_pointer_obj_base() = default;
9611
+ hazard_pointer_obj_base(const hazard_pointer_obj_base&) = default;
9612
+ hazard_pointer_obj_base(hazard_pointer_obj_base&&) = default;
9613
+ hazard_pointer_obj_base& operator=(const hazard_pointer_obj_base&) = default;
9614
+ hazard_pointer_obj_base& operator=(hazard_pointer_obj_base&&) = default;
9615
+ ~hazard_pointer_obj_base() = default;
9616
+ private:
9617
+ D deleter; // exposition only
9618
+ };
9619
+ }
9620
+ ```
9621
+
9622
+ `D` shall be a function object type [[func.require]] for which, given a
9623
+ value `d` of type `D` and a value `ptr` of type `T*`, the expression
9624
+ `d(ptr)` is valid.
9625
+
9626
+ The behavior of a program that adds specializations for
9627
+ `hazard_pointer_obj_base` is undefined.
9628
+
9629
+ `D` shall meet the requirements for *Cpp17DefaultConstructible* and
9630
+ *Cpp17MoveAssignable*.
9631
+
9632
+ `T` may be an incomplete type. It shall be complete before any member of
9633
+ the resulting specialization of `hazard_pointer_obj_base` is referenced.
9634
+
9635
+ ``` cpp
9636
+ void retire(D d = D()) noexcept;
9637
+ ```
9638
+
9639
+ *Mandates:* `T` is a hazard-protectable type.
9640
+
9641
+ *Preconditions:* `*this` is a base class subobject of an object `x` of
9642
+ type `T`. `x` is not retired. Move-assigning `d` to `deleter` does not
9643
+ exit via an exception.
9644
+
9645
+ *Effects:* Move-assigns `d` to `deleter`, thereby setting it as the
9646
+ deleter of `x`, then retires `x`. May reclaim possibly-reclaimable
9647
+ objects.
9648
+
9649
+ #### Class `hazard_pointer` <a id="saferecl.hp.holder">[[saferecl.hp.holder]]</a>
9650
+
9651
+ ##### General <a id="saferecl.hp.holder.general">[[saferecl.hp.holder.general]]</a>
9652
+
9653
+ ``` cpp
9654
+ namespace std {
9655
+ class hazard_pointer {
9656
+ public:
9657
+ hazard_pointer() noexcept;
9658
+ hazard_pointer(hazard_pointer&&) noexcept;
9659
+ hazard_pointer& operator=(hazard_pointer&&) noexcept;
9660
+ ~hazard_pointer();
9661
+
9662
+ bool empty() const noexcept;
9663
+ template<class T> T* protect(const atomic<T*>& src) noexcept;
9664
+ template<class T> bool try_protect(T*& ptr, const atomic<T*>& src) noexcept;
9665
+ template<class T> void reset_protection(const T* ptr) noexcept;
9666
+ void reset_protection(nullptr_t = nullptr) noexcept;
9667
+ void swap(hazard_pointer&) noexcept;
9668
+ };
9669
+ }
9670
+ ```
9671
+
9672
+ An object of type `hazard_pointer` is either empty or *owns* a hazard
9673
+ pointer. Each hazard pointer is owned by exactly one object of type
9674
+ `hazard_pointer`.
9675
+
9676
+ [*Note 1*: An empty `hazard_pointer` object is different from a
9677
+ `hazard_pointer` object that owns an unassociated hazard pointer. An
9678
+ empty `hazard_pointer` object does not own any hazard
9679
+ pointers. — *end note*]
9680
+
9681
+ ##### Constructors, destructor, and assignment <a id="saferecl.hp.holder.ctor">[[saferecl.hp.holder.ctor]]</a>
9682
+
9683
+ ``` cpp
9684
+ hazard_pointer() noexcept;
9685
+ ```
9686
+
9687
+ *Ensures:* `*this` is empty.
9688
+
9689
+ ``` cpp
9690
+ hazard_pointer(hazard_pointer&& other) noexcept;
9691
+ ```
9692
+
9693
+ *Ensures:* If `other` is empty, `*this` is empty. Otherwise, `*this`
9694
+ owns the hazard pointer originally owned by `other`; `other` is empty.
9695
+
9696
+ ``` cpp
9697
+ ~hazard_pointer();
9698
+ ```
9699
+
9700
+ *Effects:* If `*this` is not empty, destroys the hazard pointer owned by
9701
+ `*this`, thereby ending its current protection epoch.
9702
+
9703
+ ``` cpp
9704
+ hazard_pointer& operator=(hazard_pointer&& other) noexcept;
9705
+ ```
9706
+
9707
+ *Effects:* If `this == &other` is `true`, no effect. Otherwise, if
9708
+ `*this` is not empty, destroys the hazard pointer owned by `*this`,
9709
+ thereby ending its current protection epoch.
9710
+
9711
+ *Ensures:* If `other` was empty, `*this` is empty. Otherwise, `*this`
9712
+ owns the hazard pointer originally owned by `other`. If `this != &other`
9713
+ is `true`, `other` is empty.
9714
+
9715
+ *Returns:* `*this`.
9716
+
9717
+ ##### Member functions <a id="saferecl.hp.holder.mem">[[saferecl.hp.holder.mem]]</a>
9718
+
9719
+ ``` cpp
9720
+ bool empty() const noexcept;
9721
+ ```
9722
+
9723
+ *Returns:* `true` if and only if `*this` is empty.
9724
+
9725
+ ``` cpp
9726
+ template<class T> T* protect(const atomic<T*>& src) noexcept;
9727
+ ```
9728
+
9729
+ *Effects:* Equivalent to:
9730
+
9731
+ ``` cpp
9732
+ T* ptr = src.load(memory_order::relaxed);
9733
+ while (!try_protect(ptr, src)) {}
9734
+ return ptr;
9735
+ ```
9736
+
9737
+ ``` cpp
9738
+ template<class T> bool try_protect(T*& ptr, const atomic<T*>& src) noexcept;
9739
+ ```
9740
+
9741
+ *Mandates:* `T` is a hazard-protectable type.
9742
+
9743
+ *Preconditions:* `*this` is not empty.
9744
+
9745
+ *Effects:* Performs the following steps in order:
9746
+
9747
+ - Initializes a variable `old` of type `T*` with the value of `ptr`.
9748
+ - Evaluates `reset_protection(old)`.
9749
+ - Assigns the value of `src.load(memory_order::acquire)` to `ptr`.
9750
+ - If `old == ptr` is `false`, evaluates `reset_protection()`.
9751
+
9752
+ *Returns:* `old == ptr`.
9753
+
9754
+ ``` cpp
9755
+ template<class T> void reset_protection(const T* ptr) noexcept;
9756
+ ```
9757
+
9758
+ *Mandates:* `T` is a hazard-protectable type.
9759
+
9760
+ *Preconditions:* `*this` is not empty.
9761
+
9762
+ *Effects:* If `ptr` is a null pointer value, invokes
9763
+ `reset_protection()`. Otherwise, associates the hazard pointer owned by
9764
+ `*this` with `*ptr`, thereby ending the current protection epoch.
9765
+
9766
+ *Complexity:* Constant.
9767
+
9768
+ ``` cpp
9769
+ void reset_protection(nullptr_t = nullptr) noexcept;
9770
+ ```
9771
+
9772
+ *Preconditions:* `*this` is not empty.
9773
+
9774
+ *Ensures:* The hazard pointer owned by `*this` is unassociated.
9775
+
9776
+ *Complexity:* Constant.
9777
+
9778
+ ``` cpp
9779
+ void swap(hazard_pointer& other) noexcept;
9780
+ ```
9781
+
9782
+ *Effects:* Swaps the hazard pointer ownership of this object with that
9783
+ of `other`.
9784
+
9785
+ [*Note 1*: The owned hazard pointers, if any, remain unchanged during
9786
+ the swap and continue to be associated with the respective objects that
9787
+ they were protecting before the swap, if any. No protection epochs are
9788
+ ended or initiated. — *end note*]
9789
+
9790
+ *Complexity:* Constant.
9791
+
9792
+ ##### Non-member functions <a id="saferecl.hp.holder.nonmem">[[saferecl.hp.holder.nonmem]]</a>
9793
+
9794
+ ``` cpp
9795
+ hazard_pointer make_hazard_pointer();
9796
+ ```
9797
+
9798
+ *Effects:* Constructs a hazard pointer.
9799
+
9800
+ *Returns:* A `hazard_pointer` object that owns the newly-constructed
9801
+ hazard pointer.
9802
+
9803
+ *Throws:* May throw `bad_alloc` if memory for the hazard pointer could
9804
+ not be allocated.
9805
+
9806
+ ``` cpp
9807
+ void swap(hazard_pointer& a, hazard_pointer& b) noexcept;
9808
+ ```
9809
+
9810
+ *Effects:* Equivalent to `a.swap(b)`.
9811
+
9812
  <!-- Link reference definitions -->
9813
+ [alg.min.max]: algorithms.md#alg.min.max
9814
  [alg.sorting]: algorithms.md#alg.sorting
9815
  [allocator.requirements.general]: library.md#allocator.requirements.general
9816
  [atomic.types.int.comp]: #atomic.types.int.comp
9817
  [atomic.types.pointer.comp]: #atomic.types.pointer.comp
9818
  [atomics]: #atomics
 
9841
  [atomics.wait]: #atomics.wait
9842
  [barrier.syn]: #barrier.syn
9843
  [basic.align]: basic.md#basic.align
9844
  [basic.fundamental]: basic.md#basic.fundamental
9845
  [basic.life]: basic.md#basic.life
9846
+ [basic.stc.general]: basic.md#basic.stc.general
9847
  [basic.stc.thread]: basic.md#basic.stc.thread
9848
  [bitmask.types]: library.md#bitmask.types
9849
  [cfenv]: numerics.md#cfenv
9850
  [class.prop]: class.md#class.prop
9851
  [compliance]: library.md#compliance
9852
  [concept.booleantestable]: concepts.md#concept.booleantestable
9853
  [condition.variable.syn]: #condition.variable.syn
9854
  [conv.rval]: expr.md#conv.rval
9855
  [cpp17.defaultconstructible]: #cpp17.defaultconstructible
9856
  [cpp17.destructible]: #cpp17.destructible
9857
+ [cpp17.lessthancomparable]: #cpp17.lessthancomparable
9858
  [cpp17.moveassignable]: #cpp17.moveassignable
9859
  [cpp17.moveconstructible]: #cpp17.moveconstructible
9860
  [defns.block]: intro.md#defns.block
9861
  [except.terminate]: except.md#except.terminate
9862
  [expr.pre]: expr.md#expr.pre
9863
+ [expr.rel]: expr.md#expr.rel
9864
+ [format.string.std]: text.md#format.string.std
9865
  [func.invoke]: utilities.md#func.invoke
9866
  [func.require]: utilities.md#func.require
9867
  [function.objects]: utilities.md#function.objects
9868
  [future.syn]: #future.syn
9869
  [futures]: #futures
 
9877
  [futures.task]: #futures.task
9878
  [futures.task.general]: #futures.task.general
9879
  [futures.task.members]: #futures.task.members
9880
  [futures.task.nonmembers]: #futures.task.nonmembers
9881
  [futures.unique.future]: #futures.unique.future
9882
+ [hazard.pointer.syn]: #hazard.pointer.syn
9883
  [intro.multithread]: basic.md#intro.multithread
9884
  [intro.progress]: basic.md#intro.progress
9885
  [intro.races]: basic.md#intro.races
9886
  [latch.syn]: #latch.syn
9887
  [limits.syn]: support.md#limits.syn
9888
  [mutex.syn]: #mutex.syn
9889
+ [rcu.syn]: #rcu.syn
9890
  [res.on.data.races]: library.md#res.on.data.races
9891
  [res.on.exception.handling]: library.md#res.on.exception.handling
9892
+ [saferecl]: #saferecl
9893
+ [saferecl.general]: #saferecl.general
9894
+ [saferecl.hp]: #saferecl.hp
9895
+ [saferecl.hp.base]: #saferecl.hp.base
9896
+ [saferecl.hp.general]: #saferecl.hp.general
9897
+ [saferecl.hp.holder]: #saferecl.hp.holder
9898
+ [saferecl.hp.holder.ctor]: #saferecl.hp.holder.ctor
9899
+ [saferecl.hp.holder.general]: #saferecl.hp.holder.general
9900
+ [saferecl.hp.holder.mem]: #saferecl.hp.holder.mem
9901
+ [saferecl.hp.holder.nonmem]: #saferecl.hp.holder.nonmem
9902
+ [saferecl.rcu]: #saferecl.rcu
9903
+ [saferecl.rcu.base]: #saferecl.rcu.base
9904
+ [saferecl.rcu.domain]: #saferecl.rcu.domain
9905
+ [saferecl.rcu.domain.func]: #saferecl.rcu.domain.func
9906
+ [saferecl.rcu.domain.general]: #saferecl.rcu.domain.general
9907
+ [saferecl.rcu.domain.members]: #saferecl.rcu.domain.members
9908
+ [saferecl.rcu.general]: #saferecl.rcu.general
9909
  [semaphore.syn]: #semaphore.syn
9910
  [shared.mutex.syn]: #shared.mutex.syn
9911
  [stdatomic.h.syn]: #stdatomic.h.syn
9912
  [stopcallback]: #stopcallback
9913
  [stopcallback.cons]: #stopcallback.cons
9914
  [stopcallback.general]: #stopcallback.general
9915
+ [stopcallback.inplace]: #stopcallback.inplace
9916
+ [stopcallback.inplace.cons]: #stopcallback.inplace.cons
9917
+ [stopcallback.inplace.general]: #stopcallback.inplace.general
9918
  [stopsource]: #stopsource
9919
  [stopsource.cons]: #stopsource.cons
9920
  [stopsource.general]: #stopsource.general
9921
+ [stopsource.inplace]: #stopsource.inplace
9922
+ [stopsource.inplace.cons]: #stopsource.inplace.cons
9923
+ [stopsource.inplace.general]: #stopsource.inplace.general
9924
+ [stopsource.inplace.mem]: #stopsource.inplace.mem
9925
  [stopsource.mem]: #stopsource.mem
 
9926
  [stoptoken]: #stoptoken
9927
+ [stoptoken.concepts]: #stoptoken.concepts
9928
  [stoptoken.general]: #stoptoken.general
9929
+ [stoptoken.inplace]: #stoptoken.inplace
9930
+ [stoptoken.inplace.general]: #stoptoken.inplace.general
9931
+ [stoptoken.inplace.mem]: #stoptoken.inplace.mem
9932
  [stoptoken.mem]: #stoptoken.mem
9933
+ [stoptoken.never]: #stoptoken.never
9934
  [syserr]: diagnostics.md#syserr
9935
  [syserr.syserr]: diagnostics.md#syserr.syserr
9936
  [term.padding.bits]: basic.md#term.padding.bits
9937
  [term.unevaluated.operand]: expr.md#term.unevaluated.operand
9938
  [thread]: #thread