[cpp-threads] RE: volatile, memory models, threads
Peter Dimov
pdimov at mmltd.net
Wed Mar 1 13:04:23 GMT 2006
Nick Maclaren wrote:
> "Peter Dimov" <pdimov at mmltd.net> wrote:
>>
>> Right, and it is the object representation that is the subject of
>> 3.9.3/1. "shall have the same representation and (alignment
>> requirements)." Object representation includes size (among other
>> things).
>
> Well, you may be right, but there is nothing that you have quoted that
> states (or even implies) that 3.9.3/1 refers to the object
> representation rather than the value representation. My assertion is
> that it can be read either way, and the footnote strongly implies the
> latter.
Referring to the value representation would be meaningless in this context.
The value representation of a const int x is completely invisible to a
conforming program, because in order to inspect, for example, value bit 0,
you need to write x & 1, and the lvalue to rvalue conversion drops the
qualifiers, so you're actually looking at the value representation of the
corresponding non-const int.
>> No. sizeof(x) is always the same when x is of type cv X, no matter
>> whether x is an argument, return value, or part of an array, and the
>> object representation of x is always the sequence of sizeof(x) ==
>> sizeof(X) bytes, starting from &x. It may well be the case that
>> physically, padding is inserted between x1 and x2 so that the
>> arguments occupy more space than they would otherwise, but this
>> doesn't change the representation of x1 or x2. A conforming program
>> is still allowed to inspect the object representation byte by byte
>> (or copy it into another object of the same type for PODs.)
>
> Firstly, I said size and I meant size. The value returned by sizeof
> is NOT always the number of bytes occupied by an object, where that
> object is an argument or return value (or potentially, a member of a
> union). The reason that can differ from the sizeof value is that it
> is not possible to have an array of any of those, and therefore no
> pointer arithmetic can be done on their addresses.
>
> The result of this is that the actual size of the object is never
> visible to a strictly conforming program, and so the implementations
> can use the "as if" rule. Some early ones implemented sizeof to be
> the actual size of the object but, as far as I know, all current ones
> have corrected that to be the normal size of the object.
>
> Seriously.
This is all pretty basic knowledge, seriously. :-)
But why does it matter? The definition of an object is a sequence of N
bytes, where N is returned by sizeof. A POD object is completely determined
by these bytes, you can read them, encrypt them, decrypt them into another
sequence of N bytes (with the appropriate alignment), and you'll have a copy
of the original object back.
A compiler can align individual variables however it likes, true. So what?
> Secondly, where is what you claim above stated as a requirement?
>
> I have already SAID that it is implied by the ability to add
> qualifiers. I repeat my apology for creating unnecessary confusion,
> but I also repeat my assertion that the ONLY way in which
> cv-qualified types are required to have the same size (in the sizeof
> sense) is because such qualifiers can be added. Drop that and there
> is NOTHING that I know of IN THE STANDARD stopping them from
> being different sizes.
3.9.3/1 seems pretty clear to me, sorry. :-)
It is actually pointer arithmetic that imposes the size requirement if we
pretend that 3.9.3/1 doesn't. A language that doesn't have pointer
arithmetic can have 'int const' with alignment 4 and 'int' with alignment 8,
and every int* would be a valid int const*, but not vice versa.
But to get back to our atomics.
I agree with you that in the hypothetical syntax
atomic int x;
'atomic' can't be a cv-qualifier if atomic ints have different alignment
requirements or contain a per-object spinlock.
The library-like syntax of
atomic<int> x;
solves the above problems by making atomic<int> a completely separate type.
For completeness, let me outline another alternative:
int x;
with
atomic_increment( &x );
failing to compile if x doesn't meet the alignment requirements for
atomicity or placement (uncached memory). It would be the responsibility of
the programmer to use whatever non-portable mechanisms are provided by the
platform to ensure that x is aligned, placed appropriately in uncached
memory, or doesn't share a cache line with another atomic.
More information about the cpp-threads
mailing list