From Jason Turner

[thread.mutex.requirements.mutex]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmp1kjm96xc/{from.md → to.md} +52 -47
tmp/tmp1kjm96xc/{from.md → to.md} RENAMED
@@ -1,12 +1,12 @@
1
  #### Mutex types <a id="thread.mutex.requirements.mutex">[[thread.mutex.requirements.mutex]]</a>
2
 
3
- The *mutex types* are the standard library types `std::mutex`,
4
- `std::recursive_mutex`, `std::timed_mutex`,
5
- `std::recursive_timed_mutex`, and `std::shared_timed_mutex`. They shall
6
- meet the requirements set out in this section. In this description, `m`
7
- denotes an object of a mutex type.
8
 
9
  The mutex types shall meet the `Lockable` requirements (
10
  [[thread.req.lockable.req]]).
11
 
12
  The mutex types shall be `DefaultConstructible` and `Destructible`. If
@@ -19,37 +19,39 @@ functions of the mutex types shall be:
19
 
20
  - `resource_unavailable_try_again` — if any native handle type
21
  manipulated is not available.
22
  - `operation_not_permitted` — if the thread does not have the privilege
23
  to perform the operation.
24
- - `device_or_resource_busy` — if any native handle type manipulated is
25
- already locked.
26
  - `invalid_argument` — if any native handle type manipulated as part of
27
  mutex construction is incorrect.
28
 
29
  The implementation shall provide lock and unlock operations, as
30
  described below. For purposes of determining the existence of a data
31
  race, these behave as atomic operations ([[intro.multithread]]). The
32
  lock and unlock operations on a single mutex shall appear to occur in a
33
- single total order. this can be viewed as the modification order (
34
- [[intro.multithread]]) of the mutex. Construction and destruction of an
35
- object of a mutex type need not be thread-safe; other synchronization
36
- should be used to ensure that mutex objects are initialized and visible
37
- to other threads.
 
 
 
 
38
 
39
  The expression `m.lock()` shall be well-formed and have the following
40
  semantics:
41
 
42
- *Requires:* If `m` is of type `std::mutex`, `std::timed_mutex`, or
43
- `std::shared_timed_mutex`, the calling thread does not own the mutex.
44
 
45
  *Effects:* Blocks the calling thread until ownership of the mutex can be
46
  obtained for the calling thread.
47
 
48
- The calling thread owns the mutex.
49
 
50
- *Return type:* `void`
51
 
52
  *Synchronization:* Prior `unlock()` operations on the same object shall
53
  *synchronize with* ([[intro.multithread]]) this operation.
54
 
55
  *Throws:* `system_error` when an exception is
@@ -59,51 +61,53 @@ required ([[thread.req.exception]]).
59
 
60
  - `operation_not_permitted` — if the thread does not have the privilege
61
  to perform the operation.
62
  - `resource_deadlock_would_occur` — if the implementation detects that a
63
  deadlock would occur.
64
- - `device_or_resource_busy` — if the mutex is already locked and
65
- blocking is not possible.
66
 
67
  The expression `m.try_lock()` shall be well-formed and have the
68
  following semantics:
69
 
70
- *Requires:* If `m` is of type `std::mutex`, `std::timed_mutex`, or
71
- `std::shared_timed_mutex`, the calling thread does not own the mutex.
72
 
73
  *Effects:* Attempts to obtain ownership of the mutex for the calling
74
  thread without blocking. If ownership is not obtained, there is no
75
  effect and `try_lock()` immediately returns. An implementation may fail
76
- to obtain the lock even if it is not held by any other thread. This
77
- spurious failure is normally uncommon, but allows interesting
78
- implementations based on a simple compare and exchange
79
- (Clause  [[atomics]]). An implementation should ensure that `try_lock()`
80
- does not consistently return `false` in the absence of contending mutex
81
- acquisitions.
82
 
83
- *Return type:* `bool`
 
 
 
 
 
 
 
84
 
85
  *Returns:* `true` if ownership of the mutex was obtained for the calling
86
  thread, otherwise `false`.
87
 
88
  *Synchronization:* If `try_lock()` returns `true`, prior `unlock()`
89
  operations on the same object *synchronize
90
- with* ([[intro.multithread]]) this operation. Since `lock()` does not
91
- synchronize with a failed subsequent `try_lock()`, the visibility rules
92
- are weak enough that little would be known about the state after a
93
- failure, even in the absence of spurious failures.
 
 
94
 
95
  *Throws:* Nothing.
96
 
97
  The expression `m.unlock()` shall be well-formed and have the following
98
  semantics:
99
 
100
- The calling thread shall own the mutex.
101
 
102
  *Effects:* Releases the calling thread’s ownership of the mutex.
103
 
104
- *Return type:* `void`
105
 
106
  *Synchronization:* This operation synchronizes
107
  with ([[intro.multithread]]) subsequent lock operations that obtain
108
  ownership on the same object.
109
 
