From Jason Turner

[thread.mutex.requirements]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmplkn231ie/{from.md → to.md} +59 -46
tmp/tmplkn231ie/{from.md → to.md} RENAMED
@@ -10,18 +10,20 @@ 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 `mutex`,
16
  `recursive_mutex`, `timed_mutex`, `recursive_timed_mutex`,
17
  `shared_mutex`, and `shared_timed_mutex`. They meet the requirements set
18
- out in this subclause. In this description, `m` denotes an object of a
19
- mutex type.
20
 
21
- The mutex types meet the *Cpp17Lockable* requirements
22
- [[thread.req.lockable.req]].
23
 
24
  The mutex types meet *Cpp17DefaultConstructible* and
25
  *Cpp17Destructible*. If initialization of an object of a mutex type
26
  fails, an exception of type `system_error` is thrown. The mutex types
27
  are neither copyable nor movable.
@@ -39,15 +41,15 @@ functions of the mutex types are as follows:
39
  The implementation provides lock and unlock operations, as described
40
  below. For purposes of determining the existence of a data race, these
41
  behave as atomic operations [[intro.multithread]]. The lock and unlock
42
  operations on a single mutex appears to occur in a single total order.
43
 
44
- [*Note 1*: This can be viewed as the modification order
45
  [[intro.multithread]] of the mutex. — *end note*]
46
 
47
- [*Note 2*: Construction and destruction of an object of a mutex type
48
- need not be thread-safe; other synchronization should be used to ensure
49
  that mutex objects are initialized and visible to other
50
  threads. — *end note*]
51
 
52
  The expression `m.lock()` is well-formed and has the following
53
  semantics:
@@ -57,17 +59,17 @@ semantics:
57
  the mutex.
58
 
59
  *Effects:* Blocks the calling thread until ownership of the mutex can be
60
  obtained for the calling thread.
61
 
62
- *Ensures:* The calling thread owns the mutex.
63
-
64
- *Return type:* `void`.
65
-
66
  *Synchronization:* Prior `unlock()` operations on the same object
67
  *synchronize with*[[intro.multithread]] this operation.
68
 
 
 
 
 
69
  *Throws:* `system_error` when an exception is
70
  required [[thread.req.exception]].
71
 
72
  *Error conditions:*
73
 
@@ -93,24 +95,23 @@ interesting implementations based on a simple compare and
93
  exchange [[atomics]]. — *end note*]
94
 
95
  An implementation should ensure that `try_lock()` does not consistently
96
  return `false` in the absence of contending mutex acquisitions.
97
 
98
- *Return type:* `bool`.
99
-
100
- *Returns:* `true` if ownership of the mutex was obtained for the calling
101
- thread, otherwise `false`.
102
-
103
  *Synchronization:* If `try_lock()` returns `true`, prior `unlock()`
104
  operations on the same object *synchronize with*[[intro.multithread]]
105
  this operation.
106
 
107
  [*Note 2*: Since `lock()` does not synchronize with a failed subsequent
108
  `try_lock()`, the visibility rules are weak enough that little would be
109
  known about the state after a failure, even in the absence of spurious
110
  failures. — *end note*]
111
 
 
 
 
 
112
  *Throws:* Nothing.
113
 
114
  The expression `m.unlock()` is well-formed and has the following
115
  semantics:
116
 
@@ -152,11 +153,11 @@ The class `mutex` provides a non-recursive mutex with exclusive
152
  ownership semantics. If one thread owns a mutex object, attempts by
153
  another thread to acquire ownership of that object will fail (for
154
  `try_lock()`) or block (for `lock()`) until the owning thread has
155
  released ownership with a call to `unlock()`.
156
 
157
- [*Note 3*: After a thread `A` has called `unlock()`, releasing a mutex,
158
  it is possible for another thread `B` to lock the same mutex, observe
159
  that it is no longer in use, unlock it, and destroy it, before thread
160
  `A` appears to have returned from its unlock call. Implementations are
161
  required to handle such scenarios correctly, as long as thread `A`
162
  doesn’t access the mutex after the unlock call returns. These cases
@@ -165,11 +166,11 @@ used to protect the reference count. — *end note*]
165
 
166
  The class `mutex` meets all of the mutex requirements
167
  [[thread.mutex.requirements]]. It is a standard-layout class
