std::atomic_flag_test_and_set,std::atomic_flag_test_and_set_explicit(3)

NAME
std::atomic_flag_test_and_set,std::atomic_flag_test_and_set_explicit - std::atomic_flag_test_and_set,std::atomic_flag_test_and_set_explicit

Synopsis
   Defined in header <atomic>
   bool atomic_flag_test_and_set( volatile std::atomic_flag*
   p ) noexcept;
   bool atomic_flag_test_and_set( std::atomic_flag* p )
   noexcept;
   bool atomic_flag_test_and_set_explicit( volatile (1) (since
   std::atomic_flag* p, C++11)
   std::memory_order order ) noexcept; (2) (since
   bool atomic_flag_test_and_set_explicit( std::atomic_flag* C++11)
   p,
   std::memory_order order ) noexcept;
   Atomically changes the state of a std::atomic_flag pointed to by p to set (true) and
   returns the value it held before.

Parameters
   p - pointer to std::atomic_flag to access
   order - the memory synchronization order for this operation

Return value
   The value previously held by the flag pointed to by p

Possible implementation

First version
   bool atomic_flag_test_and_set(volatile std::atomic_flag* p)
   {
       return p->test_and_set();
   }

Second version
   bool atomic_flag_test_and_set(std::atomic_flag* p)
   {
       return p->test_and_set();
   }
                        Third version
   bool atomic_flag_test_and_set_explicit(volatile std::atomic_flag* p,
                        std::memory_order order)
   {
       return p->test_and_set(order);
   }
                        Fourth version
   bool atomic_flag_test_and_set_explicit(std::atomic_flag* p,
                        std::memory_order order)
   {
       return p->test_and_set(order);
   }

Example
   A spinlock mutex can be implemented in userspace using an atomic_flag. // Run this code
 #include <thread>
 #include <vector>
 #include <iostream>
 #include <atomic>
 std::atomic_flag lock = ATOMIC_FLAG_INIT;
 void f(int n)
 {
     for (int cnt = 0; cnt < 100; ++cnt) {
         while(std::atomic_flag_test_and_set_explicit(&lock, std::memory_order_acquire))
              ; // spin until the lock is acquired
         std::cout << "Output from thread " << n << '\n';
         std::atomic_flag_clear_explicit(&lock, 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>...

See also
   atomic_flag the lock-free boolean atomic type
   (C++11) (class)
   atomic_flag_clear
   atomic_flag_clear_explicit atomically sets the value of the flag to false
   (C++11) (function)
   (C++11)
   memory_order defines memory ordering constraints for the given atomic
   (C++11) operation
                        (enum)