From Jason Turner

[thread.lock]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmp7t_k09r1/{from.md → to.md} +136 -173
tmp/tmp7t_k09r1/{from.md → to.md} RENAMED
@@ -46,41 +46,37 @@ namespace std {
46
  lock_guard& operator=(const lock_guard&) = delete;
47
 
48
  private:
49
  mutex_type& pm; // exposition only
50
  };
51
-
52
- template<class Mutex> lock_guard(lock_guard<Mutex>) -> lock_guard<Mutex>;
53
  }
54
  ```
55
 
56
  An object of type `lock_guard` controls the ownership of a lockable
57
  object within a scope. A `lock_guard` object maintains ownership of a
58
- lockable object throughout the `lock_guard` object’s lifetime (
59
- [[basic.life]]). The behavior of a program is undefined if the lockable
60
  object referenced by `pm` does not exist for the entire lifetime of the
61
  `lock_guard` object. The supplied `Mutex` type shall meet the
62
- `BasicLockable` requirements ([[thread.req.lockable.basic]]).
63
 
64
  ``` cpp
65
  explicit lock_guard(mutex_type& m);
66
  ```
67
 
68
- *Requires:* If `mutex_type` is not a recursive mutex, the calling thread
69
- does not own the mutex `m`.
70
 
71
- *Effects:* As if by `m.lock()`.
72
-
73
- *Postconditions:* `&pm == &m`
74
 
75
  ``` cpp
76
  lock_guard(mutex_type& m, adopt_lock_t);
77
  ```
78
 
79
- *Requires:* The calling thread owns the mutex `m`.
80
 
81
- *Postconditions:* `&pm == &m`
82
 
83
  *Throws:* Nothing.
84
 
85
  ``` cpp
86
  ~lock_guard();
@@ -96,52 +92,49 @@ namespace std {
96
  class scoped_lock {
97
  public:
98
  using mutex_type = Mutex; // If MutexTypes... consists of the single type Mutex
99
 
100
  explicit scoped_lock(MutexTypes&... m);
101
- explicit scoped_lock(MutexTypes&... m, adopt_lock_t);
102
  ~scoped_lock();
103
 
104
  scoped_lock(const scoped_lock&) = delete;
105
  scoped_lock& operator=(const scoped_lock&) = delete;
106
 
107
  private:
108
  tuple<MutexTypes&...> pm; // exposition only
109
  };
110
-
111
- template<class... MutexTypes>
112
- scoped_lock(scoped_lock<MutexTypes...>) -> scoped_lock<MutexTypes...>;
113
  }
114
  ```
115
 
116
  An object of type `scoped_lock` controls the ownership of lockable
117
  objects within a scope. A `scoped_lock` object maintains ownership of
118
- lockable objects throughout the `scoped_lock` object’s lifetime (
119
- [[basic.life]]). The behavior of a program is undefined if the lockable
120
  objects referenced by `pm` do not exist for the entire lifetime of the
121
  `scoped_lock` object. When `sizeof...(MutexTypes)` is `1`, the supplied
122
- `Mutex` type shall meet the `BasicLockable` requirements (
123
- [[thread.req.lockable.basic]]). Otherwise, each of the mutex types shall
124
- meet the `Lockable` requirements ([[thread.req.lockable.req]]).
125
 
126
  ``` cpp
127
  explicit scoped_lock(MutexTypes&... m);
128
  ```
129
 
130
- *Requires:* If a `MutexTypes` type is not a recursive mutex, the calling
131
- thread does not own the corresponding mutex element of `m`.
132
 
133
  *Effects:* Initializes `pm` with `tie(m...)`. Then if
134
  `sizeof...(MutexTypes)` is `0`, no effects. Otherwise if
135
  `sizeof...(MutexTypes)` is `1`, then `m.lock()`. Otherwise,
136
  `lock(m...)`.
137
 
138
  ``` cpp
139
- explicit scoped_lock(MutexTypes&... m, adopt_lock_t);
140
  ```
141
 
142
- *Requires:* The calling thread owns all the mutexes in `m`.
143
 
144
  *Effects:* Initializes `pm` with `tie(m...)`.
145
 
146
  *Throws:* Nothing.
147
 
@@ -202,12 +195,10 @@ namespace std {
202
  private:
203
  mutex_type* pm; // exposition only
204
  bool owns; // exposition only
205
  };
206
 
207
- template<class Mutex> unique_lock(unique_lock<Mutex>) -> unique_lock<Mutex>;
208
-
209
  template<class Mutex>
210
  void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y) noexcept;
211
  }
212
  ```