@@ -123,11 +127,11 @@ namespace std {
123
 
124
  void lock();
125
  bool try_lock();
126
  void unlock();
127
 
128
- typedef implementation-defined native_handle_type; // See~[thread.req.native]
129
  native_handle_type native_handle(); // See~[thread.req.native]
130
  };
131
  }
132
  ```
133
 
@@ -135,26 +139,27 @@ The class `mutex` provides a non-recursive mutex with exclusive
135
  ownership semantics. If one thread owns a mutex object, attempts by
136
  another thread to acquire ownership of that object will fail (for
137
  `try_lock()`) or block (for `lock()`) until the owning thread has
138
  released ownership with a call to `unlock()`.
139
 
140
- After a thread `A` has called `unlock()`, releasing a mutex, it is
141
- possible for another thread `B` to lock the same mutex, observe that it
142
- is no longer in use, unlock it, and destroy it, before thread `A`
143
- appears to have returned from its unlock call. Implementations are
144
  required to handle such scenarios correctly, as long as thread `A`
145
  doesn’t access the mutex after the unlock call returns. These cases
146
  typically occur when a reference-counted object contains a mutex that is
147
- used to protect the reference count.
148
 
149
- The class `mutex` shall satisfy all the `Mutex` requirements (
150
  [[thread.mutex.requirements]]). It shall be a standard-layout class
151
  (Clause  [[class]]).
152
 
153
- A program may deadlock if the thread that owns a `mutex` object calls
154
- `lock()` on that object. If the implementation can detect the deadlock,
155
- a `resource_deadlock_would_occur` error condition may be observed.
 
156
 
157
  The behavior of a program is undefined if it destroys a `mutex` object
158
  owned by any thread or a thread terminates while owning a `mutex`
159
  object.
160
 
@@ -172,11 +177,11 @@ namespace std {
172
 
173
  void lock();
174
  bool try_lock() noexcept;
175
  void unlock();
176
 
177
- typedef implementation-defined native_handle_type; // See~[thread.req.native]
178
  native_handle_type native_handle(); // See~[thread.req.native]
179
  };
180
  }
181
  ```
182
 
@@ -184,13 +189,13 @@ The class `recursive_mutex` provides a recursive mutex with exclusive
184
  ownership semantics. If one thread owns a `recursive_mutex` object,
185
  attempts by another thread to acquire ownership of that object will fail
186
  (for `try_lock()`) or block (for `lock()`) until the first thread has
187
  completely released ownership.
188
 
189
- The class `recursive_mutex` shall satisfy all the Mutex requirements (
190
- [[thread.mutex.requirements]]). It shall be a standard-layout class
191
- (Clause  [[class]]).
192
 
193
  A thread that owns a `recursive_mutex` object may acquire additional
194
  levels of ownership by calling `lock()` or `try_lock()` on that object.
195
  It is unspecified how many levels of ownership may be acquired by a
196
  single thread. If a thread has already acquired the maximum level of
 
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 shall meet the
6
+ requirements set out in this section. In this description, `m` denotes
7
+ an object of a mutex type.
8
 
9
  The mutex types shall meet the `Lockable` requirements (
10
  [[thread.req.lockable.req]]).
11
 
12
  The mutex types shall be `DefaultConstructible` and `Destructible`. If
 
19
 
20
  - `resource_unavailable_try_again` — if any native handle type
21
  manipulated is not available.
22
  - `operation_not_permitted` — if the thread does not have the privilege
23
  to perform the operation.
 
 
24
  - `invalid_argument` — if any native handle type manipulated as part of
25
  mutex construction is incorrect.
26
 
27
  The implementation shall provide lock and unlock operations, as
28
  described below. For purposes of determining the existence of a data
29
  race, these behave as atomic operations ([[intro.multithread]]). The
30
  lock and unlock operations on a single mutex shall appear to occur in a
31
+ single total order.
32
+
33
+ [*Note 1*: This can be viewed as the modification order (
34
+ [[intro.multithread]]) of the mutex. *end note*]
35
+
36
+ [*Note 2*: Construction and destruction of an object of a mutex type
37
+ need not be thread-safe; other synchronization should be used to ensure
38
+ that mutex objects are initialized and visible to other
39
+ threads. — *end note*]
40
 
41
  The expression `m.lock()` shall be well-formed and have the following
42
  semantics:
43
 
44
+ *Requires:* If `m` is of type `mutex`, `timed_mutex`, `shared_mutex`, or
45
+ `shared_timed_mutex`, the calling thread does not own the mutex.
46
 
47
  *Effects:* Blocks the calling thread until ownership of the mutex can be
48
  obtained for the calling thread.
49
 
50
+ *Postconditions:* The calling thread owns the mutex.
51
 
52
+ *Return type:* `void`.
53
 
54
  *Synchronization:* Prior `unlock()` operations on the same object shall
55
  *synchronize with* ([[intro.multithread]]) this operation.
56
 
57
  *Throws:* `system_error` when an exception is
 
61
 
62
  - `operation_not_permitted` — if the thread does not have the privilege
