<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
 "http://www.w3.org/TR/html4/strict.dtd">
<html><head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<title>P0250R0: Wording improvements for initialization and thread ids (CWG 2046)</title>
</head>
<body>
<table>
	<tr>
                <th>Doc. No.:</th>
                <td>WG21/P0250R0</td>
        </tr>
        <tr>
                <th>Date:</th>
                <td>2016-02-12</td>
        </tr>
        <tr>
                <th>Author:</th>
                <td>Hans-J. Boehm</td>
        </tr>
        <tr>
                <th>Email:</th>
                <td><a href="mailto:hboehm@google.com">hboehm@google.com</a></td>
        </tr>
</table>
<h1>P0250R0: Wording improvements for initialization and thread ids (CWG 2046)</h1>
<p>
This is an attempt to turn the Kona SG1 discussion of CWG 2046 into wording.
Unfortunately, that discussion exposed a number of related issues.
<p>
In several places the standard needs to require that some operation happens
before another one, in roughly, but not quite, the sense of the 1.10 memory model.
We expect this happens before relation to compose with
sequencing.  But our normal happens before relation no longer composes in this way,
due to the presence of <tt>memory_order_consume</tt>.  Hence we introduce the
required notion in 1.10.
<p>
Also note that sequencing is intended to be a relation on evaluations within a
single thread.  It somehow had been abused for other things in the context of
static initialization, which was never intended to be confined to a single
thread.
<p>
<b>The current version is incomplete.</b>  In particular it does not yet fully
address the thread id validity issues.  We want to
require that main, atexit handlers, and constructors/destructors run 
in a proper thread with a proper (not default constructed) thread id.
<p>
SG1 also concluded that a C++ program should be allowed to construct
multiple threads for constructors etc., even if the program itself
did not use threads. That is also not reflected here.  This "decision"
may be worth revisiting since it technically breaks compatibility with
C++03.

