tmp/tmp5ootk66j/{from.md → to.md}
RENAMED
|
@@ -1,15 +1,17 @@
|
|
| 1 |
#### Mutex types <a id="thread.mutex.requirements.mutex">[[thread.mutex.requirements.mutex]]</a>
|
| 2 |
|
|
|
|
|
|
|
| 3 |
The *mutex types* are the standard library types `mutex`,
|
| 4 |
`recursive_mutex`, `timed_mutex`, `recursive_timed_mutex`,
|
| 5 |
`shared_mutex`, and `shared_timed_mutex`. They meet the requirements set
|
| 6 |
-
out in
|
| 7 |
-
mutex type.
|
| 8 |
|
| 9 |
-
The mutex types meet the *Cpp17Lockable* requirements
|
| 10 |
-
[[thread.req.lockable.req]].
|
| 11 |
|
| 12 |
The mutex types meet *Cpp17DefaultConstructible* and
|
| 13 |
*Cpp17Destructible*. If initialization of an object of a mutex type
|
| 14 |
fails, an exception of type `system_error` is thrown. The mutex types
|
| 15 |
are neither copyable nor movable.
|
|
@@ -27,15 +29,15 @@ functions of the mutex types are as follows:
|
|
| 27 |
The implementation provides lock and unlock operations, as described
|
| 28 |
below. For purposes of determining the existence of a data race, these
|
| 29 |
behave as atomic operations [[intro.multithread]]. The lock and unlock
|
| 30 |
operations on a single mutex appears to occur in a single total order.
|
| 31 |
|
| 32 |
-
[*Note
|
| 33 |
[[intro.multithread]] of the mutex. — *end note*]
|
| 34 |
|
| 35 |
-
[*Note
|
| 36 |
-
need not be thread-safe; other synchronization
|
| 37 |
that mutex objects are initialized and visible to other
|
| 38 |
threads. — *end note*]
|
| 39 |
|
| 40 |
The expression `m.lock()` is well-formed and has the following
|
| 41 |
semantics:
|
|
@@ -45,17 +47,17 @@ semantics:
|
|
| 45 |
the mutex.
|
| 46 |
|
| 47 |
*Effects:* Blocks the calling thread until ownership of the mutex can be
|
| 48 |
obtained for the calling thread.
|
| 49 |
|
| 50 |
-
*Ensures:* The calling thread owns the mutex.
|
| 51 |
-
|
| 52 |
-
*Return type:* `void`.
|
| 53 |
-
|
| 54 |
*Synchronization:* Prior `unlock()` operations on the same object
|
| 55 |
*synchronize with*[[intro.multithread]] this operation.
|
| 56 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 57 |
*Throws:* `system_error` when an exception is
|
| 58 |
required [[thread.req.exception]].
|
| 59 |
|
| 60 |
*Error conditions:*
|
| 61 |
|
|
@@ -81,24 +83,23 @@ interesting implementations based on a simple compare and
|
|
| 81 |
exchange [[atomics]]. — *end note*]
|
| 82 |
|
| 83 |
An implementation should ensure that `try_lock()` does not consistently
|
| 84 |
return `false` in the absence of contending mutex acquisitions.
|
| 85 |
|
| 86 |
-
*Return type:* `bool`.
|
| 87 |
-
|
| 88 |
-
*Returns:* `true` if ownership of the mutex was obtained for the calling
|
| 89 |
-
thread, otherwise `false`.
|
| 90 |
-
|
| 91 |
*Synchronization:* If `try_lock()` returns `true`, prior `unlock()`
|
| 92 |
operations on the same object *synchronize with*[[intro.multithread]]
|
| 93 |
this operation.
|
| 94 |
|
| 95 |
[*Note 2*: Since `lock()` does not synchronize with a failed subsequent
|
| 96 |
`try_lock()`, the visibility rules are weak enough that little would be
|
| 97 |
known about the state after a failure, even in the absence of spurious
|
| 98 |
failures. — *end note*]
|
| 99 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 100 |
*Throws:* Nothing.
|
| 101 |
|
| 102 |
The expression `m.unlock()` is well-formed and has the following
|
| 103 |
semantics:
|
| 104 |
|
|
@@ -140,11 +141,11 @@ The class `mutex` provides a non-recursive mutex with exclusive
|
|
| 140 |
ownership semantics. If one thread owns a mutex object, attempts by
|
| 141 |
another thread to acquire ownership of that object will fail (for
|
| 142 |
`try_lock()`) or block (for `lock()`) until the owning thread has
|
| 143 |
released ownership with a call to `unlock()`.
|
| 144 |
|
| 145 |
-
[*Note
|
| 146 |
it is possible for another thread `B` to lock the same mutex, observe
|
| 147 |
that it is no longer in use, unlock it, and destroy it, before thread
|
| 148 |
`A` appears to have returned from its unlock call. Implementations are
|
| 149 |
required to handle such scenarios correctly, as long as thread `A`
|
| 150 |
doesn’t access the mutex after the unlock call returns. These cases
|
|
@@ -153,11 +154,11 @@ used to protect the reference count. — *end note*]
|
|
| 153 |
|
| 154 |
The class `mutex` meets all of the mutex requirements
|
| 155 |
[[thread.mutex.requirements]]. It is a standard-layout class
|
| 156 |
[[class.prop]].
|
| 157 |
|
| 158 |
-
[*Note
|
| 159 |
object calls `lock()` on that object. If the implementation can detect
|
| 160 |
the deadlock, a `resource_deadlock_would_occur` error condition might be
|
| 161 |
observed. — *end note*]
|
| 162 |
|
| 163 |
The behavior of a program is undefined if it destroys a `mutex` object
|
|
|
|
| 1 |
#### Mutex types <a id="thread.mutex.requirements.mutex">[[thread.mutex.requirements.mutex]]</a>
|
| 2 |
|
| 3 |
+
##### General <a id="thread.mutex.requirements.mutex.general">[[thread.mutex.requirements.mutex.general]]</a>
|
| 4 |
+
|
| 5 |
The *mutex types* are the standard library types `mutex`,
|
| 6 |
`recursive_mutex`, `timed_mutex`, `recursive_timed_mutex`,
|
| 7 |
`shared_mutex`, and `shared_timed_mutex`. They meet the requirements set
|
| 8 |
+
out in [[thread.mutex.requirements.mutex]]. In this description, `m`
|
| 9 |
+
denotes an object of a mutex type.
|
| 10 |
|
| 11 |
+
[*Note 1*: The mutex types meet the *Cpp17Lockable* requirements
|
| 12 |
+
[[thread.req.lockable.req]]. — *end note*]
|
| 13 |
|
| 14 |
The mutex types meet *Cpp17DefaultConstructible* and
|
| 15 |
*Cpp17Destructible*. If initialization of an object of a mutex type
|
| 16 |
fails, an exception of type `system_error` is thrown. The mutex types
|
| 17 |
are neither copyable nor movable.
|
|
|
|
| 29 |
The implementation provides lock and unlock operations, as described
|
| 30 |
below. For purposes of determining the existence of a data race, these
|
| 31 |
behave as atomic operations [[intro.multithread]]. The lock and unlock
|
| 32 |
operations on a single mutex appears to occur in a single total order.
|
| 33 |
|
| 34 |
+
[*Note 2*: This can be viewed as the modification order
|
| 35 |
[[intro.multithread]] of the mutex. — *end note*]
|
| 36 |
|
| 37 |
+
[*Note 3*: Construction and destruction of an object of a mutex type
|
| 38 |
+
need not be thread-safe; other synchronization can be used to ensure
|
| 39 |
that mutex objects are initialized and visible to other
|
| 40 |
threads. — *end note*]
|
| 41 |
|
| 42 |
The expression `m.lock()` is well-formed and has the following
|
| 43 |
semantics:
|
|
|
|
| 47 |
the mutex.
|
| 48 |
|
| 49 |
*Effects:* Blocks the calling thread until ownership of the mutex can be
|
| 50 |
obtained for the calling thread.
|
| 51 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 52 |
*Synchronization:* Prior `unlock()` operations on the same object
|
| 53 |
*synchronize with*[[intro.multithread]] this operation.
|
| 54 |
|
| 55 |
+
*Ensures:* The calling thread owns the mutex.
|
| 56 |
+
|
| 57 |
+
*Return type:* `void`.
|
| 58 |
+
|
| 59 |
*Throws:* `system_error` when an exception is
|
| 60 |
required [[thread.req.exception]].
|
| 61 |
|
| 62 |
*Error conditions:*
|
| 63 |
|
|
|
|
| 83 |
exchange [[atomics]]. — *end note*]
|
| 84 |
|
| 85 |
An implementation should ensure that `try_lock()` does not consistently
|
| 86 |
return `false` in the absence of contending mutex acquisitions.
|
| 87 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 88 |
*Synchronization:* If `try_lock()` returns `true`, prior `unlock()`
|
| 89 |
operations on the same object *synchronize with*[[intro.multithread]]
|
| 90 |
this operation.
|
| 91 |
|
| 92 |
[*Note 2*: Since `lock()` does not synchronize with a failed subsequent
|
| 93 |
`try_lock()`, the visibility rules are weak enough that little would be
|
| 94 |
known about the state after a failure, even in the absence of spurious
|
| 95 |
failures. — *end note*]
|
| 96 |
|
| 97 |
+
*Return type:* `bool`.
|
| 98 |
+
|
| 99 |
+
*Returns:* `true` if ownership was obtained, otherwise `false`.
|
| 100 |
+
|
| 101 |
*Throws:* Nothing.
|
| 102 |
|
| 103 |
The expression `m.unlock()` is well-formed and has the following
|
| 104 |
semantics:
|
| 105 |
|
|
|
|
| 141 |
ownership semantics. If one thread owns a mutex object, attempts by
|
| 142 |
another thread to acquire ownership of that object will fail (for
|
| 143 |
`try_lock()`) or block (for `lock()`) until the owning thread has
|
| 144 |
released ownership with a call to `unlock()`.
|
| 145 |
|
| 146 |
+
[*Note 4*: After a thread `A` has called `unlock()`, releasing a mutex,
|
| 147 |
it is possible for another thread `B` to lock the same mutex, observe
|
| 148 |
that it is no longer in use, unlock it, and destroy it, before thread
|
| 149 |
`A` appears to have returned from its unlock call. Implementations are
|
| 150 |
required to handle such scenarios correctly, as long as thread `A`
|
| 151 |
doesn’t access the mutex after the unlock call returns. These cases
|
|
|
|
| 154 |
|
| 155 |
The class `mutex` meets all of the mutex requirements
|
| 156 |
[[thread.mutex.requirements]]. It is a standard-layout class
|
| 157 |
[[class.prop]].
|
| 158 |
|
| 159 |
+
[*Note 5*: A program can deadlock if the thread that owns a `mutex`
|
| 160 |
object calls `lock()` on that object. If the implementation can detect
|
| 161 |
the deadlock, a `resource_deadlock_would_occur` error condition might be
|
| 162 |
observed. — *end note*]
|
| 163 |
|
| 164 |
The behavior of a program is undefined if it destroys a `mutex` object
|