std::atomic_fetch_add, std::atomic_fetch_add_explicit - cppreference.com

From cppreference.com

Defined in header

<atomic>

template<classT>Tatomic_fetch_add(std::atomic<T>*obj,typenamestd::atomic<T>::difference_typearg)noexcept; (1) (since C++11)template<classT>Tatomic_fetch_add(volatilestd::atomic<T>*obj,typenamestd::atomic<T>::difference_typearg)noexcept; (2) (since C++11)template<classT>Tatomic_fetch_add_explicit(std::atomic<T>*obj,typenamestd::atomic<T>::difference_typearg,std::memory_orderorder)noexcept; (3) (since C++11)template<classT>Tatomic_fetch_add_explicit(volatilestd::atomic<T>*obj,typenamestd::atomic<T>::difference_typearg,std::memory_orderorder)noexcept; (4) (since C++11)Performs atomic addition. Atomically adds arg to the value pointed to by obj and returns the value obj held previously. The operation is performed as if the following was executed:

1,2)obj->fetch_add(arg)

3,4)obj->fetch_add(arg,order)

If std::atomic<T> has no fetch_add member (this member is only provided for

integral

,

floating-point

(since C++20) and

pointer

types except bool), the program is ill-formed.

Parameters

obj - pointer to the atomic object to modify arg - the value to add to the value stored in the atomic object order - the memory synchronization ordering Return value

The value immediately preceding the effects of this function in the

modification order

of *obj.

Example

Single-writer/multiple-reader lock can be made with std::atomic_fetch_add. Note that this simplistic implementation is not lockout-free.

Run this code

#include<atomic>#include<chrono>#include<iostream>#include<string>#include<thread>#include<vector>usingnamespacestd::chrono_literals;// meaning of cnt:// 5: readers and writer are in race. There are no active readers or writers.// 4...0: there are 1...5 active readers, The writer is blocked.// -1: writer won the race and readers are blocked.constintN=5;// four concurrent readers are allowedstd::atomic<int>cnt(N);std::vector<int>data;voidreader(intid){for(;;){// lockwhile(std::atomic_fetch_sub(&cnt,1)<=0)std::atomic_fetch_add(&cnt,1);// readif(!data.empty())std::cout<<("reader "+std::to_string(id)+" sees "+std::to_string(*data.rbegin())+'\n');if(data.size()==25)break;// unlockstd::atomic_fetch_add(&cnt,1);// pausestd::this_thread::sleep_for(1ms);}}voidwriter(){for(intn=0;n<25;++n){// lockwhile(std::atomic_fetch_sub(&cnt,N+1)!=N)std::atomic_fetch_add(&cnt,N+1);// writedata.push_back(n);std::cout<<"writer pushed back "<<n<<'\n';// unlockstd::atomic_fetch_add(&cnt,N+1);// pausestd::this_thread::sleep_for(1ms);}}intmain(){std::vector<std::thread>v;for(intn=0;n<N;++n)v.emplace_back(reader,n);v.emplace_back(writer);for(auto&t:v)t.join();}Output:

writer pushed back 0 reader 2 sees 0 reader 3 sees 0 reader 1 sees 0 <...> reader 2 sees 24 reader 4 sees 24 reader 1 sees 24 Defect reports

The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

DR Applied to Behavior as published Correct behavior

P0558R1

C++11 exact type match was required because
T was deduced from multiple arguments T is only deduced
from objSee also

atomically adds the argument to the value stored in the atomic object and obtains the value held previously
(public member function of std::atomic<T>)

[edit]

(C++11)(C++11)

subtracts a non-atomic value from an atomic object and obtains the previous value of the atomic
(function template)

[edit]

C documentation

for atomic_fetch_add, atomic_fetch_add_explicit