From Jason Turner

[thread.lock]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmp72ygan_h/{from.md → to.md} +69 -71
tmp/tmp72ygan_h/{from.md → to.md} RENAMED
@@ -1,7 +1,9 @@
1
  ### Locks <a id="thread.lock">[[thread.lock]]</a>
2
 
 
 
3
  A *lock* is an object that holds a reference to a lockable object and
4
  may unlock the lockable object during the lock’s destruction (such as
5
  when leaving block scope). An execution agent may use a lock to aid in
6
  managing ownership of a lockable object in an exception safe manner. A
7
  lock is said to *own* a lockable object if it is currently managing the
@@ -61,39 +63,36 @@ object referenced by `pm` does not exist for the entire lifetime of the
61
 
62
  ``` cpp
63
  explicit lock_guard(mutex_type& m);
64
  ```
65
 
66
- *Preconditions:* If `mutex_type` is not a recursive mutex, the calling
67
- thread does not own the mutex `m`.
68
-
69
  *Effects:* Initializes `pm` with `m`. Calls `m.lock()`.
70
 
71
  ``` cpp
72
  lock_guard(mutex_type& m, adopt_lock_t);
73
  ```
74
 
75
- *Preconditions:* The calling thread owns the mutex `m`.
76
 
77
  *Effects:* Initializes `pm` with `m`.
78
 
79
  *Throws:* Nothing.
80
 
81
  ``` cpp
82
  ~lock_guard();
83
  ```
84
 
85
- *Effects:* As if by `pm.unlock()`.
86
 
87
  #### Class template `scoped_lock` <a id="thread.lock.scoped">[[thread.lock.scoped]]</a>
88
 
89
  ``` cpp
90
  namespace std {
91
  template<class... MutexTypes>
92
  class scoped_lock {
93
  public:
94
- using mutex_type = Mutex; // If MutexTypes... consists of the single type Mutex
95
 
96
  explicit scoped_lock(MutexTypes&... m);
97
  explicit scoped_lock(adopt_lock_t, MutexTypes&... m);
98
  ~scoped_lock();
99
 
@@ -109,32 +108,35 @@ namespace std {
109
  An object of type `scoped_lock` controls the ownership of lockable
110
  objects within a scope. A `scoped_lock` object maintains ownership of
111
  lockable objects throughout the `scoped_lock` object’s lifetime
112
  [[basic.life]]. The behavior of a program is undefined if the lockable
113
  objects referenced by `pm` do not exist for the entire lifetime of the
114
- `scoped_lock` object. When `sizeof...(MutexTypes)` is `1`, the supplied
115
- `Mutex` type shall meet the *Cpp17BasicLockable* requirements
116
- [[thread.req.lockable.basic]]. Otherwise, each of the mutex types shall
117
- meet the *Cpp17Lockable* requirements [[thread.req.lockable.req]].
 
 
 
 
 
118
 
119
  ``` cpp
120
  explicit scoped_lock(MutexTypes&... m);
121
  ```
122
 
123
- *Preconditions:* If a `MutexTypes` type is not a recursive mutex, the
124
- calling thread does not own the corresponding mutex element of `m`.
125
-
126
  *Effects:* Initializes `pm` with `tie(m...)`. Then if
127
  `sizeof...(MutexTypes)` is `0`, no effects. Otherwise if
128
  `sizeof...(MutexTypes)` is `1`, then `m.lock()`. Otherwise,
129
  `lock(m...)`.
130
 
131
  ``` cpp
132
  explicit scoped_lock(adopt_lock_t, MutexTypes&... m);
133
  ```
134
 
135
- *Preconditions:* The calling thread owns all the mutexes in `m`.
 
136
 
137
  *Effects:* Initializes `pm` with `tie(m...)`.
138
 
139
  *Throws:* Nothing.
140
 
@@ -145,10 +147,12 @@ explicit scoped_lock(adopt_lock_t, MutexTypes&... m);
145
  *Effects:* For all `i` in \[`0`, `sizeof...(MutexTypes)`),
146
  `get<i>(pm).unlock()`.
147
 
148
  #### Class template `unique_lock` <a id="thread.lock.unique">[[thread.lock.unique]]</a>
149
 
 
 
150
  ``` cpp