213
 
@@ -216,123 +207,113 @@ object within a scope. Ownership of the lockable object may be acquired
216
  at construction or after construction, and may be transferred, after
217
  acquisition, to another `unique_lock` object. Objects of type
218
  `unique_lock` are not copyable but are movable. The behavior of a
219
  program is undefined if the contained pointer `pm` is not null and the
220
  lockable object pointed to by `pm` does not exist for the entire
221
- remaining lifetime ([[basic.life]]) of the `unique_lock` object. The
222
- supplied `Mutex` type shall meet the `BasicLockable` requirements (
223
- [[thread.req.lockable.basic]]).
224
 
225
- [*Note 1*: `unique_lock<Mutex>` meets the `BasicLockable` requirements.
226
- If `Mutex` meets the `Lockable` requirements (
227
- [[thread.req.lockable.req]]), `unique_lock<Mutex>` also meets the
228
- `Lockable` requirements; if `Mutex` meets the `TimedLockable`
229
- requirements ([[thread.req.lockable.timed]]), `unique_lock<Mutex>` also
230
- meets the `TimedLockable` requirements. — *end note*]
231
 
232
- ##### `unique_lock` constructors, destructor, and assignment <a id="thread.lock.unique.cons">[[thread.lock.unique.cons]]</a>
233
 
234
  ``` cpp
235
  unique_lock() noexcept;
236
  ```
237
 
238
- *Effects:* Constructs an object of type `unique_lock`.
239
-
240
- *Postconditions:* `pm == 0` and `owns == false`.
241
 
242
  ``` cpp
243
  explicit unique_lock(mutex_type& m);
244
  ```
245
 
246
- *Requires:* If `mutex_type` is not a recursive mutex the calling thread
247
- does not own the mutex.
248
 
249
- *Effects:* Constructs an object of type `unique_lock` and calls
250
- `m.lock()`.
251
 
252
- *Postconditions:* `pm == addressof(m)` and `owns == true`.
253
 
254
  ``` cpp
255
  unique_lock(mutex_type& m, defer_lock_t) noexcept;
256
  ```
257
 
258
- *Effects:* Constructs an object of type `unique_lock`.
259
-
260
- *Postconditions:* `pm == addressof(m)` and `owns == false`.
261
 
262
  ``` cpp
263
  unique_lock(mutex_type& m, try_to_lock_t);
264
  ```
265
 
266
- *Requires:* The supplied `Mutex` type shall meet the `Lockable`
267
- requirements ([[thread.req.lockable.req]]). If `mutex_type` is not a
268
  recursive mutex the calling thread does not own the mutex.
269
 
270
- *Effects:* Constructs an object of type `unique_lock` and calls
271
- `m.try_lock()`.
272
 
273
- *Postconditions:* `pm == addressof(m)` and `owns == res`, where `res` is
274
- the value returned by the call to `m.try_lock()`.
275
 
276
  ``` cpp
277
  unique_lock(mutex_type& m, adopt_lock_t);
278
  ```
279
 
280
- *Requires:* The calling thread owns the mutex.
281
 
282
- *Effects:* Constructs an object of type `unique_lock`.
283
-
284
- *Postconditions:* `pm == addressof(m)` and `owns == true`.
285
 
286
  *Throws:* Nothing.
287
 
288
  ``` cpp
289
  template<class Clock, class Duration>
290
  unique_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time);
291
  ```
292
 
293
- *Requires:* If `mutex_type` is not a recursive mutex the calling thread
294
- does not own the mutex. The supplied `Mutex` type shall meet the
295
- `TimedLockable` requirements ([[thread.req.lockable.timed]]).
296
 
297
- *Effects:* Constructs an object of type `unique_lock` and calls
298
- `m.try_lock_until(abs_time)`.
299
 
300
- *Postconditions:* `pm == addressof(m)` and `owns == res`, where `res` is
301
- the value returned by the call to `m.try_lock_until(abs_time)`.
302
 
303
  ``` cpp
304
  template<class Rep, class Period>
305
  unique_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time);
306
  ```
307
 
308
- *Requires:* If `mutex_type` is not a recursive mutex the calling thread
309
- does not own the mutex. The supplied `Mutex` type shall meet the
310
- `TimedLockable` requirements ([[thread.req.lockable.timed]]).
311
 
312
- *Effects:* Constructs an object of type `unique_lock` and calls
313
- `m.try_lock_for(rel_time)`.
314
 
