std::condit...::notify_one(3)

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

πŸ’… std::condition_variable_any::notify_one πŸ’…

okay bestie, so this is literally the C++ Standard Library page for std::condition_variable_any::notify_one and it's giving "wake up one of your waiting threads" energy, periodt. let me break it down for you 🫢


✨ NAME ✨

std::condition_variable_any::notify_one β€” like yes that's the whole name, it's not deep, we're just being thorough πŸ’…


🌸 Synopsis 🌸

void notify_one() noexcept;

(since C++11 about time bestie)

if any threads are waiting on *this, calling notify_one unblocks one of the waiting threads. just one. not them all. she's selective like that 😌


πŸŽ€ Parameters πŸŽ€

(none) β€” literally nothing to pass in, so easy πŸ’–


πŸ¦‹ Return value πŸ¦‹

(none) β€” it gives you nothing back, like it's not about the closure it's about the vibes ✨


πŸ’œ Notes πŸ’œ

okay this part is actually highkey important so listen up πŸ”₯

the effects of notify_one()/notify_all() and each of the three atomic parts of wait()/wait_for()/wait_until() β€” that's (unlock+wait, wakeup, and lock) β€” happen in a single total order that you can think of as the modification order of an atomic variable. here's the main character energy part: the order is specific to this individual condition variable. this makes it literally impossible for notify_one() to, for example, be delayed and unblock a thread that started waiting just after the call to notify_one() was made. no cap, the ordering is locked in fr fr.

the notifying thread does not need to hold the lock on the same mutex as the one held by the waiting thread(s). in fact, doing so is a pessimization, since the notified thread would immediately block again, waiting for the notifying thread to release the lock. like why would you do that to her 😭 however, some implementations (in particular many implementations of pthreads) recognize this situation and avoid this "hurry up and wait" scenario by transferring the waiting thread from the condition variable's queue directly to the queue of the mutex within the notify call, without waking it up. iconic behavior honestly πŸ‘‘

🚨 notifying while under the lock may nevertheless be necessary when precise scheduling of events is required, e.g. if the waiting thread would exit the program if the condition is satisfied, causing destruction of the notifying thread's condition variable. a spurious wakeup after mutex unlock but before notify would result in notify called on a destroyed object. that's the danger zone bestie, be careful πŸ’€

🧚 Example 🧚

// Run this code

#include <chrono>
#include <condition_variable>
#include <iostream>
#include <thread>
using namespace std::chrono_literals;

std::condition_variable_any cv;
std::mutex cv_m;
int i = 0;
bool done = false;

void waits()
{
    std::unique_lock<std::mutex> lk(cv_m);
    std::cout << "Waiting... \n";
    cv.wait(lk, []{ return i == 1; });
    std::cout << "...finished waiting; i == " << i << '\n';
    done = true;
}

void signals()
{
    std::this_thread::sleep_for(200ms);
    std::cout << "Notifying falsely...\n";
    cv.notify_one(); // waiting thread is notified with i == 0.
                     // cv.wait wakes up, checks i, and goes back to waiting

    std::unique_lock<std::mutex> lk(cv_m);
    i = 1;
    while (!done)
    {
        std::cout << "Notifying true change...\n";
        lk.unlock();
        cv.notify_one(); // waiting thread is notified with i == 1, cv.wait returns
        std::this_thread::sleep_for(300ms);
        lk.lock();
    }
}

int main()
{
    std::thread t1(waits), t2(signals);
    t1.join();
    t2.join();
}

Possible output:

Waiting...
Notifying falsely...
Notifying true change...
...finished waiting; i == 1

🌈 See also 🌈

  • notify_all β€” notifies all waiting threads (public member function) β€” she's the extrovert, tells everyone πŸ’«
  • C documentation for cnd_signal β€” the C version, iykyk 🌸

πŸ™ˆ Hidden category πŸ™ˆ

  • Pages with unreviewed LWG DR marker β€” it's in the vault bestie, lowkey mysterious πŸ‘€

okay so that's the whole thing, no gatekeeping here πŸ’– this page came from cppreference.com, version date 2024.06.10, and the manual ref is std::condit...::notify_one(3). go forth and notify exactly one thread, you absolute main character πŸŽ€βœ¨πŸ‘‘

πŸ“¦ where this page comes from