#include "Tutorial.h" void ConditionVariableTutorial() { /// .`ConditionVariable` /// `ConditionVariable` in general is a synchronization primitive used to block/awaken the /// thread. `ConditionVariable` is associated with `Mutex` used to protect some data; in /// the thread that is to be blocked, `Mutex` has to locked; call to `Wait` atomically /// unlocks the `Mutex` and puts the thread to waiting. Another thread then can resume the /// thread by calling `Signal`, which also causes `Mutex` to lock again. Multiple threads /// can be waiting on single `ConditionVariable`; `Signal` resumes single waiting thread, /// `Brodcast` resumes all waitng threads. bool stop = false; BiVector data; Mutex m; ConditionVariable cv; Thread t; t.Run([&stop, &data, &m, &cv] { Mutex::Lock __(m); for(;;) { while(data.GetCount()) { int q = data.PopTail(); LOG("Data received: " << q); } if(stop) break; cv.Wait(m); } }); for(int i = 0; i < 10; i++) { { Mutex::Lock __(m); data.AddHead(i); } cv.Signal(); Sleep(1); } stop = true; cv.Signal(); t.Wait(); /// Important note: rarely thread can be resumed from `Wait` even if no other called /// `Signal`. This is not a bud, but ^https://en.wikipedia.org/wiki/Spurious_wakeup:design /// decision for performance reason^. In practice it only means that situation has to be /// (re)checked after resume. }