From Jason Turner

[atomics.order]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmp8nyociw9/{from.md → to.md} +83 -86
tmp/tmp8nyociw9/{from.md → to.md} RENAMED
@@ -1,144 +1,141 @@
1
  ## Order and consistency <a id="atomics.order">[[atomics.order]]</a>
2
 
3
  ``` cpp
4
  namespace std {
5
- enum memory_order {
6
- memory_order_relaxed, memory_order_consume, memory_order_acquire,
7
- memory_order_release, memory_order_acq_rel, memory_order_seq_cst
8
  };
 
 
 
 
 
 
9
  }
10
  ```
11
 
12
  The enumeration `memory_order` specifies the detailed regular
13
  (non-atomic) memory synchronization order as defined in
14
  [[intro.multithread]] and may provide for operation ordering. Its
15
  enumerated values and their meanings are as follows:
16
 
17
- - `memory_order_relaxed`: no operation orders memory.
18
- - `memory_order_release`, `memory_order_acq_rel`, and
19
- `memory_order_seq_cst`: a store operation performs a release operation
20
- on the affected memory location.
21
- - `memory_order_consume`: a load operation performs a consume operation
22
  on the affected memory location. \[*Note 1*: Prefer
23
- `memory_order_acquire`, which provides stronger guarantees than
24
- `memory_order_consume`. Implementations have found it infeasible to
25
- provide performance better than that of `memory_order_acquire`.
26
  Specification revisions are under consideration. — *end note*]
27
- - `memory_order_acquire`, `memory_order_acq_rel`, and
28
- `memory_order_seq_cst`: a load operation performs an acquire operation
29
- on the affected memory location.
30
 
31
- [*Note 2*: Atomic operations specifying `memory_order_relaxed` are
32
  relaxed with respect to memory ordering. Implementations must still
33
  guarantee that any given atomic access to a particular atomic object be
34
  indivisible with respect to all other atomic accesses to that
35
  object. — *end note*]
36
 
37
- An atomic operation *A* that performs a release operation on an atomic
38
- object *M* synchronizes with an atomic operation *B* that performs an
39
- acquire operation on *M* and takes its value from any side effect in the
40
- release sequence headed by *A*.
41
-
42
- There shall be a single total order *S* on all `memory_order_seq_cst`
43
- operations, consistent with the “happens before” order and modification
44
- orders for all affected locations, such that each `memory_order_seq_cst`
45
- operation *B* that loads a value from an atomic object *M* observes one
46
- of the following values:
47
-
48
- - the result of the last modification *A* of *M* that precedes *B* in
49
- *S*, if it exists, or
50
- - if *A* exists, the result of some modification of *M* that is not
51
- `memory_order_seq_cst` and that does not happen before *A*, or
52
- - if *A* does not exist, the result of some modification of *M* that is
53
- not `memory_order_seq_cst`.
54
-
55
- [*Note 3*: Although it is not explicitly required that *S* include
56
- locks, it can always be extended to an order that does include lock and
57
- unlock operations, since the ordering between those is already included
58
- in the “happens before” ordering. *end note*]
59
-
60
- For an atomic operation *B* that reads the value of an atomic object
61
- *M*, if there is a `memory_order_seq_cst` fence *X* sequenced before
62
- *B*, then *B* observes either the last `memory_order_seq_cst`
63
- modification of *M* preceding *X* in the total order *S* or a later
64
- modification of *M* in its modification order.
65
-
66
- For atomic operations *A* and *B* on an atomic object *M*, where *A*
67
- modifies *M* and *B* takes its value, if there is a
68
- `memory_order_seq_cst` fence *X* such that *A* is sequenced before *X*
69
- and *B* follows *X* in *S*, then *B* observes either the effects of *A*
70
- or a later modification of *M* in its modification order.
71
-
72
- For atomic operations *A* and *B* on an atomic object *M*, where *A*
73
- modifies *M* and *B* takes its value, if there are
74
- `memory_order_seq_cst` fences *X* and *Y* such that *A* is sequenced
75
- before *X*, *Y* is sequenced before *B*, and *X* precedes *Y* in *S*,
76
- then *B* observes either the effects of *A* or a later modification of
77
- *M* in its modification order.
78
-
79
- For atomic modifications *A* and *B* of an atomic object *M*, *B* occurs
80
- later than *A* in the modification order of *M* if:
81
-
82
- - there is a `memory_order_seq_cst` fence *X* such that *A* is sequenced
83
- before *X*, and *X* precedes *B* in *S*, or
84
- - there is a `memory_order_seq_cst` fence *Y* such that *Y* is sequenced
85
- before *B*, and *A* precedes *Y* in *S*, or
86
- - there are `memory_order_seq_cst` fences *X* and *Y* such that *A* is
87
- sequenced before *X*, *Y* is sequenced before *B*, and *X* precedes
88
- *Y* in *S*.
89
-
90
- [*Note 4*: `memory_order_seq_cst` ensures sequential consistency only
91
  for a program that is free of data races and uses exclusively
92
- `memory_order_seq_cst` operations. Any use of weaker ordering will
93
- invalidate this guarantee unless extreme care is used. In particular,
94
- `memory_order_seq_cst` fences ensure a total order only for the fences
95
- themselves. Fences cannot, in general, be used to restore sequential
96
- consistency for atomic operations with weaker ordering
97
- specifications. — *end note*]
98
 