315
- *Postconditions:* `pm == addressof(m)` and `owns == res`, where `res` is
316
- the value returned by the call to `m.try_lock_for(rel_time)`.
317
 
318
  ``` cpp
319
  unique_lock(unique_lock&& u) noexcept;
320
  ```
321
 
322
- *Postconditions:* `pm == u_p.pm` and `owns == u_p.owns` (where `u_p` is
323
- the state of `u` just prior to this construction), `u.pm == 0` and
324
  `u.owns == false`.
325
 
326
  ``` cpp
327
  unique_lock& operator=(unique_lock&& u);
328
  ```
329
 
330
  *Effects:* If `owns` calls `pm->unlock()`.
331
 
332
- *Postconditions:* `pm == u_p.pm` and `owns == u_p.owns` (where `u_p` is
333
- the state of `u` just prior to this construction), `u.pm == 0` and
334
  `u.owns == false`.
335
 
336
  [*Note 1*: With a recursive mutex it is possible for both `*this` and
337
  `u` to own the same mutex before the assignment. In this case, `*this`
338
  will own the mutex after the assignment and `u` will not. — *end note*]
@@ -343,44 +324,44 @@ will own the mutex after the assignment and `u` will not. — *end note*]
343
  ~unique_lock();
344
  ```
345
 
346
  *Effects:* If `owns` calls `pm->unlock()`.
347
 
348
- ##### `unique_lock` locking <a id="thread.lock.unique.locking">[[thread.lock.unique.locking]]</a>
349
 
350
  ``` cpp
351
  void lock();
352
  ```
353
 
354
  *Effects:* As if by `pm->lock()`.
355
 
356
- *Postconditions:* `owns == true`.
357
 
358
  *Throws:* Any exception thrown by `pm->lock()`. `system_error` when an
359
- exception is required ([[thread.req.exception]]).
360
 
361
  *Error conditions:*
362
 
363
  - `operation_not_permitted` — if `pm` is `nullptr`.
364
  - `resource_deadlock_would_occur` — if on entry `owns` is `true`.
365
 
366
  ``` cpp
367
  bool try_lock();
368
  ```
369
 
370
- *Requires:* The supplied `Mutex` shall meet the `Lockable`
371
- requirements ([[thread.req.lockable.req]]).
372
 
373
  *Effects:* As if by `pm->try_lock()`.
374
 
375
  *Returns:* The value returned by the call to `try_lock()`.
376
 
377
- *Postconditions:* `owns == res`, where `res` is the value returned by
378
- the call to `try_lock()`.
379
 
380
  *Throws:* Any exception thrown by `pm->try_lock()`. `system_error` when
381
- an exception is required ([[thread.req.exception]]).
382
 
383
  *Error conditions:*
384
 
385
  - `operation_not_permitted` — if `pm` is `nullptr`.
386
  - `resource_deadlock_would_occur` — if on entry `owns` is `true`.
@@ -388,22 +369,22 @@ an exception is required ([[thread.req.exception]]).
388
  ``` cpp
389
  template<class Clock, class Duration>
390
  bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
391
  ```
392
 
393
- *Requires:* The supplied `Mutex` type shall meet the `TimedLockable`
394
- requirements ([[thread.req.lockable.timed]]).
395
 
396
  *Effects:* As if by `pm->try_lock_until(abs_time)`.
397
 
398
  *Returns:* The value returned by the call to `try_lock_until(abs_time)`.
399
 
400
- *Postconditions:* `owns == res`, where `res` is the value returned by
401
- the call to `try_lock_until(abs_time)`.
402
 
403
  *Throws:* Any exception thrown by `pm->try_lock_until()`. `system_error`
404
- when an exception is required ([[thread.req.exception]]).
405
 
406
  *Error conditions:*
407
 
408
  - `operation_not_permitted` — if `pm` is `nullptr`.
409
  - `resource_deadlock_would_occur` — if on entry `owns` is `true`.
@@ -411,22 +392,22 @@ when an exception is required ([[thread.req.exception]]).
411
  ``` cpp
412
  template<class Rep, class Period>
413
  bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