151
  namespace std {
152
  template<class Mutex>
153
  class unique_lock {
154
  public:
@@ -194,13 +198,10 @@ namespace std {
194
 
195
  private:
196
  mutex_type* pm; // exposition only
197
  bool owns; // exposition only
198
  };
199
-
200
- template<class Mutex>
201
- void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y) noexcept;
202
  }
203
  ```
204
 
205
  An object of type `unique_lock` controls the ownership of a lockable
206
  object within a scope. Ownership of the lockable object may be acquired
@@ -224,19 +225,16 @@ meets the *Cpp17TimedLockable* requirements. — *end note*]
224
 
225
  ``` cpp
226
  unique_lock() noexcept;
227
  ```
228
 
229
- *Ensures:* `pm == 0` and `owns == false`.
230
 
231
  ``` cpp
232
  explicit unique_lock(mutex_type& m);
233
  ```
234
 
235
- *Preconditions:* If `mutex_type` is not a recursive mutex the calling
236
- thread does not own the mutex.
237
-
238
  *Effects:* Calls `m.lock()`.
239
 
240
  *Ensures:* `pm == addressof(m)` and `owns == true`.
241
 
242
  ``` cpp
@@ -248,35 +246,33 @@ unique_lock(mutex_type& m, defer_lock_t) noexcept;
248
  ``` cpp
249
  unique_lock(mutex_type& m, try_to_lock_t);
250
  ```
251
 
252
  *Preconditions:* The supplied `Mutex` type meets the *Cpp17Lockable*
253
- requirements [[thread.req.lockable.req]]. If `mutex_type` is not a
254
- recursive mutex the calling thread does not own the mutex.
255
 
256
  *Effects:* Calls `m.try_lock()`.
257
 
258
  *Ensures:* `pm == addressof(m)` and `owns == res`, where `res` is the
259
  value returned by the call to `m.try_lock()`.
260
 
261
  ``` cpp
262
  unique_lock(mutex_type& m, adopt_lock_t);
263
  ```
264
 
265
- *Preconditions:* The calling thread owns the mutex.
266
 
267
  *Ensures:* `pm == addressof(m)` and `owns == true`.
268
 
269
  *Throws:* Nothing.
270
 
271
  ``` cpp
272
  template<class Clock, class Duration>
273
  unique_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time);
274
  ```
275
 
276
- *Preconditions:* If `mutex_type` is not a recursive mutex the calling
277
- thread does not own the mutex. The supplied `Mutex` type meets the
278
  *Cpp17TimedLockable* requirements [[thread.req.lockable.timed]].
279
 
280
  *Effects:* Calls `m.try_lock_until(abs_time)`.
281
 
282
  *Ensures:* `pm == addressof(m)` and `owns == res`, where `res` is the
@@ -285,12 +281,11 @@ value returned by the call to `m.try_lock_until(abs_time)`.
285
  ``` cpp
286
  template<class Rep, class Period>
287
  unique_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time);
288
  ```
289
 
290
- *Preconditions:* If `mutex_type` is not a recursive mutex the calling
291
- thread does not own the mutex. The supplied `Mutex` type meets the
292
  *Cpp17TimedLockable* requirements [[thread.req.lockable.timed]].
293
 
294
  *Effects:* Calls `m.try_lock_for(rel_time)`.
295
 
296
  *Ensures:* `pm == addressof(m)` and `owns == res`, where `res` is the
@@ -351,14 +346,14 @@ bool try_lock();
351
  *Preconditions:* The supplied `Mutex` meets the *Cpp17Lockable*
352
  requirements [[thread.req.lockable.req]].
353
 
354
  *Effects:* As if by `pm->try_lock()`.
355
 
356
- *Returns:* The value returned by the call to `try_lock()`.
 
357
 
358
- *Ensures:* `owns == res`, where `res` is the value returned by the call
359
- to `try_lock()`.
360
 
361
  *Throws:* Any exception thrown by `pm->try_lock()`. `system_error` when
362
  an exception is required [[thread.req.exception]].
363
 
364
  *Error conditions:*
@@ -374,17 +369,17 @@ template<class Clock, class Duration>
374
  *Preconditions:* The supplied `Mutex` type meets the
