-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathSemaphore.cxx
136 lines (119 loc) · 2.61 KB
/
Semaphore.cxx
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#include <condition_variable>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <mutex>
#include <thread>
#include <vector>
// Semaphore implementation
class Semaphore
{
public:
Semaphore(int cnt = 0): counter(cnt) { }
void p();
void v();
private:
int counter;
std::mutex mtx;
std::condition_variable cv;
};
void Semaphore::p()
{
std::unique_lock<std::mutex> lck(mtx);
while(counter <= 0)
cv.wait(lck);
counter--;
}
void Semaphore::v()
{
std::unique_lock<std::mutex> lck(mtx);
counter++;
cv.notify_one();
}
// Producer Consumer without synchronization
class ProducerConsumer
{
public:
ProducerConsumer();
void produce();
void consume();
protected:
int nextIn, nextOut;
const int MAX = 35;
std::vector<int> conveyorbelt;
};
ProducerConsumer::ProducerConsumer(): nextIn(0), nextOut(0)
{
conveyorbelt = std::vector<int>(MAX, 0);
}
void ProducerConsumer::produce()
{
conveyorbelt[nextIn] = 1;
nextIn = (nextIn + 1) % MAX;
}
void ProducerConsumer::consume()
{
std::cout<<conveyorbelt[nextOut]<<" ";
conveyorbelt[nextOut] = 0;
nextOut = (nextOut + 1) % MAX;
}
// Producer Consumer with synchronization
class ProducerConsumerProtected: public ProducerConsumer
{
public:
ProducerConsumerProtected(): nEmpty(MAX), nOccup() { }
void produce();
void consume();
private:
std::mutex mtxIn, mtxOut;
Semaphore nEmpty, nOccup;
};
void ProducerConsumerProtected::produce()
{
nEmpty.p();
mtxIn.lock();
conveyorbelt[nextIn] = 1;
nextIn = (nextIn + 1) % MAX;
mtxIn.unlock();
nOccup.v();
}
void ProducerConsumerProtected::consume()
{
nOccup.p();
mtxOut.lock();
std::cout<<conveyorbelt[nextOut]<<" ";
conveyorbelt[nextOut] = 0;
nextOut = (nextOut + 1) % MAX;
mtxOut.unlock();
nEmpty.v();
}
int main()
{
srand(time(nullptr));
std::cout<<"Producer/Consumer problem"<<std::endl;
std::cout<<"> 0: Empty\n> 1: Product"<<std::endl;
std::cout<<"Each consumer print what it consummed with a space"<<std::endl;
std::cout<<"- Producer Consumer unprotected"<<std::endl;
ProducerConsumer pc;
const int times = 70;
std::thread tid[100];
for(int i = 0; i < times; i++)
{
auto func = rand() % 2 ? &ProducerConsumer::produce : &ProducerConsumer::consume;
tid[i] = std::thread(func, &pc);
}
for(int i = 0; i < times; i++)
tid[i].join();
std::cout<<std::endl;
std::cout<<"- Producer Consumer protected"<<std::endl;
ProducerConsumerProtected pcp;
for(int i = 0; i < times; i++)
{
auto func = rand() % 3 > 0 ? &ProducerConsumerProtected::produce : &ProducerConsumerProtected::consume;
tid[i] = std::thread(func, &pcp);
}
for(int i = 0; i < times; i++)
tid[i].join();
std::cout<<std::endl;
return 0;
}