std::atomic<T>::exchange

From cppreference.com
< cpp‎ | atomic‎ | atomic
 
 
Concurrency support library
Threads
(C++11)
(C++20)
(C++20)
this_thread namespace
(C++11)
(C++11)
(C++11)
Atomic types
(C++11)
(C++20)
Initialization of atomic types
(C++11)(deprecated in C++20)
(C++11)(deprecated in C++20)
Free functions for atomic operations
Free functions for atomic flags
Memory ordering
Mutual exclusion
(C++11)
Generic lock management
(C++11)
(C++11)
(C++11)
(C++11)(C++11)(C++11)
(C++11)
(C++11)
Condition variables
(C++11)
Semaphores
Latches and barriers
(C++20)
(C++20)
Futures
(C++11)
(C++11)
(C++11)
(C++11)
 
 
(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. The operation is 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)

Parameters

desired - value to assign
order - memory order constraints to enforce

Return value

The value of the atomic variable before the call.

Example

#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

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)