mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-15 14:16:07 -06:00
50 lines
No EOL
1.4 KiB
C++
50 lines
No EOL
1.4 KiB
C++
#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<int> 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 bug, 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.
|
|
} |