std::atomic::wait(3)

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

πŸ’… std::atomic::wait(3) β€” C++ Standard Libary (man page 3) πŸ’…

πŸ’– NAME πŸ’–

std::atomic::wait β€” std::atomic::wait. That's it. The name is the name, and it's giving "I wait on atomics" energy. periodt. πŸ’…


✨ Synopsis ✨

Here's the exact synopsis, bestie:

          void wait( T old, std::memory_order order =
       (1) (since C++20)
                                std::memory_order::seq_cst ) const noexcept;
          void wait( T old, std::memory_order order =
                                std::memory_order::seq_cst ) const volatile
       (2) (since C++20)
          noexcept;

Okay so there are two overloads, both (since C++20): overload (1) is the const noexcept one, overload (2) is the const volatile noexcept one, and the default order is std::memory_order::seq_cst. Slay. ✨

Performs atomic waiting operations. Behaves as if it repeatedly performs the following steps:

  1. Compare the value representation of this->load(order) with that of old.
  2. If those are equal, then blocks until *this is notified by notify_one() or notify_all(), or the thread is unblocked spuriously.
  3. Otherwise, returns.

These functions are guaranteed to return only if value has changed, even if underlying implementation unblocks spuriously. No cap. 😌

🚨 If order is one of std::memory_order::release and std::memory_order::acq_rel, the behavior is undefined. That's not a cute look, bestie β€” do not do it. πŸ’€

πŸŽ€ Parameters πŸŽ€

  • old β€” the value to check the atomic's object no longer contains.
  • order β€” memory order constraints to enforce.

That's the whole list. 🫢


πŸ’œ Return value πŸ’œ

(none) β€” literally nothing. The function just does its wait thing and dips. 🫢


🌈 Notes 🌈

This form of change-detection is often more efficient than simple polling or pure spinlocks. Highkey iconic for waiting. ✨

Due to the ABA problem, transient changes from old to another value and back to old might be missed, and not unblock. 😭

πŸŒ€ ABA be like: "I left, I came back, and nobody noticed." That's the whole problem. Not me crying over transient changes. πŸ’€

The comparison is bitwise (similar to std::memcmp); no comparison operator is used. Padding bits that never participate in an object's value representation are ignored. Fr fr, it's bitwise business. 🧚


🧚 Example 🧚

// Run this code

        #include <atomic>
        #include <chrono>
        #include <future>
        #include <iostream>
        #include <thread>

        using namespace std::literals;

        int main()
        {
            std::atomic<bool> all_tasks_completed{false};
            std::atomic<unsigned> completion_count{};
            std::future<void> task_futures[16];
            std::atomic<unsigned> outstanding_task_count{16};

            // Spawn several tasks which take different amounts of
            // time, then decrement the outstanding task count.
            for (std::future<void>& task_future : task_futures)
                task_future = std::async([&]
                {
                    // This sleep represents doing real work...
                    std::this_thread::sleep_for(50ms);

                    ++completion_count;
                    --outstanding_task_count;

                    // When the task count falls to zero, notify
                    // the waiter (main thread in this case).
                    if (outstanding_task_count.load() == 0)
                    {
                        all_tasks_completed = true;
                        all_tasks_completed.notify_one();
                    }
                });

            all_tasks_completed.wait(false);

            std::cout << "Tasks completed = " << completion_count.load() <<
       '\n';
        }

πŸ–₯️ Output: πŸ–₯️

Tasks completed = 16

πŸ‘€ See also πŸ‘€

  • notify_one β€” notifies at least one thread waiting on the atomic object (C++20) (public member function).
  • notify_all β€” notifies all threads blocked waiting on the atomic object (C++20) (public member function).
  • atomic_notify_one β€” notifies a thread blocked in atomic_wait (C++20) (function template).
  • atomic_notify_all β€” notifies all threads blocked in atomic_wait (C++20) (function template).

πŸ’– source/version: http://cppreference.com Β· date: 2024.06.10 Β· page: std::atomic::wait(3) β€” byeeee bestie, go wait on something iconic 🫢✨

πŸ“¦ where this page comes from