414
  ```
415
 
416
- *Requires:* The supplied `Mutex` type shall meet the `TimedLockable`
417
- requirements ([[thread.req.lockable.timed]]).
418
 
419
  *Effects:* As if by `pm->try_lock_for(rel_time)`.
420
 
421
- *Returns:* The value returned by the call to `try_lock_until(rel_time)`.
422
 
423
- *Postconditions:* `owns == res`, where `res` is the value returned by
424
- the call to `try_lock_for(rel_time)`.
425
 
426
  *Throws:* Any exception thrown by `pm->try_lock_for()`. `system_error`
427
- when an exception is required ([[thread.req.exception]]).
428
 
429
  *Error conditions:*
430
 
431
  - `operation_not_permitted` — if `pm` is `nullptr`.
432
  - `resource_deadlock_would_occur` — if on entry `owns` is `true`.
@@ -435,20 +416,20 @@ when an exception is required ([[thread.req.exception]]).
435
  void unlock();
436
  ```
437
 
438
  *Effects:* As if by `pm->unlock()`.
439
 
440
- *Postconditions:* `owns == false`.
441
 
442
  *Throws:* `system_error` when an exception is
443
- required ([[thread.req.exception]]).
444
 
445
  *Error conditions:*
446
 
447
  - `operation_not_permitted` — if on entry `owns` is `false`.
448
 
449
- ##### `unique_lock` modifiers <a id="thread.lock.unique.mod">[[thread.lock.unique.mod]]</a>
450
 
451
  ``` cpp
452
  void swap(unique_lock& u) noexcept;
453
  ```
454
 
@@ -458,20 +439,20 @@ void swap(unique_lock& u) noexcept;
458
  mutex_type* release() noexcept;
459
  ```
460
 
461
  *Returns:* The previous value of `pm`.
462
 
463
- *Postconditions:* `pm == 0` and `owns == false`.
464
 
465
  ``` cpp
466
  template<class Mutex>
467
  void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y) noexcept;
468
  ```
469
 
470
  *Effects:* As if by `x.swap(y)`.
471
 
472
- ##### `unique_lock` observers <a id="thread.lock.unique.obs">[[thread.lock.unique.obs]]</a>
473
 
474
  ``` cpp
475
  bool owns_lock() const noexcept;
476
  ```
477
 
@@ -503,15 +484,13 @@ namespace std {
503
  explicit shared_lock(mutex_type& m); // blocking
504
  shared_lock(mutex_type& m, defer_lock_t) noexcept;
505
  shared_lock(mutex_type& m, try_to_lock_t);
506
  shared_lock(mutex_type& m, adopt_lock_t);
507
  template<class Clock, class Duration>
508
- shared_lock(mutex_type& m,
509
- const chrono::time_point<Clock, Duration>& abs_time);
510
  template<class Rep, class Period>
511
- shared_lock(mutex_type& m,
512
- const chrono::duration<Rep, Period>& rel_time);
513
  ~shared_lock();
514
 
515
  shared_lock(const shared_lock&) = delete;
516
  shared_lock& operator=(const shared_lock&) = delete;
517
 
@@ -539,12 +518,10 @@ namespace std {
539
  private:
540
  mutex_type* pm; // exposition only
541
  bool owns; // exposition only
542
  };
543
 
544
- template<class Mutex> shared_lock(shared_lock<Mutex>) -> shared_lock<Mutex>;
545
-
546
  template<class Mutex>
547
  void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;
548
  }
549
  ```
550
 
@@ -553,99 +530,89 @@ lockable object within a scope. Shared ownership of the lockable object
553
  may be acquired at construction or after construction, and may be
554
  transferred, after acquisition, to another `shared_lock` object. Objects
555
  of type `shared_lock` are not copyable but are movable. The behavior of
556
  a program is undefined if the contained pointer `pm` is not null and the
557
  lockable object pointed to by `pm` does not exist for the entire
558
- remaining lifetime ([[basic.life]]) of the `shared_lock` object. The
559
- supplied `Mutex` type shall meet the shared mutex requirements (
560
- [[thread.sharedtimedmutex.requirements]]).
561
 
562
- [*Note 1*: `shared_lock<Mutex>` meets the `TimedLockable`
563
- requirements ([[thread.req.lockable.timed]]). — *end note*]
564
 
565
- ##### `shared_lock` constructors, destructor, and assignment <a id="thread.lock.shared.cons">[[thread.lock.shared.cons]]</a>
566
 
567
  ``` cpp
568
  shared_lock() noexcept;
569
  ```
570
 
571
- *Effects:* Constructs an object of type `shared_lock`.
572
-
573
- *Postconditions:* `pm == nullptr` and `owns == false`.
574
 
575
  ``` cpp
576
  explicit shared_lock(mutex_type& m);
577
  ```
578
 
579
- *Requires:* The calling thread does not own the mutex for any ownership
580
- mode.
581
 
