std::atomic...et_explicit(3)

πŸ“¦ version 2024.07.05, in nixpkgs unstable, opensuse-leap 16.0

πŸ’… std::atomic_flag_test_and_set / std::atomic_flag_test_and_set_explicit πŸ’…

okay bestie, this is the C++ Standard Libary manual page std::atomic...et_explicit(3) β€” and it's giving β€œtiny atomic flag, huge main character energy.” We're literally flipping a flag to true and getting the old value back. No cap. 🫢

✨ 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* obj )
       (1) (since C++11)
          noexcept;
          bool atomic_flag_test_and_set( std::atomic_flag* obj ) noexcept;
       (2) (since C++11)
          bool atomic_flag_test_and_set_explicit( volatile std::atomic_flag*
          obj,
       (3) (since C++11)
                                                  std::memory_order order )
          noexcept;
          bool atomic_flag_test_and_set_explicit( std::atomic_flag* obj,
                                                  std::memory_order order )
       (4) (since C++11)
          noexcept;

Quick translation: this atomically changes the state of the std::atomic_flag pointed to by obj to set (true) and returns the value it held before. πŸ’–

  • 1,2) the memory synchronization order is std::memory_order_seq_cst.
  • 3,4) the memory synchronization order is order.

All four are noexcept, and all four are (since C++11) β€” iconic behavior, no notes. ✨

πŸŽ€ Parameters πŸŽ€

  • obj β€” pointer to std::atomic_flag to access.
  • order β€” the memory synchronization order.

πŸ’– Return value πŸ’–

The value previously held by the flag pointed to by obj. That's it, that's the tea. πŸ“

πŸ¦‹ Notes πŸ¦‹

std::atomic_flag_test_and_set and std::atomic_flag_test_and_set_explicit can be implemented as obj->test_and_set() and obj->test_and_set(order) respectively. lowkey neat, highkey useful. 🧚

πŸ”₯ Example πŸ”₯

A spinlock mutex can be implemented in userspace using an std::atomic_flag.

        // Run this code

        #include <atomic>
        #include <iostream>
        #include <thread>
        #include <vector>

        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 operation; (C++11); (enum).
  • C documentation for atomic_flag_test_and_set, atomic_flag_test_and_set_explicit.

mwah πŸ’‹ that's the whole page. source: http://cppreference.com, version/date: 2024.06.10. go forth and atomic-flag, bestie πŸ«ΆπŸ’…βœ¨

πŸ“¦ where this page comes from