Skip to content

Commit 23cb6b3

Browse files
committed
P3475R2 Defang and deprecate memory_order::consume
1 parent 422ded5 commit 23cb6b3

File tree

6 files changed

+49
-255
lines changed

6 files changed

+49
-255
lines changed

source/basic.tex

Lines changed: 4 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -6306,122 +6306,17 @@
63066306
the value written'' by the last mutex release.
63076307
\end{note}
63086308

6309-
\pnum
6310-
An evaluation $A$ \defn{carries a dependency} to an evaluation $B$ if
6311-
\begin{itemize}
6312-
\item
6313-
the value of $A$ is used as an operand of $B$, unless:
6314-
\begin{itemize}
6315-
\item
6316-
$B$ is an invocation of any specialization of
6317-
\tcode{std::kill_dependency}\iref{atomics.order}, or
6318-
\item
6319-
$A$ is the left operand of a built-in logical \logop{and} (\tcode{\&\&},
6320-
see~\ref{expr.log.and}) or logical \logop{or} (\tcode{||}, see~\ref{expr.log.or})
6321-
operator, or
6322-
\item
6323-
$A$ is the left operand of a conditional (\tcode{?:}, see~\ref{expr.cond})
6324-
operator, or
6325-
\item
6326-
$A$ is the left operand of the built-in comma (\tcode{,})
6327-
operator\iref{expr.comma}; \end{itemize} or
6328-
\item
6329-
$A$ writes a scalar object or bit-field $M$, $B$ reads the value
6330-
written by $A$ from $M$, and $A$ is sequenced before $B$, or
6331-
\item
6332-
for some evaluation $X$, $A$ carries a dependency to $X$, and
6333-
$X$ carries a dependency to $B$.
6334-
\end{itemize}
6335-
\begin{note}
6336-
``Carries a dependency to'' is a subset of ``is sequenced before'',
6337-
and is similarly strictly intra-thread.
6338-
\end{note}
6339-
6340-
\pnum
6341-
An evaluation $A$ is \defn{dependency-ordered before} an evaluation
6342-
$B$ if
6343-
\begin{itemize}
6344-
\item
6345-
$A$ performs a release operation on an atomic object $M$, and, in
6346-
another thread, $B$ performs a consume operation on $M$ and reads
6347-
the value written by $A$, or
6348-
6349-
\item
6350-
for some evaluation $X$, $A$ is dependency-ordered before $X$ and
6351-
$X$ carries a dependency to $B$.
6352-
6353-
\end{itemize}
6354-
\begin{note}
6355-
The relation ``is dependency-ordered before'' is analogous to
6356-
``synchronizes with'', but uses release/consume in place of release/acquire.
6357-
\end{note}
6358-
6359-
\pnum
6360-
An evaluation $A$ \defn{inter-thread happens before} an evaluation $B$
6361-
if
6362-
\begin{itemize}
6363-
\item
6364-
$A$ synchronizes with $B$, or
6365-
\item
6366-
$A$ is dependency-ordered before $B$, or
6367-
\item
6368-
for some evaluation $X$
6369-
\begin{itemize}
6370-
\item
6371-
$A$ synchronizes with $X$ and $X$
6372-
is sequenced before $B$, or
6373-
\item
6374-
$A$ is sequenced before $X$ and $X$
6375-
inter-thread happens before $B$, or
6376-
\item
6377-
$A$ inter-thread happens before $X$ and $X$
6378-
inter-thread happens before $B$.
6379-
\end{itemize}
6380-
\end{itemize}
6381-
\begin{note}
6382-
The ``inter-thread happens before'' relation describes arbitrary
6383-
concatenations of ``sequenced before'', ``synchronizes with'' and
6384-
``dependency-ordered before'' relationships, with two exceptions. The first
6385-
exception is that a concatenation never ends with
6386-
``dependency-ordered before'' followed by ``sequenced before''. The reason for
6387-
this limitation is that a consume operation participating in a
6388-
``dependency-ordered before'' relationship provides ordering only with respect
6389-
to operations to which this consume operation actually carries a dependency. The
6390-
reason that this limitation applies only to the end of such a concatenation is
6391-
that any subsequent release operation will provide the required ordering for a
6392-
prior consume operation. The second exception is that a concatenation never
6393-
consist entirely of ``sequenced before''. The reasons for this
6394-
limitation are (1) to permit ``inter-thread happens before'' to be transitively
6395-
closed and (2) the ``happens before'' relation, defined below, provides for
6396-
relationships consisting entirely of ``sequenced before''.
6397-
\end{note}
6398-
63996309
\pnum
64006310
An evaluation $A$ \defn{happens before} an evaluation $B$
6401-
(or, equivalently, $B$ \defn{happens after} $A$) if
6402-
\begin{itemize}
6403-
\item $A$ is sequenced before $B$, or
6404-
\item $A$ inter-thread happens before $B$.
6405-
\end{itemize}
6406-
The implementation shall ensure that no program execution demonstrates a cycle
6407-
in the ``happens before'' relation.
6408-
\begin{note}
6409-
This cycle would otherwise be
6410-
possible only through the use of consume operations.
6411-
\end{note}
6412-
6413-
\pnum
6414-
An evaluation $A$ \defn{simply happens before} an evaluation $B$
6311+
(or, equivalently, $B$ happens after $A$)
64156312
if either
64166313
\begin{itemize}
64176314
\item $A$ is sequenced before $B$, or
64186315
\item $A$ synchronizes with $B$, or
6419-
\item $A$ simply happens before $X$ and
6420-
$X$ simply happens before $B$.
6316+
\item $A$ happens before $X$ and $X$ happens before $B$.
64216317
\end{itemize}
64226318
\begin{note}
6423-
In the absence of consume operations,
6424-
the happens before and simply happens before relations are identical.
6319+
An evaluation cannot happen before itself.
64256320
\end{note}
64266321

