Comment #19 on issue 580241 by
bcwh...@chromium.org: Win32 Clang Can't Read
> However, synchronizing the access would seem to obviate the need for
> volatile in the first place...
I had a recent discussion on this as well. See comments #86, #88, and
onwards on
https://codereview.chromium.org/1410213004/ ...
But basically... (quoting JF)
C++11 atomics can also be volatile, which tells the compiler among other
things
"there can be external modification which you are not aware of" (it also
means
the compiler must respect ordering of volatiles between each other,
allowing you
to use them for signals and such). In the case of shared memory (in the same
process, or between different processes) it means the compiler can't do
usual
atomic optimization such as those in
http://wg21.link/n4455. Without
volatile
the compiler can prove that a variable is use atomically only in certain
places,
and assume no other accesses occur as "as-if" the atomic uses. Realistically
compilers today don't do much of this, but they will in the future and the
bugs
it'll create will be wonderful to track down.
volatile doesn't provide no-tear guarantees, nor write ordering guarantees.
It
merely tells the compiler that it can't elide or duplicate accesses, and
can't
reorder volatile accesses w.r.t. each other (it can reorder non-volatile
w.r.t.
volatile). To get no-tear and happens-before you need atomic, so in the
case of
the ill-defined shared memory you need volatile+atomic.
Furthermore, for cross-process shared memory you need lock-free atomics! In
the
same process you're guaranteed address-free even when not lock-free, but
across
process you have no guarantee that non-lock-free operations work properly
(they
in fact do not on implementations I'm aware of). As an added
recommendation, I'd
have a check that the types you're using in shared memory have
CHECK(var.is_lock_free()). Practically speaking, this means you can't use
64-bit
values because they can tear on some ARM and MIPS CPUs.