From Jason Turner

[thread.mutex]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmp0a_rdupc/{from.md → to.md} +17 -27
tmp/tmp0a_rdupc/{from.md → to.md} RENAMED
@@ -12,11 +12,11 @@ race-free programs [[intro.multithread]].
12
  namespace std {
13
  // [thread.mutex.class], class mutex
14
  class mutex;
15
  // [thread.mutex.recursive], class recursive_mutex
16
  class recursive_mutex;
17
- // [thread.timedmutex.class] class timed_mutex
18
  class timed_mutex;
19
  // [thread.timedmutex.recursive], class recursive_timed_mutex
20
  class recursive_timed_mutex;
21
 
22
  struct defer_lock_t { explicit defer_lock_t() = default; };
@@ -61,11 +61,11 @@ namespace std {
61
  }
62
  ```
63
 
64
  ### Mutex requirements <a id="thread.mutex.requirements">[[thread.mutex.requirements]]</a>
65
 
66
- #### In general <a id="thread.mutex.requirements.general">[[thread.mutex.requirements.general]]</a>
67
 
68
  A mutex object facilitates protection against data races and allows safe
69
  synchronization of data between execution agents
70
  [[thread.req.lockable]]. An execution agent *owns* a mutex from the time
71
  it successfully calls one of the lock functions until it calls unlock.
@@ -219,13 +219,13 @@ another thread to acquire ownership of that object will fail (for
219
  released ownership with a call to `unlock()`.
220
 
221
  [*Note 4*: After a thread `A` has called `unlock()`, releasing a mutex,
222
  it is possible for another thread `B` to lock the same mutex, observe
223
  that it is no longer in use, unlock it, and destroy it, before thread
224
- `A` appears to have returned from its unlock call. Implementations are
225
- required to handle such scenarios correctly, as long as thread `A`
226
- doesn’t access the mutex after the unlock call returns. These cases
227
  typically occur when a reference-counted object contains a mutex that is
228
  used to protect the reference count. — *end note*]
229
 
230
  The class `mutex` meets all of the mutex requirements
231
  [[thread.mutex.requirements]]. It is a standard-layout class
@@ -281,11 +281,11 @@ ownership for a `recursive_mutex` object, additional calls to
281
  of type `system_error`. A thread shall call `unlock()` once for each
282
  level of ownership acquired by calls to `lock()` and `try_lock()`. Only
283
  when all levels of ownership have been released may ownership be
284
  acquired by another thread.
285
 
286
- The behavior of a program is undefined if:
287
 
288
  - it destroys a `recursive_mutex` object owned by any thread or
289
  - a thread terminates while owning a `recursive_mutex` object.
290
 
291
  #### Timed mutex types <a id="thread.timedmutex.requirements">[[thread.timedmutex.requirements]]</a>
@@ -392,11 +392,11 @@ a call to `unlock()` or the call to `try_lock_for()` or
392
 
393
  The class `timed_mutex` meets all of the timed mutex requirements
394
  [[thread.timedmutex.requirements]]. It is a standard-layout class
395
  [[class.prop]].
396
 
397
- The behavior of a program is undefined if:
398
 
399
  - it destroys a `timed_mutex` object owned by any thread,
400
  - a thread that owns a `timed_mutex` object calls `lock()`,
401
  `try_lock()`, `try_lock_for()`, or `try_lock_until()` on that object,
402
  or
@@ -451,11 +451,11 @@ for a `recursive_timed_mutex` object, additional calls to `try_lock()`,
451
  `unlock()` once for each level of ownership acquired by calls to
452
  `lock()`, `try_lock()`, `try_lock_for()`, and `try_lock_until()`. Only
453
  when all levels of ownership have been released may ownership of the
454
  object be acquired by another thread.
455
 
456
- The behavior of a program is undefined if:
457
 
458
  - it destroys a `recursive_timed_mutex` object owned by any thread, or
459
  - a thread terminates while owning a `recursive_timed_mutex` object.
460
 
461
  #### Shared mutex types <a id="thread.sharedmutex.requirements">[[thread.sharedmutex.requirements]]</a>
@@ -580,11 +580,11 @@ ownership semantics.
580
 
581
  The class `shared_mutex` meets all of the shared mutex requirements
582
  [[thread.sharedmutex.requirements]]. It is a standard-layout class
583
  [[class.prop]].
584
 
585
- The behavior of a program is undefined if:
586
 
587
  - it destroys a `shared_mutex` object owned by any thread,
588
  - a thread attempts to recursively gain any ownership of a
589
  `shared_mutex`, or
590
  - a thread terminates while possessing any ownership of a
@@ -706,11 +706,11 @@ shared ownership semantics.
706
 
707
  The class `shared_timed_mutex` meets all of the shared timed mutex
708
  requirements [[thread.sharedtimedmutex.requirements]]. It is a
709
  standard-layout class [[class.prop]].
710
 
711
- The behavior of a program is undefined if:
712
 
713
  - it destroys a `shared_timed_mutex` object owned by any thread,
714
  - a thread attempts to recursively gain any ownership of a
715
  `shared_timed_mutex`, or
716
  - a thread terminates while possessing any ownership of a
@@ -890,11 +890,11 @@ namespace std {
890
 
891
  unique_lock(const unique_lock&) = delete;
892
  unique_lock& operator=(const unique_lock&) = delete;
893
 
894
  unique_lock(unique_lock&& u) noexcept;
895
- unique_lock& operator=(unique_lock&& u);
896
 
897
  // [thread.lock.unique.locking], locking
898
  void lock();
899
  bool try_lock();
900
 
@@ -1016,24 +1016,16 @@ unique_lock(unique_lock&& u) noexcept;
1016
  *Ensures:* `pm == u_p.pm` and `owns == u_p.owns` (where `u_p` is the
1017
  state of `u` just prior to this construction), `u.pm == 0` and
1018
  `u.owns == false`.
1019
 
1020
  ``` cpp
1021
- unique_lock& operator=(unique_lock&& u);
1022
  ```
1023
 
1024
- *Effects:* If `owns` calls `pm->unlock()`.
1025
 
1026
- *Ensures:* `pm == u_p.pm` and `owns == u_p.owns` (where `u_p` is the
1027
- state of `u` just prior to this construction), `u.pm == 0` and
1028
- `u.owns == false`.
1029
-
1030
- [*Note 1*: With a recursive mutex it is possible for both `*this` and
1031
- `u` to own the same mutex before the assignment. In this case, `*this`
1032
- will own the mutex after the assignment and `u` will not. — *end note*]
1033
-
1034
- *Throws:* Nothing.
1035
 
1036
  ``` cpp
1037
  ~unique_lock();
1038
  ```
1039
 
@@ -1338,15 +1330,13 @@ state of `sl` just prior to this construction), `sl.pm == nullptr` and
1338
 
1339
  ``` cpp
1340
  shared_lock& operator=(shared_lock&& sl) noexcept;
1341
  ```
1342
 
1343
- *Effects:* If `owns` calls `pm->unlock_shared()`.
1344
 
1345
- *Ensures:* `pm == sl_p.pm` and `owns == sl_p.owns` (where `sl_p` is the
1346
- state of `sl` just prior to this assignment), `sl.pm == nullptr` and
1347
- `sl.owns == false`.
1348
 
1349
  ##### Locking <a id="thread.lock.shared.locking">[[thread.lock.shared.locking]]</a>
1350
 
1351
  ``` cpp
1352
  void lock();
@@ -1571,11 +1561,11 @@ template<class Callable, class... Args>
1571
 
1572
  *Mandates:* `is_invocable_v<Callable, Args...>` is `true`.
1573
 
1574
  *Effects:* An execution of `call_once` that does not call its `func` is
1575
  a *passive* execution. An execution of `call_once` that calls its `func`
1576
- is an *active* execution. An active execution calls *INVOKE*(
1577
  std::forward\<Callable\>(func),
1578
  std::forward\<Args\>(args)...) [[func.require]]. If such a call to
1579
  `func` throws an exception the execution is *exceptional*, otherwise it
1580
  is *returning*. An exceptional execution propagates the exception to the
1581
  caller of `call_once`. Among all executions of `call_once` for any given
 
12
  namespace std {
13
  // [thread.mutex.class], class mutex
14
  class mutex;
15
  // [thread.mutex.recursive], class recursive_mutex
16
  class recursive_mutex;
17
+ // [thread.timedmutex.class], class timed_mutex
18
  class timed_mutex;
19
  // [thread.timedmutex.recursive], class recursive_timed_mutex
20
  class recursive_timed_mutex;
21
 
22
  struct defer_lock_t { explicit defer_lock_t() = default; };
 
61
  }
62
  ```
63
 
64
  ### Mutex requirements <a id="thread.mutex.requirements">[[thread.mutex.requirements]]</a>
65
 
66
+ #### General <a id="thread.mutex.requirements.general">[[thread.mutex.requirements.general]]</a>
67
 
68
  A mutex object facilitates protection against data races and allows safe
69
  synchronization of data between execution agents
70
  [[thread.req.lockable]]. An execution agent *owns* a mutex from the time
71
  it successfully calls one of the lock functions until it calls unlock.
 
219
  released ownership with a call to `unlock()`.
220
 
221
  [*Note 4*: After a thread `A` has called `unlock()`, releasing a mutex,
222
  it is possible for another thread `B` to lock the same mutex, observe
223
  that it is no longer in use, unlock it, and destroy it, before thread
224
+ `A` appears to have returned from its unlock call. Conforming
225
+ implementations handle such scenarios correctly, as long as thread `A`
226
+ does not access the mutex after the unlock call returns. These cases
227
  typically occur when a reference-counted object contains a mutex that is
228
  used to protect the reference count. — *end note*]
229
 
230
  The class `mutex` meets all of the mutex requirements
231
  [[thread.mutex.requirements]]. It is a standard-layout class
 
281
  of type `system_error`. A thread shall call `unlock()` once for each
282
  level of ownership acquired by calls to `lock()` and `try_lock()`. Only
283
  when all levels of ownership have been released may ownership be
284
  acquired by another thread.
285
 
286
+ The behavior of a program is undefined if
287
 
288
  - it destroys a `recursive_mutex` object owned by any thread or
289
  - a thread terminates while owning a `recursive_mutex` object.
290
 
291
  #### Timed mutex types <a id="thread.timedmutex.requirements">[[thread.timedmutex.requirements]]</a>
 
392
 
393
  The class `timed_mutex` meets all of the timed mutex requirements
394
  [[thread.timedmutex.requirements]]. It is a standard-layout class
395
  [[class.prop]].
396
 
397
+ The behavior of a program is undefined if
398
 
399
  - it destroys a `timed_mutex` object owned by any thread,
400
  - a thread that owns a `timed_mutex` object calls `lock()`,
401
  `try_lock()`, `try_lock_for()`, or `try_lock_until()` on that object,
402
  or
 
451
  `unlock()` once for each level of ownership acquired by calls to
452
  `lock()`, `try_lock()`, `try_lock_for()`, and `try_lock_until()`. Only
453
  when all levels of ownership have been released may ownership of the
454
  object be acquired by another thread.
455
 
456
+ The behavior of a program is undefined if
457
 
458
  - it destroys a `recursive_timed_mutex` object owned by any thread, or
459
  - a thread terminates while owning a `recursive_timed_mutex` object.
460
 
461
  #### Shared mutex types <a id="thread.sharedmutex.requirements">[[thread.sharedmutex.requirements]]</a>
 
580
 
581
  The class `shared_mutex` meets all of the shared mutex requirements
582
  [[thread.sharedmutex.requirements]]. It is a standard-layout class
583
  [[class.prop]].
584
 
585
+ The behavior of a program is undefined if
586
 
587
  - it destroys a `shared_mutex` object owned by any thread,
588
  - a thread attempts to recursively gain any ownership of a
589
  `shared_mutex`, or
590
  - a thread terminates while possessing any ownership of a
 
706
 
707
  The class `shared_timed_mutex` meets all of the shared timed mutex
708
  requirements [[thread.sharedtimedmutex.requirements]]. It is a
709
  standard-layout class [[class.prop]].
710
 
711
+ The behavior of a program is undefined if
712
 
713
  - it destroys a `shared_timed_mutex` object owned by any thread,
714
  - a thread attempts to recursively gain any ownership of a
715
  `shared_timed_mutex`, or
716
  - a thread terminates while possessing any ownership of a
 
890
 
891
  unique_lock(const unique_lock&) = delete;
892
  unique_lock& operator=(const unique_lock&) = delete;
893
 
894
  unique_lock(unique_lock&& u) noexcept;
895
+ unique_lock& operator=(unique_lock&& u) noexcept;
896
 
897
  // [thread.lock.unique.locking], locking
898
  void lock();
899
  bool try_lock();
900
 
 
1016
  *Ensures:* `pm == u_p.pm` and `owns == u_p.owns` (where `u_p` is the
1017
  state of `u` just prior to this construction), `u.pm == 0` and
1018
  `u.owns == false`.
1019
 
1020
  ``` cpp
1021
+ unique_lock& operator=(unique_lock&& u) noexcept;
1022
  ```
1023
 
1024
+ *Effects:* Equivalent to: `unique_lock(std::move(u)).swap(*this)`
1025
 
1026
+ *Returns:* `*this`.
 
 
 
 
 
 
 
 
1027
 
1028
  ``` cpp
1029
  ~unique_lock();
1030
  ```
1031
 
 
1330
 
1331
  ``` cpp
1332
  shared_lock& operator=(shared_lock&& sl) noexcept;
1333
  ```
1334
 
1335
+ *Effects:* Equivalent to: `shared_lock(std::move(sl)).swap(*this)`
1336
 
1337
+ *Returns:* `*this`.
 
 
1338
 
1339
  ##### Locking <a id="thread.lock.shared.locking">[[thread.lock.shared.locking]]</a>
1340
 
1341
  ``` cpp
1342
  void lock();
 
1561
 
1562
  *Mandates:* `is_invocable_v<Callable, Args...>` is `true`.
1563
 
1564
  *Effects:* An execution of `call_once` that does not call its `func` is
1565
  a *passive* execution. An execution of `call_once` that calls its `func`
1566
+ is an *active* execution. An active execution evaluates *INVOKE*(
1567
  std::forward\<Callable\>(func),
1568
  std::forward\<Args\>(args)...) [[func.require]]. If such a call to
1569
  `func` throws an exception the execution is *exceptional*, otherwise it
1570
  is *returning*. An exceptional execution propagates the exception to the
1571
  caller of `call_once`. Among all executions of `call_once` for any given