std::atomic_exchange,std::atomic_exchange_explicit(3)

NAME
std::atomic_exchange,std::atomic_exchange_explicit - std::atomic_exchange,std::atomic_exchange_explicit

Synopsis
   Defined in header <atomic>
   template< class T >
   T atomic_exchange( std::atomic<T>* obj,
   typename std::atomic<T>::value_type desr )
   noexcept;
   template< class T >
   T atomic_exchange( volatile std::atomic<T>*
   obj,
   typename std::atomic<T>::value_type desr )
   noexcept;
   template< class T > (1) (since C++11)
   T atomic_exchange_explicit( std::atomic<T>*
   obj,
   typename std::atomic<T>::value_type desr,
   std::memory_order order ) noexcept; (2) (since C++11)
   template< class T >
   T atomic_exchange_explicit( volatile
   std::atomic<T>* obj,
   typename std::atomic<T>::value_type desr,
   std::memory_order order ) noexcept;
   1) Atomically replaces the value pointed to by obj with the value of desr and
   returns the value obj held previously, as if by obj->exchange(desr)
   2) Atomically replaces the value pointed to by obj with the value of desr and
   returns the value obj held previously, as if by obj->exchange(desr, order)

Parameters
   obj - pointer to the atomic object to modify
   desr - the value to store in the atomic object
   order - the memory synchronization ordering for this operation: all values are
           permitted.

Return value
   The value held previously by the atomic object pointed to by obj

Example
   A spinlock mutex can be implemented in userspace using an atomic exchange operation,
   similar to std::atomic_flag_test_and_set: // Run this code
 #include <thread>
 #include <vector>
 #include <iostream>
 #include <atomic>
 std::atomic<bool> lock(false); // holds true when locked
                        // holds false when unlocked
 void f(int n)
 {
     for (int cnt = 0; cnt < 100; ++cnt) {
         while(std::atomic_exchange_explicit(&lock, true, std::memory_order_acquire))
              ; // spin until acquired
         std::cout << "Output from thread " << n << '\n';
         std::atomic_store_explicit(&lock, false, std::memory_order_release);
     }
 }
 int main()
 {
     std::vector<std::thread> v;
     for (int n = 0; n < 10; ++n) {
         v.emplace_back(f, n);
     }
     for (auto& t : v) {
         t.join();
     }
 }

Output:
 Output from thread 2
 Output from thread 6
 Output from thread 7
 ...<exactly 1000 lines>...
  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 required because T is T is deduced from the
                      deduced from multiple arguments atomic argument only

See also
                        atomically replaces the value of the atomic
   exchange object and obtains the value held previously
                        (public member function of std::atomic<T>)
   atomic_compare_exchange_weak
   atomic_compare_exchange_weak_explicit atomically compares the value of the atomic
   atomic_compare_exchange_strong object with non-atomic argument and performs
   atomic_compare_exchange_strong_explicit atomic exchange if equal or atomic load if
   (C++11) not
   (C++11) (function template)
   (C++11)
   (C++11)
   std::atomic_exchange(std::shared_ptr) specializes atomic operations for
   std::atomic_exchange_explicit(std::shared_ptr) std::shared_ptr
   (deprecated in C++20) (function template)