Consider the following code:
#include <atomic>
extern std::atomic<int> i;
void f(void)
{
while (!i.load(std::memory_order_relaxed))
;
}
I'm looking for a citation from the C++11 standard that says that the compiler is not allowed to transform the loop into
if (!i.load(std::memory_order_relaxed)) {
while (1)
;
}
I've seen some discussion here but nothing conclusive.
Edit: A previous version of this post called an extern function inside the loop.
Edit 2: For motivation: The book "Effective Java" says that the HotSpot VM performs the following transformation:
while (!done)
i++;
to
if (!done)
while (true)
i++;
even though it's perfectly defined behavior for another thread to change the done variable concurrently.
The purpose of a memory model is to enable thread communication. When one thread writes values to memory and another thread reads from memory, the memory model dictates what values the reading thread might see. LockingLocking is typically the easiest way to share data among threads.
Also, certain compiler optimizations can result in reordering of memory operations. Notably, if several reads access the same memory location, the compiler might choose to perform the read only once and keep the value in a register for subsequent reads.
The C# ECMA specification guarantees that the following types will be written atomically: reference types, bool, char, byte, sbyte, short, ushort, uint, int and float. Values of other types—including user-defined value types—could be written into memory in multiple atomic writes.
In the .NET Framework 4.5, the csc.exe compiler that compiles C# to IL doesn’t do many optimizations, so it won’t reorder memory operations. However, the just-in-time (JIT) compiler that converts IL to machine code will, in fact, perform some optimizations that reorder memory operations, as I’ll discuss.
Forget about relaxed, there's no guarantee that an atomic store ever become visible to an atomic load in a different thread. The best you get is the normative encouragement in [atomics.order]/12 (and analogous wording in [intro.progress]/18):
Implementations should make atomic stores visible to atomic loads within a reasonable amount of time.
...which is not a requirement.
(C11 has identical wording in §7.11.3/16)
Since hoisting the load leads to behavior indistinguishable from a non-hoisted load where the store never becomes visible, and since the latter is conforming, an implementation is allowed by the as-if rule to hoist the load regardless of the memory order used.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With