168
  [[class.prop]].
169
 
170
- [*Note 4*: A program can deadlock if the thread that owns a `mutex`
171
  object calls `lock()` on that object. If the implementation can detect
172
  the deadlock, a `resource_deadlock_would_occur` error condition might be
173
  observed. — *end note*]
174
 
175
  The behavior of a program is undefined if it destroys a `mutex` object
@@ -224,19 +225,21 @@ The behavior of a program is undefined if:
224
  - it destroys a `recursive_mutex` object owned by any thread or
225
  - a thread terminates while owning a `recursive_mutex` object.
226
 
227
  #### Timed mutex types <a id="thread.timedmutex.requirements">[[thread.timedmutex.requirements]]</a>
228
 
 
 
229
  The *timed mutex types* are the standard library types `timed_mutex`,
230
  `recursive_timed_mutex`, and `shared_timed_mutex`. They meet the
231
  requirements set out below. In this description, `m` denotes an object
232
  of a mutex type, `rel_time` denotes an object of an instantiation of
233
  `duration` [[time.duration]], and `abs_time` denotes an object of an
234
  instantiation of `time_point` [[time.point]].
235
 
236
- The timed mutex types meet the *Cpp17TimedLockable* requirements
237
- [[thread.req.lockable.timed]].
238
 
239
  The expression `m.try_lock_for(rel_time)` is well-formed and has the
240
  following semantics:
241
 
242
  *Preconditions:* If `m` is of type `timed_mutex` or
@@ -252,18 +255,18 @@ the mutex object.
252
 
253
  [*Note 1*: As with `try_lock()`, there is no guarantee that ownership
254
  will be obtained if the lock is available, but implementations are
255
  expected to make a strong effort to do so. — *end note*]
256
 
257
- *Return type:* `bool`.
258
-
259
- *Returns:* `true` if ownership was obtained, otherwise `false`.
260
-
261
  *Synchronization:* If `try_lock_for()` returns `true`, prior `unlock()`
262
  operations on the same object *synchronize with*[[intro.multithread]]
263
  this operation.
264
 
 
 
 
 
265
  *Throws:* Timeout-related exceptions [[thread.req.timing]].
266
 
267
  The expression `m.try_lock_until(abs_time)` is well-formed and has the
268
  following semantics:
269
 
@@ -278,18 +281,18 @@ before the absolute timeout [[thread.req.timing]] specified by
278
 
279
  [*Note 2*: As with `try_lock()`, there is no guarantee that ownership
280
  will be obtained if the lock is available, but implementations are
281
  expected to make a strong effort to do so. — *end note*]
282
 
283
- *Return type:* `bool`.
284
-
285
- *Returns:* `true` if ownership was obtained, otherwise `false`.
286
-
287
  *Synchronization:* If `try_lock_until()` returns `true`, prior
288
  `unlock()` operations on the same object *synchronize
289
  with*[[intro.multithread]] this operation.
290
 
 
 
 
 
291
  *Throws:* Timeout-related exceptions [[thread.req.timing]].
292
 
293
  ##### Class `timed_mutex` <a id="thread.timedmutex.class">[[thread.timedmutex.class]]</a>
294
 
