forked from keineahnung2345/leetcode-cpp-practices
-
Notifications
You must be signed in to change notification settings - Fork 0
/
1117. Building H2O.cpp
74 lines (61 loc) · 2.34 KB
/
1117. Building H2O.cpp
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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
//https://leetcode.com/problems/building-h2o/discuss/721793/CORRECT-and-efficient-C%2B%2B-solution-with-mutex-and-condition-variables.-99
//https://github.com/keineahnung2345/cpp-code-snippets/blob/master/thread/conditional_variable_notify_one.cpp
//Runtime: 172 ms, faster than 77.24% of C++ online submissions for Building H2O.
//Memory Usage: 9.2 MB, less than 18.16% of C++ online submissions for Building H2O.
class H2O {
private:
int waitH, waitO;
int needH, needO;
condition_variable cvH, cvO;
mutex mtx;
bool building;
void reset(){
needH = 2;
needO = 1;
building = false;
}
public:
H2O() {
waitH = waitO = 0;
needH = 2;
needO = 1;
building = false;
}
void hydrogen(function<void()> releaseHydrogen) {
unique_lock<mutex> ul(mtx);
++waitH;
//condition 1: not building and the needed resource is collected
//condition 2: still building and need H
cvH.wait(ul, [&](){return
(!building && waitH >= 2 && waitO >= 1) || (building && needH > 0);});
building = true;
--waitH; //this H thread stop waiting
--needH; //this H thread is used, so need one less H
//wake up a H thread to continue building
if(needH > 0) cvH.notify_one();
//wake up a O thread to continue building
if(needO > 0) cvO.notify_one();
//complete building
if(needH == 0 && needO == 0) reset();
// releaseHydrogen() outputs "H". Do not change or remove this line.
releaseHydrogen();
}
void oxygen(function<void()> releaseOxygen) {
unique_lock<mutex> ul(mtx);
++waitO;
//condition 2: still building and need O
cvO.wait(ul, [&](){return
(!building && waitH >= 2 && waitO >= 1) || (building && needO > 0);});
building = true;
--waitO;
--needO;
/*
need one or more H, we can notify all because after a thread is waken up,
it will decrease needH, and so the condition 2 in cvH will be updated
*/
if(needH > 0) cvH.notify_all();
if(needH == 0 && needO == 0) reset();
// releaseOxygen() outputs "O". Do not change or remove this line.
releaseOxygen();
}
};