Reputation: 724
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.
Upvotes: 15
Views: 852
Reputation: 137425
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.
Upvotes: 2