Foundations — std - condition_variable
Before you can read the parent note, you need to see what a thread is, what "shared memory" looks like, why two threads touching the same box at once is dangerous, and what a lock physically does. This page builds every one of those pictures from nothing.
1. A thread — a worker with its own hands
Picture a kitchen. One cook = one thread. Two cooks = two threads working in parallel. They share the same kitchen (the same memory), but each has their own hands and their own place in their own recipe.

Why the topic needs it: a condition_variable only makes sense when one worker must wait for another worker. No second thread, no waiting, no doorbell.
2. Shared memory — the one box both workers reach into
Look at figure s01 again: the red box in the middle is one variable both cooks can touch. When cook A writes and cook B reads, they are talking through that box — that is the only way threads communicate.
Why the topic needs it: the "condition" a thread waits for is always a fact about shared state ("is the queue non-empty?"). Without a shared box, there is nothing to wait for.
3. The race condition — why sharing is dangerous
Say the shared box holds the number 5, and both cooks run "read it, add 1, write it back". You'd expect 7. But watch the timeline:

Both read 5 before either writes, both compute 6, both write 6. One +1 vanished. The bug appears only sometimes, depending on who was faster — that unpredictability is the "race".
Why the topic needs it: the whole reason wait and notify are entangled with a mutex is to prevent races on the shared condition. You cannot understand the API until you feel this danger.
4. The mutex — a single key for the box
Picture a bathroom with one key on a hook. You take the key, go in, lock the door. Anyone else who wants in stands outside until you come out and hang the key back.

Because only the key-holder can enter, only one thread modifies the box at a time — the vanished-+1 race from figure s02 becomes impossible.
Why the topic needs it: cv.wait takes a locked mutex, works with it, and hands it back. The mutex is half of every condition-variable pattern.
5. RAII locks — lock_guard and unique_lock
Holding the key by hand is error-prone: if you forget to hang it back (an early return, an exception), everyone else waits forever — a Deadlock. C++ fixes this with RAII: a small object grabs the key when it is created and hangs it back automatically when it goes out of scope (the closing }).
Why the topic needs it: the parent note uses lock_guard for the producer (lock, push, auto-unlock) and unique_lock for the consumer (because it calls wait). Knowing the difference is knowing why those two choices differ.
6. #include, ::, and <> — reading the notation itself
Three pieces of pure C++ syntax appear on every line of the parent note. Let's earn each symbol.
Why the topic needs it: every symbol on the parent page — std::condition_variable, std::unique_lock<std::mutex>, std::queue<int> — is built from exactly these three notations. Now none of them is mysterious.
7. The predicate P() — a yes/no question about the box
The []{ ... } is C++'s way of writing a throwaway function inline. Read []{ return ready; } as "the question: is ready true right now?"
Why the topic needs it: the predicate is the "some fact becomes true" from the core idea. It is the bridge between "a thread is waiting" and "for what."
8. Spurious wakeup — why we loop, not if
Because a wakeup might be fake, the thread must re-check the predicate every time it wakes — which is exactly why the equivalence above is a while loop, not a single if. Wake, ask "is it really true?", and if not, go back to sleep.
Why the topic needs it: this single fact is the reason cv.wait(lk, pred) exists at all instead of a plain "sleep until poked."
Prerequisite map
Read top to bottom: threads make sharing possible, sharing creates races, the mutex tames races, RAII locks wield the mutex safely, the predicate says what to wait for, spurious wakeups force the loop — and all of it converges on std::condition_variable.
Equipment checklist
A thread is
Shared state is
A race condition is
A mutex is
std::lock_guard vs std::unique_lock
unique_lock can unlock and re-lock mid-scope — which cv.wait requires.std:: and :: mean
std is the standard-library namespace (drawer); :: means "reach into that drawer for this name."<int> in std::queue<int> means
int values.A predicate is
true/false, here written as a lambda []{ return ...; }, stating the condition to wait for.A spurious wakeup is
cv.wait(lock, P) is equivalent to
while(!P()) cv.wait(lock); — keep sleeping while the answer is "no."