295
  ``` cpp
@@ -392,16 +395,21 @@ The behavior of a program is undefined if:
392
  - it destroys a `recursive_timed_mutex` object owned by any thread, or
393
  - a thread terminates while owning a `recursive_timed_mutex` object.
394
 
395
  #### Shared mutex types <a id="thread.sharedmutex.requirements">[[thread.sharedmutex.requirements]]</a>
396
 
 
 
397
  The standard library types `shared_mutex` and `shared_timed_mutex` are
398
  *shared mutex types*. Shared mutex types meet the requirements of mutex
399
  types [[thread.mutex.requirements.mutex]] and additionally meet the
400
  requirements set out below. In this description, `m` denotes an object
401
  of a shared mutex type.
402
 
 
 
 
403
  In addition to the exclusive lock ownership mode specified in 
404
  [[thread.mutex.requirements.mutex]], shared mutex types provide a
405
  *shared lock* ownership mode. Multiple execution agents can
406
  simultaneously hold a shared lock ownership of a shared mutex type. But
407
  no execution agent holds a shared lock while another execution agent
@@ -420,17 +428,17 @@ semantics:
420
 
421
  *Effects:* Blocks the calling thread until shared ownership of the mutex
422
  can be obtained for the calling thread. If an exception is thrown then a
423
  shared lock has not been acquired for the current thread.
424
 
425
- *Ensures:* The calling thread has a shared lock on the mutex.
426
-
427
- *Return type:* `void`.
428
-
429
  *Synchronization:* Prior `unlock()` operations on the same object
430
  synchronize with [[intro.multithread]] this operation.
431
 
 
 
 
 
432
  *Throws:* `system_error` when an exception is
433
  required [[thread.req.exception]].
434
 
435
  *Error conditions:*
436
 
@@ -464,19 +472,18 @@ following semantics:
464
  calling thread without blocking. If shared ownership is not obtained,
465
  there is no effect and `try_lock_shared()` immediately returns. An
466
  implementation may fail to obtain the lock even if it is not held by any
467
  other thread.
468
 
469
- *Return type:* `bool`.
470
-
471
- *Returns:* `true` if the shared ownership lock was acquired, `false`
472
- otherwise.
473
-
474
  *Synchronization:* If `try_lock_shared()` returns `true`, prior
475
  `unlock()` operations on the same object synchronize
476
  with [[intro.multithread]] this operation.
477
 
 
 
 
 
478
  *Throws:* Nothing.
479
 
480
  ##### Class `shared_mutex` <a id="thread.sharedmutex.class">[[thread.sharedmutex.class]]</a>
481
 
482
  ``` cpp
@@ -522,19 +529,25 @@ The behavior of a program is undefined if:
522
 
523
  `shared_mutex` may be a synonym for `shared_timed_mutex`.
524
 
525
  #### Shared timed mutex types <a id="thread.sharedtimedmutex.requirements">[[thread.sharedtimedmutex.requirements]]</a>
526
 
 
 
527
  The standard library type `shared_timed_mutex` is a *shared timed mutex
528
  type*. Shared timed mutex types meet the requirements of timed mutex
529
  types [[thread.timedmutex.requirements]], shared mutex types
530
  [[thread.sharedmutex.requirements]], and additionally meet the
531
  requirements set out below. In this description, `m` denotes an object
532
- of a shared timed mutex type, `rel_type` denotes an object of an
533
  instantiation of `duration` [[time.duration]], and `abs_time` denotes an
534
  object of an instantiation of `time_point` [[time.point]].
535
 
 
 
 
 
536
  The expression `m.try_lock_shared_for(rel_time)` is well-formed and has
537
  the following semantics:
538
 
539
  *Preconditions:* The calling thread has no ownership of the mutex.
540
 
@@ -551,18 +564,18 @@ will be obtained if the lock is available, but implementations are
551
  expected to make a strong effort to do so. — *end note*]
552
 
553
  If an exception is thrown then a shared lock has not been acquired for
554
  the current thread.
555
 
556
- *Return type:* `bool`.
557
-
558
- *Returns:* `true` if the shared lock was acquired, `false` otherwise.
559
-
560
  *Synchronization:* If `try_lock_shared_for()` returns `true`, prior
561
  `unlock()` operations on the same object synchronize
562
  with [[intro.multithread]] this operation.
563
 
 
 
 
 
564
  *Throws:* Timeout-related exceptions [[thread.req.timing]].
565
 
566
  The expression `m.try_lock_shared_until(abs_time)` is well-formed and
567
  has the following semantics:
568
 
@@ -580,18 +593,18 @@ will be obtained if the lock is available, but implementations are
580
  expected to make a strong effort to do so. — *end note*]
581
 
582
  If an exception is thrown then a shared lock has not been acquired for
583
  the current thread.
584
 
585
- *Return type:* `bool`.
586
-
587
- *Returns:* `true` if the shared lock was acquired, `false` otherwise.
588
-
589
  *Synchronization:* If `try_lock_shared_until()` returns `true`, prior
590
  `unlock()` operations on the same object synchronize
591
  with [[intro.multithread]] this operation.
592
 
 
 
 
 
593
  *Throws:* Timeout-related exceptions [[thread.req.timing]].
594
 
595
  ##### Class `shared_timed_mutex` <a id="thread.sharedtimedmutex.class">[[thread.sharedtimedmutex.class]]</a>
