From Jason Turner

[thread.mutex.requirements]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmp0pwae2ss/{from.md → to.md} +220 -29
tmp/tmp0pwae2ss/{from.md → to.md} RENAMED
@@ -5,22 +5,20 @@
5
  A mutex object facilitates protection against data races and allows safe
6
  synchronization of data between execution agents (
7
  [[thread.req.lockable]]). An execution agent *owns* a mutex from the
8
  time it successfully calls one of the lock functions until it calls
9
  unlock. Mutexes can be either recursive or non-recursive, and can grant
10
- simultaneous ownership to one or many execution agents. The mutex types
11
- supplied by the standard library provide exclusive ownership semantics:
12
- only one thread may own the mutex at a time. Both recursive and
13
- non-recursive mutexes are supplied.
14
 
15
  #### Mutex types <a id="thread.mutex.requirements.mutex">[[thread.mutex.requirements.mutex]]</a>
16
 
17
  The *mutex types* are the standard library types `std::mutex`,
18
- `std::recursive_mutex`, `std::timed_mutex`, and
19
- `std::recursive_timed_mutex`. They shall meet the requirements set out
20
- in this section. In this description, `m` denotes an object of a mutex
21
- type.
22
 
23
  The mutex types shall meet the `Lockable` requirements (
24
  [[thread.req.lockable.req]]).
25
 
26
  The mutex types shall be `DefaultConstructible` and `Destructible`. If
@@ -51,12 +49,12 @@ should be used to ensure that mutex objects are initialized and visible
51
  to other threads.
52
 
53
  The expression `m.lock()` shall be well-formed and have the following
54
  semantics:
55
 
56
- *Requires:* If `m` is of type `std::mutex` or `std::timed_mutex`, the
57
- calling thread does not own the mutex.
58
 
59
  *Effects:* Blocks the calling thread until ownership of the mutex can be
60
  obtained for the calling thread.
61
 
62
  The calling thread owns the mutex.
@@ -79,12 +77,12 @@ required ([[thread.req.exception]]).
79
  blocking is not possible.
80
 
81
  The expression `m.try_lock()` shall be well-formed and have the
82
  following semantics:
83
 
84
- *Requires:* If `m` is of type `std::mutex` or `std::timed_mutex`, the
85
- calling thread does not own the mutex.
86
 
87
  *Effects:* Attempts to obtain ownership of the mutex for the calling
88
  thread without blocking. If ownership is not obtained, there is no
89
  effect and `try_lock()` immediately returns. An implementation may fail
90
  to obtain the lock even if it is not held by any other thread. This
@@ -115,12 +113,12 @@ The calling thread shall own the mutex.
115
 
116
  *Effects:* Releases the calling thread’s ownership of the mutex.
117
 
118
  *Return type:* `void`
119
 
120
- *Synchronization:* This operation *synchronizes
121
- with* ([[intro.multithread]]) subsequent lock operations that obtain
122
  ownership on the same object.
123
 
124
  *Throws:* Nothing.
125
 
126
  ##### Class `mutex` <a id="thread.mutex.class">[[thread.mutex.class]]</a>
@@ -221,26 +219,25 @@ The behavior of a program is undefined if:
221
  - a thread terminates while owning a `recursive_mutex` object.
222
 
223
  #### Timed mutex types <a id="thread.timedmutex.requirements">[[thread.timedmutex.requirements]]</a>
224
 
225
  The *timed mutex types* are the standard library types
226
- `std::timed_mutex` and `std::recursive_timed_mutex`. They shall meet the
227
- requirements set out below. In this description, `m` denotes an object
228
- of a mutex type, `rel_time` denotes an object of an instantiation of
229
- `duration` ([[time.duration]]), and `abs_time` denotes an object of an
230
- instantiation of `time_point` ([[time.point]]).
 
231
 
232
  The timed mutex types shall meet the `TimedLockable` requirements (
233
  [[thread.req.lockable.timed]]).
234
 
235
  The expression `m.try_lock_for(rel_time)` shall be well-formed and have
236
  the following semantics:
237
 
238
- If the tick `period` of `rel_time` is not exactly convertible to the
239
- native tick `period`, the `duration` shall be rounded up to the nearest
240
- native tick `period`. If `m` is of type `std::timed_mutex`, the calling
241
- thread does not own the mutex.
242
 
243
  *Effects:* The function attempts to obtain ownership of the mutex within
244
  the relative timeout ([[thread.req.timing]]) specified by `rel_time`.
