[cpp-threads] Review of N2995 and resulting email threads
Paul E. McKenney
paulmck at linux.vnet.ibm.com
Sat Oct 24 17:32:23 BST 2009
On Sat, Oct 24, 2009 at 06:39:34PM +0300, Peter Dimov wrote:
> Paul E. McKenney wrote:
>> Hello!
>>
>> It was suggested that I review N2995 and the related email threads and
>> comment appropriately.
>
> ...
>
>> o 1.10p4: Add note:
>>
>> [Note: Atomic and locking objects are not trivially
>> copyable [3.9], so executions that access atomic
>> or locking objects as non-atomic objects, for example
>> through an array of character type, will have undefined
>> behaviour - end note]
>>
>> --- I believe that this is straightforward enough to qualify
>> --- as editorial.
>
> I still think that this note is incorrect, as there are ways to read an
> atomic object without UB. In fact, you acknowledge this objection of mine
> in:
>
>> o 1.10p14: Use of casts or unions can result in atomic and
>> non-atomic accesses to the same memory location, so the "at least
>> one of which is not atomic" must remain. Peter Dimov pointed out
>> that memcpy() can have the same effect. Therefore, I am -not-
>> OK with the suggested modifications to the first sentence --
>> if any of the accesses are non-atomic, there can be a data race.
>> It is not necessary for -all- of them to be non-atomic.
OK, so your point is that there are the following additional cases?
Keeping in mind that by 3.9p3, atomic and locking objects cannot be
considered to be trivially copyable.
1. A data-race-free memcpy() or similar operation copies the
memory locations. In this case, on systems with conventional
memory architectures, successive memcpy() operations would
be expected to produce identical strings of bytes when there
are no intervening atomic operations. Note that there are
implementations where the copy cannot be used as the same type of
atomic, for example, when queued locks are involved in enforcing
atomic access to complex variables.
2. On systems with conventional memory architectures, even when
a memcpy() executes concurrently with an atomic operation,
you should expect the memcpy() to produce a valid string of
bytes.
Of course, undefined behavior still permits the system to operate
in this manner. My preference at this point would be to maintain
undefined behavior for C++0x, and add refinements in later versions of
the standard, perhaps enumerating the mechanisms that could safely read
out the representation of an atomic variable. Or do you believe that
there are use cases of this that are sufficiently urgent that we should
note that memcpy() and memmove() can safely read out the representation?
One argument in favor of retaining undefined behavior is that there
have been systems that have special hardware implementing atomic types,
and that such systems might appear again.
Further thoughts?
Thanx, Paul
More information about the cpp-threads
mailing list