]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/thread/include/boost/thread/v2/shared_mutex.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / thread / include / boost / thread / v2 / shared_mutex.hpp
CommitLineData
7c673cae
FG
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
16namespace boost
17{
18namespace thread_v2
19{
20
21class shared_mutex
22{
23public:
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
57class upgrade_mutex
58{
59public:
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
161namespace 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
1056namespace 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