245
  If the time specified by `rel_time` is less than or equal to
246
  `rel_time.zero()`, the function attempts to obtain ownership without
@@ -256,17 +253,17 @@ implementations are expected to make a strong effort to do so.
256
 
257
  *Synchronization:* If `try_lock_for()` returns `true`, prior `unlock()`
258
  operations on the same object *synchronize
259
  with* ([[intro.multithread]]) this operation.
260
 
261
- *Throws:* Nothing.
262
 
263
  The expression `m.try_lock_until(abs_time)` shall be well-formed and
264
  have the following semantics:
265
 
266
- *Requires:* If `m` is of type `std::timed_mutex`, the calling thread
267
- does not own the mutex.
268
 
269
  *Effects:* The function attempts to obtain ownership of the mutex. If
270
  `abs_time` has already passed, the function attempts to obtain ownership
271
  without blocking (as if by calling `try_lock()`). The function shall
272
  return before the absolute timeout ([[thread.req.timing]]) specified by
@@ -281,11 +278,11 @@ strong effort to do so.
281
 
282
  *Synchronization:* If `try_lock_until()` returns `true`, prior
283
  `unlock()` operations on the same object *synchronize
284
  with* ([[intro.multithread]]) this operation.
285
 
286
- *Throws:* Nothing.
287
 
288
  ##### Class `timed_mutex` <a id="thread.timedmutex.class">[[thread.timedmutex.class]]</a>
289
 
