samedi 28 février 2015

C++11 memory model: why can't compiler move statements across load() operations during optimization?

As I understand, for the sequentially consistent and acquire-release memory models if some x.store(some_value) operation from one thread is synchronized with a x.load() operation from the another one, then:


Rule 1. All memory operations that happen before the x.store(some_value) operation must appear before the x.load() operation.


This point seems clear to me:



-Thread 1-
y = 1;
x.store(2, memory_order_release);

-Thread 2-
if (x.load(memory_order_acquire) == 2)
assert(y == 1)


Here if the compiler places y = 1 operation after x.store(2), assert can fail and this is not the behavior that we expect.


Rule 2. All memory operations that happen after the x.load() operation must also appear after the x.store(some_value) operation.


But now I'm confused: why can't the compiler move the statements across load() operations? How can it violate the expected behavior of the program? I think of a such example:



-Thread 1-
x.store(2, memory_order_release); // x == 0 initially

-Thread 2-
while (x.load(memory_order_acquire) == 1);
y = 2; // y == 0 initially


Here, if compiler places y = 2 operation before while(), y becomes 2 (otherwise there is the infinite loop and y stays unchanged), but this example seems forced (I'm even not sure that compiler can do such "optimization"), and I suspect that there are more realistic situations for which Rule 2 was created.


Could you please give me the explanation of the Rule 2's necessity?


Aucun commentaire:

Enregistrer un commentaire