375
  *Cpp17TimedLockable* requirements [[thread.req.lockable.timed]].
376
 
377
  *Effects:* As if by `pm->try_lock_until(abs_time)`.
378
 
379
- *Returns:* The value returned by the call to `try_lock_until(abs_time)`.
 
380
 
381
- *Ensures:* `owns == res`, where `res` is the value returned by the call
382
- to `try_lock_until(abs_time)`.
383
 
384
- *Throws:* Any exception thrown by `pm->try_lock_until()`. `system_error`
385
- when an exception is required [[thread.req.exception]].
386
 
387
  *Error conditions:*
388
 
389
  - `operation_not_permitted` — if `pm` is `nullptr`.
390
  - `resource_deadlock_would_occur` — if on entry `owns` is `true`.
@@ -397,17 +392,17 @@ template<class Rep, class Period>
397
  *Preconditions:* The supplied `Mutex` type meets the
398
  *Cpp17TimedLockable* requirements [[thread.req.lockable.timed]].
399
 
400
  *Effects:* As if by `pm->try_lock_for(rel_time)`.
401
 
402
- *Returns:* The value returned by the call to `try_lock_for(rel_time)`.
 
403
 
404
- *Ensures:* `owns == res`, where `res` is the value returned by the call
405
- to `try_lock_for(rel_time)`.
406
 
407
- *Throws:* Any exception thrown by `pm->try_lock_for()`. `system_error`
408
- when an exception is required [[thread.req.exception]].
409
 
410
  *Error conditions:*
411
 
412
  - `operation_not_permitted` — if `pm` is `nullptr`.
413
  - `resource_deadlock_would_occur` — if on entry `owns` is `true`.
@@ -437,14 +432,14 @@ void swap(unique_lock& u) noexcept;
437
 
438
  ``` cpp
439
  mutex_type* release() noexcept;
440
  ```
441
 
442
- *Returns:* The previous value of `pm`.
443
-
444
  *Ensures:* `pm == 0` and `owns == false`.
445
 
 
 
446
  ``` cpp
447
  template<class Mutex>
448
  void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y) noexcept;
449
  ```
450
 
@@ -470,10 +465,12 @@ mutex_type *mutex() const noexcept;
470
 
471
  *Returns:* `pm`.
472
 
473
  #### Class template `shared_lock` <a id="thread.lock.shared">[[thread.lock.shared]]</a>
474
 
 
 
475
  ``` cpp
476
  namespace std {
477
  template<class Mutex>
478
  class shared_lock {
479
  public:
@@ -517,13 +514,10 @@ namespace std {
517
 
518
  private:
519
  mutex_type* pm; // exposition only
520
  bool owns; // exposition only
521
  };
522
-
523
- template<class Mutex>
524
- void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;
525
  }
526
  ```
527
 
528
  An object of type `shared_lock` controls the shared ownership of a
529
  lockable object within a scope. Shared ownership of the lockable object
@@ -531,15 +525,19 @@ may be acquired at construction or after construction, and may be
531
  transferred, after acquisition, to another `shared_lock` object. Objects
532
  of type `shared_lock` are not copyable but are movable. The behavior of
533
  a program is undefined if the contained pointer `pm` is not null and the
534
  lockable object pointed to by `pm` does not exist for the entire
535
  remaining lifetime [[basic.life]] of the `shared_lock` object. The
536
- supplied `Mutex` type shall meet the shared mutex requirements
537
- [[thread.sharedtimedmutex.requirements]].
538
 
539
- [*Note 1*: `shared_lock<Mutex>` meets the *Cpp17TimedLockable*
540
- requirements [[thread.req.lockable.timed]]. *end note*]
 
 
 
 
541
 
542
  ##### Constructors, destructor, and assignment <a id="thread.lock.shared.cons">[[thread.lock.shared.cons]]</a>
543
 
544
  ``` cpp
545
  shared_lock() noexcept;
@@ -549,13 +547,10 @@ shared_lock() noexcept;
549
 
550
  ``` cpp
551
  explicit shared_lock(mutex_type& m);
552
  ```
553
 
554
- *Preconditions:* The calling thread does not own the mutex for any
555
- ownership mode.
556
-
557
  *Effects:* Calls `m.lock_shared()`.
558
 
559
  *Ensures:* `pm == addressof(m)` and `owns == true`.
560
 
561
  ``` cpp
