| unconditional (1) | template <class Lock> void wait (Lock& lck); |
|---|---|
| predicate (2) | template <class Lock, class Predicate> void wait (Lock& lck, Predicate pred); |
lck.unlock() , allowing other locked threads to continue.lck.lock() , leaving lck in the same state as when the function was called. Then the function returns (notice that this last mutex locking may block again the thread before returning).false, and notifications can only unblock the thread when it becomes true (which is specially useful to check against spurious wake-up calls). This version (2) behaves as if implemented as:1
while (!pred()) wait(lck);
bool.true.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// condition_variable_any::wait (with predicate)
#include <iostream> // std::cout
#include <thread> // std::thread, std::this_thread::yield
#include <mutex> // std::mutex
#include <condition_variable> // std::condition_variable_any
std::mutex mtx;
std::condition_variable_any cv;
int cargo = 0;
bool shipment_available() {return cargo!=0;}
void consume (int n) {
for (int i=0; i<n; ++i) {
mtx.lock();
cv.wait(mtx,shipment_available);
// consume:
std::cout << cargo << '\n';
cargo=0;
mtx.unlock();
}
}
int main ()
{
std::thread consumer_thread (consume,10);
// produce 10 items when needed:
for (int i=0; i<10; ++i) {
while (shipment_available()) std::this_thread::yield();
mtx.lock();
cargo = i+1;
cv.notify_one();
mtx.unlock();
}
consumer_thread.join();
return 0;
}
1 2 3 4 5 6 7 8 9 10
condition_variable_any object and the arguments are in a valid state (basic guarantee). Additionally, on exception, the state of lck is attempted to be restored before exiting the function scope (by calling lck.lock()).condition_variable_any object and the arguments in a valid state (basic guarantee).