596
 
597
  ``` cpp
 
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
+ ##### General <a id="thread.mutex.requirements.mutex.general">[[thread.mutex.requirements.mutex.general]]</a>
16
+
17
  The *mutex types* are the standard library types `mutex`,
18
  `recursive_mutex`, `timed_mutex`, `recursive_timed_mutex`,
19
  `shared_mutex`, and `shared_timed_mutex`. They meet the requirements set
20
+ out in [[thread.mutex.requirements.mutex]]. In this description, `m`
21
+ denotes an object of a mutex type.
22
 
23
+ [*Note 1*: The mutex types meet the *Cpp17Lockable* requirements
24
+ [[thread.req.lockable.req]]. — *end note*]
25
 
26
  The mutex types meet *Cpp17DefaultConstructible* and
27
  *Cpp17Destructible*. If initialization of an object of a mutex type
28
  fails, an exception of type `system_error` is thrown. The mutex types
29
  are neither copyable nor movable.
 
41
  The implementation provides lock and unlock operations, as described
42
  below. For purposes of determining the existence of a data race, these
43
  behave as atomic operations [[intro.multithread]]. The lock and unlock
44
  operations on a single mutex appears to occur in a single total order.
45
 
46
+ [*Note 2*: This can be viewed as the modification order
47
  [[intro.multithread]] of the mutex. — *end note*]
48
 
49
+ [*Note 3*: Construction and destruction of an object of a mutex type
50
+ need not be thread-safe; other synchronization can be used to ensure
51
  that mutex objects are initialized and visible to other
52
  threads. — *end note*]
53
 
54
  The expression `m.lock()` is well-formed and has the following
55
  semantics:
 
59
  the mutex.
60
 
61
  *Effects:* Blocks the calling thread until ownership of the mutex can be
62
  obtained for the calling thread.
63
 
 
 
 
 
64
  *Synchronization:* Prior `unlock()` operations on the same object
65
  *synchronize with*[[intro.multithread]] this operation.
66
 
67
+ *Ensures:* The calling thread owns the mutex.
68
+
69
+ *Return type:* `void`.
70
+
71
  *Throws:* `system_error` when an exception is
72
  required [[thread.req.exception]].
73
 
74
  *Error conditions:*
75
 
 
95
  exchange [[atomics]]. — *end note*]
96
 
97
  An implementation should ensure that `try_lock()` does not consistently
98
  return `false` in the absence of contending mutex acquisitions.
99
 
 
 
 
 
 
100
  *Synchronization:* If `try_lock()` returns `true`, prior `unlock()`
101
  operations on the same object *synchronize with*[[intro.multithread]]
102
  this operation.
103
 
104
  [*Note 2*: Since `lock()` does not synchronize with a failed subsequent
105
  `try_lock()`, the visibility rules are weak enough that little would be
106
  known about the state after a failure, even in the absence of spurious
107
  failures. — *end note*]
108
 
109
+ *Return type:* `bool`.
110
+
111
+ *Returns:* `true` if ownership was obtained, otherwise `false`.
112
+
113
  *Throws:* Nothing.
114
 
115
  The expression `m.unlock()` is well-formed and has the following
116
  semantics:
117
 
 
153
  ownership semantics. If one thread owns a mutex object, attempts by
154
  another thread to acquire ownership of that object will fail (for
155
  `try_lock()`) or block (for `lock()`) until the owning thread has
156
  released ownership with a call to `unlock()`.
157
 
158
+ [*Note 4*: After a thread `A` has called `unlock()`, releasing a mutex,
159
  it is possible for another thread `B` to lock the same mutex, observe
160
  that it is no longer in use, unlock it, and destroy it, before thread
161
  `A` appears to have returned from its unlock call. Implementations are
162
  required to handle such scenarios correctly, as long as thread `A`
163
  doesn’t access the mutex after the unlock call returns. These cases
 
166
 
167
  The class `mutex` meets all of the mutex requirements
168
  [[thread.mutex.requirements]]. It is a standard-layout class
169
  [[class.prop]].
170
 
171
+ [*Note 5*: A program can deadlock if the thread that owns a `mutex`
172
  object calls `lock()` on that object. If the implementation can detect
173
  the deadlock, a `resource_deadlock_would_occur` error condition might be
174
  observed. — *end note*]
175
 
176
  The behavior of a program is undefined if it destroys a `mutex` object
 
225
  - it destroys a `recursive_mutex` object owned by any thread or
226
  - a thread terminates while owning a `recursive_mutex` object.
227
 
228
  #### Timed mutex types <a id="thread.timedmutex.requirements">[[thread.timedmutex.requirements]]</a>
229
 
230
+ ##### General <a id="thread.timedmutex.requirements.general">[[thread.timedmutex.requirements.general]]</a>
231
+
232
  The *timed mutex types* are the standard library types `timed_mutex`,
233
  `recursive_timed_mutex`, and `shared_timed_mutex`. They meet the
234
  requirements set out below. In this description, `m` denotes an object
235
  of a mutex type, `rel_time` denotes an object of an instantiation of
236
  `duration` [[time.duration]], and `abs_time` denotes an object of an
237
  instantiation of `time_point` [[time.point]].
238
 
239
+ [*Note 1*: The timed mutex types meet the *Cpp17TimedLockable*
240
+ requirements [[thread.req.lockable.timed]]. — *end note*]
241
 
242
  The expression `m.try_lock_for(rel_time)` is well-formed and has the
243
  following semantics:
244
 
245
  *Preconditions:* If `m` is of type `timed_mutex` or
 
255
 
256
  [*Note 1*: As with `try_lock()`, there is no guarantee that ownership
257
  will be obtained if the lock is available, but implementations are
258
  expected to make a strong effort to do so. — *end note*]
259
 
 
 
 
 
260
  *Synchronization:* If `try_lock_for()` returns `true`, prior `unlock()`
261
  operations on the same object *synchronize with*[[intro.multithread]]
262
  this operation.
263
 
264
+ *Return type:* `bool`.
265
+
266
+ *Returns:* `true` if ownership was obtained, otherwise `false`.
267
+
268
  *Throws:* Timeout-related exceptions [[thread.req.timing]].
269
 
270
  The expression `m.try_lock_until(abs_time)` is well-formed and has the
271
  following semantics:
272
 
 
281
 
282
  [*Note 2*: As with `try_lock()`, there is no guarantee that ownership
283
  will be obtained if the lock is available, but implementations are
284
  expected to make a strong effort to do so. — *end note*]
285
 
 
 
 
 
286
  *Synchronization:* If `try_lock_until()` returns `true`, prior
287
  `unlock()` operations on the same object *synchronize
288
  with*[[intro.multithread]] this operation.
289
 
290
+ *Return type:* `bool`.
291
+
292
+ *Returns:* `true` if ownership was obtained, otherwise `false`.
293
+
294
  *Throws:* Timeout-related exceptions [[thread.req.timing]].
295
 
296
  ##### Class `timed_mutex` <a id="thread.timedmutex.class">[[thread.timedmutex.class]]</a>
297
 
298
  ``` cpp
 