@@ -566,34 +561,31 @@ shared_lock(mutex_type& m, defer_lock_t) noexcept;
566
 
567
  ``` cpp
568
  shared_lock(mutex_type& m, try_to_lock_t);
569
  ```
570
 
571
- *Preconditions:* The calling thread does not own the mutex for any
572
- ownership mode.
573
-
574
  *Effects:* Calls `m.try_lock_shared()`.
575
 
576
  *Ensures:* `pm == addressof(m)` and `owns == res` where `res` is the
577
  value returned by the call to `m.try_lock_shared()`.
578
 
579
  ``` cpp
580
  shared_lock(mutex_type& m, adopt_lock_t);
581
  ```
582
 
583
- *Preconditions:* The calling thread has shared ownership of the mutex.
584
 
585
  *Ensures:* `pm == addressof(m)` and `owns == true`.
586
 
587
  ``` cpp
588
  template<class Clock, class Duration>
589
  shared_lock(mutex_type& m,
590
  const chrono::time_point<Clock, Duration>& abs_time);
591
  ```
592
 
593
- *Preconditions:* The calling thread does not own the mutex for any
594
- ownership mode.
595
 
596
  *Effects:* Calls `m.try_lock_shared_until(abs_time)`.
597
 
598
  *Ensures:* `pm == addressof(m)` and `owns == res` where `res` is the
599
  value returned by the call to `m.try_lock_shared_until(abs_time)`.
@@ -602,12 +594,12 @@ value returned by the call to `m.try_lock_shared_until(abs_time)`.
602
  template<class Rep, class Period>
603
  shared_lock(mutex_type& m,
604
  const chrono::duration<Rep, Period>& rel_time);
605
  ```
606
 
607
- *Preconditions:* The calling thread does not own the mutex for any
608
- ownership mode.
609
 
610
  *Effects:* Calls `m.try_lock_shared_for(rel_time)`.
611
 
612
  *Ensures:* `pm == addressof(m)` and `owns == res` where `res` is the
613
  value returned by the call to `m.try_lock_shared_for(rel_time)`.
@@ -658,15 +650,15 @@ when an exception is required [[thread.req.exception]].
658
  bool try_lock();
659
  ```
660
 
661
  *Effects:* As if by `pm->try_lock_shared()`.
662
 
663
- *Returns:* The value returned by the call to `pm->try_lock_shared()`.
664
-
665
  *Ensures:* `owns == res`, where `res` is the value returned by the call
666
  to `pm->try_lock_shared()`.
667
 
 
 
668
  *Throws:* Any exception thrown by `pm->try_lock_shared()`.
669
  `system_error` when an exception is required [[thread.req.exception]].
670
 
671
  *Error conditions:*
672
 
@@ -676,18 +668,21 @@ to `pm->try_lock_shared()`.
676
  ``` cpp
677
  template<class Clock, class Duration>
678
  bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
679
  ```
680
 
 
 
 
681
  *Effects:* As if by `pm->try_lock_shared_until(abs_time)`.
682
 
683
- *Returns:* The value returned by the call to
684
- `pm->try_lock_shared_until(abs_time)`.
685
-
686
  *Ensures:* `owns == res`, where `res` is the value returned by the call
687
  to `pm->try_lock_shared_until(abs_time)`.
688
 
 
 
 
689
  *Throws:* Any exception thrown by `pm->try_lock_shared_until(abs_time)`.
690
  `system_error` when an exception is required [[thread.req.exception]].
691
 
692
  *Error conditions:*
693
 
@@ -697,18 +692,21 @@ to `pm->try_lock_shared_until(abs_time)`.
697
  ``` cpp
698
  template<class Rep, class Period>
699
  bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
700
  ```
701
 
 
 
 
702
  *Effects:* As if by `pm->try_lock_shared_for(rel_time)`.
703
 
704
- *Returns:* The value returned by the call to
705
- `pm->try_lock_shared_for(rel_time)`.
706
-
707
  *Ensures:* `owns == res`, where `res` is the value returned by the call
708
  to `pm->try_lock_shared_for(rel_time)`.
