Skip to content

Commit accb1d8

Browse files
committed
P0250R3 Wording improvements for initialization and thread ids
Fixes CWG2046, CWG1784. [basic.start.dynamic] Swap order of new p2 and old p2 so the description flows better. Rephrase "avoid deadlocks" note to clarify that it is a suggestion for implementations and not a consequence of the prior rules. [basic.start.term] Move last sentence of new p2 into p3 so that it appears in a more natural place in the description. [support.start.term] Replace "can" with "may" as this note is discussing possibility, not permission.
1 parent 49caa2b commit accb1d8

File tree

3 files changed

+106
-52
lines changed

3 files changed

+106
-52
lines changed

source/basic.tex

Lines changed: 76 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -2432,8 +2432,12 @@
24322432

24332433
\pnum
24342434
\indextext{program!start|(}%
2435-
A program shall contain a global function called \tcode{main}, which is the designated
2436-
start of the program. It is \impldef{defining \tcode{main} in freestanding environment}
2435+
A program shall contain a global function called \tcode{main}.
2436+
Executing a program starts a main thread of execution~(\ref{intro.multithread}, \ref{thread.threads})
2437+
in which the \tcode{main} function is invoked,
2438+
and in which variables of static storage duration
2439+
might be initialized~(\ref{basic.start.static}) and destroyed~(\ref{basic.start.term}).
2440+
It is \impldef{defining \tcode{main} in freestanding environment}
24372441
whether a program in a freestanding environment is required to define a \tcode{main}
24382442
function. \begin{note} In a freestanding environment, start-up and termination is
24392443
\impldef{start-up and termination in freestanding environment}; start-up contains the
@@ -2559,7 +2563,8 @@
25592563
\indextext{initialization!dynamic}%
25602564
\defn{static initialization};
25612565
all other initialization is \defn{dynamic initialization}.
2562-
Static initialization shall be performed before any dynamic initialization takes place.
2566+
All static initialization strongly happens before~(\ref{intro.races})
2567+
any dynamic initialization.
25632568
\begin{note} The dynamic initialization of non-local variables is described
25642569
in~\ref{basic.start.dynamic}; that of local static variables is described
25652570
in~\ref{stmt.dcl}. \end{note}
@@ -2627,12 +2632,17 @@
26272632
unordered initialization, and \tcode{V} is defined before \tcode{W} in
26282633
every translation unit in which \tcode{W} is defined, the initialization of
26292634
\tcode{V} is sequenced before the initialization of \tcode{W} if the
2630-
program does not start a thread (\ref{intro.multithread}) and otherwise
2631-
happens before the initialization of \tcode{W}.
2635+
program does not start a thread~(\ref{intro.multithread})
2636+
other than the main thread~(\ref{basic.start.main})
2637+
and otherwise strongly happens before the initialization of \tcode{W}.
26322638

26332639
\item
2634-
Otherwise, if a program starts a thread before either \tcode{V} or \tcode{W} is
2635-
initialized, the initializations of \tcode{V} and \tcode{W} are unsequenced.
2640+
Otherwise, if the program starts a thread
2641+
other than the main thread
2642+
before either \tcode{V} or \tcode{W} is initialized,
2643+
it is unspecified in which threads
2644+
the initializations of \tcode{V} and \tcode{W} occur;
2645+
the initializations are unsequenced if they occur in the same thread.
26362646

26372647
\item
26382648
Otherwise, the initializations of \tcode{V} and \tcode{W} are indeterminately sequenced.
@@ -2642,18 +2652,31 @@
26422652
ordered variables concurrently with another sequence.
26432653
\end{note}
26442654

2655+
\pnum
2656+
\indextext{non-initialization odr-use|see{odr-use, non-initialization}}%
2657+
A \defnx{non-initialization odr-use}{odr-use!non-initialization}
2658+
is an odr-use~(\ref{basic.def.odr}) not caused directly or indirectly by
2659+
the initialization of a non-local static or thread storage duration variable.
2660+
26452661
\pnum
26462662
\indextext{evaluation!unspecified order of}%
2647-
It is \impldef{dynamic initialization of static variables before \tcode{main}} whether the
2648-
dynamic initialization of a non-local non-inline variable with static storage duration
2649-
happens before the first statement of \tcode{main}. If the initialization is deferred to
2650-
happen after the first statement of \tcode{main}, it happens before the
2651-
first odr-use~(\ref{basic.def.odr}) of any non-inline function or non-inline variable
2652-
defined in the same translation unit as the variable
2653-
to be initialized.\footnote{A non-local variable with static storage duration
2663+
It is \impldef{dynamic initialization of static variables before \tcode{main}}
2664+
whether the dynamic initialization of a
2665+
non-local non-inline variable with static storage duration
2666+
is sequenced before the first statement of \tcode{main} or is deferred.
2667+
If it is deferred, it strongly happens before
2668+
any non-initialization odr-use
2669+
of any non-inline function or non-inline variable
2670+
defined in the same translation unit as the variable to be initialized.%
2671+
\footnote{A non-local variable with static storage duration
26542672
having initialization
2655-
with side effects must be initialized even if it is not
2656-
odr-used (\ref{basic.def.odr},~\ref{basic.stc.static}).}
2673+
with side effects is initialized in this case
2674+
even if it is not itself odr-used (\ref{basic.def.odr},~\ref{basic.stc.static}).}
2675+
It is \impldef{threads and program points at which deferred dynamic initialization is performed}
2676+
in which threads and at which points in the program such deferred dynamic initialization occurs.
2677+
\begin{note}
2678+
Such points should be chosen in a way that allows the programmer to avoid deadlocks.
2679+
\end{note}
26572680
\begin{example}
26582681
\begin{codeblock}
26592682
// - File 1 -
@@ -2694,21 +2717,26 @@
26942717
\pnum
26952718
It is \impldef{dynamic initialization of static inline variables before \tcode{main}}
26962719
whether the dynamic initialization of a
2697-
non-local inline variable with static storage duration happens before the
2698-
first statement of \tcode{main}. If the initialization is deferred
2699-
to happen after the first statement of \tcode{main}, it happens before
2700-
the first odr-use~(\ref{basic.def.odr}) of that variable.
2720+
non-local inline variable with static storage duration
2721+
is sequenced before the first statement of \tcode{main} or is deferred.
2722+
If it is deferred, it strongly happens before
2723+
any non-initialization odr-use
2724+
of that variable.
2725+
It is \impldef{threads and program points at which deferred dynamic initialization is performed}
2726+
in which threads and at which points in the program such deferred dynamic initialization occurs.
27012727

27022728
\pnum
27032729
It is \impldef{dynamic initialization of thread-local variables before entry}
2704-
whether the dynamic initialization of a non-local non-inline variable with static
2705-
or thread storage duration is sequenced before
2706-
the first statement of the initial function of the thread.
2707-
If the initialization is deferred to some point in time sequenced after
2708-
the first statement of the initial function of the thread,
2709-
it is sequenced before the first odr-use~(\ref{basic.def.odr})
2710-
of any non-inline variable with thread storage duration defined
2711-
in the same translation unit as the variable to be initialized.
2730+
whether the dynamic initialization of a
2731+
non-local non-inline variable with thread storage duration
2732+
is sequenced before the first statement of the initial function of a thread or is deferred.
2733+
If it is deferred,
2734+
the initialization associated with the entity for thread \placeholder{t}
2735+
is sequenced before the first non-initialization odr-use by \placeholder{t}
2736+
of any non-inline variable with thread storage duration
2737+
defined in the same translation unit as the variable to be initialized.
2738+
It is \impldef{threads and program points at which deferred dynamic initialization is performed}
2739+
in which threads and at which points in the program such deferred dynamic initialization occurs.
27122740

27132741
\pnum
27142742
If the initialization of a non-local variable with static or thread storage duration
@@ -2724,24 +2752,34 @@
27242752
\indextext{\idxcode{main} function!return from}%
27252753
Destructors~(\ref{class.dtor}) for initialized objects
27262754
(that is, objects whose lifetime~(\ref{basic.life}) has begun)
2727-
with static storage duration
2728-
are called as a result of returning from \tcode{main} and as a result of calling
2755+
with static storage duration,
2756+
and functions registered with \tcode{std::atexit},
2757+
are called as part of a call to
27292758
\indextext{\idxcode{exit}}%
27302759
\indexlibrary{\idxcode{exit}}%
27312760
\tcode{std::exit}~(\ref{support.start.term}).
2761+
The call to \tcode{std::exit} is sequenced before
2762+
the invocations of the destructors and the registered functions.
2763+
\begin{note}
2764+
Returning from \tcode{main} invokes \tcode{std::exit}~(\ref{basic.start.main}).
2765+
\end{note}
2766+
2767+
\pnum
27322768
Destructors for initialized objects with thread storage duration within a given thread
27332769
are called as a result of returning from the initial function of that thread and as a
27342770
result of that thread calling \tcode{std::exit}.
27352771
The completions of the destructors for all initialized objects with thread storage
2736-
duration within that thread are sequenced before the initiation of the destructors of
2772+
duration within that thread strongly happen before the initiation of the destructors of
27372773
any object with static storage duration.
2738-
If the completion of the constructor or dynamic initialization of an object with thread
2739-
storage duration is sequenced before that of another, the completion of the destructor
2740-
of the second is sequenced before the initiation of the destructor of the first.
2774+
2775+
\pnum
27412776
If the completion of the constructor or dynamic initialization of an object with static
2777+
storage duration strongly happens before that of another, the completion of the destructor
2778+
of the second is sequenced before the initiation of the destructor of the first.
2779+
If the completion of the constructor or dynamic initialization of an object with thread
27422780
storage duration is sequenced before that of another, the completion of the destructor
27432781
of the second is sequenced before the initiation of the destructor of the first.
2744-
\begin{note} This definition permits concurrent destruction. \end{note} If an object is
2782+
If an object is
27452783
initialized statically, the object is destroyed in the same order as if
27462784
the object was dynamically initialized. For an object of array or class
27472785
type, all subobjects of that object are destroyed before any block-scope
@@ -2763,13 +2801,13 @@
27632801
\indextext{\idxcode{atexit}}%
27642802
\indexlibrary{\idxcode{atexit}}%
27652803
If the completion of the initialization of an object with static storage
2766-
duration is sequenced before a call to \tcode{std::atexit}~(see
2804+
duration strongly happens before a call to \tcode{std::atexit}~(see
27672805
\tcode{<cstdlib>},~\ref{support.start.term}), the call to the function passed to
27682806
\tcode{std::atexit} is sequenced before the call to the destructor for the object. If a
2769-
call to \tcode{std::atexit} is sequenced before the completion of the initialization of
2807+
call to \tcode{std::atexit} strongly happens before the completion of the initialization of
27702808
an object with static storage duration, the call to the destructor for the
27712809
object is sequenced before the call to the function passed to \tcode{std::atexit}. If a
2772-
call to \tcode{std::atexit} is sequenced before another call to \tcode{std::atexit}, the
2810+
call to \tcode{std::atexit} strongly happens before another call to \tcode{std::atexit}, the
27732811
call to the function passed to the second \tcode{std::atexit} call is sequenced before
27742812
the call to the function passed to the first \tcode{std::atexit} call.
27752813

source/intro.tex

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -794,23 +794,13 @@
794794
A conforming implementation executing a well-formed program shall
795795
produce the same observable behavior as one of the possible executions
796796
of the corresponding instance of the abstract machine with the
797-
same program and the same input. However, if any such execution contains an undefined operation, this International Standard places no
797+
same program and the same input.
798+
\indextext{behavior!undefined}%
799+
However, if any such execution contains an undefined operation, this International Standard places no
798800
requirement on the implementation executing that program with that input
799801
(not even with regard to operations preceding the first undefined
800802
operation).
801803

802-
\indextext{behavior!unspecified}%
803-
\indextext{behavior!undefined}%
804-
\indextext{behavior!on receipt of signal}%
805-
\indextext{signal}%
806-
\pnum
807-
If a signal handler is executed as a result of a call to the \tcode{std::raise}
808-
function, then the execution of the handler is sequenced after the invocation
809-
of the \tcode{std::raise} function and before its return.
810-
\begin{note} When a signal is received for another reason, the execution of the
811-
signal handler is usually unsequenced with respect to the rest of the program.
812-
\end{note}
813-
814804
\pnum
815805
An instance of each object with automatic storage
816806
duration~(\ref{basic.stc.auto}) is associated with each entry into its
@@ -1123,6 +1113,16 @@
11231113
described above) are features of the function calls as evaluated,
11241114
whatever the syntax of the expression that calls the function might be.%
11251115
\indextext{value computation|)}%
1116+
1117+
\indextext{behavior!on receipt of signal}%
1118+
\indextext{signal}%
1119+
\pnum
1120+
If a signal handler is executed as a result of a call to the \tcode{std::raise}
1121+
function, then the execution of the handler is sequenced after the invocation
1122+
of the \tcode{std::raise} function and before its return.
1123+
\begin{note} When a signal is received for another reason, the execution of the
1124+
signal handler is usually unsequenced with respect to the rest of the program.
1125+
\end{note}
11261126
\indextext{program execution|)}
11271127

