From Jason Turner

[atomics.types.operations]

Diff to HTML by rtfpessoa

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