395
  - it destroys a `recursive_timed_mutex` object owned by any thread, or
396
  - a thread terminates while owning a `recursive_timed_mutex` object.
397
 
398
  #### Shared mutex types <a id="thread.sharedmutex.requirements">[[thread.sharedmutex.requirements]]</a>
399
 
400
+ ##### General <a id="thread.sharedmutex.requirements.general">[[thread.sharedmutex.requirements.general]]</a>
401
+
402
  The standard library types `shared_mutex` and `shared_timed_mutex` are
403
  *shared mutex types*. Shared mutex types meet the requirements of mutex
404
  types [[thread.mutex.requirements.mutex]] and additionally meet the
405
  requirements set out below. In this description, `m` denotes an object
406
  of a shared mutex type.
407
 
408
+ [*Note 1*: The shared mutex types meet the *Cpp17SharedLockable*
409
+ requirements [[thread.req.lockable.shared]]. — *end note*]
410
+
411
  In addition to the exclusive lock ownership mode specified in 
412
  [[thread.mutex.requirements.mutex]], shared mutex types provide a
413
  *shared lock* ownership mode. Multiple execution agents can
414
  simultaneously hold a shared lock ownership of a shared mutex type. But
415
  no execution agent holds a shared lock while another execution agent
 
428
 
429
  *Effects:* Blocks the calling thread until shared ownership of the mutex
