This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of Immediate status.
compare_exchange_weak writes a value on spurious failure, not memory contentsSection: 32.5.7.2 [atomics.ref.ops], 32.5.8.2 [atomics.types.operations] Status: Immediate Submitter: Jonathan Wakely Opened: 2026-03-24 Last modified: 2026-03-27
Priority: 3
View other active issues in [atomics.ref.ops].
View all other issues in [atomics.ref.ops].
View all issues with Immediate status.
Discussion:
[atomic.ref.ops] says:
-27- Remarks: A weak compare-and-exchange operation may fail spuriously. That is, even when the contents of memory referred to byI think this is missing an update from P0528R3 which should have changed "the same memory contents" to something like "the same value". When the comparison succeeds but the weak CAS fails anyway, the bits ofexpectedandptrare equal, it may returnfalseand store back toexpectedthe same memory contents that were originally there.
exchange are replaced by the bits copied from *ptr.
Those bits might differ from the original bits of expected in their padding.
[Croydon 2026-03-24; Set priority to 2 and send to SG1.]
[Croydon 2026-03-27; SG1 approved the change.]
[Croydon 2026-03-27; move to Immediate.]
Proposed resolution:
This wording is relative to N5032.
Modify 32.5.7.2 [atomics.ref.ops] as indicated:
constexpr bool compare_exchange_weak(value_type& expected, value_type desired, memory_order order = memory_order::seq_cst) const noexcept; constexpr bool compare_exchange_strong(value_type& expected, value_type desired, memory_order order = memory_order::seq_cst) const noexcept;-23- Constraints:
is_const_v<T>isfalse.-24- Preconditions:
failureismemory_order::relaxed,memory_order::acquire, ormemory_order::seq_cst.-25- Effects: Retrieves the value in
expected. It then atomically compares the value representation of the value referenced by*ptrfor equality with that previously retrieved fromexpected, and iftrue, replaces the value referenced by*ptrwith that indesired. If and only if the comparison istrue, memory is affected according to the value ofsuccess, and if the comparison isfalse, memory is affected according to the value offailure. When only onememory_orderargument is supplied, the value ofsuccessisorder, and the value offailureisorderexcept that a value ofmemory_order::acq_relshall be replaced by the valuememory_order::acquireand a value ofmemory_order::releaseshall be replaced by the valuememory_order::relaxed. If and only if the comparison isfalsethen, after the atomic operation, the value inexpectedis replaced by the value read from the value referenced by*ptrduring the atomic comparison. If the operation returnstrue, these operations are atomic read-modify-write operations (6.10.2.2 [intro.races]) on the value referenced by*ptr. Otherwise, these operations are atomic load operations on that memory.-26- Returns: The result of the comparison.
-27- Remarks: A weak compare-and-exchange operation may fail spuriously. That is, even when the
contents of memoryvalue representations referred to byexpectedandptrarecompare equal, it may returnfalseand store back toexpectedthe samememory contents that werevalue representation that was originally there.[Note 2: This spurious failure enables implementation of compare-and-exchange on a broader class of machines, e.g., load-locked store-conditional machines. A consequence of spurious failure is that nearly all uses of weak compare-and-exchange will be in a loop. When a compare-and-exchange is in a loop, the weak version will yield better performance on some platforms. When a weak compare-and-exchange would require a loop and a strong one would not, the strong one is preferable. — end note]
Modify 32.5.8.2 [atomics.types.operations] as indicated:
bool compare_exchange_weak(T& expected, T desired, memory_order success, memory_order failure) volatile noexcept; constexpr bool compare_exchange_weak(T& expected, T desired, memory_order success, memory_order failure) noexcept; bool compare_exchange_strong(T& expected, T desired, memory_order success, memory_order failure) volatile noexcept; constexpr bool compare_exchange_strong(T& expected, T desired, memory_order success, memory_order failure) noexcept; bool compare_exchange_weak(T& expected, T desired, memory_order order = memory_order::seq_cst) volatile noexcept; constexpr bool compare_exchange_weak(T& expected, T desired, memory_order order = memory_order::seq_cst) noexcept; bool compare_exchange_strong(T& expected, T desired, memory_order order = memory_order::seq_cst) volatile noexcept; constexpr bool compare_exchange_strong(T& expected, T desired, memory_order order = memory_order::seq_cst) noexcept;-21- Constraints: For the
volatileoverload of this function,is_always_lock_freeistrue.-22- Preconditions:
failureismemory_order::relaxed,memory_order::acquire, ormemory_order::seq_cst.-25- Effects: Retrieves the value in
expected. It then atomically compares the value representation of the value pointed to bythisfor equality with that previously retrieved fromexpected, and iftrue, replaces the value pointed to bythiswith that indesired. If and only if the comparison istrue, memory is affected according to the value ofsuccess, and if the comparison isfalse, memory is affected according to the value offailure. When only onememory_orderargument is supplied, the value ofsuccessisorder, and the value offailureisorderexcept that a value ofmemory_order::acq_relshall be replaced by the valuememory_order::acquireand a value ofmemory_order::releaseshall be replaced by the valuememory_order::relaxed. If and only if the comparison isfalsethen, after the atomic operation, the value inexpectedis replaced by the value read from the value pointed to bythisduring the atomic comparison. If the operation returnstrue, these operations are atomic read-modify-write operations (6.10.2 [intro.multithread]6.10.2.2 [intro.races]) on the value pointed to bythis. Otherwise, these operations are atomic load operations on that memory.-24- Returns: The result of the comparison.
-25- [Note 4: For example, the effect of
compare_exchange_strongon objects without padding bits (6.9.1 [basic.types.general]) is— end note]if (memcmp(this, &expected, sizeof(*this)) == 0) memcpy(this, &desired, sizeof(*this)); else memcpy(&expected, this, sizeof(*this));[Example 1: The expected use of the compare-and-exchange operations is as follows. The compare-and-exchange operations will update expected when another iteration of the loop is needed.
— end example]expected = current.load(); do { desired = function(expected); } while (!current.compare_exchange_weak(expected, desired));[Example 2: Because the expected value is updated only on failure, code releasing the memory containing the expected value on success will work. For example, list head insertion will act atomically and would not introduce a data race in the following code:
— end example]do { p->next = head; // make new list node point to the current head } while (!head.compare_exchange_weak(p->next, p)); // try to insert-26- Recommended practice: Implementations should ensure that weak compare-and-exchange operations do not consistently return false unless either the atomic object has value different from
expectedor there are concurrent modifications to the atomic object.-27- Remarks: A weak compare-and-exchange operation may fail spuriously. That is, even when the
contents of memoryvalue representations referred to byexpectedandthisarecompare equal, it may returnfalseand store back toexpectedthe samememory contents that werevalue representation that was originally there.[Note 2: This spurious failure enables implementation of compare-and-exchange on a broader class of machines, e.g., load-locked store-conditional machines. A consequence of spurious failure is that nearly all uses of weak compare-and-exchange will be in a loop. When a compare-and-exchange is in a loop, the weak version will yield better performance on some platforms. When a weak compare-and-exchange would require a loop and a strong one would not, the strong one is preferable. — end note]