709
 
 
 
 
710
  *Throws:* Any exception thrown by `pm->try_lock_shared_for(rel_time)`.
711
  `system_error` when an exception is required [[thread.req.exception]].
712
 
713
  *Error conditions:*
714
 
@@ -740,14 +738,14 @@ void swap(shared_lock& sl) noexcept;
740
 
741
  ``` cpp
742
  mutex_type* release() noexcept;
743
  ```
744
 
745
- *Returns:* The previous value of `pm`.
746
-
747
  *Ensures:* `pm == nullptr` and `owns == false`.
748
 
 
 
749
  ``` cpp
750
  template<class Mutex>
751
  void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;
752
  ```
753
 
 
1
  ### Locks <a id="thread.lock">[[thread.lock]]</a>
2
 
3
+ #### General <a id="thread.lock.general">[[thread.lock.general]]</a>
4
+
5
  A *lock* is an object that holds a reference to a lockable object and
6
  may unlock the lockable object during the lock’s destruction (such as
7
  when leaving block scope). An execution agent may use a lock to aid in
8
  managing ownership of a lockable object in an exception safe manner. A
9
  lock is said to *own* a lockable object if it is currently managing the
 
63
 
64
  ``` cpp
65
  explicit lock_guard(mutex_type& m);
66
  ```
67
 
 
 
 
68
  *Effects:* Initializes `pm` with `m`. Calls `m.lock()`.
69
 
70
  ``` cpp
71
  lock_guard(mutex_type& m, adopt_lock_t);
72
  ```
73
 
74
+ *Preconditions:* The calling thread holds a non-shared lock on `m`.
75
 
76
  *Effects:* Initializes `pm` with `m`.
77
 
78
  *Throws:* Nothing.
79
 
80
  ``` cpp
81
  ~lock_guard();
82
  ```
83
 
84
+ *Effects:* Equivalent to: `pm.unlock()`
85
 
86
  #### Class template `scoped_lock` <a id="thread.lock.scoped">[[thread.lock.scoped]]</a>
87
 
88
  ``` cpp
89
  namespace std {
90
  template<class... MutexTypes>
91
  class scoped_lock {
92
  public:
93
+ using mutex_type = see below; // Only if sizeof...(MutexTypes) == 1 is true
94
 
95
  explicit scoped_lock(MutexTypes&... m);
96
  explicit scoped_lock(adopt_lock_t, MutexTypes&... m);
97
  ~scoped_lock();
98
 
 
108
  An object of type `scoped_lock` controls the ownership of lockable
109
  objects within a scope. A `scoped_lock` object maintains ownership of
110
  lockable objects throughout the `scoped_lock` object’s lifetime
111
  [[basic.life]]. The behavior of a program is undefined if the lockable
112
  objects referenced by `pm` do not exist for the entire lifetime of the
113
+ `scoped_lock` object.
114
+
115
+ - If `sizeof...(MutexTypes)` is one, let `Mutex` denote the sole type
116
+ constituting the pack `MutexTypes`. `Mutex` shall meet the
117
+ *Cpp17BasicLockable* requirements [[thread.req.lockable.basic]]. The
118
+ member *typedef-name* `mutex_type` denotes the same type as `Mutex`.
119
+ - Otherwise, all types in the template parameter pack `MutexTypes` shall
120
+ meet the *Cpp17Lockable* requirements [[thread.req.lockable.req]] and
121
+ there is no member `mutex_type`.
122
 
123
  ``` cpp
124
  explicit scoped_lock(MutexTypes&... m);
125
  ```
126
 
 
 
 
127
  *Effects:* Initializes `pm` with `tie(m...)`. Then if
128
  `sizeof...(MutexTypes)` is `0`, no effects. Otherwise if
129
  `sizeof...(MutexTypes)` is `1`, then `m.lock()`. Otherwise,
130
  `lock(m...)`.
131
 
132
  ``` cpp
133
  explicit scoped_lock(adopt_lock_t, MutexTypes&... m);
