Date: Thu, 26 May 2022 11:18:26 +0200
On 26/05/2022 10.02, language.lawyer--- via Std-Discussion wrote:
>> std::pair<int16_t, int16_t> mixed_size() {
>> int32_t x = 0;
>>
>> {
>> auto x_atomic = std::atomic_ref<int32_t>(x);
>> x_atomic.store(0xabbafafa, std::memory_order_relaxed);
>> // atomic_ref lifetime ends so we can use x again
>> }
>>
>> auto x_parts = reinterpret_cast<int16_t*>(&x);
>> int16_t& x_left = x_parts[0];
>> int16_t& x_right = x_parts[1];
>
> The last two lines have undefined behavior.
... irrespective of anything "atomic"; there is
no "array of int16_t" object at x, so you're
violating the pointer arithmetic and/or aliasing
rules.
The following example:
> std::int32_t mixed_atomicity() {
> int32_t x = 0;
>
> {
> auto x_atomic = std::atomic_ref<int32_t>(x);
> x_atomic.store(42, std::memory_order_relaxed);
> // atomic_ref lifetime ends so we can use x again
> }
>
> // Obviously reading 42 is sane here, but there is no codified semantics
> // governing non-atomically reading an atomic location in any circumstance
> int32_t read = x;
> returnread;
> }
just uses the plain non-atomic semantics; the atomic store stored a value
into x (in addition to all the concurrency effects the atomic store might
have), and the usual lvalue-to-rvalue conversion then reads the value of x.
Jens
>> std::pair<int16_t, int16_t> mixed_size() {
>> int32_t x = 0;
>>
>> {
>> auto x_atomic = std::atomic_ref<int32_t>(x);
>> x_atomic.store(0xabbafafa, std::memory_order_relaxed);
>> // atomic_ref lifetime ends so we can use x again
>> }
>>
>> auto x_parts = reinterpret_cast<int16_t*>(&x);
>> int16_t& x_left = x_parts[0];
>> int16_t& x_right = x_parts[1];
>
> The last two lines have undefined behavior.
... irrespective of anything "atomic"; there is
no "array of int16_t" object at x, so you're
violating the pointer arithmetic and/or aliasing
rules.
The following example:
> std::int32_t mixed_atomicity() {
> int32_t x = 0;
>
> {
> auto x_atomic = std::atomic_ref<int32_t>(x);
> x_atomic.store(42, std::memory_order_relaxed);
> // atomic_ref lifetime ends so we can use x again
> }
>
> // Obviously reading 42 is sane here, but there is no codified semantics
> // governing non-atomically reading an atomic location in any circumstance
> int32_t read = x;
> returnread;
> }
just uses the plain non-atomic semantics; the atomic store stored a value
into x (in addition to all the concurrency effects the atomic store might
have), and the usual lvalue-to-rvalue conversion then reads the value of x.
Jens
Received on 2022-05-26 09:18:29