582
- *Effects:* Constructs an object of type `shared_lock` and calls
583
- `m.lock_shared()`.
584
 
585
- *Postconditions:* `pm == addressof(m)` and `owns == true`.
586
 
587
  ``` cpp
588
  shared_lock(mutex_type& m, defer_lock_t) noexcept;
589
  ```
590
 
591
- *Effects:* Constructs an object of type `shared_lock`.
592
-
593
- *Postconditions:* `pm == addressof(m)` and `owns == false`.
594
 
595
  ``` cpp
596
  shared_lock(mutex_type& m, try_to_lock_t);
597
  ```
598
 
599
- *Requires:* The calling thread does not own the mutex for any ownership
600
- mode.
601
 
602
- *Effects:* Constructs an object of type `shared_lock` and calls
603
- `m.try_lock_shared()`.
604
 
605
- *Postconditions:* `pm == addressof(m)` and `owns == res` where `res` is
606
- the value returned by the call to `m.try_lock_shared()`.
607
 
608
  ``` cpp
609
  shared_lock(mutex_type& m, adopt_lock_t);
610
  ```
611
 
612
- *Requires:* The calling thread has shared ownership of the mutex.
613
 
614
- *Effects:* Constructs an object of type `shared_lock`.
615
-
616
- *Postconditions:* `pm == addressof(m)` and `owns == true`.
617
 
618
  ``` cpp
619
  template<class Clock, class Duration>
620
  shared_lock(mutex_type& m,
621
  const chrono::time_point<Clock, Duration>& abs_time);
622
  ```
623
 
624
- *Requires:* The calling thread does not own the mutex for any ownership
625
- mode.
626
 
627
- *Effects:* Constructs an object of type `shared_lock` and calls
628
- `m.try_lock_shared_until(abs_time)`.
629
 
630
- *Postconditions:* `pm == addressof(m)` and `owns == res` where `res` is
631
- the value returned by the call to `m.try_lock_shared_until(abs_time)`.
632
 
633
  ``` cpp
634
  template<class Rep, class Period>
635
  shared_lock(mutex_type& m,
636
  const chrono::duration<Rep, Period>& rel_time);
637
  ```
638
 
639
- *Requires:* The calling thread does not own the mutex for any ownership
640
- mode.
641
 
642
- *Effects:* Constructs an object of type `shared_lock` and calls
643
- `m.try_lock_shared_for(rel_time)`.
644
 
645
- *Postconditions:* `pm == addressof(m)` and `owns == res` where `res` is
646
- the value returned by the call to `m.try_lock_shared_for(rel_time)`.
647
 
648
  ``` cpp
649
  ~shared_lock();
650
  ```
651
 
@@ -653,36 +620,36 @@ the value returned by the call to `m.try_lock_shared_for(rel_time)`.
653
 
654
  ``` cpp
655
  shared_lock(shared_lock&& sl) noexcept;
656
  ```
657
 
658
- *Postconditions:* `pm == sl_p.pm` and `owns == sl_p.owns` (where `sl_p`
659
- is the state of `sl` just prior to this construction),
660
- `sl.pm == nullptr` and `sl.owns == false`.
661
 
662
  ``` cpp
663
  shared_lock& operator=(shared_lock&& sl) noexcept;
664
  ```
665
 
666
  *Effects:* If `owns` calls `pm->unlock_shared()`.
667
 
668
- *Postconditions:* `pm == sl_p.pm` and `owns == sl_p.owns` (where `sl_p`
669
- is the state of `sl` just prior to this assignment), `sl.pm == nullptr`
670
- and `sl.owns == false`.
671
 
672
- ##### `shared_lock` locking <a id="thread.lock.shared.locking">[[thread.lock.shared.locking]]</a>
673
 
674
  ``` cpp
675
  void lock();
676
  ```
677
 
678
  *Effects:* As if by `pm->lock_shared()`.
679
 
680
- *Postconditions:* `owns == true`.
681
 
682
  *Throws:* Any exception thrown by `pm->lock_shared()`. `system_error`
683
- when an exception is required ([[thread.req.exception]]).
684
 
685
  *Error conditions:*
686
 
687
  - `operation_not_permitted` — if `pm` is `nullptr`.
688
  - `resource_deadlock_would_occur` — if on entry `owns` is `true`.
@@ -693,39 +660,36 @@ bool try_lock();
693
 
694
  *Effects:* As if by `pm->try_lock_shared()`.
695
 
696
  *Returns:* The value returned by the call to `pm->try_lock_shared()`.
697
 
