The C++11 standard includes the wonderful std::atomic<T>
, which has member functions like this one:
integral fetch_add(integral, memory_order = memory_order_seq_cst);
However, it seems to be lacking in an add_fetch
method. tbb::atomic<T>
overloads the +=
operator to behave like add_and_fetch
:
value_type operator+=( D addend ) {
return fetch_and_add(addend)+addend;
}
Through empirical observation, std::atomic<T>
behaves the same way, but I cannot find where it says so in the standard or if that is just my STL implementation. Is this behavior guaranteed by the standard?
std::atomic<> wraps operations that, in pre-C++ 11 times, had to be performed using (for example) interlocked functions with MSVC or atomic bultins in case of GCC. Also, std::atomic<> gives you more control by allowing various memory orders that specify synchronization and ordering constraints.
Yes, it would be threadsafe. Assuming of course there are no bugs in the std::atomic implementation - but it's not usually hard to get right. This is exactly what std::atomic is meant to do.
std::atomic is neither copyable nor movable. The compatibility macro _Atomic is provided in <stdatomic.
atomic::fetch_add (C++11)Atomically adds a value to an existing value that is stored in an atomic object. Memory is affected according to the value of order .
You're right that it doesn't actually provide that functionality but that's because it isn't needed. It can be emulated with the operations already there.
atomic_fetch_add
is an atomic operation that fetches the current value then adds something. That "something" is totally under your control and is not changed by atomic_fetch_add
.
The standard guarantees that:
You can then simply add the value yourself to what was returned, and you have the current value as of the time the atomic operation was done. So basically:
def atomic_add_fetch (item, addendum):
return atomic_fetch_add (item, addendum) + addendum
is the pseudo-code for an atomic_add_fetch
operation.
std::atomic<T>
if T
is an integral type, has a member operator+=
which does the same thing. It is described, along with all other atomic compound assignment operators in §29.6.5/30-32
C A::operator op=(M operand) volatile noexcept;
C A::operator op=(M operand) noexcept;
Effects: fetch_key(operand)
Returns: fetch_key(operand) op operand
However, it seems to be lacking in an add_fetch method.
Why would it need one? add_fetch
would be this:
return atomic_value.fetch_add(number) + number;
Yes, it technically requires an extra addition. But that's pretty minor.
In any case, there is no add_fetch
in the standard. There's just fetch_add
, which returns the original value.
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