134
  ```
135
 
136
+ *Preconditions:* The calling thread holds a non-shared lock on each
137
+ element of `m`.
138
 
139
  *Effects:* Initializes `pm` with `tie(m...)`.
140
 
141
  *Throws:* Nothing.
142
 
 
147
  *Effects:* For all `i` in \[`0`, `sizeof...(MutexTypes)`),
148
  `get<i>(pm).unlock()`.
149
 
150
  #### Class template `unique_lock` <a id="thread.lock.unique">[[thread.lock.unique]]</a>
151
 
152
+ ##### General <a id="thread.lock.unique.general">[[thread.lock.unique.general]]</a>
153
+
154
  ``` cpp
155
  namespace std {
156
  template<class Mutex>
157
  class unique_lock {
158
  public:
 
198
 
199
  private:
200
  mutex_type* pm; // exposition only
201
  bool owns; // exposition only
202
  };
 
 
 
203
  }
204
  ```
205
 
206
  An object of type `unique_lock` controls the ownership of a lockable
207
  object within a scope. Ownership of the lockable object may be acquired
 
225
 
226
  ``` cpp
227
  unique_lock() noexcept;
228
  ```
229
 
230
+ *Ensures:* `pm == nullptr` and `owns == false`.
231
 
232
  ``` cpp
233
  explicit unique_lock(mutex_type& m);
234
  ```
235
 
 
 
 
236
  *Effects:* Calls `m.lock()`.
237
 
238
  *Ensures:* `pm == addressof(m)` and `owns == true`.
239
 
240
  ``` cpp
 
246
  ``` cpp
247
  unique_lock(mutex_type& m, try_to_lock_t);
248
  ```
249
 
250
  *Preconditions:* The supplied `Mutex` type meets the *Cpp17Lockable*
251
+ requirements [[thread.req.lockable.req]].
 
252
 
253
  *Effects:* Calls `m.try_lock()`.
254
 
255
  *Ensures:* `pm == addressof(m)` and `owns == res`, where `res` is the
256
  value returned by the call to `m.try_lock()`.
257
 
258
  ``` cpp
259
  unique_lock(mutex_type& m, adopt_lock_t);
260
  ```
261
 
262
+ *Preconditions:* The calling thread holds a non-shared lock on `m`.
263
 
264
  *Ensures:* `pm == addressof(m)` and `owns == true`.
265
 
266
  *Throws:* Nothing.
267
 
268
  ``` cpp
269
  template<class Clock, class Duration>
270
  unique_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time);
271
  ```
272
 
273
+ *Preconditions:* The supplied `Mutex` type meets the
 
274
  *Cpp17TimedLockable* requirements [[thread.req.lockable.timed]].
275
 
276
  *Effects:* Calls `m.try_lock_until(abs_time)`.
277
 
278
  *Ensures:* `pm == addressof(m)` and `owns == res`, where `res` is the
 
281
  ``` cpp
282
  template<class Rep, class Period>
283
  unique_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time);
284
  ```
285
 
286
+ *Preconditions:* The supplied `Mutex` type meets the
 
287
  *Cpp17TimedLockable* requirements [[thread.req.lockable.timed]].
288
 
289
  *Effects:* Calls `m.try_lock_for(rel_time)`.
290
 
291
  *Ensures:* `pm == addressof(m)` and `owns == res`, where `res` is the
 
346
  *Preconditions:* The supplied `Mutex` meets the *Cpp17Lockable*
347
  requirements [[thread.req.lockable.req]].
348
 
349
  *Effects:* As if by `pm->try_lock()`.
350
 
351
+ *Ensures:* `owns == res`, where `res` is the value returned by
352
+ `pm->try_lock()`.
353
 
354
+ *Returns:* The value returned by `pm->try_lock()`.
 
355
 
356
  *Throws:* Any exception thrown by `pm->try_lock()`. `system_error` when
357
  an exception is required [[thread.req.exception]].
358
 
359
  *Error conditions:*
 
369
  *Preconditions:* The supplied `Mutex` type meets the
370
  *Cpp17TimedLockable* requirements [[thread.req.lockable.timed]].
371
 
372
  *Effects:* As if by `pm->try_lock_until(abs_time)`.
373
 
374
+ *Ensures:* `owns == res`, where `res` is the value returned by
375
+ `pm->try_lock_until(abs_time)`.
376
 
377
+ *Returns:* The value returned by `pm->try_lock_until(abs_time)`.
 