290
  ``` cpp
291
  namespace std {
@@ -295,11 +292,11 @@ namespace std {
295
  ~timed_mutex();
296
 
297
  timed_mutex(const timed_mutex&) = delete;
298
  timed_mutex& operator=(const timed_mutex&) = delete;
299
 
300
- void lock();
301
  bool try_lock();
302
  template <class Rep, class Period>
303
  bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
304
  template <class Clock, class Duration>
305
  bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
@@ -341,11 +338,11 @@ namespace std {
341
  ~recursive_timed_mutex();
342
 
343
  recursive_timed_mutex(const recursive_timed_mutex&) = delete;
344
  recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete;
345
 
346
- void lock();
347
  bool try_lock() noexcept;
348
  template <class Rep, class Period>
349
  bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
350
  template <class Clock, class Duration>
351
  bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
@@ -385,5 +382,199 @@ the object be acquired by another thread.
385
  The behavior of a program is undefined if:
386
 
387
  - it destroys a `recursive_timed_mutex` object owned by any thread, or
388
  - a thread terminates while owning a `recursive_timed_mutex` object.
389
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
  A mutex object facilitates protection against data races and allows safe
6
  synchronization of data between execution agents (
7
  [[thread.req.lockable]]). An execution agent *owns* a mutex from the
8
  time it successfully calls one of the lock functions until it calls
9
  unlock. Mutexes can be either recursive or non-recursive, and can grant
10
+ simultaneous ownership to one or many execution agents. Both recursive
11
+ and non-recursive mutexes are supplied.
 
 
12
 
13
  #### Mutex types <a id="thread.mutex.requirements.mutex">[[thread.mutex.requirements.mutex]]</a>
14
 
15
  The *mutex types* are the standard library types `std::mutex`,
16
+ `std::recursive_mutex`, `std::timed_mutex`,
17
+ `std::recursive_timed_mutex`, and `std::shared_timed_mutex`. They shall
18
+ meet the requirements set out in this section. In this description, `m`
19
+ denotes an object of a mutex type.
20
 
21
  The mutex types shall meet the `Lockable` requirements (
22
  [[thread.req.lockable.req]]).
23
 
24
  The mutex types shall be `DefaultConstructible` and `Destructible`. If
 
49
  to other threads.
50
 
51
  The expression `m.lock()` shall be well-formed and have the following
52
  semantics:
53
 
54
+ *Requires:* If `m` is of type `std::mutex`, `std::timed_mutex`, or
55
+ `std::shared_timed_mutex`, the calling thread does not own the mutex.
56
 
57
  *Effects:* Blocks the calling thread until ownership of the mutex can be
58
  obtained for the calling thread.
59
 
60
  The calling thread owns the mutex.
 
77
  blocking is not possible.
78
 
79
  The expression `m.try_lock()` shall be well-formed and have the
80
  following semantics:
81
 
82
+ *Requires:* If `m` is of type `std::mutex`, `std::timed_mutex`, or
83
+ `std::shared_timed_mutex`, the calling thread does not own the mutex.
84
 
85
  *Effects:* Attempts to obtain ownership of the mutex for the calling
86
  thread without blocking. If ownership is not obtained, there is no
87
  effect and `try_lock()` immediately returns. An implementation may fail
88
  to obtain the lock even if it is not held by any other thread. This
 
113
 
114
  *Effects:* Releases the calling thread’s ownership of the mutex.
115
 
116
  *Return type:* `void`
117
 
118
+ *Synchronization:* This operation synchronizes
119
+ with ([[intro.multithread]]) subsequent lock operations that obtain
120
  ownership on the same object.
121
 
122
  *Throws:* Nothing.
123
 
124
  ##### Class `mutex` <a id="thread.mutex.class">[[thread.mutex.class]]</a>
 
219
  - a thread terminates while owning a `recursive_mutex` object.
220
 
221
  #### Timed mutex types <a id="thread.timedmutex.requirements">[[thread.timedmutex.requirements]]</a>
222
 
223
  The *timed mutex types* are the standard library types
224
+ `std::timed_mutex`, `std::recursive_timed_mutex`, and
225
+ `std::shared_timed_mutex`. They shall meet the requirements set out
226
+ below. In this description, `m` denotes an object of a mutex type,
227
+ `rel_time` denotes an object of an instantiation of `duration` (
228
+ [[time.duration]]), and `abs_time` denotes an object of an instantiation
229
+ of `time_point` ([[time.point]]).
230
 
231
  The timed mutex types shall meet the `TimedLockable` requirements (
232
  [[thread.req.lockable.timed]]).
233
 
234
  The expression `m.try_lock_for(rel_time)` shall be well-formed and have
235
  the following semantics:
236
 
237
+ If `m` is of type `std::timed_mutex` or `std::shared_timed_mutex`, the
238
+ calling thread does not own the mutex.
 
 
239
 
240
  *Effects:* The function attempts to obtain ownership of the mutex within
241
  the relative timeout ([[thread.req.timing]]) specified by `rel_time`.
242
  If the time specified by `rel_time` is less than or equal to
243
  `rel_time.zero()`, the function attempts to obtain ownership without
 
253
 
254
  *Synchronization:* If `try_lock_for()` returns `true`, prior `unlock()`
255
  operations on the same object *synchronize
256
  with* ([[intro.multithread]]) this operation.
257
 
258
+ *Throws:* Timeout-related exceptions ([[thread.req.timing]]).
259
 
260
  The expression `m.try_lock_until(abs_time)` shall be well-formed and
261
  have the following semantics:
262
 
263
+ *Requires:* If `m` is of type `std::timed_mutex` or
264
+ `std::shared_timed_mutex`, the calling thread does not own the mutex.
265
 
266
  *Effects:* The function attempts to obtain ownership of the mutex. If
267
  `abs_time` has already passed, the function attempts to obtain ownership
268
  without blocking (as if by calling `try_lock()`). The function shall
269
  return before the absolute timeout ([[thread.req.timing]]) specified by
 
278
 
279
  *Synchronization:* If `try_lock_until()` returns `true`, prior
280
  `unlock()` operations on the same object *synchronize
281
  with* ([[intro.multithread]]) this operation.
282
 
283
+ *Throws:* Timeout-related exceptions ([[thread.req.timing]]).
284
 
285
  ##### Class `timed_mutex` <a id="thread.timedmutex.class">[[thread.timedmutex.class]]</a>
286
 
287
  ``` cpp
