[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