Chris@16
|
1 #ifndef BOOST_THREAD_V2_SHARED_MUTEX_HPP
|
Chris@16
|
2 #define BOOST_THREAD_V2_SHARED_MUTEX_HPP
|
Chris@16
|
3
|
Chris@16
|
4 // shared_mutex.hpp
|
Chris@16
|
5 //
|
Chris@16
|
6 // Copyright Howard Hinnant 2007-2010.
|
Chris@16
|
7 // Copyright Vicente J. Botet Escriba 2012.
|
Chris@16
|
8 //
|
Chris@16
|
9 // Distributed under the Boost Software License, Version 1.0. (See
|
Chris@16
|
10 // accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
11 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
12
|
Chris@16
|
13 /*
|
Chris@16
|
14 <shared_mutex> synopsis
|
Chris@16
|
15
|
Chris@16
|
16 namespace boost
|
Chris@16
|
17 {
|
Chris@16
|
18 namespace thread_v2
|
Chris@16
|
19 {
|
Chris@16
|
20
|
Chris@16
|
21 class shared_mutex
|
Chris@16
|
22 {
|
Chris@16
|
23 public:
|
Chris@16
|
24
|
Chris@16
|
25 shared_mutex();
|
Chris@16
|
26 ~shared_mutex();
|
Chris@16
|
27
|
Chris@16
|
28 shared_mutex(const shared_mutex&) = delete;
|
Chris@16
|
29 shared_mutex& operator=(const shared_mutex&) = delete;
|
Chris@16
|
30
|
Chris@16
|
31 // Exclusive ownership
|
Chris@16
|
32
|
Chris@16
|
33 void lock();
|
Chris@16
|
34 bool try_lock();
|
Chris@16
|
35 template <class Rep, class Period>
|
Chris@16
|
36 bool try_lock_for(const boost::chrono::duration<Rep, Period>& rel_time);
|
Chris@16
|
37 template <class Clock, class Duration>
|
Chris@16
|
38 bool
|
Chris@16
|
39 try_lock_until(
|
Chris@16
|
40 const boost::chrono::time_point<Clock, Duration>& abs_time);
|
Chris@16
|
41 void unlock();
|
Chris@16
|
42
|
Chris@16
|
43 // Shared ownership
|
Chris@16
|
44
|
Chris@16
|
45 void lock_shared();
|
Chris@16
|
46 bool try_lock_shared();
|
Chris@16
|
47 template <class Rep, class Period>
|
Chris@16
|
48 bool
|
Chris@16
|
49 try_lock_shared_for(const boost::chrono::duration<Rep, Period>& rel_time);
|
Chris@16
|
50 template <class Clock, class Duration>
|
Chris@16
|
51 bool
|
Chris@16
|
52 try_lock_shared_until(
|
Chris@16
|
53 const boost::chrono::time_point<Clock, Duration>& abs_time);
|
Chris@16
|
54 void unlock_shared();
|
Chris@16
|
55 };
|
Chris@16
|
56
|
Chris@16
|
57 class upgrade_mutex
|
Chris@16
|
58 {
|
Chris@16
|
59 public:
|
Chris@16
|
60
|
Chris@16
|
61 upgrade_mutex();
|
Chris@16
|
62 ~upgrade_mutex();
|
Chris@16
|
63
|
Chris@16
|
64 upgrade_mutex(const upgrade_mutex&) = delete;
|
Chris@16
|
65 upgrade_mutex& operator=(const upgrade_mutex&) = delete;
|
Chris@16
|
66
|
Chris@16
|
67 // Exclusive ownership
|
Chris@16
|
68
|
Chris@16
|
69 void lock();
|
Chris@16
|
70 bool try_lock();
|
Chris@16
|
71 template <class Rep, class Period>
|
Chris@16
|
72 bool try_lock_for(const boost::chrono::duration<Rep, Period>& rel_time);
|
Chris@16
|
73 template <class Clock, class Duration>
|
Chris@16
|
74 bool
|
Chris@16
|
75 try_lock_until(
|
Chris@16
|
76 const boost::chrono::time_point<Clock, Duration>& abs_time);
|
Chris@16
|
77 void unlock();
|
Chris@16
|
78
|
Chris@16
|
79 // Shared ownership
|
Chris@16
|
80
|
Chris@16
|
81 void lock_shared();
|
Chris@16
|
82 bool try_lock_shared();
|
Chris@16
|
83 template <class Rep, class Period>
|
Chris@16
|
84 bool
|
Chris@16
|
85 try_lock_shared_for(const boost::chrono::duration<Rep, Period>& rel_time);
|
Chris@16
|
86 template <class Clock, class Duration>
|
Chris@16
|
87 bool
|
Chris@16
|
88 try_lock_shared_until(
|
Chris@16
|
89 const boost::chrono::time_point<Clock, Duration>& abs_time);
|
Chris@16
|
90 void unlock_shared();
|
Chris@16
|
91
|
Chris@16
|
92 // Upgrade ownership
|
Chris@16
|
93
|
Chris@16
|
94 void lock_upgrade();
|
Chris@16
|
95 bool try_lock_upgrade();
|
Chris@16
|
96 template <class Rep, class Period>
|
Chris@16
|
97 bool
|
Chris@16
|
98 try_lock_upgrade_for(
|
Chris@16
|
99 const boost::chrono::duration<Rep, Period>& rel_time);
|
Chris@16
|
100 template <class Clock, class Duration>
|
Chris@16
|
101 bool
|
Chris@16
|
102 try_lock_upgrade_until(
|
Chris@16
|
103 const boost::chrono::time_point<Clock, Duration>& abs_time);
|
Chris@16
|
104 void unlock_upgrade();
|
Chris@16
|
105
|
Chris@16
|
106 // Shared <-> Exclusive
|
Chris@16
|
107
|
Chris@16
|
108 bool try_unlock_shared_and_lock();
|
Chris@16
|
109 template <class Rep, class Period>
|
Chris@16
|
110 bool
|
Chris@16
|
111 try_unlock_shared_and_lock_for(
|
Chris@16
|
112 const boost::chrono::duration<Rep, Period>& rel_time);
|
Chris@16
|
113 template <class Clock, class Duration>
|
Chris@16
|
114 bool
|
Chris@16
|
115 try_unlock_shared_and_lock_until(
|
Chris@16
|
116 const boost::chrono::time_point<Clock, Duration>& abs_time);
|
Chris@16
|
117 void unlock_and_lock_shared();
|
Chris@16
|
118
|
Chris@16
|
119 // Shared <-> Upgrade
|
Chris@16
|
120
|
Chris@16
|
121 bool try_unlock_shared_and_lock_upgrade();
|
Chris@16
|
122 template <class Rep, class Period>
|
Chris@16
|
123 bool
|
Chris@16
|
124 try_unlock_shared_and_lock_upgrade_for(
|
Chris@16
|
125 const boost::chrono::duration<Rep, Period>& rel_time);
|
Chris@16
|
126 template <class Clock, class Duration>
|
Chris@16
|
127 bool
|
Chris@16
|
128 try_unlock_shared_and_lock_upgrade_until(
|
Chris@16
|
129 const boost::chrono::time_point<Clock, Duration>& abs_time);
|
Chris@16
|
130 void unlock_upgrade_and_lock_shared();
|
Chris@16
|
131
|
Chris@16
|
132 // Upgrade <-> Exclusive
|
Chris@16
|
133
|
Chris@16
|
134 void unlock_upgrade_and_lock();
|
Chris@16
|
135 bool try_unlock_upgrade_and_lock();
|
Chris@16
|
136 template <class Rep, class Period>
|
Chris@16
|
137 bool
|
Chris@16
|
138 try_unlock_upgrade_and_lock_for(
|
Chris@16
|
139 const boost::chrono::duration<Rep, Period>& rel_time);
|
Chris@16
|
140 template <class Clock, class Duration>
|
Chris@16
|
141 bool
|
Chris@16
|
142 try_unlock_upgrade_and_lock_until(
|
Chris@16
|
143 const boost::chrono::time_point<Clock, Duration>& abs_time);
|
Chris@16
|
144 void unlock_and_lock_upgrade();
|
Chris@16
|
145 };
|
Chris@16
|
146
|
Chris@16
|
147 } // thread_v2
|
Chris@16
|
148 } // boost
|
Chris@16
|
149
|
Chris@16
|
150 */
|
Chris@16
|
151
|
Chris@16
|
152 #include <boost/thread/detail/config.hpp>
|
Chris@16
|
153 #include <boost/thread/mutex.hpp>
|
Chris@16
|
154 #include <boost/thread/condition_variable.hpp>
|
Chris@16
|
155 #include <boost/thread/mutex.hpp>
|
Chris@16
|
156 #include <boost/chrono.hpp>
|
Chris@16
|
157 #include <climits>
|
Chris@16
|
158 #include <boost/system/system_error.hpp>
|
Chris@16
|
159 #define BOOST_THREAD_INLINE inline
|
Chris@16
|
160
|
Chris@16
|
161 namespace boost {
|
Chris@16
|
162 namespace thread_v2 {
|
Chris@16
|
163
|
Chris@16
|
164 class shared_mutex
|
Chris@16
|
165 {
|
Chris@16
|
166 typedef ::boost::mutex mutex_t;
|
Chris@16
|
167 typedef ::boost::condition_variable cond_t;
|
Chris@16
|
168 typedef unsigned count_t;
|
Chris@16
|
169
|
Chris@16
|
170 mutex_t mut_;
|
Chris@16
|
171 cond_t gate1_;
|
Chris@16
|
172 cond_t gate2_;
|
Chris@16
|
173 count_t state_;
|
Chris@16
|
174
|
Chris@16
|
175 static const count_t write_entered_ = 1U << (sizeof(count_t)*CHAR_BIT - 1);
|
Chris@16
|
176 static const count_t n_readers_ = ~write_entered_;
|
Chris@16
|
177
|
Chris@16
|
178 public:
|
Chris@16
|
179 BOOST_THREAD_INLINE shared_mutex();
|
Chris@16
|
180 BOOST_THREAD_INLINE ~shared_mutex();
|
Chris@16
|
181
|
Chris@16
|
182 #ifndef BOOST_NO_CXX11_DELETED_FUNCTIONS
|
Chris@16
|
183 shared_mutex(shared_mutex const&) = delete;
|
Chris@16
|
184 shared_mutex& operator=(shared_mutex const&) = delete;
|
Chris@16
|
185 #else // BOOST_NO_CXX11_DELETED_FUNCTIONS
|
Chris@16
|
186 private:
|
Chris@16
|
187 shared_mutex(shared_mutex const&);
|
Chris@16
|
188 shared_mutex& operator=(shared_mutex const&);
|
Chris@16
|
189 public:
|
Chris@16
|
190 #endif // BOOST_NO_CXX11_DELETED_FUNCTIONS
|
Chris@16
|
191
|
Chris@16
|
192 // Exclusive ownership
|
Chris@16
|
193
|
Chris@16
|
194 BOOST_THREAD_INLINE void lock();
|
Chris@16
|
195 BOOST_THREAD_INLINE bool try_lock();
|
Chris@16
|
196 template <class Rep, class Period>
|
Chris@16
|
197 bool try_lock_for(const boost::chrono::duration<Rep, Period>& rel_time)
|
Chris@16
|
198 {
|
Chris@16
|
199 return try_lock_until(boost::chrono::steady_clock::now() + rel_time);
|
Chris@16
|
200 }
|
Chris@16
|
201 template <class Clock, class Duration>
|
Chris@16
|
202 bool
|
Chris@16
|
203 try_lock_until(
|
Chris@16
|
204 const boost::chrono::time_point<Clock, Duration>& abs_time);
|
Chris@16
|
205 BOOST_THREAD_INLINE void unlock();
|
Chris@16
|
206
|
Chris@16
|
207
|
Chris@16
|
208 // Shared ownership
|
Chris@16
|
209
|
Chris@16
|
210 BOOST_THREAD_INLINE void lock_shared();
|
Chris@16
|
211 BOOST_THREAD_INLINE bool try_lock_shared();
|
Chris@16
|
212 template <class Rep, class Period>
|
Chris@16
|
213 bool
|
Chris@16
|
214 try_lock_shared_for(const boost::chrono::duration<Rep, Period>& rel_time)
|
Chris@16
|
215 {
|
Chris@16
|
216 return try_lock_shared_until(boost::chrono::steady_clock::now() +
|
Chris@16
|
217 rel_time);
|
Chris@16
|
218 }
|
Chris@16
|
219 template <class Clock, class Duration>
|
Chris@16
|
220 bool
|
Chris@16
|
221 try_lock_shared_until(
|
Chris@16
|
222 const boost::chrono::time_point<Clock, Duration>& abs_time);
|
Chris@16
|
223 BOOST_THREAD_INLINE void unlock_shared();
|
Chris@16
|
224
|
Chris@16
|
225 #if defined BOOST_THREAD_USES_DATETIME
|
Chris@16
|
226 bool timed_lock(system_time const& timeout);
|
Chris@16
|
227 template<typename TimeDuration>
|
Chris@16
|
228 bool timed_lock(TimeDuration const & relative_time)
|
Chris@16
|
229 {
|
Chris@16
|
230 return timed_lock(get_system_time()+relative_time);
|
Chris@16
|
231 }
|
Chris@16
|
232 bool timed_lock_shared(system_time const& timeout);
|
Chris@16
|
233 template<typename TimeDuration>
|
Chris@16
|
234 bool timed_lock_shared(TimeDuration const & relative_time)
|
Chris@16
|
235 {
|
Chris@16
|
236 return timed_lock_shared(get_system_time()+relative_time);
|
Chris@16
|
237 }
|
Chris@16
|
238 #endif
|
Chris@16
|
239 };
|
Chris@16
|
240
|
Chris@16
|
241 template <class Clock, class Duration>
|
Chris@16
|
242 bool
|
Chris@16
|
243 shared_mutex::try_lock_until(
|
Chris@16
|
244 const boost::chrono::time_point<Clock, Duration>& abs_time)
|
Chris@16
|
245 {
|
Chris@16
|
246 boost::unique_lock<mutex_t> lk(mut_);
|
Chris@16
|
247 if (state_ & write_entered_)
|
Chris@16
|
248 {
|
Chris@16
|
249 while (true)
|
Chris@16
|
250 {
|
Chris@16
|
251 boost::cv_status status = gate1_.wait_until(lk, abs_time);
|
Chris@16
|
252 if ((state_ & write_entered_) == 0)
|
Chris@16
|
253 break;
|
Chris@16
|
254 if (status == boost::cv_status::timeout)
|
Chris@16
|
255 return false;
|
Chris@16
|
256 }
|
Chris@16
|
257 }
|
Chris@16
|
258 state_ |= write_entered_;
|
Chris@16
|
259 if (state_ & n_readers_)
|
Chris@16
|
260 {
|
Chris@16
|
261 while (true)
|
Chris@16
|
262 {
|
Chris@16
|
263 boost::cv_status status = gate2_.wait_until(lk, abs_time);
|
Chris@16
|
264 if ((state_ & n_readers_) == 0)
|
Chris@16
|
265 break;
|
Chris@16
|
266 if (status == boost::cv_status::timeout)
|
Chris@16
|
267 {
|
Chris@16
|
268 state_ &= ~write_entered_;
|
Chris@16
|
269 return false;
|
Chris@16
|
270 }
|
Chris@16
|
271 }
|
Chris@16
|
272 }
|
Chris@16
|
273 return true;
|
Chris@16
|
274 }
|
Chris@16
|
275
|
Chris@16
|
276 template <class Clock, class Duration>
|
Chris@16
|
277 bool
|
Chris@16
|
278 shared_mutex::try_lock_shared_until(
|
Chris@16
|
279 const boost::chrono::time_point<Clock, Duration>& abs_time)
|
Chris@16
|
280 {
|
Chris@16
|
281 boost::unique_lock<mutex_t> lk(mut_);
|
Chris@16
|
282 if ((state_ & write_entered_) || (state_ & n_readers_) == n_readers_)
|
Chris@16
|
283 {
|
Chris@16
|
284 while (true)
|
Chris@16
|
285 {
|
Chris@16
|
286 boost::cv_status status = gate1_.wait_until(lk, abs_time);
|
Chris@16
|
287 if ((state_ & write_entered_) == 0 &&
|
Chris@16
|
288 (state_ & n_readers_) < n_readers_)
|
Chris@16
|
289 break;
|
Chris@16
|
290 if (status == boost::cv_status::timeout)
|
Chris@16
|
291 return false;
|
Chris@16
|
292 }
|
Chris@16
|
293 }
|
Chris@16
|
294 count_t num_readers = (state_ & n_readers_) + 1;
|
Chris@16
|
295 state_ &= ~n_readers_;
|
Chris@16
|
296 state_ |= num_readers;
|
Chris@16
|
297 return true;
|
Chris@16
|
298 }
|
Chris@16
|
299
|
Chris@16
|
300 #if defined BOOST_THREAD_USES_DATETIME
|
Chris@16
|
301 bool shared_mutex::timed_lock(system_time const& abs_time)
|
Chris@16
|
302 {
|
Chris@16
|
303 boost::unique_lock<mutex_t> lk(mut_);
|
Chris@16
|
304 if (state_ & write_entered_)
|
Chris@16
|
305 {
|
Chris@16
|
306 while (true)
|
Chris@16
|
307 {
|
Chris@16
|
308 bool status = gate1_.timed_wait(lk, abs_time);
|
Chris@16
|
309 if ((state_ & write_entered_) == 0)
|
Chris@16
|
310 break;
|
Chris@16
|
311 if (!status)
|
Chris@16
|
312 return false;
|
Chris@16
|
313 }
|
Chris@16
|
314 }
|
Chris@16
|
315 state_ |= write_entered_;
|
Chris@16
|
316 if (state_ & n_readers_)
|
Chris@16
|
317 {
|
Chris@16
|
318 while (true)
|
Chris@16
|
319 {
|
Chris@16
|
320 bool status = gate2_.timed_wait(lk, abs_time);
|
Chris@16
|
321 if ((state_ & n_readers_) == 0)
|
Chris@16
|
322 break;
|
Chris@16
|
323 if (!status)
|
Chris@16
|
324 {
|
Chris@16
|
325 state_ &= ~write_entered_;
|
Chris@16
|
326 return false;
|
Chris@16
|
327 }
|
Chris@16
|
328 }
|
Chris@16
|
329 }
|
Chris@16
|
330 return true;
|
Chris@16
|
331 }
|
Chris@16
|
332 bool shared_mutex::timed_lock_shared(system_time const& abs_time)
|
Chris@16
|
333 {
|
Chris@16
|
334 boost::unique_lock<mutex_t> lk(mut_);
|
Chris@16
|
335 if (state_ & write_entered_)
|
Chris@16
|
336 {
|
Chris@16
|
337 while (true)
|
Chris@16
|
338 {
|
Chris@16
|
339 bool status = gate1_.timed_wait(lk, abs_time);
|
Chris@16
|
340 if ((state_ & write_entered_) == 0)
|
Chris@16
|
341 break;
|
Chris@16
|
342 if (!status )
|
Chris@16
|
343 return false;
|
Chris@16
|
344 }
|
Chris@16
|
345 }
|
Chris@16
|
346 state_ |= write_entered_;
|
Chris@16
|
347 if (state_ & n_readers_)
|
Chris@16
|
348 {
|
Chris@16
|
349 while (true)
|
Chris@16
|
350 {
|
Chris@16
|
351 bool status = gate2_.timed_wait(lk, abs_time);
|
Chris@16
|
352 if ((state_ & n_readers_) == 0)
|
Chris@16
|
353 break;
|
Chris@16
|
354 if (!status)
|
Chris@16
|
355 {
|
Chris@16
|
356 state_ &= ~write_entered_;
|
Chris@16
|
357 return false;
|
Chris@16
|
358 }
|
Chris@16
|
359 }
|
Chris@16
|
360 }
|
Chris@16
|
361 return true;
|
Chris@16
|
362 }
|
Chris@16
|
363 #endif
|
Chris@16
|
364 class upgrade_mutex
|
Chris@16
|
365 {
|
Chris@16
|
366 typedef boost::mutex mutex_t;
|
Chris@16
|
367 typedef boost::condition_variable cond_t;
|
Chris@16
|
368 typedef unsigned count_t;
|
Chris@16
|
369
|
Chris@16
|
370 mutex_t mut_;
|
Chris@16
|
371 cond_t gate1_;
|
Chris@16
|
372 cond_t gate2_;
|
Chris@16
|
373 count_t state_;
|
Chris@16
|
374
|
Chris@16
|
375 static const unsigned write_entered_ = 1U << (sizeof(count_t)*CHAR_BIT - 1);
|
Chris@16
|
376 static const unsigned upgradable_entered_ = write_entered_ >> 1;
|
Chris@16
|
377 static const unsigned n_readers_ = ~(write_entered_ | upgradable_entered_);
|
Chris@16
|
378
|
Chris@16
|
379 public:
|
Chris@16
|
380
|
Chris@16
|
381 BOOST_THREAD_INLINE upgrade_mutex();
|
Chris@16
|
382 BOOST_THREAD_INLINE ~upgrade_mutex();
|
Chris@16
|
383
|
Chris@16
|
384 #ifndef BOOST_CXX11_NO_DELETED_FUNCTIONS
|
Chris@16
|
385 upgrade_mutex(const upgrade_mutex&) = delete;
|
Chris@16
|
386 upgrade_mutex& operator=(const upgrade_mutex&) = delete;
|
Chris@16
|
387 #else // BOOST_CXX11_NO_DELETED_FUNCTIONS
|
Chris@16
|
388 private:
|
Chris@16
|
389 upgrade_mutex(const upgrade_mutex&);
|
Chris@16
|
390 upgrade_mutex& operator=(const upgrade_mutex&);
|
Chris@16
|
391 public:
|
Chris@16
|
392 #endif // BOOST_CXX11_NO_DELETED_FUNCTIONS
|
Chris@16
|
393
|
Chris@16
|
394 // Exclusive ownership
|
Chris@16
|
395
|
Chris@16
|
396 BOOST_THREAD_INLINE void lock();
|
Chris@16
|
397 BOOST_THREAD_INLINE bool try_lock();
|
Chris@16
|
398 template <class Rep, class Period>
|
Chris@16
|
399 bool try_lock_for(const boost::chrono::duration<Rep, Period>& rel_time)
|
Chris@16
|
400 {
|
Chris@16
|
401 return try_lock_until(boost::chrono::steady_clock::now() + rel_time);
|
Chris@16
|
402 }
|
Chris@16
|
403 template <class Clock, class Duration>
|
Chris@16
|
404 bool
|
Chris@16
|
405 try_lock_until(
|
Chris@16
|
406 const boost::chrono::time_point<Clock, Duration>& abs_time);
|
Chris@16
|
407 BOOST_THREAD_INLINE void unlock();
|
Chris@16
|
408
|
Chris@16
|
409 // Shared ownership
|
Chris@16
|
410
|
Chris@16
|
411 BOOST_THREAD_INLINE void lock_shared();
|
Chris@16
|
412 BOOST_THREAD_INLINE bool try_lock_shared();
|
Chris@16
|
413 template <class Rep, class Period>
|
Chris@16
|
414 bool
|
Chris@16
|
415 try_lock_shared_for(const boost::chrono::duration<Rep, Period>& rel_time)
|
Chris@16
|
416 {
|
Chris@16
|
417 return try_lock_shared_until(boost::chrono::steady_clock::now() +
|
Chris@16
|
418 rel_time);
|
Chris@16
|
419 }
|
Chris@16
|
420 template <class Clock, class Duration>
|
Chris@16
|
421 bool
|
Chris@16
|
422 try_lock_shared_until(
|
Chris@16
|
423 const boost::chrono::time_point<Clock, Duration>& abs_time);
|
Chris@16
|
424 BOOST_THREAD_INLINE void unlock_shared();
|
Chris@16
|
425
|
Chris@16
|
426 // Upgrade ownership
|
Chris@16
|
427
|
Chris@16
|
428 BOOST_THREAD_INLINE void lock_upgrade();
|
Chris@16
|
429 BOOST_THREAD_INLINE bool try_lock_upgrade();
|
Chris@16
|
430 template <class Rep, class Period>
|
Chris@16
|
431 bool
|
Chris@16
|
432 try_lock_upgrade_for(
|
Chris@16
|
433 const boost::chrono::duration<Rep, Period>& rel_time)
|
Chris@16
|
434 {
|
Chris@16
|
435 return try_lock_upgrade_until(boost::chrono::steady_clock::now() +
|
Chris@16
|
436 rel_time);
|
Chris@16
|
437 }
|
Chris@16
|
438 template <class Clock, class Duration>
|
Chris@16
|
439 bool
|
Chris@16
|
440 try_lock_upgrade_until(
|
Chris@16
|
441 const boost::chrono::time_point<Clock, Duration>& abs_time);
|
Chris@16
|
442 BOOST_THREAD_INLINE void unlock_upgrade();
|
Chris@16
|
443
|
Chris@16
|
444 // Shared <-> Exclusive
|
Chris@16
|
445
|
Chris@16
|
446 BOOST_THREAD_INLINE bool try_unlock_shared_and_lock();
|
Chris@16
|
447 template <class Rep, class Period>
|
Chris@16
|
448 bool
|
Chris@16
|
449 try_unlock_shared_and_lock_for(
|
Chris@16
|
450 const boost::chrono::duration<Rep, Period>& rel_time)
|
Chris@16
|
451 {
|
Chris@16
|
452 return try_unlock_shared_and_lock_until(
|
Chris@16
|
453 boost::chrono::steady_clock::now() + rel_time);
|
Chris@16
|
454 }
|
Chris@16
|
455 template <class Clock, class Duration>
|
Chris@16
|
456 bool
|
Chris@16
|
457 try_unlock_shared_and_lock_until(
|
Chris@16
|
458 const boost::chrono::time_point<Clock, Duration>& abs_time);
|
Chris@16
|
459 BOOST_THREAD_INLINE void unlock_and_lock_shared();
|
Chris@16
|
460
|
Chris@16
|
461 // Shared <-> Upgrade
|
Chris@16
|
462
|
Chris@16
|
463 BOOST_THREAD_INLINE bool try_unlock_shared_and_lock_upgrade();
|
Chris@16
|
464 template <class Rep, class Period>
|
Chris@16
|
465 bool
|
Chris@16
|
466 try_unlock_shared_and_lock_upgrade_for(
|
Chris@16
|
467 const boost::chrono::duration<Rep, Period>& rel_time)
|
Chris@16
|
468 {
|
Chris@16
|
469 return try_unlock_shared_and_lock_upgrade_until(
|
Chris@16
|
470 boost::chrono::steady_clock::now() + rel_time);
|
Chris@16
|
471 }
|
Chris@16
|
472 template <class Clock, class Duration>
|
Chris@16
|
473 bool
|
Chris@16
|
474 try_unlock_shared_and_lock_upgrade_until(
|
Chris@16
|
475 const boost::chrono::time_point<Clock, Duration>& abs_time);
|
Chris@16
|
476 BOOST_THREAD_INLINE void unlock_upgrade_and_lock_shared();
|
Chris@16
|
477
|
Chris@16
|
478 // Upgrade <-> Exclusive
|
Chris@16
|
479
|
Chris@16
|
480 BOOST_THREAD_INLINE void unlock_upgrade_and_lock();
|
Chris@16
|
481 BOOST_THREAD_INLINE bool try_unlock_upgrade_and_lock();
|
Chris@16
|
482 template <class Rep, class Period>
|
Chris@16
|
483 bool
|
Chris@16
|
484 try_unlock_upgrade_and_lock_for(
|
Chris@16
|
485 const boost::chrono::duration<Rep, Period>& rel_time)
|
Chris@16
|
486 {
|
Chris@16
|
487 return try_unlock_upgrade_and_lock_until(
|
Chris@16
|
488 boost::chrono::steady_clock::now() + rel_time);
|
Chris@16
|
489 }
|
Chris@16
|
490 template <class Clock, class Duration>
|
Chris@16
|
491 bool
|
Chris@16
|
492 try_unlock_upgrade_and_lock_until(
|
Chris@16
|
493 const boost::chrono::time_point<Clock, Duration>& abs_time);
|
Chris@16
|
494 BOOST_THREAD_INLINE void unlock_and_lock_upgrade();
|
Chris@16
|
495
|
Chris@16
|
496 #if defined BOOST_THREAD_USES_DATETIME
|
Chris@16
|
497 inline bool timed_lock(system_time const& abs_time);
|
Chris@16
|
498 template<typename TimeDuration>
|
Chris@16
|
499 bool timed_lock(TimeDuration const & relative_time)
|
Chris@16
|
500 {
|
Chris@16
|
501 return timed_lock(get_system_time()+relative_time);
|
Chris@16
|
502 }
|
Chris@16
|
503 inline bool timed_lock_shared(system_time const& abs_time);
|
Chris@16
|
504 template<typename TimeDuration>
|
Chris@16
|
505 bool timed_lock_shared(TimeDuration const & relative_time)
|
Chris@16
|
506 {
|
Chris@16
|
507 return timed_lock_shared(get_system_time()+relative_time);
|
Chris@16
|
508 }
|
Chris@16
|
509 inline bool timed_lock_upgrade(system_time const& abs_time);
|
Chris@16
|
510 template<typename TimeDuration>
|
Chris@16
|
511 bool timed_lock_upgrade(TimeDuration const & relative_time)
|
Chris@16
|
512 {
|
Chris@16
|
513 return timed_lock_upgrade(get_system_time()+relative_time);
|
Chris@16
|
514 }
|
Chris@16
|
515 #endif
|
Chris@16
|
516
|
Chris@16
|
517 };
|
Chris@16
|
518
|
Chris@16
|
519 template <class Clock, class Duration>
|
Chris@16
|
520 bool
|
Chris@16
|
521 upgrade_mutex::try_lock_until(
|
Chris@16
|
522 const boost::chrono::time_point<Clock, Duration>& abs_time)
|
Chris@16
|
523 {
|
Chris@16
|
524 boost::unique_lock<mutex_t> lk(mut_);
|
Chris@16
|
525 if (state_ & (write_entered_ | upgradable_entered_))
|
Chris@16
|
526 {
|
Chris@16
|
527 while (true)
|
Chris@16
|
528 {
|
Chris@16
|
529 boost::cv_status status = gate1_.wait_until(lk, abs_time);
|
Chris@16
|
530 if ((state_ & (write_entered_ | upgradable_entered_)) == 0)
|
Chris@16
|
531 break;
|
Chris@16
|
532 if (status == boost::cv_status::timeout)
|
Chris@16
|
533 return false;
|
Chris@16
|
534 }
|
Chris@16
|
535 }
|
Chris@16
|
536 state_ |= write_entered_;
|
Chris@16
|
537 if (state_ & n_readers_)
|
Chris@16
|
538 {
|
Chris@16
|
539 while (true)
|
Chris@16
|
540 {
|
Chris@16
|
541 boost::cv_status status = gate2_.wait_until(lk, abs_time);
|
Chris@16
|
542 if ((state_ & n_readers_) == 0)
|
Chris@16
|
543 break;
|
Chris@16
|
544 if (status == boost::cv_status::timeout)
|
Chris@16
|
545 {
|
Chris@16
|
546 state_ &= ~write_entered_;
|
Chris@16
|
547 return false;
|
Chris@16
|
548 }
|
Chris@16
|
549 }
|
Chris@16
|
550 }
|
Chris@16
|
551 return true;
|
Chris@16
|
552 }
|
Chris@16
|
553
|
Chris@16
|
554 template <class Clock, class Duration>
|
Chris@16
|
555 bool
|
Chris@16
|
556 upgrade_mutex::try_lock_shared_until(
|
Chris@16
|
557 const boost::chrono::time_point<Clock, Duration>& abs_time)
|
Chris@16
|
558 {
|
Chris@16
|
559 boost::unique_lock<mutex_t> lk(mut_);
|
Chris@16
|
560 if ((state_ & write_entered_) || (state_ & n_readers_) == n_readers_)
|
Chris@16
|
561 {
|
Chris@16
|
562 while (true)
|
Chris@16
|
563 {
|
Chris@16
|
564 boost::cv_status status = gate1_.wait_until(lk, abs_time);
|
Chris@16
|
565 if ((state_ & write_entered_) == 0 &&
|
Chris@16
|
566 (state_ & n_readers_) < n_readers_)
|
Chris@16
|
567 break;
|
Chris@16
|
568 if (status == boost::cv_status::timeout)
|
Chris@16
|
569 return false;
|
Chris@16
|
570 }
|
Chris@16
|
571 }
|
Chris@16
|
572 count_t num_readers = (state_ & n_readers_) + 1;
|
Chris@16
|
573 state_ &= ~n_readers_;
|
Chris@16
|
574 state_ |= num_readers;
|
Chris@16
|
575 return true;
|
Chris@16
|
576 }
|
Chris@16
|
577
|
Chris@16
|
578 template <class Clock, class Duration>
|
Chris@16
|
579 bool
|
Chris@16
|
580 upgrade_mutex::try_lock_upgrade_until(
|
Chris@16
|
581 const boost::chrono::time_point<Clock, Duration>& abs_time)
|
Chris@16
|
582 {
|
Chris@16
|
583 boost::unique_lock<mutex_t> lk(mut_);
|
Chris@16
|
584 if ((state_ & (write_entered_ | upgradable_entered_)) ||
|
Chris@16
|
585 (state_ & n_readers_) == n_readers_)
|
Chris@16
|
586 {
|
Chris@16
|
587 while (true)
|
Chris@16
|
588 {
|
Chris@16
|
589 boost::cv_status status = gate1_.wait_until(lk, abs_time);
|
Chris@16
|
590 if ((state_ & (write_entered_ | upgradable_entered_)) == 0 &&
|
Chris@16
|
591 (state_ & n_readers_) < n_readers_)
|
Chris@16
|
592 break;
|
Chris@16
|
593 if (status == boost::cv_status::timeout)
|
Chris@16
|
594 return false;
|
Chris@16
|
595 }
|
Chris@16
|
596 }
|
Chris@16
|
597 count_t num_readers = (state_ & n_readers_) + 1;
|
Chris@16
|
598 state_ &= ~n_readers_;
|
Chris@16
|
599 state_ |= upgradable_entered_ | num_readers;
|
Chris@16
|
600 return true;
|
Chris@16
|
601 }
|
Chris@16
|
602
|
Chris@16
|
603 #if defined BOOST_THREAD_USES_DATETIME
|
Chris@16
|
604 bool upgrade_mutex::timed_lock(system_time const& abs_time)
|
Chris@16
|
605 {
|
Chris@16
|
606 boost::unique_lock<mutex_t> lk(mut_);
|
Chris@16
|
607 if (state_ & (write_entered_ | upgradable_entered_))
|
Chris@16
|
608 {
|
Chris@16
|
609 while (true)
|
Chris@16
|
610 {
|
Chris@16
|
611 bool status = gate1_.timed_wait(lk, abs_time);
|
Chris@16
|
612 if ((state_ & (write_entered_ | upgradable_entered_)) == 0)
|
Chris@16
|
613 break;
|
Chris@16
|
614 if (!status)
|
Chris@16
|
615 return false;
|
Chris@16
|
616 }
|
Chris@16
|
617 }
|
Chris@16
|
618 state_ |= write_entered_;
|
Chris@16
|
619 if (state_ & n_readers_)
|
Chris@16
|
620 {
|
Chris@16
|
621 while (true)
|
Chris@16
|
622 {
|
Chris@16
|
623 bool status = gate2_.timed_wait(lk, abs_time);
|
Chris@16
|
624 if ((state_ & n_readers_) == 0)
|
Chris@16
|
625 break;
|
Chris@16
|
626 if (!status)
|
Chris@16
|
627 {
|
Chris@16
|
628 state_ &= ~write_entered_;
|
Chris@16
|
629 return false;
|
Chris@16
|
630 }
|
Chris@16
|
631 }
|
Chris@16
|
632 }
|
Chris@16
|
633 return true;
|
Chris@16
|
634 }
|
Chris@16
|
635 bool upgrade_mutex::timed_lock_shared(system_time const& abs_time)
|
Chris@16
|
636 {
|
Chris@16
|
637 boost::unique_lock<mutex_t> lk(mut_);
|
Chris@16
|
638 if ((state_ & write_entered_) || (state_ & n_readers_) == n_readers_)
|
Chris@16
|
639 {
|
Chris@16
|
640 while (true)
|
Chris@16
|
641 {
|
Chris@16
|
642 bool status = gate1_.timed_wait(lk, abs_time);
|
Chris@16
|
643 if ((state_ & write_entered_) == 0 &&
|
Chris@16
|
644 (state_ & n_readers_) < n_readers_)
|
Chris@16
|
645 break;
|
Chris@16
|
646 if (!status)
|
Chris@16
|
647 return false;
|
Chris@16
|
648 }
|
Chris@16
|
649 }
|
Chris@16
|
650 count_t num_readers = (state_ & n_readers_) + 1;
|
Chris@16
|
651 state_ &= ~n_readers_;
|
Chris@16
|
652 state_ |= num_readers;
|
Chris@16
|
653 return true;
|
Chris@16
|
654 }
|
Chris@16
|
655 bool upgrade_mutex::timed_lock_upgrade(system_time const& abs_time)
|
Chris@16
|
656 {
|
Chris@16
|
657 boost::unique_lock<mutex_t> lk(mut_);
|
Chris@16
|
658 if ((state_ & (write_entered_ | upgradable_entered_)) ||
|
Chris@16
|
659 (state_ & n_readers_) == n_readers_)
|
Chris@16
|
660 {
|
Chris@16
|
661 while (true)
|
Chris@16
|
662 {
|
Chris@16
|
663 bool status = gate1_.timed_wait(lk, abs_time);
|
Chris@16
|
664 if ((state_ & (write_entered_ | upgradable_entered_)) == 0 &&
|
Chris@16
|
665 (state_ & n_readers_) < n_readers_)
|
Chris@16
|
666 break;
|
Chris@16
|
667 if (!status)
|
Chris@16
|
668 return false;
|
Chris@16
|
669 }
|
Chris@16
|
670 }
|
Chris@16
|
671 count_t num_readers = (state_ & n_readers_) + 1;
|
Chris@16
|
672 state_ &= ~n_readers_;
|
Chris@16
|
673 state_ |= upgradable_entered_ | num_readers;
|
Chris@16
|
674 return true;
|
Chris@16
|
675 }
|
Chris@16
|
676
|
Chris@16
|
677 #endif
|
Chris@16
|
678 template <class Clock, class Duration>
|
Chris@16
|
679 bool
|
Chris@16
|
680 upgrade_mutex::try_unlock_shared_and_lock_until(
|
Chris@16
|
681 const boost::chrono::time_point<Clock, Duration>& abs_time)
|
Chris@16
|
682 {
|
Chris@16
|
683 boost::unique_lock<mutex_t> lk(mut_);
|
Chris@16
|
684 if (state_ != 1)
|
Chris@16
|
685 {
|
Chris@16
|
686 while (true)
|
Chris@16
|
687 {
|
Chris@16
|
688 boost::cv_status status = gate2_.wait_until(lk, abs_time);
|
Chris@16
|
689 if (state_ == 1)
|
Chris@16
|
690 break;
|
Chris@16
|
691 if (status == boost::cv_status::timeout)
|
Chris@16
|
692 return false;
|
Chris@16
|
693 }
|
Chris@16
|
694 }
|
Chris@16
|
695 state_ = write_entered_;
|
Chris@16
|
696 return true;
|
Chris@16
|
697 }
|
Chris@16
|
698
|
Chris@16
|
699 template <class Clock, class Duration>
|
Chris@16
|
700 bool
|
Chris@16
|
701 upgrade_mutex::try_unlock_shared_and_lock_upgrade_until(
|
Chris@16
|
702 const boost::chrono::time_point<Clock, Duration>& abs_time)
|
Chris@16
|
703 {
|
Chris@16
|
704 boost::unique_lock<mutex_t> lk(mut_);
|
Chris@16
|
705 if ((state_ & (write_entered_ | upgradable_entered_)) != 0)
|
Chris@16
|
706 {
|
Chris@16
|
707 while (true)
|
Chris@16
|
708 {
|
Chris@16
|
709 boost::cv_status status = gate2_.wait_until(lk, abs_time);
|
Chris@16
|
710 if ((state_ & (write_entered_ | upgradable_entered_)) == 0)
|
Chris@16
|
711 break;
|
Chris@16
|
712 if (status == boost::cv_status::timeout)
|
Chris@16
|
713 return false;
|
Chris@16
|
714 }
|
Chris@16
|
715 }
|
Chris@16
|
716 state_ |= upgradable_entered_;
|
Chris@16
|
717 return true;
|
Chris@16
|
718 }
|
Chris@16
|
719
|
Chris@16
|
720 template <class Clock, class Duration>
|
Chris@16
|
721 bool
|
Chris@16
|
722 upgrade_mutex::try_unlock_upgrade_and_lock_until(
|
Chris@16
|
723 const boost::chrono::time_point<Clock, Duration>& abs_time)
|
Chris@16
|
724 {
|
Chris@16
|
725 boost::unique_lock<mutex_t> lk(mut_);
|
Chris@16
|
726 if ((state_ & n_readers_) != 1)
|
Chris@16
|
727 {
|
Chris@16
|
728 while (true)
|
Chris@16
|
729 {
|
Chris@16
|
730 boost::cv_status status = gate2_.wait_until(lk, abs_time);
|
Chris@16
|
731 if ((state_ & n_readers_) == 1)
|
Chris@16
|
732 break;
|
Chris@16
|
733 if (status == boost::cv_status::timeout)
|
Chris@16
|
734 return false;
|
Chris@16
|
735 }
|
Chris@16
|
736 }
|
Chris@16
|
737 state_ = write_entered_;
|
Chris@16
|
738 return true;
|
Chris@16
|
739 }
|
Chris@16
|
740
|
Chris@16
|
741 //////
|
Chris@16
|
742 // shared_mutex
|
Chris@16
|
743
|
Chris@16
|
744 shared_mutex::shared_mutex()
|
Chris@16
|
745 : state_(0)
|
Chris@16
|
746 {
|
Chris@16
|
747 }
|
Chris@16
|
748
|
Chris@16
|
749 shared_mutex::~shared_mutex()
|
Chris@16
|
750 {
|
Chris@16
|
751 boost::lock_guard<mutex_t> _(mut_);
|
Chris@16
|
752 }
|
Chris@16
|
753
|
Chris@16
|
754 // Exclusive ownership
|
Chris@16
|
755
|
Chris@16
|
756 void
|
Chris@16
|
757 shared_mutex::lock()
|
Chris@16
|
758 {
|
Chris@16
|
759 boost::unique_lock<mutex_t> lk(mut_);
|
Chris@16
|
760 while (state_ & write_entered_)
|
Chris@16
|
761 gate1_.wait(lk);
|
Chris@16
|
762 state_ |= write_entered_;
|
Chris@16
|
763 while (state_ & n_readers_)
|
Chris@16
|
764 gate2_.wait(lk);
|
Chris@16
|
765 }
|
Chris@16
|
766
|
Chris@16
|
767 bool
|
Chris@16
|
768 shared_mutex::try_lock()
|
Chris@16
|
769 {
|
Chris@16
|
770 boost::unique_lock<mutex_t> lk(mut_);
|
Chris@16
|
771 if (state_ == 0)
|
Chris@16
|
772 {
|
Chris@16
|
773 state_ = write_entered_;
|
Chris@16
|
774 return true;
|
Chris@16
|
775 }
|
Chris@16
|
776 return false;
|
Chris@16
|
777 }
|
Chris@16
|
778
|
Chris@16
|
779 void
|
Chris@16
|
780 shared_mutex::unlock()
|
Chris@16
|
781 {
|
Chris@16
|
782 boost::lock_guard<mutex_t> _(mut_);
|
Chris@16
|
783 state_ = 0;
|
Chris@16
|
784 gate1_.notify_all();
|
Chris@16
|
785 }
|
Chris@16
|
786
|
Chris@16
|
787 // Shared ownership
|
Chris@16
|
788
|
Chris@16
|
789 void
|
Chris@16
|
790 shared_mutex::lock_shared()
|
Chris@16
|
791 {
|
Chris@16
|
792 boost::unique_lock<mutex_t> lk(mut_);
|
Chris@16
|
793 while ((state_ & write_entered_) || (state_ & n_readers_) == n_readers_)
|
Chris@16
|
794 gate1_.wait(lk);
|
Chris@16
|
795 count_t num_readers = (state_ & n_readers_) + 1;
|
Chris@16
|
796 state_ &= ~n_readers_;
|
Chris@16
|
797 state_ |= num_readers;
|
Chris@16
|
798 }
|
Chris@16
|
799
|
Chris@16
|
800 bool
|
Chris@16
|
801 shared_mutex::try_lock_shared()
|
Chris@16
|
802 {
|
Chris@16
|
803 boost::unique_lock<mutex_t> lk(mut_);
|
Chris@16
|
804 count_t num_readers = state_ & n_readers_;
|
Chris@16
|
805 if (!(state_ & write_entered_) && num_readers != n_readers_)
|
Chris@16
|
806 {
|
Chris@16
|
807 ++num_readers;
|
Chris@16
|
808 state_ &= ~n_readers_;
|
Chris@16
|
809 state_ |= num_readers;
|
Chris@16
|
810 return true;
|
Chris@16
|
811 }
|
Chris@16
|
812 return false;
|
Chris@16
|
813 }
|
Chris@16
|
814
|
Chris@16
|
815 void
|
Chris@16
|
816 shared_mutex::unlock_shared()
|
Chris@16
|
817 {
|
Chris@16
|
818 boost::lock_guard<mutex_t> _(mut_);
|
Chris@16
|
819 count_t num_readers = (state_ & n_readers_) - 1;
|
Chris@16
|
820 state_ &= ~n_readers_;
|
Chris@16
|
821 state_ |= num_readers;
|
Chris@16
|
822 if (state_ & write_entered_)
|
Chris@16
|
823 {
|
Chris@16
|
824 if (num_readers == 0)
|
Chris@16
|
825 gate2_.notify_one();
|
Chris@16
|
826 }
|
Chris@16
|
827 else
|
Chris@16
|
828 {
|
Chris@16
|
829 if (num_readers == n_readers_ - 1)
|
Chris@16
|
830 gate1_.notify_one();
|
Chris@16
|
831 }
|
Chris@16
|
832 }
|
Chris@16
|
833
|
Chris@16
|
834 // upgrade_mutex
|
Chris@16
|
835
|
Chris@16
|
836 upgrade_mutex::upgrade_mutex()
|
Chris@16
|
837 : gate1_(),
|
Chris@16
|
838 gate2_(),
|
Chris@16
|
839 state_(0)
|
Chris@16
|
840 {
|
Chris@16
|
841 }
|
Chris@16
|
842
|
Chris@16
|
843 upgrade_mutex::~upgrade_mutex()
|
Chris@16
|
844 {
|
Chris@16
|
845 boost::lock_guard<mutex_t> _(mut_);
|
Chris@16
|
846 }
|
Chris@16
|
847
|
Chris@16
|
848 // Exclusive ownership
|
Chris@16
|
849
|
Chris@16
|
850 void
|
Chris@16
|
851 upgrade_mutex::lock()
|
Chris@16
|
852 {
|
Chris@16
|
853 boost::unique_lock<mutex_t> lk(mut_);
|
Chris@16
|
854 while (state_ & (write_entered_ | upgradable_entered_))
|
Chris@16
|
855 gate1_.wait(lk);
|
Chris@16
|
856 state_ |= write_entered_;
|
Chris@16
|
857 while (state_ & n_readers_)
|
Chris@16
|
858 gate2_.wait(lk);
|
Chris@16
|
859 }
|
Chris@16
|
860
|
Chris@16
|
861 bool
|
Chris@16
|
862 upgrade_mutex::try_lock()
|
Chris@16
|
863 {
|
Chris@16
|
864 boost::unique_lock<mutex_t> lk(mut_);
|
Chris@16
|
865 if (state_ == 0)
|
Chris@16
|
866 {
|
Chris@16
|
867 state_ = write_entered_;
|
Chris@16
|
868 return true;
|
Chris@16
|
869 }
|
Chris@16
|
870 return false;
|
Chris@16
|
871 }
|
Chris@16
|
872
|
Chris@16
|
873 void
|
Chris@16
|
874 upgrade_mutex::unlock()
|
Chris@16
|
875 {
|
Chris@16
|
876 boost::lock_guard<mutex_t> _(mut_);
|
Chris@16
|
877 state_ = 0;
|
Chris@16
|
878 gate1_.notify_all();
|
Chris@16
|
879 }
|
Chris@16
|
880
|
Chris@16
|
881 // Shared ownership
|
Chris@16
|
882
|
Chris@16
|
883 void
|
Chris@16
|
884 upgrade_mutex::lock_shared()
|
Chris@16
|
885 {
|
Chris@16
|
886 boost::unique_lock<mutex_t> lk(mut_);
|
Chris@16
|
887 while ((state_ & write_entered_) || (state_ & n_readers_) == n_readers_)
|
Chris@16
|
888 gate1_.wait(lk);
|
Chris@16
|
889 count_t num_readers = (state_ & n_readers_) + 1;
|
Chris@16
|
890 state_ &= ~n_readers_;
|
Chris@16
|
891 state_ |= num_readers;
|
Chris@16
|
892 }
|
Chris@16
|
893
|
Chris@16
|
894 bool
|
Chris@16
|
895 upgrade_mutex::try_lock_shared()
|
Chris@16
|
896 {
|
Chris@16
|
897 boost::unique_lock<mutex_t> lk(mut_);
|
Chris@16
|
898 count_t num_readers = state_ & n_readers_;
|
Chris@16
|
899 if (!(state_ & write_entered_) && num_readers != n_readers_)
|
Chris@16
|
900 {
|
Chris@16
|
901 ++num_readers;
|
Chris@16
|
902 state_ &= ~n_readers_;
|
Chris@16
|
903 state_ |= num_readers;
|
Chris@16
|
904 return true;
|
Chris@16
|
905 }
|
Chris@16
|
906 return false;
|
Chris@16
|
907 }
|
Chris@16
|
908
|
Chris@16
|
909 void
|
Chris@16
|
910 upgrade_mutex::unlock_shared()
|
Chris@16
|
911 {
|
Chris@16
|
912 boost::lock_guard<mutex_t> _(mut_);
|
Chris@16
|
913 count_t num_readers = (state_ & n_readers_) - 1;
|
Chris@16
|
914 state_ &= ~n_readers_;
|
Chris@16
|
915 state_ |= num_readers;
|
Chris@16
|
916 if (state_ & write_entered_)
|
Chris@16
|
917 {
|
Chris@16
|
918 if (num_readers == 0)
|
Chris@16
|
919 gate2_.notify_one();
|
Chris@16
|
920 }
|
Chris@16
|
921 else
|
Chris@16
|
922 {
|
Chris@16
|
923 if (num_readers == n_readers_ - 1)
|
Chris@16
|
924 gate1_.notify_one();
|
Chris@16
|
925 }
|
Chris@16
|
926 }
|
Chris@16
|
927
|
Chris@16
|
928 // Upgrade ownership
|
Chris@16
|
929
|
Chris@16
|
930 void
|
Chris@16
|
931 upgrade_mutex::lock_upgrade()
|
Chris@16
|
932 {
|
Chris@16
|
933 boost::unique_lock<mutex_t> lk(mut_);
|
Chris@16
|
934 while ((state_ & (write_entered_ | upgradable_entered_)) ||
|
Chris@16
|
935 (state_ & n_readers_) == n_readers_)
|
Chris@16
|
936 gate1_.wait(lk);
|
Chris@16
|
937 count_t num_readers = (state_ & n_readers_) + 1;
|
Chris@16
|
938 state_ &= ~n_readers_;
|
Chris@16
|
939 state_ |= upgradable_entered_ | num_readers;
|
Chris@16
|
940 }
|
Chris@16
|
941
|
Chris@16
|
942 bool
|
Chris@16
|
943 upgrade_mutex::try_lock_upgrade()
|
Chris@16
|
944 {
|
Chris@16
|
945 boost::unique_lock<mutex_t> lk(mut_);
|
Chris@16
|
946 count_t num_readers = state_ & n_readers_;
|
Chris@16
|
947 if (!(state_ & (write_entered_ | upgradable_entered_))
|
Chris@16
|
948 && num_readers != n_readers_)
|
Chris@16
|
949 {
|
Chris@16
|
950 ++num_readers;
|
Chris@16
|
951 state_ &= ~n_readers_;
|
Chris@16
|
952 state_ |= upgradable_entered_ | num_readers;
|
Chris@16
|
953 return true;
|
Chris@16
|
954 }
|
Chris@16
|
955 return false;
|
Chris@16
|
956 }
|
Chris@16
|
957
|
Chris@16
|
958 void
|
Chris@16
|
959 upgrade_mutex::unlock_upgrade()
|
Chris@16
|
960 {
|
Chris@16
|
961 {
|
Chris@16
|
962 boost::lock_guard<mutex_t> _(mut_);
|
Chris@16
|
963 count_t num_readers = (state_ & n_readers_) - 1;
|
Chris@16
|
964 state_ &= ~(upgradable_entered_ | n_readers_);
|
Chris@16
|
965 state_ |= num_readers;
|
Chris@16
|
966 }
|
Chris@16
|
967 gate1_.notify_all();
|
Chris@16
|
968 }
|
Chris@16
|
969
|
Chris@16
|
970 // Shared <-> Exclusive
|
Chris@16
|
971
|
Chris@16
|
972 bool
|
Chris@16
|
973 upgrade_mutex::try_unlock_shared_and_lock()
|
Chris@16
|
974 {
|
Chris@16
|
975 boost::unique_lock<mutex_t> lk(mut_);
|
Chris@16
|
976 if (state_ == 1)
|
Chris@16
|
977 {
|
Chris@16
|
978 state_ = write_entered_;
|
Chris@16
|
979 return true;
|
Chris@16
|
980 }
|
Chris@16
|
981 return false;
|
Chris@16
|
982 }
|
Chris@16
|
983
|
Chris@16
|
984 void
|
Chris@16
|
985 upgrade_mutex::unlock_and_lock_shared()
|
Chris@16
|
986 {
|
Chris@16
|
987 {
|
Chris@16
|
988 boost::lock_guard<mutex_t> _(mut_);
|
Chris@16
|
989 state_ = 1;
|
Chris@16
|
990 }
|
Chris@16
|
991 gate1_.notify_all();
|
Chris@16
|
992 }
|
Chris@16
|
993
|
Chris@16
|
994 // Shared <-> Upgrade
|
Chris@16
|
995
|
Chris@16
|
996 bool
|
Chris@16
|
997 upgrade_mutex::try_unlock_shared_and_lock_upgrade()
|
Chris@16
|
998 {
|
Chris@16
|
999 boost::unique_lock<mutex_t> lk(mut_);
|
Chris@16
|
1000 if (!(state_ & (write_entered_ | upgradable_entered_)))
|
Chris@16
|
1001 {
|
Chris@16
|
1002 state_ |= upgradable_entered_;
|
Chris@16
|
1003 return true;
|
Chris@16
|
1004 }
|
Chris@16
|
1005 return false;
|
Chris@16
|
1006 }
|
Chris@16
|
1007
|
Chris@16
|
1008 void
|
Chris@16
|
1009 upgrade_mutex::unlock_upgrade_and_lock_shared()
|
Chris@16
|
1010 {
|
Chris@16
|
1011 {
|
Chris@16
|
1012 boost::lock_guard<mutex_t> _(mut_);
|
Chris@16
|
1013 state_ &= ~upgradable_entered_;
|
Chris@16
|
1014 }
|
Chris@16
|
1015 gate1_.notify_all();
|
Chris@16
|
1016 }
|
Chris@16
|
1017
|
Chris@16
|
1018 // Upgrade <-> Exclusive
|
Chris@16
|
1019
|
Chris@16
|
1020 void
|
Chris@16
|
1021 upgrade_mutex::unlock_upgrade_and_lock()
|
Chris@16
|
1022 {
|
Chris@16
|
1023 boost::unique_lock<mutex_t> lk(mut_);
|
Chris@16
|
1024 count_t num_readers = (state_ & n_readers_) - 1;
|
Chris@16
|
1025 state_ &= ~(upgradable_entered_ | n_readers_);
|
Chris@16
|
1026 state_ |= write_entered_ | num_readers;
|
Chris@16
|
1027 while (state_ & n_readers_)
|
Chris@16
|
1028 gate2_.wait(lk);
|
Chris@16
|
1029 }
|
Chris@16
|
1030
|
Chris@16
|
1031 bool
|
Chris@16
|
1032 upgrade_mutex::try_unlock_upgrade_and_lock()
|
Chris@16
|
1033 {
|
Chris@16
|
1034 boost::unique_lock<mutex_t> lk(mut_);
|
Chris@16
|
1035 if (state_ == (upgradable_entered_ | 1))
|
Chris@16
|
1036 {
|
Chris@16
|
1037 state_ = write_entered_;
|
Chris@16
|
1038 return true;
|
Chris@16
|
1039 }
|
Chris@16
|
1040 return false;
|
Chris@16
|
1041 }
|
Chris@16
|
1042
|
Chris@16
|
1043 void
|
Chris@16
|
1044 upgrade_mutex::unlock_and_lock_upgrade()
|
Chris@16
|
1045 {
|
Chris@16
|
1046 {
|
Chris@16
|
1047 boost::lock_guard<mutex_t> _(mut_);
|
Chris@16
|
1048 state_ = upgradable_entered_ | 1;
|
Chris@16
|
1049 }
|
Chris@16
|
1050 gate1_.notify_all();
|
Chris@16
|
1051 }
|
Chris@16
|
1052
|
Chris@16
|
1053 } // thread_v2
|
Chris@16
|
1054 } // boost
|
Chris@16
|
1055
|
Chris@16
|
1056 namespace boost {
|
Chris@16
|
1057 //using thread_v2::shared_mutex;
|
Chris@16
|
1058 using thread_v2::upgrade_mutex;
|
Chris@16
|
1059 typedef thread_v2::upgrade_mutex shared_mutex;
|
Chris@16
|
1060 }
|
Chris@16
|
1061
|
Chris@16
|
1062 #endif
|