If one uses a single atomic variable and std::memory_order_seq_cst
, are non-atomic operations guaranteed not to be reordered?
For example, if I have
std::atomic<bool> quux = {false};
void foo() {
bar();
quux.store(true, std::memory_order_seq_cst);
moo();
}
is bar()
guaranteed not to get reordered after the call of store
, and moo()
not to get reordered before the call of store
, as long as I use std::memory_order_seq_cst
, at least from the perspective of another thread?
Or, to put it in code, are the following assumptions valid if run from another thread?
if(quux.load(std::memory_order_seq_cst) == true) {
// bar guaranteed to be called; its side-effects are visible
// moo might have been called, but is not guaranteed to
} else {
// bar might have been called, but is not guaranteed to
// moo might have been called, but is not guaranteed to
}
Note that I assume that neither bar
nor moo
use atomic operations, mutexes, locks, fences or other synchronization features.
According to the link http://en.cppreference.com/w/cpp/atomic/memory_order linked by @Maxim there is an error with regards of the memory_order_seq_cst.The text above is exchanged with memory_order_acq_rel. The text for memory_order_seq_cst:
memory_order_seq_cst: A load operation with this memory order performs an acquire operation, a store performs a release operation, and read-modify-write performs both an acquire operation and a release operation, plus a single total order exists in which all threads observe all modifications in the same order (see Sequentially-consistent ordering below)
So in your case the store operation is equivalent to a release which means that moo() can be reordered before the fence.
If one uses a single atomic variable and
std::memory_order_seq_cst
, are non-atomic operations guaranteed not to be reordered?
The standard is pretty clear on this http://en.cppreference.com/w/cpp/atomic/memory_order:
memory_order_seq_cst
A load operation with this memory order performs an acquire operation, a store performs a release operation, and read-modify-write performs both an acquire operation and a release operation, plus a single total order exists in which all threads observe all modifications in the same order.
memory_order_acquire
A load operation with this memory order performs the acquire operation on the affected memory location: no reads or writes in the current thread can be reordered before this load.
memory_order_release
A store operation with this memory order performs the release operation: no reads or writes in the current thread can be reordered after this store.
In other words, no loads or stores (both non-atomic and atomic) can be reordered around memory_order_seq_cst
operations.
is
bar()
guaranteed not to get reordered after the call of store, andmoo()
not to get reordered before the call of store, as long as I use std::memory_order_seq_cst, at least from the perspective of another thread?
If the definitions of bar
and moo
are not available in the current translation unit, the compiler assumes that these functions do memory loads and/or have side effects (do I/O or stores to memory), and hence cannot be reordered around memory_order_seq_cst
operations.
If the definitions are available and the functions do not do I/O or memory loads/stores then they can be reordered. These would be pure functions or functions that do nothing and return void
or a constant.
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