An atomic write to an unrelated variable (let's call it `gatom') in `g' does not in any way guarantee that the write to `result_of_f' happens before a read from `result_of_f'.However, if g, for example, modifies an atomic variable, then that's not allowed, because the access to the atomic guarantees that other threads see the write to result_of_f as happening before a read on the same atomic, and it guarantees that other thread see the write of result_of_h as happening after that read, (and therefore they cannot modify result_of_h after the read without a race condition -- the atomic write in g() can funtion like an aquire of the shared resource result_of_h).
An atomic write to `gatom' does not in any way guarantee that a write to `result_of_f' happens before a read from `gatom'.
An atomic read from `gatom' does not guarantee that a read from `result_of_h' happens after the read from `gatom'.
An atomic read from `result_of_f' does not guarantee that a read from `result_of_h' happens after the read from `result_of_f'.
An atomic variable only guarantees that reads and writes are completed in isolation. They do not impose any mutual or identity ordering. If one thread (`i') increments a variable (`v1') while another thread (`d') decrements a variable (`v2') the sole use of atomic reads and writes to the variables (`v1' and `v2') is insufficient to enforce a `v1++'->`v2--' pattern; it is entirely possible to get `v1++'->`v1++'->`v2--' as an ordering. This lack of any mutual or identity ordering holds for single threaded applications as well as applications with multiple threads.
So, we wind up back at the compiler and sequence points. If the compiler doesn't recognize a sequence point, and so reorders, the use of atomic doesn't buy you correct ordering. Any given compiler may recognize any specific atomic operation as a sequence point, but that is not something enforced by the standards. (Well, I do not know C11 at all so it may be something in that standard.) If a compiler does recognize atomic reads and writes and necessary sequence points the compiler doesn't reorder so you get the canonical ordering.
It has nothing to do with atomic variables. This is about sequence points. (C11 may specifically have mentioned atomic variables as sequence points.) According to the standard a compiler can not reorder any sequence point that matches certain criteria. This criteria includes calling standard "IO" functions (like `printf'), any operation with a `volatile' variable, mutating (writing) any object, and something to do with global variables that I can't really recall because almost every compiler ignores that bit.so you are saying if 'g()' modifies an atomic variable, then the compiler cannot reorder the sequence of calls?
Of course, there is what the standard says and then there is what compilers do.
Many compiler, by default, assume that functions beyond inspection always constitute necessary sequence points. This isn't mandated by the standard, but it is a practical approach.how does the compiler know what f(),g() and h() are doing if they are in a separate compilation unit?
Some compiler, at higher optimization levels, can break code for any number of reasons; reordering necessary sequence points is one possible break.
Soma