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