63
  to perform the operation.
64
  - `resource_deadlock_would_occur` — if the implementation detects that a
65
  deadlock would occur.
 
 
66
 
67
  The expression `m.try_lock()` shall be well-formed and have the
68
  following semantics:
69
 
70
+ *Requires:* If `m` is of type `mutex`, `timed_mutex`, `shared_mutex`, or
71
+ `shared_timed_mutex`, the calling thread does not own the mutex.
72
 
73
  *Effects:* Attempts to obtain ownership of the mutex for the calling
74
  thread without blocking. If ownership is not obtained, there is no
75
  effect and `try_lock()` immediately returns. An implementation may fail
76
+ to obtain the lock even if it is not held by any other thread.
 
 
 
 
 
77
 
78
+ [*Note 1*: This spurious failure is normally uncommon, but allows
79
+ interesting implementations based on a simple compare and exchange
80
+ (Clause  [[atomics]]). — *end note*]
81
+
82
+ An implementation should ensure that `try_lock()` does not consistently
83
+ return `false` in the absence of contending mutex acquisitions.
84
+
85
+ *Return type:* `bool`.
86
 
87
  *Returns:* `true` if ownership of the mutex was obtained for the calling
88
  thread, otherwise `false`.
89
 
90
  *Synchronization:* If `try_lock()` returns `true`, prior `unlock()`
91
  operations on the same object *synchronize
92
+ with* ([[intro.multithread]]) this operation.
93
+
94
+ [*Note 2*: Since `lock()` does not synchronize with a failed subsequent
95
+ `try_lock()`, the visibility rules are weak enough that little would be
96
+ known about the state after a failure, even in the absence of spurious
97
+ failures. — *end note*]
98
 
99
  *Throws:* Nothing.
100
 
101
  The expression `m.unlock()` shall be well-formed and have the following
102
  semantics:
103
 
104
+ *Requires:* The calling thread shall own the mutex.
105
 
106
  *Effects:* Releases the calling thread’s ownership of the mutex.
107
 
108
+ *Return type:* `void`.
109
 
110
  *Synchronization:* This operation synchronizes
111
  with ([[intro.multithread]]) subsequent lock operations that obtain
112
  ownership on the same object.
113
 
 
127
 
128
  void lock();
129
  bool try_lock();
130
  void unlock();
131
 
132
+ using native_handle_type = implementation-defined; // See~[thread.req.native]
133
  native_handle_type native_handle(); // See~[thread.req.native]
134
  };
135
  }
136
  ```
137
 
 
139
  ownership semantics. If one thread owns a mutex object, attempts by
140
  another thread to acquire ownership of that object will fail (for
141
  `try_lock()`) or block (for `lock()`) until the owning thread has
142
  released ownership with a call to `unlock()`.
143
 
144
+ [*Note 3*: After a thread `A` has called `unlock()`, releasing a mutex,
145
+ it is possible for another thread `B` to lock the same mutex, observe
146
+ that it is no longer in use, unlock it, and destroy it, before thread
147
+ `A` appears to have returned from its unlock call. Implementations are
148
  required to handle such scenarios correctly, as long as thread `A`
149
  doesn’t access the mutex after the unlock call returns. These cases
150
  typically occur when a reference-counted object contains a mutex that is
151
+ used to protect the reference count. — *end note*]
152
 
153
+ The class `mutex` shall satisfy all of the mutex requirements (
154
  [[thread.mutex.requirements]]). It shall be a standard-layout class
155
  (Clause  [[class]]).
156
 
157
+ [*Note 4*: A program may deadlock if the thread that owns a `mutex`
158
+ object calls `lock()` on that object. If the implementation can detect
159
+ the deadlock, a `resource_deadlock_would_occur` error condition may be
160
+ observed. — *end note*]
161
 
162
  The behavior of a program is undefined if it destroys a `mutex` object
163
  owned by any thread or a thread terminates while owning a `mutex`
164
  object.
165
 
 
177
 
178
  void lock();
179
  bool try_lock() noexcept;
180
  void unlock();
181
 
182
+ using native_handle_type = implementation-defined; // See~[thread.req.native]
183
  native_handle_type native_handle(); // See~[thread.req.native]
184
  };
185
  }
186
  ```
187
 
 
189
  ownership semantics. If one thread owns a `recursive_mutex` object,
190
  attempts by another thread to acquire ownership of that object will fail
191
  (for `try_lock()`) or block (for `lock()`) until the first thread has
192
  completely released ownership.
193
 
194
+ The class `recursive_mutex` shall satisfy all of the mutex
195
+ requirements ([[thread.mutex.requirements]]). It shall be a
196
+ standard-layout class (Clause  [[class]]).
197
 
198
  A thread that owns a `recursive_mutex` object may acquire additional
199
  levels of ownership by calling `lock()` or `try_lock()` on that object.
200
  It is unspecified how many levels of ownership may be acquired by a
201
  single thread. If a thread has already acquired the maximum level of