Section: 32.5.8.2 [atomics.types.operations] Status: C++11 Submitter: BSI Opened: 2010-08-25 Last modified: 2016-01-28
Priority: Not Prioritized
View other active issues in [atomics.types.operations].
View all other issues in [atomics.types.operations].
View all issues with C++11 status.
Discussion:
Addresses GB-136
GB requests normative clarification in 32.5.8.2 [atomics.types.operations] p.4 that concurrent access constitutes a race, as already done on p.6 and p.7.
[ Resolution proposed in ballot comment: ]
Initialisation of atomics:
We believe the intent is that for any atomics there is a distinguished initialisation write, but that this need not happens-before all the other operations on that atomic - specifically so that the initialisation write might be non-atomic and hence give rise to a data race, and hence undefined behaviour, in examples such as this (from Hans):atomic<atomic<int> *> p f() | { atomic<int>x; | W_na x p.store(&x,mo_rlx); | W_rlx p=&x } |(where na is nonatomic and rlx is relaxed). We suspect also that no other mixed atomic/nonatomic access to the same location is intended to be permitted. Either way, a note would probably help.
[2011-02-26: Hans comments and drafts wording]
I think the important point here is to clarify that races on atomics
are possible, and can be introduced as a result of non-atomic
initialization operations. There are other parts of this that remain unclear
to me, such as whether there are other ways to introduce data races on atomics,
or whether the races with initialization also introduce undefined behavior
by the 3.8 lifetime rules. But I don't think that it is necessary to resolve
those issues before releasing the standard. That's particularly true
since we've introduced atomic_init
, which allows easier ways to
construct initialization races.
[2011-03 Madrid]
Accepted to be applied immediately to the WP
Proposed resolution:
Update 99 [atomics.types.operations.req] p. 5 as follows:
constexpr A::A(C desired);5 Effects: Initializes the object with the value
desired
.[ Note: Construction is not atomic. — end note ]Initialization is not an atomic operation (1.10) [intro.multithread]. [Note: It is possible to have an access to an atomic objectA
race with its construction, for example by communicating the address of the just-constructed objectA
to another thread viamemory_order_relaxed
atomic operations on a suitable atomic pointer variable, and then immediately accessingA
in the receiving thread. This results in undefined behavior. — end note]
In response to the editor comment to 99 [atomics.types.operations.req] p. 8: The first Effects element is the correct and intended one:
void atomic_init(volatile A *object, C desired); void atomic_init(A *object, C desired);8 Effects: Non-atomically initializes
*object
with valuedesired
. This function shall only be applied to objects that have been default constructed, and then only once. [ Note: these semantics ensure compatibility with C. — end note ] [ Note: Concurrent access from another thread, even via an atomic operation, constitutes a data race. — end note ][Editor's note: The preceding text is from the WD as amended by N3196. N3193 makes different changes, marked up in the paper as follows:] Effects: Dynamically initializes an atomic variable. Non-atomically That is, non-atomically assigns the value desired to*object
. [ Note: this operation may need to initialize locks. — end note ] Concurrent access from another thread, even via an atomic operation, constitutes a data race.