From Jason Turner

[thread.mutex.requirements.mutex]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmp7n11cuue/{from.md → to.md} +53 -52
tmp/tmp7n11cuue/{from.md → to.md} RENAMED
@@ -1,116 +1,117 @@
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
13
- initialization of an object of a mutex type fails, an exception of type
14
- `system_error` shall be thrown. The mutex types shall not be copyable or
15
- movable.
16
 
17
  The error conditions for error codes, if any, reported by member
18
- 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
  - `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
58
- required ([[thread.req.exception]]).
59
 
60
  *Error conditions:*
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
 
114
  *Throws:* Nothing.
115
 
116
  ##### Class `mutex` <a id="thread.mutex.class">[[thread.mutex.class]]</a>
@@ -127,12 +128,12 @@ namespace std {
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
 
138
  The class `mutex` provides a non-recursive mutex with exclusive
@@ -148,17 +149,17 @@ that it is no longer in use, unlock it, and destroy it, before thread
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.
@@ -177,36 +178,36 @@ namespace std {
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
 
188
  The class `recursive_mutex` provides a recursive mutex with exclusive
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
202
  ownership for a `recursive_mutex` object, additional calls to
203
- `try_lock()` shall fail, and additional calls to `lock()` shall throw an
204
- exception of type `system_error`. A thread shall call `unlock()` once
205
- for each level of ownership acquired by calls to `lock()` and
206
- `try_lock()`. Only when all levels of ownership have been released may
207
- ownership be acquired by another thread.
208
 
209
  The behavior of a program is undefined if:
210
 
211
  - it destroys a `recursive_mutex` object owned by any thread or
212
  - a thread terminates while owning a `recursive_mutex` object.
 
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 this subclause. In this description, `m` denotes an object of a
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.
16
 
17
  The error conditions for error codes, if any, reported by member
18
+ functions of the mutex types are as follows:
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 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 1*: This can be viewed as the modification order
33
+ [[intro.multithread]] of the mutex. — *end note*]
34
 
35
  [*Note 2*: Construction and destruction of an object of a mutex type
36
  need not be thread-safe; other synchronization should be used to ensure
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:
42
 
43
+ *Preconditions:* If `m` is of type `mutex`, `timed_mutex`,
44
+ `shared_mutex`, or `shared_timed_mutex`, the calling thread does not own
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
 
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()` is well-formed and has the following
68
+ semantics:
69
 
70
+ *Preconditions:* If `m` is of type `mutex`, `timed_mutex`,
71
+ `shared_mutex`, or `shared_timed_mutex`, the calling thread does not own
72
+ the mutex.
73
 
74
  *Effects:* Attempts to obtain ownership of the mutex for the calling
75
  thread without blocking. If ownership is not obtained, there is no
76
  effect and `try_lock()` immediately returns. An implementation may fail
77
  to obtain the lock even if it is not held by any other thread.
78
 
79
  [*Note 1*: This spurious failure is normally uncommon, but allows
80
+ 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
 
105
+ *Preconditions:* The calling thread owns the mutex.
106
 
107
  *Effects:* Releases the calling thread’s ownership of the mutex.
108
 
109
  *Return type:* `void`.
110
 
111
  *Synchronization:* This operation synchronizes
112
+ with [[intro.multithread]] subsequent lock operations that obtain
113
  ownership on the same object.
114
 
115
  *Throws:* Nothing.
116
 
117
  ##### Class `mutex` <a id="thread.mutex.class">[[thread.mutex.class]]</a>
 
128
 
129
  void lock();
130
  bool try_lock();
131
  void unlock();
132
 
133
+ using native_handle_type = implementation-defined; // see~[thread.req.native]
134
+ native_handle_type native_handle(); // see~[thread.req.native]
135
  };
136
  }
137
  ```
138
 
139
  The class `mutex` provides a non-recursive mutex with exclusive
 
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
151
  typically occur when a reference-counted object contains a mutex that is
152
  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 4*: A program can deadlock if the thread that owns a `mutex`
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
164
  owned by any thread or a thread terminates while owning a `mutex`
165
  object.
 
178
 
179
  void lock();
180
  bool try_lock() noexcept;
181
  void unlock();
182
 
183
+ using native_handle_type = implementation-defined; // see~[thread.req.native]
184
+ native_handle_type native_handle(); // see~[thread.req.native]
185
  };
186
  }
187
  ```
188
 
189
  The class `recursive_mutex` provides a recursive mutex with exclusive
190
  ownership semantics. If one thread owns a `recursive_mutex` object,
191
  attempts by another thread to acquire ownership of that object will fail
192
  (for `try_lock()`) or block (for `lock()`) until the first thread has
193
  completely released ownership.
194
 
195
+ The class `recursive_mutex` meets all of the mutex requirements
196
+ [[thread.mutex.requirements]]. It is a standard-layout class
197
+ [[class.prop]].
198
 
199
  A thread that owns a `recursive_mutex` object may acquire additional
200
  levels of ownership by calling `lock()` or `try_lock()` on that object.
201
  It is unspecified how many levels of ownership may be acquired by a
202
  single thread. If a thread has already acquired the maximum level of
203
  ownership for a `recursive_mutex` object, additional calls to
204
+ `try_lock()` fail, and additional calls to `lock()` throw an exception
205
+ of type `system_error`. A thread shall call `unlock()` once for each
206
+ level of ownership acquired by calls to `lock()` and `try_lock()`. Only
207
+ when all levels of ownership have been released may ownership be
208
+ acquired by another thread.
209
 
210
  The behavior of a program is undefined if:
211
 
212
  - it destroys a `recursive_mutex` object owned by any thread or
213
  - a thread terminates while owning a `recursive_mutex` object.