698
- *Postconditions:* `owns == res`, where `res` is the value returned by
699
- the call to `pm->try_lock_shared()`.
700
 
701
  *Throws:* Any exception thrown by `pm->try_lock_shared()`.
702
- `system_error` when an exception is
703
- required ([[thread.req.exception]]).
704
 
705
  *Error conditions:*
706
 
707
  - `operation_not_permitted` — if `pm` is `nullptr`.
708
  - `resource_deadlock_would_occur` — if on entry `owns` is `true`.
709
 
710
  ``` cpp
711
  template<class Clock, class Duration>
712
- bool
713
- try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
714
  ```
715
 
716
  *Effects:* As if by `pm->try_lock_shared_until(abs_time)`.
717
 
718
  *Returns:* The value returned by the call to
719
  `pm->try_lock_shared_until(abs_time)`.
720
 
721
- *Postconditions:* `owns == res`, where `res` is the value returned by
722
- the call to `pm->try_lock_shared_until(abs_time)`.
723
 
724
  *Throws:* Any exception thrown by `pm->try_lock_shared_until(abs_time)`.
725
- `system_error` when an exception is
726
- required ([[thread.req.exception]]).
727
 
728
  *Error conditions:*
729
 
730
  - `operation_not_permitted` — if `pm` is `nullptr`.
731
  - `resource_deadlock_would_occur` — if on entry `owns` is `true`.
@@ -738,16 +702,15 @@ template <class Rep, class Period>
738
  *Effects:* As if by `pm->try_lock_shared_for(rel_time)`.
739
 
740
  *Returns:* The value returned by the call to
741
  `pm->try_lock_shared_for(rel_time)`.
742
 
743
- *Postconditions:* `owns == res`, where `res` is the value returned by
744
- the call to `pm->try_lock_shared_for(rel_time)`.
745
 
746
  *Throws:* Any exception thrown by `pm->try_lock_shared_for(rel_time)`.
747
- `system_error` when an exception is
748
- required ([[thread.req.exception]]).
749
 
750
  *Error conditions:*
751
 
752
  - `operation_not_permitted` — if `pm` is `nullptr`.
753
  - `resource_deadlock_would_occur` — if on entry `owns` is `true`.
@@ -756,20 +719,20 @@ required ([[thread.req.exception]]).
756
  void unlock();
757
  ```
758
 
759
  *Effects:* As if by `pm->unlock_shared()`.
760
 
761
- *Postconditions:* `owns == false`.
762
 
763
  *Throws:* `system_error` when an exception is
764
- required ([[thread.req.exception]]).
765
 
766
  *Error conditions:*
767
 
768
  - `operation_not_permitted` — if on entry `owns` is `false`.
769
 
770
- ##### `shared_lock` modifiers <a id="thread.lock.shared.mod">[[thread.lock.shared.mod]]</a>
771
 
772
  ``` cpp
773
  void swap(shared_lock& sl) noexcept;
774
  ```
775
 
@@ -779,20 +742,20 @@ void swap(shared_lock& sl) noexcept;
779
  mutex_type* release() noexcept;
780
  ```
781
 
782
  *Returns:* The previous value of `pm`.
783
 
784
- *Postconditions:* `pm == nullptr` and `owns == false`.
785
 
786
  ``` cpp
787
  template<class Mutex>
788
  void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;
789
  ```
790
 
791
  *Effects:* As if by `x.swap(y)`.
792
 
793
- ##### `shared_lock` observers <a id="thread.lock.shared.obs">[[thread.lock.shared.obs]]</a>
794
 
795
  ``` cpp
796
  bool owns_lock() const noexcept;
797
  ```
798
 
 
46
  lock_guard& operator=(const lock_guard&) = delete;
47
 
48
  private:
49
  mutex_type& pm; // exposition only
50
  };
 
 
51
  }
52
  ```
53
 
54
  An object of type `lock_guard` controls the ownership of a lockable
55
  object within a scope. A `lock_guard` object maintains ownership of a
56
+ lockable object throughout the `lock_guard` object’s lifetime
57
+ [[basic.life]]. The behavior of a program is undefined if the lockable
58
  object referenced by `pm` does not exist for the entire lifetime of the
59
  `lock_guard` object. The supplied `Mutex` type shall meet the
60
+ *Cpp17BasicLockable* requirements [[thread.req.lockable.basic]].
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();
 
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
 
100
  scoped_lock(const scoped_lock&) = delete;
101
  scoped_lock& operator=(const scoped_lock&) = delete;
102
 
103
  private:
104
  tuple<MutexTypes&...> pm; // exposition only
105
  };
 
 
 
106
  }
107
  ```
