Reputation: 11037
C++11 introduced the std::atomic<>
template library. The standard specifies the store()
and load()
operations to atomically set / get a variable shared by more than one thread.
My question is: are assignment and access operations also atomic? Namely, given
std::atomic<bool> stop(false);
!stop.load()
equivalent to !stop
?stop.store(true)
equivalent to stop = true
?Upvotes: 92
Views: 44993
Reputation: 39424
Yes, they are equivalent. The standard says in [atomics.ref.ops]:
T operator=(T desired) const noexcept;
Effects: Equivalent to:
store(desired); return desired;
and
T load(memory_order order = memory_order::seq_cst) const noexcept;
Effects: Equivalent to:
return load();
Note that both =
and the conversion function use std::memory_order::seq_cst
as a consequence, which is the safest memory order, but not the fastest due to the additional synchronization needed.
This is in part to create compatibility with C atomics. C11 added the _Atomic
qualifier, so you could write code such as:
_Atomic(int) x;
x = 0;
And exactly the same code would work nowadays in C++.
An explicit load
and store
is only necessary if you care about the memory order for performance reasons.
However, it is good practice to use load
and store
with a memory order consistently. This way, you can always express which memory order you intended to use. The operator overloads don't express this intent.
Upvotes: 0
Reputation: 15020
You can do both, but the advantage of load()
/store()
is that they allow to specify memory order. It is important sometimes for performance, where you can specify std::memory_order_relaxed
while atomic<T>::operator T
and atomic<T>::operator=
would use the most safe and slow std::memory_order_seq_cst
. Sometimes it is important for correctness and readability of your code: although the default std::memory_order_seq_cst
is most safe thus most likely to be correct, it is not immediately clear for the reader what kind of operation (acquire/release/consume) you are doing, or whether you are doing such operation at all (to answer: isn't relaxed order sufficient here?).
Upvotes: 43
Reputation: 68588
Are assignment and access operations for non-reference types also atomic?
Yes, they are. atomic<T>::operator T
and atomic<T>::operator=
are equivalent to atomic<T>::load
and atomic<T>::store
respectively. All the operators are implemented in the atomic class such that they will use atomic operations as you would expect.
I'm not sure what you mean about "non-reference" types? Not sure how reference types are relevant here.
Upvotes: 73