99
  Implementations should ensure that no “out-of-thin-air” values are
100
  computed that circularly depend on their own computation.
101
 
102
- [*Note 5*:
103
 
104
  For example, with `x` and `y` initially zero,
105
 
106
  ``` cpp
107
  // Thread 1:
108
- r1 = y.load(memory_order_relaxed);
109
- x.store(r1, memory_order_relaxed);
110
  ```
111
 
112
  ``` cpp
113
  // Thread 2:
114
- r2 = x.load(memory_order_relaxed);
115
- y.store(r2, memory_order_relaxed);
116
  ```
117
 
118
  should not produce `r1 == r2 == 42`, since the store of 42 to `y` is
119
  only possible if the store to `x` stores `42`, which circularly depends
120
  on the store to `y` storing `42`. Note that without this restriction,
121
  such an execution is possible.
122
 
123
  — *end note*]
124
 
125
- [*Note 6*:
126
 
127
  The recommendation similarly disallows `r1 == r2 == 42` in the following
128
  example, with `x` and `y` again initially zero:
129
 
130
  ``` cpp
131
  // Thread 1:
132
- r1 = x.load(memory_order_relaxed);
133
- if (r1 == 42) y.store(42, memory_order_relaxed);
134
  ```
135
 
136
  ``` cpp
137
  // Thread 2:
138
- r2 = y.load(memory_order_relaxed);
139
- if (r2 == 42) x.store(42, memory_order_relaxed);
140
  ```
141
 
142
  — *end note*]
143
 