64276322
\pnum
@@ -6443,7 +6338,7 @@
64436338
\begin{note}
64446339
Informally, if $A$ strongly happens before $B$,
64456340
then $A$ appears to be evaluated before $B$
6446-
in all contexts. Strongly happens before excludes consume operations.
6341+
in all contexts.
64476342
\end{note}
64486343

64496344
\pnum

source/compatibility.tex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2368,8 +2368,8 @@
23682368
Avoid hard to diagnose or non-portable constructs.
23692369
\effect
23702370
Names of attribute identifiers may not be used as macro names. Valid \CppIII{}
2371-
code that defines \tcode{override}, \tcode{final},
2372-
\tcode{carries_dependency}, or \tcode{noreturn} as macros is invalid in this
2371+
code that defines \tcode{override}, \tcode{final}, or
2372+
\tcode{noreturn} as macros is invalid in this
23732373
revision of \Cpp{}.
23742374

23752375
\rSec2[diff.cpp03.language.support]{\ref{support}:

source/declarations.tex

Lines changed: 3 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -9140,86 +9140,6 @@
91409140
\end{codeblock}
91419141
\end{example}
91429142

9143-
\rSec2[dcl.attr.depend]{Carries dependency attribute}%
9144-
\indextext{attribute!carries dependency}
9145-
9146-
\pnum
9147-
The \grammarterm{attribute-token} \tcode{carries_dependency} specifies
9148-
dependency propagation into and out of functions.
9149-
No
9150-
\grammarterm{attribute-argument-clause} shall be present. The attribute may be
9151-
applied to a parameter of a function or lambda, in
9152-
which case it specifies that the initialization of the parameter carries a
9153-
dependency to\iref{intro.multithread} each lvalue-to-rvalue
9154-
conversion\iref{conv.lval} of that object. The attribute may also be applied
9155-
to a function or a lambda call operator, in which case it
9156-
specifies that the return value, if any, carries a dependency to the evaluation
9157-
of the function call expression.
9158-
9159-
\pnum
9160-
The first declaration of a function shall specify the \tcode{carries_dependency} attribute for its
9161-
\grammarterm{declarator-id} if any declaration of the function specifies the
9162-
\tcode{carries_dependency} attribute. Furthermore, the first declaration of a function shall specify
9163-
the \tcode{carries_dependency} attribute for a parameter if any declaration of that function
9164-
specifies the \tcode{carries_dependency} attribute for that parameter. If a function or one of its
9165-
parameters is declared with the \tcode{carries_dependency} attribute in its first declaration in one
9166-
translation unit and the same function or one of its parameters is declared without the
9167-
\tcode{carries_dependency} attribute in its first declaration in another translation unit, the
9168-
program is ill-formed, no diagnostic required.
9169-
9170-
\pnum
9171-
\begin{note}
9172-
The \tcode{carries_dependency} attribute does not change the meaning of the
9173-
program, but might result in generation of more efficient code.
9174-
\end{note}
9175-
9176-
\pnum
9177-
\begin{example}
9178-
\begin{codeblock}
9179-
/* Translation unit A. */
9180-
9181-
struct foo { int* a; int* b; };
9182-
std::atomic<struct foo *> foo_head[10];
9183-
int foo_array[10][10];
9184-
9185-
[[carries_dependency]] struct foo* f(int i) {
9186-
return foo_head[i].load(memory_order::consume);
9187-
}
9188-
9189-
int g(int* x, int* y [[carries_dependency]]) {
9190-
return kill_dependency(foo_array[*x][*y]);
9191-
}
9192-
9193-
/* Translation unit B. */
9194-
9195-
[[carries_dependency]] struct foo* f(int i);
9196-
int g(int* x, int* y [[carries_dependency]]);
9197-
9198-
int c = 3;
9199-
9200-
void h(int i) {
9201-
struct foo* p;
9202-
9203-
p = f(i);
9204-
do_something_with(g(&c, p->a));
9205-
do_something_with(g(p->a, &c));
9206-
}
9207-
\end{codeblock}
9208-
9209-
The \tcode{carries_dependency} attribute on function \tcode{f} means that the
9210-
return value carries a dependency out of \tcode{f}, so that the implementation
9211-
need not constrain ordering upon return from \tcode{f}. Implementations of
9212-
\tcode{f} and its caller may choose to preserve dependencies instead of emitting
9213-
hardware memory ordering instructions (a.k.a.\ fences).
9214-
Function \tcode{g}'s second parameter has a \tcode{carries_dependency} attribute,
9215-
but its first parameter does not. Therefore, function \tcode{h}'s first call to
9216-
\tcode{g} carries a dependency into \tcode{g}, but its second call does not. The
9217-
implementation might need to insert a fence prior to the second call to
9218-
\tcode{g}.
9219-
\end{example}
9220-
\indextext{attribute|)}%
9221-
\indextext{declaration|)}
9222-
92239143
\rSec2[dcl.attr.deprecated]{Deprecated attribute}%
92249144
\indextext{attribute!deprecated}
92259145