378
 
379
+ *Throws:* Any exception thrown by `pm->try_lock_until(abstime)`.
380
+ `system_error` when an exception is required [[thread.req.exception]].
381
 
382
  *Error conditions:*
383
 
384
  - `operation_not_permitted` — if `pm` is `nullptr`.
385
  - `resource_deadlock_would_occur` — if on entry `owns` is `true`.
 
392
  *Preconditions:* The supplied `Mutex` type meets the
393
  *Cpp17TimedLockable* requirements [[thread.req.lockable.timed]].
394
 
395
  *Effects:* As if by `pm->try_lock_for(rel_time)`.
396
 
397
+ *Ensures:* `owns == res`, where `res` is the value returned by
398
+ `pm->try_lock_for(rel_time)`.
399
 
400
+ *Returns:* The value returned by `pm->try_lock_for(rel_time)`.
 
401
 
402
+ *Throws:* Any exception thrown by `pm->try_lock_for(rel_time)`.
403
+ `system_error` when an exception is required [[thread.req.exception]].
404
 
405
  *Error conditions:*
406
 
407
  - `operation_not_permitted` — if `pm` is `nullptr`.
408
  - `resource_deadlock_would_occur` — if on entry `owns` is `true`.
 
432
 
433
  ``` cpp
434
  mutex_type* release() noexcept;
435
  ```
436
 
 
 
437
  *Ensures:* `pm == 0` and `owns == false`.
438
 
439
+ *Returns:* The previous value of `pm`.
440
+
441
  ``` cpp
442
  template<class Mutex>
443
  void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y) noexcept;
444
  ```
445
 
 
465
 
466
  *Returns:* `pm`.
467
 
468
  #### Class template `shared_lock` <a id="thread.lock.shared">[[thread.lock.shared]]</a>
469
 
470
+ ##### General <a id="thread.lock.shared.general">[[thread.lock.shared.general]]</a>
471
+
472
  ``` cpp
473
  namespace std {
474
  template<class Mutex>
475
  class shared_lock {
476
  public:
 
514
 
515
  private:
516
  mutex_type* pm; // exposition only
517
  bool owns; // exposition only
518
  };
 
 
 
519
  }
520
  ```
521
 
522
  An object of type `shared_lock` controls the shared ownership of a
523
  lockable object within a scope. Shared ownership of the lockable object
 
525
  transferred, after acquisition, to another `shared_lock` object. Objects
526
  of type `shared_lock` are not copyable but are movable. The behavior of
527
  a program is undefined if the contained pointer `pm` is not null and the
528
  lockable object pointed to by `pm` does not exist for the entire
529
  remaining lifetime [[basic.life]] of the `shared_lock` object. The
530
+ supplied `Mutex` type shall meet the *Cpp17SharedLockable* requirements
531
+ [[thread.req.lockable.shared]].
532
 
533
+ [*Note 1*: `shared_lock<Mutex>` meets the *Cpp17Lockable* requirements
534
+ [[thread.req.lockable.req]]. If `Mutex` meets the
535
+ *Cpp17SharedTimedLockable* requirements
536
+ [[thread.req.lockable.shared.timed]], `shared_lock<Mutex>` also meets
537
+ the *Cpp17TimedLockable* requirements
538
+ [[thread.req.lockable.timed]]. — *end note*]
539
 
540
  ##### Constructors, destructor, and assignment <a id="thread.lock.shared.cons">[[thread.lock.shared.cons]]</a>
541
 
542
  ``` cpp
543
  shared_lock() noexcept;
 
547
 
548
  ``` cpp
549
  explicit shared_lock(mutex_type& m);
550
  ```
551
 
 
 
 
552
  *Effects:* Calls `m.lock_shared()`.
553
 
554
  *Ensures:* `pm == addressof(m)` and `owns == true`.
555
 
556
  ``` cpp
 
561
 
562
  ``` cpp
563
  shared_lock(mutex_type& m, try_to_lock_t);
564
  ```
565
 
 
 
 
566
  *Effects:* Calls `m.try_lock_shared()`.
567
 
568
  *Ensures:* `pm == addressof(m)` and `owns == res` where `res` is the
569
  value returned by the call to `m.try_lock_shared()`.
570
 