108
 
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
 
 
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
 
 
207
  at construction or after construction, and may be transferred, after
208
  acquisition, to another `unique_lock` object. Objects of type
209
  `unique_lock` are not copyable but are movable. The behavior of a
210
  program is undefined if the contained pointer `pm` is not null and the
211
  lockable object pointed to by `pm` does not exist for the entire
212
+ remaining lifetime [[basic.life]] of the `unique_lock` object. The
213
+ supplied `Mutex` type shall meet the *Cpp17BasicLockable* requirements
214
+ [[thread.req.lockable.basic]].
215
 
216
+ [*Note 1*: `unique_lock<Mutex>` meets the *Cpp17BasicLockable*
217
+ requirements. If `Mutex` meets the *Cpp17Lockable* requirements
218
+ [[thread.req.lockable.req]], `unique_lock<Mutex>` also meets the
219
+ *Cpp17Lockable* requirements; if `Mutex` meets the *Cpp17TimedLockable*
220
+ requirements [[thread.req.lockable.timed]], `unique_lock<Mutex>` also
221
+ meets the *Cpp17TimedLockable* requirements. — *end note*]
222
 
223
+ ##### Constructors, destructor, and assignment <a id="thread.lock.unique.cons">[[thread.lock.unique.cons]]</a>
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
243
  unique_lock(mutex_type& m, defer_lock_t) noexcept;
244
  ```
245
 
246
+ *Ensures:* `pm == addressof(m)` and `owns == false`.
 
 
247
 
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
283
+ value returned by the call to `m.try_lock_until(abs_time)`.
284
 
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
297
+ value returned by the call to `m.try_lock_for(rel_time)`.
298
 
299
  ``` cpp
300
  unique_lock(unique_lock&& u) noexcept;
301
  ```
302
 
303
+ *Ensures:* `pm == u_p.pm` and `owns == u_p.owns` (where `u_p` is the
304
+ state of `u` just prior to this construction), `u.pm == 0` and
305
  `u.owns == false`.
306
 
307
  ``` cpp
308
  unique_lock& operator=(unique_lock&& u);
309
  ```
310
 
311
  *Effects:* If `owns` calls `pm->unlock()`.
312
 
313
+ *Ensures:* `pm == u_p.pm` and `owns == u_p.owns` (where `u_p` is the
314
+ state of `u` just prior to this construction), `u.pm == 0` and
315
  `u.owns == false`.
316
 
317
  [*Note 1*: With a recursive mutex it is possible for both `*this` and
318
  `u` to own the same mutex before the assignment. In this case, `*this`
319
  will own the mutex after the assignment and `u` will not. — *end note*]
 
324
  ~unique_lock();
325
  ```
326
 
327
  *Effects:* If `owns` calls `pm->unlock()`.
328
 
329
+ ##### Locking <a id="thread.lock.unique.locking">[[thread.lock.unique.locking]]</a>
330
 
331
  ``` cpp
332
  void lock();
333
  ```
334
 
335
  *Effects:* As if by `pm->lock()`.
336
 
337
+ *Ensures:* `owns == true`.
338
 
339
  *Throws:* Any exception thrown by `pm->lock()`. `system_error` when an
340
+ exception is required [[thread.req.exception]].
341
 
342
  *Error conditions:*
343
 
344
  - `operation_not_permitted` — if `pm` is `nullptr`.
345
  - `resource_deadlock_would_occur` — if on entry `owns` is `true`.
346
 
347
  ``` cpp
348
  bool try_lock();
349
  ```
350
 
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:*
365
 
366
  - `operation_not_permitted` — if `pm` is `nullptr`.
367
  - `resource_deadlock_would_occur` — if on entry `owns` is `true`.
 
369
  ``` cpp
370
  template<class Clock, class Duration>
371
  bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
372
  ```
373
 
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`.
 
392
  ``` cpp
393
  template<class Rep, class Period>
394
  bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
395
  ```
396
 
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`.
 
416
  void unlock();
417
  ```
418
 
419
  *Effects:* As if by `pm->unlock()`.
420
 
421
+ *Ensures:* `owns == false`.
422
 
423
  *Throws:* `system_error` when an exception is
424
+ required [[thread.req.exception]].
425
 
426
  *Error conditions:*
427
 
428
  - `operation_not_permitted` — if on entry `owns` is `false`.
429
 
430
+ ##### Modifiers <a id="thread.lock.unique.mod">[[thread.lock.unique.mod]]</a>
431
 
432
  ``` cpp