11281128
\rSec1[intro.multithread]{Multi-threaded executions and data races}
@@ -1327,6 +1327,20 @@
13271327
in the ``happens before'' relation. \begin{note} This cycle would otherwise be
13281328
possible only through the use of consume operations. \end{note}
13291329

1330+
\pnum
1331+
An evaluation \placeholder{A} \defn{strongly happens before} an evaluation \placeholder{B}
1332+
if either
1333+
\begin{itemize}
1334+
\item \placeholder{A} is sequenced before \placeholder{B}, or
1335+
\item \placeholder{A} synchronizes with \placeholder{B}, or
1336+
\item \placeholder{A} strongly happens before \placeholder{X} and \placeholder{X} strongly happens before \placeholder{B}.
1337+
\end{itemize}
1338+
\begin{note}
1339+
In the absence of consume operations
1340+
the happens before and strongly happens before relations are identical.
1341+
Strongly happens before essentially excludes consume operations.
1342+
\end{note}
1343+
13301344
\pnum
13311345
A \defnx{visible side effect}{side effects!visible} \placeholder{A} on a scalar object or bit-field \placeholder{M}
13321346
with respect to a value computation \placeholder{B} of \placeholder{M} satisfies the

source/support.tex

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1601,7 +1601,9 @@
16011601
function does not provide a handler for a thrown exception, \tcode{std::terminate()} shall
16021602
be called.\indexlibrary{\idxcode{terminate}}
16031603
\begin{note}
1604-
\tcode{at_quick_exit} may call a registered function from a different thread
1604+
A function registered via \tcode{at_quick_exit}
1605+
is invoked by the thread that calls \tcode{quick_exit},
1606+
which can be a different thread
16051607
than the one that registered it, so registered functions should not rely on the identity
16061608
of objects with thread storage duration.
16071609
\end{note}

0 commit comments

Comments
 (0)