[atomics.order] (original) (raw)

32 Concurrency support library [thread]

32.5 Atomic operations [atomics]

32.5.4 Order and consistency [atomics.order]

namespace std { enum class memory_order : unspecified { relaxed = 0, acquire = 2, release = 3, acq_rel = 4, seq_cst = 5 };}

The enumeration memory_order specifies the detailed regular (non-atomic) memory synchronization order as defined in[intro.multithread] and may provide for operation ordering.

Its enumerated values and their meanings are as follows:

[Note 1:

Atomic operations specifying memory_order​::​relaxed are relaxed with respect to memory ordering.

Implementations must still guarantee that any given atomic access to a particular atomic object be indivisible with respect to all other atomic accesses to that object.

— _end note_]

An atomic operation A that performs a release operation on an atomic object M synchronizes with an atomic operation B that performs an acquire operation on M and takes its value from any side effect in the release sequence headed by A.

An atomic operation A on some atomic object M iscoherence-ordered beforeanother atomic operation B on M if

There is a single total order Son all memory_order​::​seq_cst operations, including fences, that satisfies the following constraints.

First, if A and B arememory_order​::​seq_cst operations andA strongly happens before B, then A precedes B in S.

Second, for every pair of atomic operations A andB on an object M, where A is coherence-ordered before B, the following four conditions are required to be satisfied by S:

[Note 2:

This definition ensures that S is consistent with the modification order of any atomic object M.

It also ensures that a memory_order​::​seq_cst load A of Mgets its value either from the last modification of Mthat precedes A in S or from some non-memory_order​::​seq_cst modification of Mthat does not happen before any modification of Mthat precedes A in S.

— _end note_]

[Note 3:

We do not require that S be consistent with “happens before” ([intro.races]).

This allows more efficient implementation of memory_order​::​acquire and memory_order​::​releaseon some machine architectures.

It can produce surprising results when these are mixed with memory_order​::​seq_cst accesses.

— _end note_]

[Note 4:

memory_order​::​seq_cst ensures sequential consistency only for a program that is free of data races and uses exclusively memory_order​::​seq_cst atomic operations.

Any use of weaker ordering will invalidate this guarantee unless extreme care is used.

In many cases, memory_order​::​seq_cst atomic operations are reorderable with respect to other atomic operations performed by the same thread.

— _end note_]

Implementations should ensure that no “out-of-thin-air” values are computed that circularly depend on their own computation.

[Note 5:

For example, with x and y initially zero,r1 = y.load(memory_order::relaxed); x.store(r1, memory_order::relaxed);

r2 = x.load(memory_order::relaxed); y.store(r2, memory_order::relaxed);this recommendation discourages producing r1 == r2 == 42, since the store of 42 to y is only possible if the store to x stores 42, which circularly depends on the store to y storing 42.

Note that without this restriction, such an execution is possible.

— _end note_]

[Note 6:

The recommendation similarly disallows r1 == r2 == 42 in the following example, with x and y again initially zero:

r1 = x.load(memory_order::relaxed);if (r1 == 42) y.store(42, memory_order::relaxed);

r2 = y.load(memory_order::relaxed);if (r2 == 42) x.store(42, memory_order::relaxed); — _end note_]

Atomic read-modify-write operations shall always read the last value (in the modification order) written before the write associated with the read-modify-write operation.

Recommended practice: The implementation should make atomic stores visible to atomic loads, and atomic loads should observe atomic stores, within a reasonable amount of time.