@@ -9694,3 +9614,6 @@
96949614
could have the same address as \tcode{buckets}
96959615
if their respective types are all empty.
96969616
\end{example}
9617+
9618+
\indextext{attribute|)}%
9619+
\indextext{declaration|)}

source/future.tex

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -854,6 +854,9 @@
854854
void atomic_init(volatile atomic<T>*, typename atomic<T>::value_type) noexcept;
855855
template<class T>
856856
void atomic_init(atomic<T>*, typename atomic<T>::value_type) noexcept;
857+
template<class T>
858+
constexpr T kill_dependency(T y) noexcept; // freestanding
859+
inline constexpr memory_order memory_order_consume = memory_order::consume; // freestanding
857860

858861
#define @\libmacro{ATOMIC_VAR_INIT}@(value) @\seebelow@
859862
}
@@ -924,3 +927,24 @@
924927
\end{codeblock}
925928
\end{example}
926929
\end{itemdescr}
930+
931+
\rSec2[depr.atomics.order]{\tcode{memory_order::consume}}
932+
933+
\indexlibrarymember{consume}{memory_order}%
934+
\pnum
935+
The memory_order enumeration contains an additional enumerator:
936+
\begin{codeblock}
937+
consume = 1
938+
\end{codeblock}
939+
The \tcode{memory_order::consume} enumerator is allowed wherever
940+
\tcode{memory_order::acquire} is allowed, and it has the same meaning.
941+
942+
\begin{itemdecl}
943+
template<class T> constexpr T kill_dependency(T y) noexcept;
944+
\end{itemdecl}
945+
946+
\begin{itemdescr}
947+
\pnum
948+
\returns
949+
\tcode{y}.
950+
\end{itemdescr}

source/preprocessor.tex

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,6 @@
400400
\topline
401401
\lhdr{Attribute} & \rhdr{Value} \\ \rowsep
402402
\tcode{assume} & \tcode{202207L} \\
403-
\tcode{carries_dependency} & \tcode{200809L} \\
404403
\tcode{deprecated} & \tcode{201309L} \\
405404
\tcode{fallthrough} & \tcode{201603L} \\
406405
\tcode{likely} & \tcode{201803L} \\

0 commit comments

Comments
 (0)