Reputation: 21510
Following up to this question - std::memory_order_relaxed and initialization. Suppose I have code like this
class Something {
public:
int value;
};
auto&& pointer = std::atomic<Something*>{nullptr};
// thread 1
auto value = Something{1};
pointer.set(&value, std::memory_order_relaxed);
// thread 2
Something* something = nullptr;
while (!(something = pointer.load(std::memory_order_relaxed))) {}
cout << something->value << endl;
Is this guaranteed to print 1? Can an implementation be allowed to take the address of a non initialized value?
(Assuming that there are no lifetime issues with thread 2 reading the pointer set by thread 1)
Upvotes: 1
Views: 107
Reputation: 16849
No, it isn't guaranteed to print 1. The write to the field value
may be reordered WRT to the write to pointer
. If it is reordered to after the write to pointer, 'thread 2' will observe uninitialized memory.
This can and does happen in practice on ARM.
Because x86 CPUs maintain "total store order" (i.e. all stores are observable by other threads in the order they were issued by the issuing thread,) the CPU cannot cause this to happen. But, it still can happen on x86 because, while the CPU will not reorder writes, the compiler is allowed to reorder writes. I don't know if in practice compilers do that.
Upvotes: 2