288
  namespace std {
 
292
  ~timed_mutex();
293
 
294
  timed_mutex(const timed_mutex&) = delete;
295
  timed_mutex& operator=(const timed_mutex&) = delete;
296
 
297
+ void lock(); // blocking
298
  bool try_lock();
299
  template <class Rep, class Period>
300
  bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
301
  template <class Clock, class Duration>
302
  bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
 
338
  ~recursive_timed_mutex();
339
 
340
  recursive_timed_mutex(const recursive_timed_mutex&) = delete;
341
  recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete;
342
 
343
+ void lock(); // blocking
344
  bool try_lock() noexcept;
345
  template <class Rep, class Period>
346
  bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
347
  template <class Clock, class Duration>
348
  bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
 
382
  The behavior of a program is undefined if:
383
 
384
  - it destroys a `recursive_timed_mutex` object owned by any thread, or
385
  - a thread terminates while owning a `recursive_timed_mutex` object.
386
 
387
+ #### Shared timed mutex types <a id="thread.sharedtimedmutex.requirements">[[thread.sharedtimedmutex.requirements]]</a>
388
+
389
+ The standard library type `std::shared_timed_mutex` is a *shared timed
390
+ mutex type*. Shared timed mutex types shall meet the requirements of
391
+ timed mutex types ([[thread.timedmutex.requirements]]), and
392
+ additionally shall meet the requirements set out below. In this
393
+ description, `m` denotes an object of a mutex type, `rel_type` denotes
394
+ an object of an instantiation of `duration` ([[time.duration]]), and
395
+ `abs_time` denotes an object of an instantiation of `time_point` (
396
+ [[time.point]]).
397
+
398
+ In addition to the exclusive lock ownership mode specified in 
399
+ [[thread.mutex.requirements.mutex]], shared mutex types provide a
400
+ *shared lock* ownership mode. Multiple execution agents can
401
+ simultaneously hold a shared lock ownership of a shared mutex type. But
402
+ no execution agent shall hold a shared lock while another execution
403
+ agent holds an exclusive lock on the same shared mutex type, and
404
+ vice-versa. The maximum number of execution agents which can share a
405
+ shared lock on a single shared mutex type is unspecified, but shall be
406
+ at least 10000. If more than the maximum number of execution agents
407
+ attempt to obtain a shared lock, the excess execution agents shall block
408
+ until the number of shared locks are reduced below the maximum amount by
409
+ other execution agents releasing their shared lock.
410
+
411
+ The expression `m.lock_shared()` shall be well-formed and have the
412
+ following semantics:
413
+
414
+ *Requires:* The calling thread has no ownership of the mutex.
415
+
416
+ *Effects:* Blocks the calling thread until shared ownership of the mutex
417
+ can be obtained for the calling thread. If an exception is thrown then a
418
+ shared lock shall not have been acquired for the current thread.
419
+
420
+ The calling thread has a shared lock on the mutex.
421
+
422
+ *Return type:* `void`.
423
+
424
+ *Synchronization:* Prior `unlock()` operations on the same object shall
425
+ synchronize with  ([[intro.multithread]]) this operation.
426
+
427
+ *Throws:* `system_error` when an exception is required
428
+  ([[thread.req.exception]]).
429
+
430
+ *Error conditions:*
431
+
432
+ - `operation_not_permitted` — if the thread does not have the privilege
433
+ to perform the operation.
434
+ - `resource_deadlock_would_occur` — if the implementation detects that a
435
+ deadlock would occur.
436
+ - `device_or_resource_busy` — if the mutex is already locked and
437
+ blocking is not possible.
438
+
439
+ The expression `m.unlock_shared()` shall be well-formed and have the
440
+ following semantics:
441
+
442
+ *Requires:* The calling thread shall hold a shared lock on the mutex.
443
+
444
+ *Effects:* Releases a shared lock on the mutex held by the calling
445
+ thread.
446
+
447
+ *Return type:* `void`.
448
+
449
+ *Synchronization:* This operation synchronizes
450
+ with ([[intro.multithread]]) subsequent `lock()` operations that obtain
451
+ ownership on the same object.
452
+
453
+ *Throws:* Nothing.
454
+
455
+ The expression `m.try_lock_shared()` shall be well-formed and have the
456
+ following semantics:
457
+
458
+ *Requires:* The calling thread has no ownership of the mutex.
459
+
460
+ *Effects:* Attempts to obtain shared ownership of the mutex for the
461
+ calling thread without blocking. If shared ownership is not obtained,
462
+ there is no effect and `try_lock_shared()` immediately returns. An
463
+ implementation may fail to obtain the lock even if it is not held by any
464
+ other thread.
465
+
466
+ *Return type:* `bool`.
467
+
468
+ *Returns:* `true` if the shared ownership lock was acquired, `false`
469
+ otherwise.
470
+
471
+ *Synchronization:* If `try_lock_shared()` returns `true`, prior
472
+ `unlock()` operations on the same object synchronize with
473
+  ([[intro.multithread]]) this operation.
474
+
475
+ *Throws:* Nothing.
476
+
477
+ The expression `m.try_lock_shared_for(rel_time)` shall be well-formed
478
+ and have the following semantics:
479
+
480
+ *Requires:* The calling thread has no ownership of the mutex.
481
+
482
+ *Effects:* Attempts to obtain shared lock ownership for the calling
483
+ thread within the relative timeout ([[thread.req.timing]]) specified by
484
+ `rel_time`. If the time specified by `rel_time` is less than or equal to
485
+ `rel_time.zero()`, the function attempts to obtain ownership without
486
+ blocking (as if by calling `try_lock_shared()`). The function shall
487
+ return within the timeout specified by `rel_time` only if it has
488
+ obtained shared ownership of the mutex object. As with `try_lock()`,
489
+ there is no guarantee that ownership will be obtained if the lock is
490
+ available, but implementations are expected to make a strong effort to
491
+ do so. If an exception is thrown then a shared lock shall not have been
492
+ acquired for the current thread.
493
+
494
+ *Return type:* `bool`.
495
+
496
+ *Returns:* `true` if the shared lock was acquired, `false` otherwise.
497
+
498
+ *Synchronization:* If `try_lock_shared_for()` returns `true`, prior
499
+ `unlock()` operations on the same object synchronize
500
+ with ([[intro.multithread]]) this operation.
501
+
502
+ *Throws:* Timeout-related exceptions ([[thread.req.timing]]).
503
+
504
+ The expression `m.try_lock_shared_until(abs_time)` shall be well-formed
505
+ and have the following semantics:
506
+
507
+ *Requires:* The calling thread has no ownership of the mutex.
508
+
509
+ *Effects:* The function attempts to obtain shared ownership of the
510
+ mutex. If `abs_time` has already passed, the function attempts to obtain
511
+ shared ownership without blocking (as if by calling
512
+ `try_lock_shared()`). The function shall return before the absolute
513
+ timeout ([[thread.req.timing]]) specified by `abs_time` only if it has
514
+ obtained shared ownership of the mutex object. As with `try_lock()`,
515
+ there is no guarantee that ownership will be obtained if the lock is
516
+ available, but implementations are expected to make a strong effort to
517
+ do so. If an exception is thrown then a shared lock shall not have been
518
+ acquired for the current thread.
519
+
520
+ *Return type:* `bool`.
521
+
522
+ *Returns:* `true` if the shared lock was acquired, `false` otherwise.
523
+
524
+ *Synchronization:* If `try_lock_shared_until()` returns `true`, prior
525
+ `unlock()` operations on the same object synchronize
526
+ with ([[intro.multithread]]) this operation.
527
+
528
+ *Throws:* Timeout-related exceptions ([[thread.req.timing]]).
529
+
530
+ ##### Class `shared_timed_mutex` <a id="thread.sharedtimedmutex.class">[[thread.sharedtimedmutex.class]]</a>
531
+
532
+ ``` cpp
533
+ namespace std {
534
+ class shared_timed_mutex {
535
+ public:
536
+ shared_timed_mutex();
537
+ ~shared_timed_mutex();
538
+
539
+ shared_timed_mutex(const shared_timed_mutex&) = delete;
540
+ shared_timed_mutex& operator=(const shared_timed_mutex&) = delete;
541
+
542
+ // Exclusive ownership
543
+ void lock(); // blocking
544
+ bool try_lock();
545
+ template <class Rep, class Period>
546
+ bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
547
+ template <class Clock, class Duration>
548
+ bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
549
+ void unlock();
550
+
551
+ // Shared ownership
552
+ void lock_shared(); // blocking
553
+ bool try_lock_shared();
554
+ template <class Rep, class Period>
555
+ bool
556
+ try_lock_shared_for(const chrono::duration<Rep, Period>& rel_time);
557
+ template <class Clock, class Duration>
558
+ bool
559
+ try_lock_shared_until(const chrono::time_point<Clock, Duration>& abs_time);
560
+ void unlock_shared();
561
+ };
562
+ }
563
+ ```
564
+
565
+ The class `shared_timed_mutex` provides a non-recursive mutex with
566
+ shared ownership semantics.
567
+
568
+ The class `shared_timed_mutex` shall satisfy all of the
569
+ `SharedTimedMutex` requirements (
570
+ [[thread.sharedtimedmutex.requirements]]). It shall be a standard-layout
571
+ class (Clause  [[class]]).
572
+
573
+ The behavior of a program is undefined if:
574
+
575
+ - it destroys a `shared_timed_mutex` object owned by any thread,
576
+ - a thread attempts to recursively gain any ownership of a
577
+ `shared_timed_mutex`, or
578
+ - a thread terminates while possessing any ownership of a
579
+ `shared_timed_mutex`.
580
+