430
  can be obtained for the calling thread. If an exception is thrown then a
431
  shared lock has not been acquired for the current thread.
432
 
 
 
 
 
433
  *Synchronization:* Prior `unlock()` operations on the same object
434
  synchronize with [[intro.multithread]] this operation.
435
 
436
+ *Ensures:* The calling thread has a shared lock on the mutex.
437
+
438
+ *Return type:* `void`.
439
+
440
  *Throws:* `system_error` when an exception is
441
  required [[thread.req.exception]].
442
 
443
  *Error conditions:*
444
 
 
472
  calling thread without blocking. If shared ownership is not obtained,
473
  there is no effect and `try_lock_shared()` immediately returns. An
474
  implementation may fail to obtain the lock even if it is not held by any
475
  other thread.
476
 
 
 
 
 
 
477
  *Synchronization:* If `try_lock_shared()` returns `true`, prior
478
  `unlock()` operations on the same object synchronize
479
  with [[intro.multithread]] this operation.
480
 
481
+ *Return type:* `bool`.
482
+
483
+ *Returns:* `true` if the shared lock was acquired, otherwise `false`.
484
+
485
  *Throws:* Nothing.
486
 
487
  ##### Class `shared_mutex` <a id="thread.sharedmutex.class">[[thread.sharedmutex.class]]</a>
488
 
489
  ``` cpp
 
529
 
530
  `shared_mutex` may be a synonym for `shared_timed_mutex`.
531
 
532
  #### Shared timed mutex types <a id="thread.sharedtimedmutex.requirements">[[thread.sharedtimedmutex.requirements]]</a>
533
 
534
+ ##### General <a id="thread.sharedtimedmutex.requirements.general">[[thread.sharedtimedmutex.requirements.general]]</a>
535
+
536
  The standard library type `shared_timed_mutex` is a *shared timed mutex
537
  type*. Shared timed mutex types meet the requirements of timed mutex
538
  types [[thread.timedmutex.requirements]], shared mutex types
539
  [[thread.sharedmutex.requirements]], and additionally meet the
540
  requirements set out below. In this description, `m` denotes an object
541
+ of a shared timed mutex type, `rel_time` denotes an object of an
542
  instantiation of `duration` [[time.duration]], and `abs_time` denotes an
543
  object of an instantiation of `time_point` [[time.point]].
544
 
545
+ [*Note 1*: The shared timed mutex types meet the
546
+ *Cpp17SharedTimedLockable* requirements
547
+ [[thread.req.lockable.shared.timed]]. — *end note*]
548
+
549
  The expression `m.try_lock_shared_for(rel_time)` is well-formed and has
550
  the following semantics:
551
 
552
  *Preconditions:* The calling thread has no ownership of the mutex.
553
 
 
564
  expected to make a strong effort to do so. — *end note*]
565
 
566
  If an exception is thrown then a shared lock has not been acquired for
567
  the current thread.
568
 
 
 
 
 
569
  *Synchronization:* If `try_lock_shared_for()` returns `true`, prior
570
  `unlock()` operations on the same object synchronize
571
  with [[intro.multithread]] this operation.
572
 
573
+ *Return type:* `bool`.
574
+
575
+ *Returns:* `true` if the shared lock was acquired, otherwise `false`.
576
+
577
  *Throws:* Timeout-related exceptions [[thread.req.timing]].
578
 
579
  The expression `m.try_lock_shared_until(abs_time)` is well-formed and
580
  has the following semantics:
581
 
 
593
  expected to make a strong effort to do so. — *end note*]
594
 
595
  If an exception is thrown then a shared lock has not been acquired for
596
  the current thread.
597
 
 
 
 
 
598
  *Synchronization:* If `try_lock_shared_until()` returns `true`, prior
599
  `unlock()` operations on the same object synchronize
600
  with [[intro.multithread]] this operation.
601
 
602
+ *Return type:* `bool`.
603
+
604
+ *Returns:* `true` if the shared lock was acquired, otherwise `false`.
605
+
606
  *Throws:* Timeout-related exceptions [[thread.req.timing]].
607
 
608
  ##### Class `shared_timed_mutex` <a id="thread.sharedtimedmutex.class">[[thread.sharedtimedmutex.class]]</a>
609
 
610
  ``` cpp