571
  ``` cpp
572
  shared_lock(mutex_type& m, adopt_lock_t);
573
  ```
574
 
575
+ *Preconditions:* The calling thread holds a shared lock on `m`.
576
 
577
  *Ensures:* `pm == addressof(m)` and `owns == true`.
578
 
579
  ``` cpp
580
  template<class Clock, class Duration>
581
  shared_lock(mutex_type& m,
582
  const chrono::time_point<Clock, Duration>& abs_time);
583
  ```
584
 
585
+ *Preconditions:* `Mutex` meets the *Cpp17SharedTimedLockable*
586
+ requirements [[thread.req.lockable.shared.timed]].
587
 
588
  *Effects:* Calls `m.try_lock_shared_until(abs_time)`.
589
 
590
  *Ensures:* `pm == addressof(m)` and `owns == res` where `res` is the
591
  value returned by the call to `m.try_lock_shared_until(abs_time)`.
 
594
  template<class Rep, class Period>
595
  shared_lock(mutex_type& m,
596
  const chrono::duration<Rep, Period>& rel_time);
597
  ```
598
 
599
+ *Preconditions:* `Mutex` meets the *Cpp17SharedTimedLockable*
600
+ requirements [[thread.req.lockable.shared.timed]].
601
 
602
  *Effects:* Calls `m.try_lock_shared_for(rel_time)`.
603
 
604
  *Ensures:* `pm == addressof(m)` and `owns == res` where `res` is the
605
  value returned by the call to `m.try_lock_shared_for(rel_time)`.
 
650
  bool try_lock();
651
  ```
652
 
653
  *Effects:* As if by `pm->try_lock_shared()`.
654
 
 
 
655
  *Ensures:* `owns == res`, where `res` is the value returned by the call
656
  to `pm->try_lock_shared()`.
657
 
658
+ *Returns:* The value returned by the call to `pm->try_lock_shared()`.
659
+
660
  *Throws:* Any exception thrown by `pm->try_lock_shared()`.
661
  `system_error` when an exception is required [[thread.req.exception]].
662
 
663
  *Error conditions:*
664
 
 
668
  ``` cpp
669
  template<class Clock, class Duration>
670
  bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
671
  ```
672
 
673
+ *Preconditions:* `Mutex` meets the *Cpp17SharedTimedLockable*
674
+ requirements [[thread.req.lockable.shared.timed]].
675
+
676
  *Effects:* As if by `pm->try_lock_shared_until(abs_time)`.
677
 
 
 
 
678
  *Ensures:* `owns == res`, where `res` is the value returned by the call
679
  to `pm->try_lock_shared_until(abs_time)`.
680
 
681
+ *Returns:* The value returned by the call to
682
+ `pm->try_lock_shared_until(abs_time)`.
683
+
684
  *Throws:* Any exception thrown by `pm->try_lock_shared_until(abs_time)`.
685
  `system_error` when an exception is required [[thread.req.exception]].
686
 
687
  *Error conditions:*
688
 
 
692
  ``` cpp
693
  template<class Rep, class Period>
694
  bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
695
  ```
696
 
697
+ *Preconditions:* `Mutex` meets the *Cpp17SharedTimedLockable*
698
+ requirements [[thread.req.lockable.shared.timed]].
699
+
700
  *Effects:* As if by `pm->try_lock_shared_for(rel_time)`.
701
 
 
 
 
702
  *Ensures:* `owns == res`, where `res` is the value returned by the call
703
  to `pm->try_lock_shared_for(rel_time)`.
704
 
705
+ *Returns:* The value returned by the call to
706
+ `pm->try_lock_shared_for(rel_time)`.
707
+
708
  *Throws:* Any exception thrown by `pm->try_lock_shared_for(rel_time)`.
709
  `system_error` when an exception is required [[thread.req.exception]].
710
 
711
  *Error conditions:*
712
 
 
738
 
739
  ``` cpp
740
  mutex_type* release() noexcept;
741
  ```
742
 
 
 
743
  *Ensures:* `pm == nullptr` and `owns == false`.
744
 
745
+ *Returns:* The previous value of `pm`.
746
+
747
  ``` cpp
748
  template<class Mutex>
749
  void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;
750
  ```
751