std::atomic...dd_explicit(3)
π NAME
bestie, welcome to std::atomic...dd_explicit(3) from the C++ Standard Libary manual (yes, thatβs the headerβs spelling, not mine π β section 3, weβre keeping the lore). The stars of the show are std::atomic_fetch_add and std::atomic_fetch_add_explicit: atomic addition with and without an explicit memory order. Itβs giving βfetch the old value, add the new one, no cap.β β¨
π¦ Synopsis
Defined in header <atomic>.
Overload (1) β since C++11:
template< class T >
T atomic_fetch_add( std::atomic<T>* obj,
typename std::atomic<T>::difference_type arg ) noexcept;
Overload (2) β since C++11:
template< class T >
T atomic_fetch_add( volatile std::atomic<T>* obj,
typename std::atomic<T>::difference_type arg ) noexcept;
Overload (3) β since C++11:
template< class T >
T atomic_fetch_add_explicit( std::atomic<T>* obj,
typename std::atomic<T>::difference_type arg,
std::memory_order order ) noexcept;
Overload (4) β since C++11:
template< class T >
T atomic_fetch_add_explicit( volatile std::atomic<T>* obj,
typename std::atomic<T>::difference_type arg,
std::memory_order order ) noexcept;
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)
β οΈ warning, bestie: ifstd::atomic<T>has nofetch_addmember (this member is only provided for integral, floating-point (since C++20) and pointer types exceptbool), the program is ill-formed. Not a vibe. π
π Parameters
objβ pointer to the atomic object to modifyargβ the value to add to the value stored in the atomic objectorderβ the memory synchronization ordering
πΈ Return value
The value immediately preceding the effects of this function in the modification order of *obj. So you get the old value, not the new one β main character energy is all about the before pic. π«Ά
π₯ Example
Single-writer/multiple-reader lock can be made with std::atomic_fetch_add. Note that this simplistic implementation is not lockout-free.
#include <atomic>
#include <chrono>
#include <iostream>
#include <string>
#include <thread>
#include <vector>
using namespace std::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.
const int N = 5; // four concurrent readers are allowed
std::atomic<int> cnt(N);
std::vector<int> data;
void reader(int id)
{
for (;;)
{
// lock
while (std::atomic_fetch_sub(&cnt, 1) <= 0)
std::atomic_fetch_add(&cnt, 1);
// read
if (!data.empty())
std::cout << ("reader " + std::to_string(id) +
" sees " + std::to_string(*data.rbegin()) +
'\n');
if (data.size() == 25)
break;
// unlock
std::atomic_fetch_add(&cnt, 1);
// pause
std::this_thread::sleep_for(1ms);
}
}
void writer()
{
for (int n = 0; n < 25; ++n)
{
// lock
while (std::atomic_fetch_sub(&cnt, N + 1) != N)
std::atomic_fetch_add(&cnt, N + 1);
// write
data.push_back(n);
std::cout << "writer pushed back " << n << '\n';
// unlock
std::atomic_fetch_add(&cnt, N + 1);
// pause
std::this_thread::sleep_for(1ms);
}
}
int main()
{
std::vector<std::thread> v;
for (int n = 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.
P0558R1β applied to C++11. Behavior as published: exact type match was required becauseTis only deduced fromobj. Correct behavior:Twas deduced from multiple arguments.
π See also
fetch_addβ atomically adds the argument to the value stored in the atomic object and obtains the value held previously (public member function ofstd::atomic<T>).atomic_fetch_sub,atomic_fetch_sub_explicit(C++11)β subtracts a non-atomic value from an atomic object and obtains the previous value of the atomic (function template).- C documentation for
atomic_fetch_add,atomic_fetch_add_explicit.
source http://cppreference.com, version/date 2024.06.10, page std::atomic...dd_explicit(3) β stay atomic, bestie πβ¨
π¦ where this page comes from
- nixpkgs unstable: stdman 2024.07.05
- opensuse-leap 16.0: stdman 2024.07.05-bp160.1.9 Β· MIT
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms