C++ Logo

std-discussion

Advanced search

Ordering semantics of compare_exchange_weak on spurious failure

From: Nate Eldredge <nate_at_[hidden]>
Date: Tue, 31 Mar 2026 04:11:26 +0000
I was looking at the description of `std::atomic::compare_exchange_weak` in [atomics.types.operations p21-28] (https://eel.is/c++draft/atomics.types.operations#21), and it seems to be a bit ambiguous on the ordering semantics of spurious failure.

Recall that `compare_exchange_weak` can be passed two `memory_order` arguments, `success` and `failure`. From the naming, I presume that in case of spurious failure, the `failure` ordering is meant to be applied. (Example of clang doing so: https://godbolt.org/z/613P4WMhd.) However, this is not actually stated.

Ordering is only mentioned in p23 ("Effects"), which although it supposedly applies to both compare_exchange_strong and compare_exchange_weak, actually only describes the strong semantics. It does not allow for spurious failures, which are carved out later by p27 ("Remarks"). Paragraph p23 says:

"If and only if the comparison is true, memory is affected according to the value of success, and if the comparison is false, memory is affected according to the value of failure."

If we read this literally, then spurious failure ought to follow the success ordering, because the comparison is true in that case, and p27 doesn't say anything to contradict it. But that doesn't seem to be what's intended.

It seems to me that it would be helpful to rewrite p23 so that it really describes both the strong and weak behavior together. Perhaps something like the following:

------ possible wording -----
[p23] Effects: Retrieves the value in `expected`, and atomically compares it for equality with the value representation of the value pointed to by `this`.

If the comparison is false, or (for `compare_exchange_weak` only) if the operation fails spuriously, then:

  - The value in `expected` is replaced with the value pointed to by `this` during the atomic comparison. [Note: In the case of spurious failure, this value may be the same value that was already in `expected`.]

  - The value pointed to by `this` is not modified.

  - The operation is an atomic load operation on the memory pointed to by `this`, and affects memory according to the value of `failure`.

  - The operation returns `false`.

Otherwise:

  - The value in `expected` is not modified.

  - The value pointed to by `this` is atomically replaced with that in `desired`.

  - The operation is an atomic read-modify-write operation ([intro.multithread]) on the memory pointed to by `this`, and affects memory according to the value of `success`.

  - The operation returns `true`.

When only one `memory_order` argument is supplied [... keep this sentence as is].

[p24] Returns: As described above.

[p25] [Keep as is]

[p26] Remarks: For `compare_exchange_weak`, it is unspecified under what conditions spurious failure may occur. However, implementations should ensure that it does not occur consistently unless there are concurrent modifications to the atomic object. Note that `compare_exchange_strong` does not allow spurious failure. [Note 5 as is]
------- end possible wording ----

Any thoughts?


Received on 2026-03-31 04:11:28