From Jason Turner

[atomics.types.operations.req]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmptmpglnsp/{from.md → to.md} +0 -325
tmp/tmptmpglnsp/{from.md → to.md} RENAMED
@@ -1,325 +0,0 @@
1
- ### Requirements for operations on atomic types <a id="atomics.types.operations.req">[[atomics.types.operations.req]]</a>
2
-
3
- There are only a few kinds of operations on atomic types, though there
4
- are many instances on those kinds. This section specifies each general
5
- kind. The specific instances are defined in [[atomics.types.generic]],
6
- [[atomics.types.operations.general]],
7
- [[atomics.types.operations.arith]], and
8
- [[atomics.types.operations.pointer]].
9
-
10
- In the following operation definitions:
11
-
12
- - an *A* refers to one of the atomic types.
13
- - a *C* refers to its corresponding non-atomic type.
14
- - an *M* refers to type of the other argument for arithmetic operations.
15
- For integral atomic types, *M* is *C*. For atomic address types, *M*
16
- is `std::ptrdiff_t`.
17
- - the non-member functions not ending in `_explicit` have the semantics
18
- of their corresponding `_explicit` functions with `memory_order`
19
- arguments of `memory_order_seq_cst`.
20
-
21
- Many operations are volatile-qualified. The “volatile as device
22
- register” semantics have not changed in the standard. This qualification
23
- means that volatility is preserved when applying these operations to
24
- volatile objects. It does not mean that operations on non-volatile
25
- objects become volatile. Thus, volatile qualified operations on
26
- non-volatile objects may be merged under some conditions.
27
-
28
- ``` cpp
29
- A::A() noexcept = default;
30
- ```
31
-
32
- *Effects:* leaves the atomic object in an uninitialized state. These
33
- semantics ensure compatibility with C.
34
-
35
- ``` cpp
36
- constexpr A::A(C desired) noexcept;
37
- ```
38
-
39
- *Effects:* Initializes the object with the value `desired`.
40
- Initialization is not an atomic operation ([[intro.multithread]]). it
41
- is possible to have an access to an atomic object `A` race with its
42
- construction, for example by communicating the address of the
43
- just-constructed object `A` to another thread via `memory_order_relaxed`
44
- operations on a suitable atomic pointer variable, and then immediately
45
- accessing `A` in the receiving thread. This results in undefined
46
- behavior.
47
-
48
- ``` cpp
49
- #define ATOMIC_VAR_INIT(value) see below
50
- ```
51
-
52
- The macro expands to a token sequence suitable for constant
53
- initialization of an atomic variable of static storage duration of a
54
- type that is initialization-compatible with *value*. This operation may
55
- need to initialize locks. Concurrent access to the variable being
56
- initialized, even via an atomic operation, constitutes a data race.
57
-
58
- ``` cpp
59
- atomic<int> v = ATOMIC_VAR_INIT(5);
60
- ```
61
-
62
- ``` cpp
63
- bool atomic_is_lock_free(const volatile A* object) noexcept;
64
- bool atomic_is_lock_free(const A* object) noexcept;
65
- bool A::is_lock_free() const volatile noexcept;
66
- bool A::is_lock_free() const noexcept;
67
- ```
68
-
69
- *Returns:* True if the object’s operations are lock-free, false
70
- otherwise.
71
-
72
- ``` cpp
73
- void atomic_init(volatile A* object, C desired) noexcept;
74
- void atomic_init(A* object, C desired) noexcept;
75
- ```
76
-
77
- *Effects:* Non-atomically initializes `*object` with value `desired`.
78
- This function shall only be applied to objects that have been default
79
- constructed, and then only once. These semantics ensure compatibility
80
- with C. Concurrent access from another thread, even via an atomic
81
- operation, constitutes a data race.
82
-
83
- ``` cpp
84
- void atomic_store(volatile A* object, C desired) noexcept;
85
- void atomic_store(A* object, C desired) noexcept;
86
- void atomic_store_explicit(volatile A* object, C desired, memory_order order) noexcept;
87
- void atomic_store_explicit(A* object, C desired, memory_order order) noexcept;
88
- void A::store(C desired, memory_order order = memory_order_seq_cst) volatile noexcept;
89
- void A::store(C desired, memory_order order = memory_order_seq_cst) noexcept;
90
- ```
91
-
92
- *Requires:* The `order` argument shall not be `memory_order_consume`,
93
- `memory_order_acquire`, nor `memory_order_acq_rel`.
94
-
95
- *Effects:* Atomically replaces the value pointed to by `object` or by
96
- `this` with the value of `desired`. Memory is affected according to the
97
- value of `order`.
98
-
99
- ``` cpp
100
- C A::operator=(C desired) volatile noexcept;
101
- C A::operator=(C desired) noexcept;
102
- ```
103
-
104
- *Effects:* `store(desired)`
105
-
106
- *Returns:* `desired`
107
-
108
- ``` cpp
109
- C atomic_load(const volatile A* object) noexcept;
110
- C atomic_load(const A* object) noexcept;
111
- C atomic_load_explicit(const volatile A* object, memory_order) noexcept;
112
- C atomic_load_explicit(const A* object, memory_order) noexcept;
113
- C A::load(memory_order order = memory_order_seq_cst) const volatile noexcept;
114
- C A::load(memory_order order = memory_order_seq_cst) const noexcept;
115
- ```
116
-
117
- *Requires:* The `order` argument shall not be `memory_order_release` nor
118
- `memory_order_acq_rel`.
119
-
120
- *Effects:* Memory is affected according to the value of `order`.
121
-
122
- *Returns:* Atomically returns the value pointed to by `object` or by
123
- `this`.
124
-
125
- ``` cpp
126
- A::operator C() const volatile noexcept;
127
- A::operator C() const noexcept;
128
- ```
129
-
130
- *Effects:* `load()`
131
-
132
- *Returns:* The result of `load()`.
133
-
134
- ``` cpp
135
- C atomic_exchange(volatile A* object, C desired) noexcept;
136
- C atomic_exchange(A* object, C desired) noexcept;
137
- C atomic_exchange_explicit(volatile A* object, C desired, memory_order) noexcept;
138
- C atomic_exchange_explicit(A* object, C desired, memory_order) noexcept;
139
- C A::exchange(C desired, memory_order order = memory_order_seq_cst) volatile noexcept;
140
- C A::exchange(C desired, memory_order order = memory_order_seq_cst) noexcept;
141
- ```
142
-
143
- *Effects:* Atomically replaces the value pointed to by `object` or by
144
- `this` with `desired`. Memory is affected according to the value of
145
- `order`. These operations are atomic read-modify-write
146
- operations ([[intro.multithread]]).
147
-
148
- *Returns:* Atomically returns the value pointed to by `object` or by
149
- `this` immediately before the effects.
150
-
151
- ``` cpp
152
- bool atomic_compare_exchange_weak(volatile A* object, C* expected, C desired) noexcept;
153
- bool atomic_compare_exchange_weak(A* object, C* expected, C desired) noexcept;
154
- bool atomic_compare_exchange_strong(volatile A* object, C* expected, C desired) noexcept;
155
- bool atomic_compare_exchange_strong(A* object, C* expected, C desired) noexcept;
156
- bool atomic_compare_exchange_weak_explicit(volatile A* object, C* expected, C desired,
157
- memory_order success, memory_order failure) noexcept;
158
- bool atomic_compare_exchange_weak_explicit(A* object, C* expected, C desired,
159
- memory_order success, memory_order failure) noexcept;
160
- bool atomic_compare_exchange_strong_explicit(volatile A* object, C* expected, C desired,
161
- memory_order success, memory_order failure) noexcept;
162
- bool atomic_compare_exchange_strong_explicit(A* object, C* expected, C desired,
163
- memory_order success, memory_order failure) noexcept;
164
- bool A::compare_exchange_weak(C& expected, C desired,
165
- memory_order success, memory_order failure) volatile noexcept;
166
- bool A::compare_exchange_weak(C& expected, C desired,
167
- memory_order success, memory_order failure) noexcept;
168
- bool A::compare_exchange_strong(C& expected, C desired,
169
- memory_order success, memory_order failure) volatile noexcept;
170
- bool A::compare_exchange_strong(C& expected, C desired,
171
- memory_order success, memory_order failure) noexcept;
172
- bool A::compare_exchange_weak(C& expected, C desired,
173
- memory_order order = memory_order_seq_cst) volatile noexcept;
174
- bool A::compare_exchange_weak(C& expected, C desired,
175
- memory_order order = memory_order_seq_cst) noexcept;
176
- bool A::compare_exchange_strong(C& expected, C desired,
177
- memory_order order = memory_order_seq_cst) volatile noexcept;
178
- bool A::compare_exchange_strong(C& expected, C desired,
179
- memory_order order = memory_order_seq_cst) noexcept;
180
- ```
181
-
182
- *Requires:* The `failure` argument shall not be `memory_order_release`
183
- nor `memory_order_acq_rel`. The `failure` argument shall be no stronger
184
- than the `success` argument.
185
-
186
- *Effects:* Atomically, compares the contents of the memory pointed to by
187
- `object` or by `this` for equality with that in `expected`, and if true,
188
- replaces the contents of the memory pointed to by `object` or by `this`
189
- with that in `desired`, and if false, updates the contents of the memory
190
- in `expected` with the contents of the memory pointed to by `object` or
191
- by `this`. Further, if the comparison is true, memory is affected
192
- according to the value of `success`, and if the comparison is false,
193
- memory is affected according to the value of `failure`. When only one
194
- `memory_order` argument is supplied, the value of `success` is `order`,
195
- and the value of `failure` is `order` except that a value of
196
- `memory_order_acq_rel` shall be replaced by the value
197
- `memory_order_acquire` and a value of `memory_order_release` shall be
198
- replaced by the value `memory_order_relaxed`. If the operation returns
199
- `true`, these operations are atomic read-modify-write
200
- operations ([[intro.multithread]]). Otherwise, these operations are
201
- atomic load operations.
202
-
203
- *Returns:* The result of the comparison.
204
-
205
- For example, the effect of `atomic_compare_exchange_strong` is
206
-
207
- ``` cpp
208
- if (memcmp(object, expected, sizeof(*object)) == 0)
209
- memcpy(object, &desired, sizeof(*object));
210
- else
211
- memcpy(expected, object, sizeof(*object));
212
- ```
213
-
214
- the expected use of the compare-and-exchange operations is as follows.
215
- The compare-and-exchange operations will update `expected` when another
216
- iteration of the loop is needed.
217
-
218
- ``` cpp
219
- expected = current.load();
220
- do {
221
- desired = function(expected);
222
- } while (!current.compare_exchange_weak(expected, desired));
223
- ```
224
-
225
- Implementations should ensure that weak compare-and-exchange operations
226
- do not consistently return `false` unless either the atomic object has
227
- value different from `expected` or there are concurrent modifications to
228
- the atomic object.
229
-
230
- A weak compare-and-exchange operation may fail spuriously. That is, even
231
- when the contents of memory referred to by `expected` and `object` are
232
- equal, it may return false and store back to `expected` the same memory
233
- contents that were originally there. This spurious failure enables
234
- implementation of compare-and-exchange on a broader class of machines,
235
- e.g., load-locked store-conditional machines. A consequence of spurious
236
- failure is that nearly all uses of weak compare-and-exchange will be in
237
- a loop.
238
-
239
- When a compare-and-exchange is in a loop, the weak version will yield
240
- better performance on some platforms. When a weak compare-and-exchange
241
- would require a loop and a strong one would not, the strong one is
242
- preferable.
243
-
244
- The `memcpy` and `memcmp` semantics of the compare-and-exchange
245
- operations may result in failed comparisons for values that compare
246
- equal with `operator==` if the underlying type has padding bits, trap
247
- bits, or alternate representations of the same value. Thus,
248
- `compare_exchange_strong` should be used with extreme care. On the other
249
- hand, `compare_exchange_weak` should converge rapidly.
250
-
251
- The following operations perform arithmetic computations. The key,
252
- operator, and computation correspondence is:
253
-
254
- **Table: Atomic arithmetic computations** <a id="tab:atomic.arithmetic.computations">[tab:atomic.arithmetic.computations]</a>
255
-
256
- | | | | | | |
257
- | ----- | --- | -------------------- | ----- | --- | -------------------- |
258
- | `add` | `+` | addition | `sub` | `-` | subtraction |
259
- | `or` | `|` | bitwise inclusive or | `xor` | `^` | bitwise exclusive or |
260
- | `and` | `&` | bitwise and | | | |
261
-
262
- ``` cpp
263
- C atomic_fetch_key(volatile A* object, M operand) noexcept;
264
- C atomic_fetch_key(A* object, M operand) noexcept;
265
- C atomic_fetch_key_explicit(volatile A* object, M operand, memory_order order) noexcept;
266
- C atomic_fetch_key_explicit(A* object, M operand, memory_order order) noexcept;
267
- C A::fetch_key(M operand, memory_order order = memory_order_seq_cst) volatile noexcept;
268
- C A::fetch_key(M operand, memory_order order = memory_order_seq_cst) noexcept;
269
- ```
270
-
271
- *Effects:* Atomically replaces the value pointed to by `object` or by
272
- `this` with the result of the *computation* applied to the value pointed
273
- to by `object` or by `this` and the given `operand`. Memory is affected
274
- according to the value of `order`. These operations are atomic
275
- read-modify-write operations ([[intro.multithread]]).
276
-
277
- *Returns:* Atomically, the value pointed to by `object` or by `this`
278
- immediately before the effects.
279
-
280
- For signed integer types, arithmetic is defined to use two’s complement
281
- representation. There are no undefined results. For address types, the
282
- result may be an undefined address, but the operations otherwise have no
283
- undefined behavior.
284
-
285
- ``` cpp
286
- C A::operator op=(M operand) volatile noexcept;
287
- C A::operator op=(M operand) noexcept;
288
- ```
289
-
290
- *Effects:* `fetch_`*`key`*`(operand)`
291
-
292
- *Returns:* `fetch_`*`key`*`(operand) op operand`
293
-
294
- ``` cpp
295
- C A::operator++(int) volatile noexcept;
296
- C A::operator++(int) noexcept;
297
- ```
298
-
299
- *Returns:* `fetch_add(1)`
300
-
301
- ``` cpp
302
- C A::operator--(int) volatile noexcept;
303
- C A::operator--(int) noexcept;
304
- ```
305
-
306
- *Returns:* `fetch_sub(1)`
307
-
308
- ``` cpp
309
- C A::operator++() volatile noexcept;
310
- C A::operator++() noexcept;
311
- ```
312
-
313
- *Effects:* `fetch_add(1)`
314
-
315
- *Returns:* `fetch_add(1) + 1`
316
-
317
- ``` cpp
318
- C A::operator--() volatile noexcept;
319
- C A::operator--() noexcept;
320
- ```
321
-
322
- *Effects:* `fetch_sub(1)`
323
-
324
- *Returns:* `fetch_sub(1) - 1`
325
-