234 lines
8.2 KiB
Markdown
234 lines
8.2 KiB
Markdown
[atomics.order]
|
||
|
||
# 32 Concurrency support library [[thread]](./#thread)
|
||
|
||
## 32.5 Atomic operations [[atomics]](atomics#order)
|
||
|
||
### 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};}
|
||
|
||
[1](#1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L2903)
|
||
|
||
The enumeration memory_order specifies the detailed regular
|
||
(non-atomic) memory synchronization order as defined in[[intro.multithread]](intro.multithread "6.10.2 Multi-threaded executions and data races") and may provide for operation ordering[.](#1.sentence-1)
|
||
|
||
Its
|
||
enumerated values and their meanings are as follows:
|
||
|
||
- [(1.1)](#1.1)
|
||
|
||
memory_order::relaxed: no operation orders memory[.](#1.1.sentence-1)
|
||
|
||
- [(1.2)](#1.2)
|
||
|
||
memory_order::release, memory_order::acq_rel, andmemory_order::seq_cst: a store operation performs a release operation on the
|
||
affected memory location[.](#1.2.sentence-1)
|
||
|
||
- [(1.3)](#1.3)
|
||
|
||
memory_order::acquire, memory_order::acq_rel, andmemory_order::seq_cst: a load operation performs an acquire operation on the
|
||
affected memory location[.](#1.3.sentence-1)
|
||
|
||
[*Note [1](#note-1)*:
|
||
|
||
Atomic operations specifying memory_order::relaxed are relaxed
|
||
with respect to memory ordering[.](#1.sentence-3)
|
||
|
||
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[.](#1.sentence-4)
|
||
|
||
â *end note*]
|
||
|
||
[2](#2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L2928)
|
||
|
||
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[.](#2.sentence-1)
|
||
|
||
[3](#3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L2934)
|
||
|
||
An atomic operation A on some atomic object M is[*coherence-ordered before*](#def:coherence-ordered_before "32.5.4 Order and consistency [atomics.order]") another atomic operation B on M if
|
||
|
||
- [(3.1)](#3.1)
|
||
|
||
A is a modification, andB reads the value stored by A, or
|
||
|
||
- [(3.2)](#3.2)
|
||
|
||
A precedes B in the modification order of M, or
|
||
|
||
- [(3.3)](#3.3)
|
||
|
||
A and B are not
|
||
the same atomic read-modify-write operation, and
|
||
there exists an atomic modification X of M such that A reads the value stored by X andX precedes B in the modification order of M, or
|
||
|
||
- [(3.4)](#3.4)
|
||
|
||
there exists an atomic modification X of M such that A is coherence-ordered before X andX is coherence-ordered before B[.](#3.sentence-1)
|
||
|
||
[4](#4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L2954)
|
||
|
||
There is a single total order S on all memory_order::seq_cst operations, including fences,
|
||
that satisfies the following constraints[.](#4.sentence-1)
|
||
|
||
First, if A and B arememory_order::seq_cst operations andA strongly happens before B,
|
||
then A precedes B in S[.](#4.sentence-2)
|
||
|
||
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:
|
||
|
||
- [(4.1)](#4.1)
|
||
|
||
if A and B are bothmemory_order::seq_cst operations,
|
||
then A precedes B in S; and
|
||
|
||
- [(4.2)](#4.2)
|
||
|
||
if A is a memory_order::seq_cst operation andB happens before
|
||
a memory_order::seq_cst fence Y,
|
||
then A precedes Y in S; and
|
||
|
||
- [(4.3)](#4.3)
|
||
|
||
if a memory_order::seq_cst fence X happens before A andB is a memory_order::seq_cst operation,
|
||
then X precedes B in S; and
|
||
|
||
- [(4.4)](#4.4)
|
||
|
||
if a memory_order::seq_cst fence X happens before A andB happens before
|
||
a memory_order::seq_cst fence Y,
|
||
then X precedes Y in S[.](#4.sentence-3)
|
||
|
||
[5](#5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L2985)
|
||
|
||
[*Note [2](#note-2)*:
|
||
|
||
This definition ensures that S is consistent with
|
||
the modification order of any atomic object M[.](#5.sentence-1)
|
||
|
||
It also ensures that
|
||
a memory_order::seq_cst load A of M gets its value either from the last modification of M that precedes A in S or
|
||
from some non-memory_order::seq_cst modification of M that does not happen before any modification of M that precedes A in S[.](#5.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[6](#6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L2998)
|
||
|
||
[*Note [3](#note-3)*:
|
||
|
||
We do not require that S be consistent with
|
||
âhappens beforeâ ([[intro.races]](intro.races "6.10.2.2 Data races"))[.](#6.sentence-1)
|
||
|
||
This allows more efficient implementation
|
||
of memory_order::acquire and memory_order::release on some machine architectures[.](#6.sentence-2)
|
||
|
||
It can produce surprising results
|
||
when these are mixed with memory_order::seq_cst accesses[.](#6.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
[7](#7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3009)
|
||
|
||
[*Note [4](#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[.](#7.sentence-1)
|
||
|
||
Any use of weaker ordering will invalidate this guarantee
|
||
unless extreme care is used[.](#7.sentence-2)
|
||
|
||
In many cases, memory_order::seq_cst atomic operations are reorderable
|
||
with respect to other atomic operations performed by the same thread[.](#7.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
[8](#8)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3020)
|
||
|
||
Implementations should ensure that no âout-of-thin-airâ values are computed that
|
||
circularly depend on their own computation[.](#8.sentence-1)
|
||
|
||
[*Note [5](#note-5)*:
|
||
|
||
For example, with x and y initially zero,// Thread 1: r1 = y.load(memory_order::relaxed);
|
||
x.store(r1, memory_order::relaxed);
|
||
|
||
// Thread 2: 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[.](#8.sentence-3)
|
||
|
||
Note that without this restriction, such an
|
||
execution is possible[.](#8.sentence-4)
|
||
|
||
â *end note*]
|
||
|
||
[9](#9)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3043)
|
||
|
||
[*Note [6](#note-6)*:
|
||
|
||
The recommendation similarly disallows r1 == r2 == 42 in the
|
||
following example, with x and y again initially zero:
|
||
|
||
// Thread 1: r1 = x.load(memory_order::relaxed);if (r1 == 42) y.store(42, memory_order::relaxed);
|
||
|
||
// Thread 2: r2 = y.load(memory_order::relaxed);if (r2 == 42) x.store(42, memory_order::relaxed); â *end note*]
|
||
|
||
[10](#10)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3061)
|
||
|
||
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[.](#10.sentence-1)
|
||
|
||
[11](#11)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3066)
|
||
|
||
An [*atomic modify-write operation*](#def:modify-write_operation,atomic "32.5.4 Order and consistency [atomics.order]") is
|
||
an atomic read-modify-write operation
|
||
with weaker synchronization requirements as specified in [[atomics.fences]](atomics.fences "32.5.11 Fences")[.](#11.sentence-1)
|
||
|
||
[*Note [7](#note-7)*:
|
||
|
||
The intent is for atomic modify-write operations
|
||
to be implemented using mechanisms that are not ordered, in hardware,
|
||
by the implementation of acquire fences[.](#11.sentence-2)
|
||
|
||
No other semantic or hardware property
|
||
(e.g., that the mechanism is a far atomic operation) is implied[.](#11.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
[12](#12)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3078)
|
||
|
||
*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[.](#12.sentence-1)
|