Difference between revisions of "cpp/atomic/atomic/exchange"
From cppreference.com
m (→Example: let's indeed use `osyncstream` as it is available in GCC 11.2 online.) |
RobStewart (Talk | contribs) (Remove repeated "operation") |
||
Line 12: | Line 12: | ||
{{dcl end}} | {{dcl end}} | ||
− | Atomically replaces the underlying value with {{tt|desired}} | + | Atomically replaces the underlying value with {{tt|desired}} (a read-modify-write operation). Memory is affected according to the value of {{tt|order}}. |
{{rrev|since=c++20| | {{rrev|since=c++20| |
Revision as of 10:16, 4 October 2022
(since C++11) | ||
T exchange( T desired, std::memory_order order = std::memory_order_seq_cst ) noexcept; |
(1) | |
T exchange( T desired, std::memory_order order = std::memory_order_seq_cst ) volatile noexcept; |
(2) | |
Atomically replaces the underlying value with desired
(a read-modify-write operation). Memory is affected according to the value of order
.
The volatile-qualified version (2) is deprecated if std::atomic<T>::is_always_lock_free is false. |
(since C++20) |
Contents |
Parameters
desired | - | value to assign |
order | - | memory order constraints to enforce |
Return value
The value of the atomic variable before the call.
Example
Run this code
#include <algorithm> #include <atomic> #include <cstddef> #include <iostream> #include <syncstream> #include <thread> #include <vector> int main(){ const std::size_t ThreadNumber = 5; const int Sum = 5; std::atomic<int> atom{0}; std::atomic<int> counter{0}; // lambda as thread proc auto lambda = [&](const int id){ for (int next = 0; next < Sum;){ // each thread is writing a value from its own knowledge const int current = atom.exchange(next); counter++; // sync writing to prevent from interrupting by other threads std::osyncstream(std::cout) << '#' << id << " (" << std::this_thread::get_id() << ") wrote " << next << " replacing the old value " << current << '\n'; next = std::max(current, next) + 1; } }; std::vector<std::thread> v; for (std::size_t i = 0; i < ThreadNumber; ++i){ v.emplace_back(lambda, i); } for (auto& tr : v){ tr.join(); } std::cout << ThreadNumber << " threads adding 0 to " << Sum << " takes total " << counter << " times\n"; }
Possible output:
#1 (140552371918592) wrote 0 replacing the old value 0 #2 (140552363525888) wrote 0 replacing the old value 0 #1 (140552371918592) wrote 1 replacing the old value 0 #1 (140552371918592) wrote 2 replacing the old value 1 #2 (140552363525888) wrote 1 replacing the old value 1 #1 (140552371918592) wrote 3 replacing the old value 2 #1 (140552371918592) wrote 4 replacing the old value 2 #2 (140552363525888) wrote 2 replacing the old value 3 #2 (140552363525888) wrote 4 replacing the old value 0 #3 (140552355133184) wrote 0 replacing the old value 4 #0 (140552380311296) wrote 0 replacing the old value 0 #0 (140552380311296) wrote 1 replacing the old value 4 #4 (140552346740480) wrote 0 replacing the old value 1 #4 (140552346740480) wrote 2 replacing the old value 0 #4 (140552346740480) wrote 3 replacing the old value 2 #4 (140552346740480) wrote 4 replacing the old value 3 5 threads adding 0 to 5 takes total 16 times
See also
(C++11)(C++11) |
atomically replaces the value of the atomic object with non-atomic argument and returns the old value of the atomic (function template) |
(C++14) |
replaces the argument with a new value and returns its previous value (function template) |