<h2>Wording changes</h2>
<p>
(Fixes an editorial ugliness that somehow crept in.) Move 1.9p6, which uses
sequenced before, to someplace below the definition of sequenced before in
1.9p13 [intro.execution].
<p>
Add after 1.10p14 [intro.multithread]:
<blockquote>
<ins>An evaluation A <i>strongly happens before</i> an evaluation B if either</ins>
<ul>
<li><ins>A is sequenced before B, or</ins>
<li><ins>A synchronizes with B, or</ins>
<li><ins>A strongly happens before X and X strongly happens before B.</ins>
</ul>
<ins>[Note: In the absence of consume operations the happens before and strong happens before relations
are identical.  Strong happens before essentially excludes consume operations.]</ins>
</blockquote>
<p>
Change the last part of 3.6.2p2 [basic.start.static] as follows:
<blockquote>
<p>
If constant initialization is not performed, a variable with static storage
duration (3.7.1) or thread storage duration (3.7.2) is zero-initialized (8.5).
Together, zero-initialization and constant initialization are called static
initialization; all other initialization is dynamic initialization. <ins>Within each phase,</ins> static
initialization shall <del>be performed</del> <ins>strongly happen</ins> before
<ins>(1.10)</ins> any dynamic initialization <del>takes place</del>. [ Note: The dynamic
initialization of non-local variables is described in 3.6.3; that of local
static variables is described in 6.7. — end note ]
</blockquote>
<p>
Change 3.6.3p1 [basic.start.dynamic] as follows:
<blockquote>
<p>
Dynamic initialization of a
non-local variable with static storage duration is unordered if the variable is
an implicitly or explicitly instantiated specialization, and otherwise is
ordered [ Note: an explicitly specialized static data member or variable
template specialization has ordered initialization. — end note ].
Variables with ordered initialization defined within a single translation unit
shall be initialized <del>in the order of their definitions</del><ins>such that
initialization corresponding to earlier definitions strongly happen before
those for later definitions</ins> in the translation unit.  If a program starts
a thread (30.3), <del>the subsequent </del> <ins>any initialization not specified to
happen before the first thread creation may be performed by either the main
thread or a thread implicitly created to perform initializations.  If such
initializations are unordered or defined in separate translation units, no
happens before ordering is specified between them.</ins> <del>of a variable is
unsequenced with respect to the initialization of a variable defined in a
different translation unit.  Otherwise, the initialization of a variable is
indeterminately sequenced with respect to the initialization of a variable
defined in a different translation unit. If a program starts a thread, the
subsequent unordered initialization of a variable is unsequenced with respect
to every other dynamic initialization. Otherwise,</del> <ins>If two unordered
initializations happen before the start of the first additional thread, or the
program starts no additional threads, then those</ins> <del>the</del> unordered
initialization<ins>s</ins><del> of a variable is</del> <ins>are</ins>
indeterminately sequenced with respect to <ins>each other</ins> <del>every other
dynamic initialization</del>. [ Note: This definition permits initialization of
a sequence of ordered variables concurrently with another sequence. — end note
]
</blockquote>
<p>
3.6.3p2 appears to have some unfortunate interactions with signal handlers.  We
may want to address those here, but they currently are not addressed. P0270R0
has more details.
<p>
Change the beginning of 3.6.3p2 as follows:
<blockquote>
<p>
It is implementation-defined whether the dynamic initialization of a non-local
variable with static storage duration <ins>strongly</ins>
happens before the first statement of main. If the initialization is
deferred to some point in time after the first statement of main, it
<ins>strongly</ins> happens before the first odr-use (3.2) of
any function or variable defined in the same translation unit as the variable
to be initialized.
</blockquote>
<p>
Change 3.6.3p3 as follows to fix what looks like an unrelated bug:
<blockquote>
<p>
It is implementation-defined whether the dynamic initialization of a non-local
variable with <del>static or</del> thread storage duration is
sequenced before the first statement of the initial function of the
thread. If the initialization is deferred to some point in time after the first
statement of the initial function of the thread, it is
sequenced before the first odr-use (3.2) of any variable with
thread storage duration defined in the same translation unit as the variable to
be initialized.
</blockquote>
<p>
Change 3.6.4p1 [basic.start.term] as follows:
<blockquote>
<p>
Destructors (12.4) for initialized objects (that is, objects whose lifetime
(3.8) has begun) with static storage duration are called as a result of
returning from main and as a result of calling std::exit (18.5).
<ins>The return from main or the call to std::exit respectively strongly
happen before the destructor invocations.</ins>
<p>
Destructors for initialized objects with thread storage duration within a given
thread are called as a result of returning from the initial function of that
thread and as a result of that thread calling std::exit. The completions of the
destructors for all initialized objects with thread storage duration within
that thread <del>are sequenced</del> <ins>strongly happen</ins> before the
initiation of the destructors of any object with static storage duration. If
the completion of the constructor or dynamic initialization of an object with
thread storage duration is sequenced before that of another, the completion of
the destructor of the second is sequenced before the initiation of the
destructor of the first.
<p>
If the completion of the constructor or dynamic initialization of an object
with static storage duration <del>is sequenced</del> <ins>strongly
happens</ins> before that of another, the completion of the destructor of the
second <del>is sequenced</del> <ins>strongly happens</ins> before the
initiation of the destructor of the first. [ Note: This definition permits
concurrent destruction.  — end note ] If an object is initialized statically,
the object is destroyed in the same order as if the object was dynamically
initialized.  For an object of array or class type, all subobjects of that
object are destroyed before any block-scope object with static storage duration
initialized during the construction of the subobjects is destroyed. If the
destruction of an object with static or thread storage duration exits via an
exception, std::terminate is called (15.5.1).
</blockquote>
<p>
Change 3.6.4p3 [basic.start.term] as follows:
<blockquote>
<p>
If the completion of the initialization of an object with static storage duration <del>is sequenced</del> <ins>strongly happens</ins> before a call
to std::atexit (see &lt;cstdlib&gt;, 18.5), the call to the function passed to std::atexit <del>is sequenced</del> <ins>strongly happens</ins> before
the call to the destructor for the object. If a call to std::atexit <del>is sequenced</del> <ins>strongly happens</ins> before the completion of the
initialization of an object with static storage duration, the call to the destructor for the object <del>is sequenced</del> <ins>strongly happens</ins>
before the call to the function passed to std::atexit. If a call to std::atexit <del>is sequenced</del> <ins>strongly happens</ins> before another
call to std::atexit, the call to the function passed to the second std::atexit call <del>is sequenced</del> <ins>strongly happens</ins> before the
call to the function passed to the first std::atexit call.
</blockquote>
</html>