144
  Atomic read-modify-write operations shall always read the last value (in
@@ -152,9 +149,9 @@ a reasonable amount of time.
152
  template<class T>
153
  T kill_dependency(T y) noexcept;
154
  ```
155
 
156
  *Effects:* The argument does not carry a dependency to the return
157
- value ([[intro.multithread]]).
158
 
159
  *Returns:* `y`.
160
 
 
1
  ## Order and consistency <a id="atomics.order">[[atomics.order]]</a>
2
 
3
  ``` cpp
4
  namespace std {
5
+ enum class memory_order : unspecified {
6
+ relaxed, consume, acquire, release, acq_rel, seq_cst
 
7
  };
8
+ inline constexpr memory_order memory_order_relaxed = memory_order::relaxed;
9
+ inline constexpr memory_order memory_order_consume = memory_order::consume;
10
+ inline constexpr memory_order memory_order_acquire = memory_order::acquire;
11
+ inline constexpr memory_order memory_order_release = memory_order::release;
12
+ inline constexpr memory_order memory_order_acq_rel = memory_order::acq_rel;
13
+ inline constexpr memory_order memory_order_seq_cst = memory_order::seq_cst;
14
  }
15
  ```
16
 
17
  The enumeration `memory_order` specifies the detailed regular
18
  (non-atomic) memory synchronization order as defined in
19
  [[intro.multithread]] and may provide for operation ordering. Its
20
  enumerated values and their meanings are as follows:
21
 
22
+ - `memory_order::relaxed`: no operation orders memory.
23
+ - `memory_order::release`, `memory_order::acq_rel`, and
24
+ `memory_order::seq_cst`: a store operation performs a release
25
+ operation on the affected memory location.
26
+ - `memory_order::consume`: a load operation performs a consume operation
27
  on the affected memory location. \[*Note 1*: Prefer
28
+ `memory_order::acquire`, which provides stronger guarantees than
29
+ `memory_order::consume`. Implementations have found it infeasible to
30
+ provide performance better than that of `memory_order::acquire`.
31
  Specification revisions are under consideration. — *end note*]
32
+ - `memory_order::acquire`, `memory_order::acq_rel`, and
33
+ `memory_order::seq_cst`: a load operation performs an acquire
34
+ operation on the affected memory location.
35
 
36
+ [*Note 2*: Atomic operations specifying `memory_order::relaxed` are
37
  relaxed with respect to memory ordering. Implementations must still
38
  guarantee that any given atomic access to a particular atomic object be
39
  indivisible with respect to all other atomic accesses to that
40
  object. — *end note*]
41
 
42
+ An atomic operation A that performs a release operation on an atomic
43
+ object M synchronizes with an atomic operation B that performs an
44
+ acquire operation on M and takes its value from any side effect in the
45
+ release sequence headed by A.
46
+
47
+ An atomic operation A on some atomic object M is *coherence-ordered
48
+ before* another atomic operation B on M if
49
+
50
+ - A is a modification, and B reads the value stored by A, or
51
+ - A precedes B in the modification order of M, or
52
+ - A and B are not the same atomic read-modify-write operation, and there
53
+ exists an atomic modification X of M such that A reads the value
54
+ stored by X and X precedes B in the modification order of M, or
55
+ - there exists an atomic modification X of M such that A is
56
+ coherence-ordered before X and X is coherence-ordered before B.
57
+
58
+ There is a single total order S on all `memory_order::seq_cst`
59
+ operations, including fences, that satisfies the following constraints.
60
+ First, if A and B are `memory_order::seq_cst` operations and A strongly
61
+ happens before B, then A precedes B in S. Second, for every pair of
62
+ atomic operations A and B on an object M, where A is coherence-ordered
63
+ before B, the following four conditions are required to be satisfied by
64
+ S:
65
+
66
+ - if A and B are both `memory_order::seq_cst` operations, then A
67
+ precedes B in S; and
68
+ - if A is a `memory_order::seq_cst` operation and B happens before a
69
+ `memory_order::seq_cst` fence Y, then A precedes Y in S; and
70
+ - if a `memory_order::seq_cst` fence X happens before A and B is a
71
+ `memory_order::seq_cst` operation, then X precedes B in S; and
72
+ - if a `memory_order::seq_cst` fence X happens before A and B happens
73
+ before a `memory_order::seq_cst` fence Y, then X precedes Y in S.
74
+
75
+ [*Note 3*: This definition ensures that S is consistent with the
76
+ modification order of any atomic object M. It also ensures that a
77
+ `memory_order::seq_cst` load A of M gets its value either from the last
78
+ modification of M that precedes A in S or from some
79
+ non-`memory_order::seq_cst` modification of M that does not happen
80
+ before any modification of M that precedes A in S. — *end note*]
81
+
82
+ [*Note 4*: We do not require that S be consistent with “happens before”
83
+ [[intro.races]]. This allows more efficient implementation of
84
+ `memory_order::acquire` and `memory_order::release` on some machine
85
+ architectures. It can produce surprising results when these are mixed
86
+ with `memory_order::seq_cst` accesses. — *end note*]
87
+
88
+ [*Note 5*: `memory_order::seq_cst` ensures sequential consistency only
 
 
 
 
 
 
 
89
  for a program that is free of data races and uses exclusively
90
+ `memory_order::seq_cst` atomic operations. Any use of weaker ordering
91
+ will invalidate this guarantee unless extreme care is used. In many
92
+ cases, `memory_order::seq_cst` atomic operations are reorderable with
93
+ respect to other atomic operations performed by the same
94
+ thread. *end note*]
 
95
 
96
  Implementations should ensure that no “out-of-thin-air” values are
97
  computed that circularly depend on their own computation.
98
 
99
+ [*Note 6*:
100
 
101
  For example, with `x` and `y` initially zero,
102
 
103
  ``` cpp
104
  // Thread 1:
105
+ r1 = y.load(memory_order::relaxed);
106
+ x.store(r1, memory_order::relaxed);
107
  ```
108
 
109
  ``` cpp
110
  // Thread 2:
111
+ r2 = x.load(memory_order::relaxed);
112
+ y.store(r2, memory_order::relaxed);
113
  ```
114
 
115
  should not produce `r1 == r2 == 42`, since the store of 42 to `y` is
116
  only possible if the store to `x` stores `42`, which circularly depends
117
  on the store to `y` storing `42`. Note that without this restriction,
118
  such an execution is possible.
119
 
120
  — *end note*]
121
 
122
+ [*Note 7*:
123
 
124
  The recommendation similarly disallows `r1 == r2 == 42` in the following
125
  example, with `x` and `y` again initially zero:
126
 
127
  ``` cpp
128
  // Thread 1:
129
+ r1 = x.load(memory_order::relaxed);
130
+ if (r1 == 42) y.store(42, memory_order::relaxed);
131
  ```
132
 
133
  ``` cpp
134
  // Thread 2:
135
+ r2 = y.load(memory_order::relaxed);
136
+ if (r2 == 42) x.store(42, memory_order::relaxed);
137
  ```
138
 
139
  — *end note*]
140
 
141
  Atomic read-modify-write operations shall always read the last value (in
 
149
  template<class T>
150
  T kill_dependency(T y) noexcept;
151
  ```
152
 
153
  *Effects:* The argument does not carry a dependency to the return
154
+ value [[intro.multithread]].
155
 
156
  *Returns:* `y`.
157