433
  void swap(unique_lock& u) noexcept;
434
  ```
435
 
 
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
 
451
  *Effects:* As if by `x.swap(y)`.
452
 
453
+ ##### Observers <a id="thread.lock.unique.obs">[[thread.lock.unique.obs]]</a>
454
 
455
  ``` cpp
456
  bool owns_lock() const noexcept;
457
  ```
458
 
 
484
  explicit shared_lock(mutex_type& m); // blocking
485
  shared_lock(mutex_type& m, defer_lock_t) noexcept;
486
  shared_lock(mutex_type& m, try_to_lock_t);
487
  shared_lock(mutex_type& m, adopt_lock_t);
488
  template<class Clock, class Duration>
489
+ shared_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time);
 
490
  template<class Rep, class Period>
491
+ shared_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time);
 
492
  ~shared_lock();
493
 
494
  shared_lock(const shared_lock&) = delete;
495
  shared_lock& operator=(const shared_lock&) = delete;
496
 
 
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
 
 
530
  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;
546
  ```
547
 
548
+ *Ensures:* `pm == nullptr` and `owns == false`.
 
 
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
562
  shared_lock(mutex_type& m, defer_lock_t) noexcept;
563
  ```
564
 
565
+ *Ensures:* `pm == addressof(m)` and `owns == false`.
 
 
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)`.
600
 
601
  ``` cpp
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)`.
614
 
615
  ``` cpp
616
  ~shared_lock();
617
  ```
618
 
 
620
 
621
  ``` cpp
622
  shared_lock(shared_lock&& sl) noexcept;
623
  ```
624
 
625
+ *Ensures:* `pm == sl_p.pm` and `owns == sl_p.owns` (where `sl_p` is the
626
+ state of `sl` just prior to this construction), `sl.pm == nullptr` and
627
+ `sl.owns == false`.
628
 
629
  ``` cpp
630
  shared_lock& operator=(shared_lock&& sl) noexcept;
631
  ```
632
 
633
  *Effects:* If `owns` calls `pm->unlock_shared()`.
634
 
635
+ *Ensures:* `pm == sl_p.pm` and `owns == sl_p.owns` (where `sl_p` is the
636
+ state of `sl` just prior to this assignment), `sl.pm == nullptr` and
637
+ `sl.owns == false`.
638
 
639
+ ##### Locking <a id="thread.lock.shared.locking">[[thread.lock.shared.locking]]</a>
640
 
641
  ``` cpp
642
  void lock();
643
  ```
644
 
645
  *Effects:* As if by `pm->lock_shared()`.
646
 
647
+ *Ensures:* `owns == true`.
648
 
649
  *Throws:* Any exception thrown by `pm->lock_shared()`. `system_error`
650
+ when an exception is required [[thread.req.exception]].
651
 
652
  *Error conditions:*
653
 
654
  - `operation_not_permitted` — if `pm` is `nullptr`.
655
  - `resource_deadlock_would_occur` — if on entry `owns` is `true`.
 
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
 
673
  - `operation_not_permitted` — if `pm` is `nullptr`.
674
  - `resource_deadlock_would_occur` — if on entry `owns` is `true`.
675
 
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
 
694
  - `operation_not_permitted` — if `pm` is `nullptr`.
695
  - `resource_deadlock_would_occur` — if on entry `owns` is `true`.
 
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
 
715
  - `operation_not_permitted` — if `pm` is `nullptr`.
716
  - `resource_deadlock_would_occur` — if on entry `owns` is `true`.
 
719
  void unlock();
720
  ```
721
 
722
  *Effects:* As if by `pm->unlock_shared()`.
723
 
724
+ *Ensures:* `owns == false`.
725
 
726
  *Throws:* `system_error` when an exception is
727
+ required [[thread.req.exception]].
728
 
729
  *Error conditions:*
730
 
731
  - `operation_not_permitted` — if on entry `owns` is `false`.
732
 
733
+ ##### Modifiers <a id="thread.lock.shared.mod">[[thread.lock.shared.mod]]</a>
734
 
735
  ``` cpp
736
  void swap(shared_lock& sl) noexcept;
737
  ```
738
 
 
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
 
754
  *Effects:* As if by `x.swap(y)`.
755
 
756
+ ##### Observers <a id="thread.lock.shared.obs">[[thread.lock.shared.obs]]</a>
757
 
758
  ``` cpp
759
  bool owns_lock() const noexcept;
760
  ```
761