-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrwlock.cpp
More file actions
221 lines (177 loc) · 4.81 KB
/
Copy pathrwlock.cpp
File metadata and controls
221 lines (177 loc) · 4.81 KB
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
#include <iostream>
#include <atomic>
#include <vector>
#include <mutex>
#include <thread>
#include <chrono>
class shared_mutex {
private:
// 内部互斥锁,用与互斥访问_state
std::mutex _mut;
// 读者写者都用
std::condition_variable _gate1;
// 唤醒读者
std::condition_variable _gate2;
// 记录当前状态,进入写状态的写者数目和读者数目
// 4字节,4 * 8 - 1 = 31,1<<31就是只有最高位是1的数字
static const unsigned _writer_entered = 1U << (sizeof(unsigned) * 8 - 1);
const static unsigned _readers_cnt = ~_writer_entered;
// 当前状态,可以使用上面的两个常量获取状态,是否安全我就不知道了
unsigned _state;
bool no_writer() {
return (_state & _writer_entered) == 0;
}
bool no_readers() {
return (_state & _readers_cnt) == 0;
}
bool no_reader_no_writer() {
return _state == 0;
}
bool no_writer_no_max_reader() {
return (_state & _writer_entered) == 0 && (_state & _readers_cnt) != _readers_cnt;
}
public:
shared_mutex() noexcept;
~shared_mutex();
void lock();
void unlock();
bool try_lock();
void lock_shared();
void unlock_shared();
bool try_lock_shared();
};
void shared_mutex::lock() {
std::unique_lock<std::mutex> lk{_mut};
// 等待写者退出或者说排队
_gate1.wait(lk, std::bind(&shared_mutex::no_writer, this));
_state |= _writer_entered;
// 等待已进入的读者出来
_gate2.wait(lk, std::bind(&shared_mutex::no_readers, this));
}
void shared_mutex::unlock() {
// 解锁吧
std::unique_lock<std::mutex> lk;
// 此时没有读者,但不确定有没有读者等待写者进入
_state = 0;
// 提醒写者和读者,所以就是随机唤醒的。。。
_gate1.notify_all();
}
bool shared_mutex::try_lock() {
std::unique_lock<std::mutex> lk{_mut};
if (no_reader_no_writer()) {
_state |= _writer_entered;
return true;
}
return false;
}
void shared_mutex::lock_shared() {
// 写优先
std::unique_lock<std::mutex> lk{_mut};
// 首先排在写锁后面
_gate1.wait(lk, std::bind(&shared_mutex::no_writer_no_max_reader, this));
// 最高位为0,直接加1就行了
++_state;
}
void shared_mutex::unlock_shared() {
std::unique_lock<std::mutex> lk{_mut};
--_state;
unsigned readers = _state & _readers_cnt;
// 写者减1
if (no_writer()) {
// 队原来满了
if (readers == _readers_cnt - 1) {
_gate1.notify_one();
}
} else {
// 没读者了,唤醒写者
if (readers == 0) {
_gate2.notify_one();
}
}
}
bool shared_mutex::try_lock_shared() {
std::unique_lock<std::mutex> lk{_mut};
if (no_writer_no_max_reader()) {
++_state;
return true;
}
return false;
}
shared_mutex::shared_mutex() noexcept : _state(0) {
}
shared_mutex::~shared_mutex() {
// 在这里等待所有写者和读者退出,并且禁止读者进入
std::unique_lock<std::mutex> lk{_mut};
_gate1.wait(lk, std::bind(&shared_mutex::no_writer, this));
// 然后等待读者出去
_state |= _writer_entered;
_gate2.wait(lk, std::bind(&shared_mutex::no_readers, this));
// 然后结束了
}
// 两个工具类
template<typename Mutex>
class lock_guard {
private:
Mutex &m;
public:
explicit lock_guard(Mutex &_m);
~lock_guard();
};
template<typename Mutex>
lock_guard<Mutex>::lock_guard(Mutex &_m) : m(_m) {
m.lock();
}
template<typename Mutex>
lock_guard<Mutex>::~lock_guard() {
m.unlock();
}
template<typename Mutex>
class shared_lock_guard {
private:
Mutex &m;
public:
explicit shared_lock_guard(Mutex &_m);
~shared_lock_guard();
};
template<typename Mutex>
shared_lock_guard<Mutex>::shared_lock_guard(Mutex &_m) : m(_m) {
m.lock_shared();
}
template<typename Mutex>
shared_lock_guard<Mutex>::~shared_lock_guard() {
m.unlock_shared();
}
volatile int val = 0;
shared_mutex mut;
std::atomic_bool end{false};
void read(int id) {
while (!end) {
std::this_thread::sleep_for(std::chrono::milliseconds(10));
shared_lock_guard<shared_mutex> gd{mut};
printf("%d val = %d\n", id, val);
}
}
void write(int id) {
while (!end) {
std::this_thread::sleep_for(std::chrono::milliseconds(30));
lock_guard<shared_mutex> gd{mut};
++val;
printf("%d val add 1\n", id);
}
}
int main() {
std::vector<std::thread> ts;
// 线程集合
for (int i = 0; i < 7; ++i) {
ts.emplace_back(read, i);
}
for (int i = 0; i < 2; ++i) {
ts.emplace_back(write, i * 10);
}
std::this_thread::sleep_for(std::chrono::seconds(3));
end = true;
for (auto &t : ts) {
t.join();
}
return 0;
}