This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of NAD Editorial status.
Section: 33 [thread] Status: NAD Editorial Submitter: Canada Opened: 2010-08-25 Last modified: 2016-01-28
Priority: Not Prioritized
View all other issues in [thread].
View all issues with NAD Editorial status.
Duplicate of: 1443
Discussion:
Addresses CA-9, GB-122
[CA-9:]
Imposed happens-before edges should be in
synchronizes-with
Each use of the words "happens-before" should be
replaced with the words "synchronizes-with" in the
following sentences:
27.2.3p2
30.3.1.2p6
30.3.1.5p7
30.6.4p7
30.6.9p5
30.6.10.1p23
Rationale: Happens-before is defined in 1.10p11 in a way
that (deliberately) does not make it explicitly transitively
closed. Adding edges to happens-before directly, as in
27.2.3p2 etc., does not provide transitivity with
sequenced-before or any other existing happens-before
edge. This lack of transitivity seems to be unintentional.
[GB-122]
At various points in the standard new edges are added to happens-before, for example 27.2.3:2 adds happens-before edges between writes and reads from a stream:
If one thread makes a library call a that writes a value to a stream and, as a result, another thread reads this value from the stream through a library call b such that this does not result in a data race, then a happens before b.
Happens-before is defined in 1.10:11 in a deliberate way that makes it not explicitly transitively closed. Adding edges to happens-before directly, as in 27.2.3:2, does not provide transitivity with sequenced-before or any other existing happens-before edge. This lack of transitivity seems to be unintentional. In order to achieve transitivity we suggest each edge be added to inter-thread-happens-before as a synchronises-with edge (as per conversation with Hans Boehm). In the standard, each use of the words "happens-before" should be replaced with the words "synchronizes-with" in the following sentences:
27.2.3:2, 30.3.1.2:6, 30.3.1.5:7, 30.6.4:7, 30.6.9:5, 30.6.10.1:23
Proposed resolution:
[Beman provided specific wording for the proposed resolution.]
Change 27.2.3 Thread Safety [iostreams.threadsafety] paragraph 2:
If one thread makes a library call a that writes a value to a stream
and, as a result, another thread reads this value from the stream through a library
call b such that this does not result in a data race, then a
happens before synchronizes with b.
Change 30.3.1.2 thread constructors [thread.thread.constr] paragraph 6:
Synchronization: The invocation of the constructor happens
before synchronizes with the invocation of the copy of f.
Change 30.3.1.5 thread members [thread.thread.member] paragraph 7:
Synchronization: The completion of the thread represented by *this
happens before synchronizes with (1.10) join()
returns returning. [ Note: Operations on *this
are not synchronized. --end note ]
Change 30.6.4 Associated asynchronous state [futures.state] paragraph 7:
Calls to functions that successfully set the stored result of an associated
asynchronous state synchronize with (1.10) calls to functions successfully detecting
the ready state resulting from that setting. The storage of the result (whether normal
or exceptional) into the associated asynchronous state happens before
synchronizes with (1.10) that state is being set to ready.
Change 30.6.9 Function template async [futures.async] paragraph 5:
Synchronization: the invocation of async happens before
synchronizes with (1.10) the invocation of f. [ Note: this
statement applies even when the corresponding future object is moved to another thread. — end
note ] If the invocation is not deferred, a call to a waiting function on an asynchronous return object
that shares the associated asynchronous state created by this async call shall block until the associated
thread has completed. If the invocation is not deferred, the join() on the created thread
happens before synchronizes with (1.10) the first function that successfully
detects the ready status of the associated asynchronous state returns or before the function that
gives up the last reference to the associated asynchronous state returns, whichever happens first.
If the invocation is deferred, the completion of the invocation of the deferred function happens
before synchronizes with the calls to the waiting functions return.
Change 30.6.10.1 packaged_task member functions [futures.task.members] paragraph 23:
Synchronization: a successful call to operator() synchronizes with (1.10) a call
to any member function of a future, shared_future, or atomic_future object
that shares the associated asynchronous state of *this. The completion of the invocation
of the stored task and the storage of the result (whether normal or exceptional) into the associated
asynchronous state happens before synchronizes with (1.10) the state is
being set to ready. [ Note: operator() synchronizes and serializes with other
functions through the associated asynchronous state. —end note ]