1 #ifndef BOOST_THREAD_V2_SHARED_MUTEX_HPP
2 #define BOOST_THREAD_V2_SHARED_MUTEX_HPP
6 // Copyright Howard Hinnant 2007-2010.
7 // Copyright Vicente J. Botet Escriba 2012.
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)
14 <shared_mutex> synopsis
28 shared_mutex(const shared_mutex&) = delete;
29 shared_mutex& operator=(const shared_mutex&) = delete;
31 // Exclusive ownership
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>
40 const boost::chrono::time_point<Clock, Duration>& abs_time);
46 bool try_lock_shared();
47 template <class Rep, class Period>
49 try_lock_shared_for(const boost::chrono::duration<Rep, Period>& rel_time);
50 template <class Clock, class Duration>
52 try_lock_shared_until(
53 const boost::chrono::time_point<Clock, Duration>& abs_time);
64 upgrade_mutex(const upgrade_mutex&) = delete;
65 upgrade_mutex& operator=(const upgrade_mutex&) = delete;
67 // Exclusive ownership
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>
76 const boost::chrono::time_point<Clock, Duration>& abs_time);
82 bool try_lock_shared();
83 template <class Rep, class Period>
85 try_lock_shared_for(const boost::chrono::duration<Rep, Period>& rel_time);
86 template <class Clock, class Duration>
88 try_lock_shared_until(
89 const boost::chrono::time_point<Clock, Duration>& abs_time);
95 bool try_lock_upgrade();
96 template <class Rep, class Period>
99 const boost::chrono::duration<Rep, Period>& rel_time);
100 template <class Clock, class Duration>
102 try_lock_upgrade_until(
103 const boost::chrono::time_point<Clock, Duration>& abs_time);
104 void unlock_upgrade();
106 // Shared <-> Exclusive
108 bool try_unlock_shared_and_lock();
109 template <class Rep, class Period>
111 try_unlock_shared_and_lock_for(
112 const boost::chrono::duration<Rep, Period>& rel_time);
113 template <class Clock, class Duration>
115 try_unlock_shared_and_lock_until(
116 const boost::chrono::time_point<Clock, Duration>& abs_time);
117 void unlock_and_lock_shared();
119 // Shared <-> Upgrade
121 bool try_unlock_shared_and_lock_upgrade();
122 template <class Rep, class Period>
124 try_unlock_shared_and_lock_upgrade_for(
125 const boost::chrono::duration<Rep, Period>& rel_time);
126 template <class Clock, class Duration>
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();
132 // Upgrade <-> Exclusive
134 void unlock_upgrade_and_lock();
135 bool try_unlock_upgrade_and_lock();
136 template <class Rep, class Period>
138 try_unlock_upgrade_and_lock_for(
139 const boost::chrono::duration<Rep, Period>& rel_time);
140 template <class Clock, class Duration>
142 try_unlock_upgrade_and_lock_until(
143 const boost::chrono::time_point<Clock, Duration>& abs_time);
144 void unlock_and_lock_upgrade();
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 #ifdef BOOST_THREAD_USES_CHRONO
157 #include <boost/chrono.hpp>
160 #include <boost/system/system_error.hpp>
161 #include <boost/bind.hpp>
164 namespace thread_v2 {
168 typedef boost::mutex mutex_t;
169 typedef boost::condition_variable cond_t;
170 typedef unsigned count_t;
174 // the gate2_ condition variable is only used by functions that
175 // have taken write_entered_ but are waiting for no_readers()
179 static const count_t write_entered_ = 1U << (sizeof(count_t)*CHAR_BIT - 1);
180 static const count_t n_readers_ = ~write_entered_;
182 bool no_writer() const
184 return (state_ & write_entered_) == 0;
187 bool one_writer() const
189 return (state_ & write_entered_) != 0;
192 bool no_writer_no_readers() const
194 //return (state_ & write_entered_) == 0 &&
195 // (state_ & n_readers_) == 0;
199 bool no_writer_no_max_readers() const
201 return (state_ & write_entered_) == 0 &&
202 (state_ & n_readers_) != n_readers_;
205 bool no_readers() const
207 return (state_ & n_readers_) == 0;
210 bool one_or_more_readers() const
212 return (state_ & n_readers_) > 0;
215 shared_mutex(shared_mutex const&);
216 shared_mutex& operator=(shared_mutex const&);
222 // Exclusive ownership
226 #ifdef BOOST_THREAD_USES_CHRONO
227 template <class Rep, class Period>
228 bool try_lock_for(const boost::chrono::duration<Rep, Period>& rel_time)
230 return try_lock_until(chrono::steady_clock::now() + rel_time);
232 template <class Clock, class Duration>
234 const boost::chrono::time_point<Clock, Duration>& abs_time);
236 #if defined BOOST_THREAD_USES_DATETIME
238 bool timed_lock(T const & abs_or_rel_time);
245 bool try_lock_shared();
246 #ifdef BOOST_THREAD_USES_CHRONO
247 template <class Rep, class Period>
248 bool try_lock_shared_for(const boost::chrono::duration<Rep, Period>& rel_time)
250 return try_lock_shared_until(chrono::steady_clock::now() + rel_time);
252 template <class Clock, class Duration>
253 bool try_lock_shared_until(
254 const boost::chrono::time_point<Clock, Duration>& abs_time);
256 #if defined BOOST_THREAD_USES_DATETIME
258 bool timed_lock_shared(T const & abs_or_rel_time);
260 void unlock_shared();
263 inline shared_mutex::shared_mutex()
268 inline shared_mutex::~shared_mutex()
270 boost::lock_guard<mutex_t> _(mut_);
273 // Exclusive ownership
275 inline void shared_mutex::lock()
277 boost::unique_lock<mutex_t> lk(mut_);
278 gate1_.wait(lk, boost::bind(&shared_mutex::no_writer, boost::ref(*this)));
279 state_ |= write_entered_;
280 gate2_.wait(lk, boost::bind(&shared_mutex::no_readers, boost::ref(*this)));
283 inline bool shared_mutex::try_lock()
285 boost::unique_lock<mutex_t> lk(mut_);
286 if (!no_writer_no_readers())
290 state_ = write_entered_;
294 #ifdef BOOST_THREAD_USES_CHRONO
295 template <class Clock, class Duration>
296 bool shared_mutex::try_lock_until(
297 const boost::chrono::time_point<Clock, Duration>& abs_time)
299 boost::unique_lock<mutex_t> lk(mut_);
300 if (!gate1_.wait_until(lk, abs_time, boost::bind(
301 &shared_mutex::no_writer, boost::ref(*this))))
305 state_ |= write_entered_;
306 if (!gate2_.wait_until(lk, abs_time, boost::bind(
307 &shared_mutex::no_readers, boost::ref(*this))))
309 state_ &= ~write_entered_;
316 #if defined BOOST_THREAD_USES_DATETIME
318 bool shared_mutex::timed_lock(T const & abs_or_rel_time)
320 boost::unique_lock<mutex_t> lk(mut_);
321 if (!gate1_.timed_wait(lk, abs_or_rel_time, boost::bind(
322 &shared_mutex::no_writer, boost::ref(*this))))
326 state_ |= write_entered_;
327 if (!gate2_.timed_wait(lk, abs_or_rel_time, boost::bind(
328 &shared_mutex::no_readers, boost::ref(*this))))
330 state_ &= ~write_entered_;
337 inline void shared_mutex::unlock()
339 boost::lock_guard<mutex_t> _(mut_);
340 BOOST_ASSERT(one_writer());
341 BOOST_ASSERT(no_readers());
343 // notify all since multiple *lock_shared*() calls may be able
344 // to proceed in response to this notification
350 inline void shared_mutex::lock_shared()
352 boost::unique_lock<mutex_t> lk(mut_);
353 gate1_.wait(lk, boost::bind(&shared_mutex::no_writer_no_max_readers, boost::ref(*this)));
354 count_t num_readers = (state_ & n_readers_) + 1;
355 state_ &= ~n_readers_;
356 state_ |= num_readers;
359 inline bool shared_mutex::try_lock_shared()
361 boost::unique_lock<mutex_t> lk(mut_);
362 if (!no_writer_no_max_readers())
366 count_t num_readers = (state_ & n_readers_) + 1;
367 state_ &= ~n_readers_;
368 state_ |= num_readers;
372 #ifdef BOOST_THREAD_USES_CHRONO
373 template <class Clock, class Duration>
374 bool shared_mutex::try_lock_shared_until(
375 const boost::chrono::time_point<Clock, Duration>& abs_time)
377 boost::unique_lock<mutex_t> lk(mut_);
378 if (!gate1_.wait_until(lk, abs_time, boost::bind(
379 &shared_mutex::no_writer_no_max_readers, boost::ref(*this))))
383 count_t num_readers = (state_ & n_readers_) + 1;
384 state_ &= ~n_readers_;
385 state_ |= num_readers;
390 #if defined BOOST_THREAD_USES_DATETIME
392 bool shared_mutex::timed_lock_shared(T const & abs_or_rel_time)
394 boost::unique_lock<mutex_t> lk(mut_);
395 if (!gate1_.timed_wait(lk, abs_or_rel_time, boost::bind(
396 &shared_mutex::no_writer_no_max_readers, boost::ref(*this))))
400 count_t num_readers = (state_ & n_readers_) + 1;
401 state_ &= ~n_readers_;
402 state_ |= num_readers;
407 inline void shared_mutex::unlock_shared()
409 boost::lock_guard<mutex_t> _(mut_);
410 BOOST_ASSERT(one_or_more_readers());
411 count_t num_readers = (state_ & n_readers_) - 1;
412 state_ &= ~n_readers_;
413 state_ |= num_readers;
416 if (num_readers == n_readers_ - 1)
421 if (num_readers == 0)
430 namespace thread_v2 {
434 typedef boost::mutex mutex_t;
435 typedef boost::condition_variable cond_t;
436 typedef unsigned count_t;
440 // the gate2_ condition variable is only used by functions that
441 // have taken write_entered_ but are waiting for no_readers()
445 static const unsigned write_entered_ = 1U << (sizeof(count_t)*CHAR_BIT - 1);
446 static const unsigned upgradable_entered_ = write_entered_ >> 1;
447 static const unsigned n_readers_ = ~(write_entered_ | upgradable_entered_);
449 bool no_writer() const
451 return (state_ & write_entered_) == 0;
454 bool one_writer() const
456 return (state_ & write_entered_) != 0;
459 bool no_writer_no_max_readers() const
461 return (state_ & write_entered_) == 0 &&
462 (state_ & n_readers_) != n_readers_;
465 bool no_writer_no_upgrader() const
467 return (state_ & (write_entered_ | upgradable_entered_)) == 0;
470 bool no_writer_no_upgrader_no_readers() const
472 //return (state_ & (write_entered_ | upgradable_entered_)) == 0 &&
473 // (state_ & n_readers_) == 0;
477 bool no_writer_no_upgrader_one_reader() const
479 //return (state_ & (write_entered_ | upgradable_entered_)) == 0 &&
480 // (state_ & n_readers_) == 1;
484 bool no_writer_no_upgrader_no_max_readers() const
486 return (state_ & (write_entered_ | upgradable_entered_)) == 0 &&
487 (state_ & n_readers_) != n_readers_;
490 bool no_upgrader() const
492 return (state_ & upgradable_entered_) == 0;
495 bool one_upgrader() const
497 return (state_ & upgradable_entered_) != 0;
500 bool no_readers() const
502 return (state_ & n_readers_) == 0;
505 bool one_reader() const
507 return (state_ & n_readers_) == 1;
510 bool one_or_more_readers() const
512 return (state_ & n_readers_) > 0;
515 upgrade_mutex(const upgrade_mutex&);
516 upgrade_mutex& operator=(const upgrade_mutex&);
522 // Exclusive ownership
526 #ifdef BOOST_THREAD_USES_CHRONO
527 template <class Rep, class Period>
528 bool try_lock_for(const boost::chrono::duration<Rep, Period>& rel_time)
530 return try_lock_until(chrono::steady_clock::now() + rel_time);
532 template <class Clock, class Duration>
534 const boost::chrono::time_point<Clock, Duration>& abs_time);
536 #if defined BOOST_THREAD_USES_DATETIME
538 bool timed_lock(T const & abs_or_rel_time);
545 bool try_lock_shared();
546 #ifdef BOOST_THREAD_USES_CHRONO
547 template <class Rep, class Period>
548 bool try_lock_shared_for(const boost::chrono::duration<Rep, Period>& rel_time)
550 return try_lock_shared_until(chrono::steady_clock::now() + rel_time);
552 template <class Clock, class Duration>
553 bool try_lock_shared_until(
554 const boost::chrono::time_point<Clock, Duration>& abs_time);
556 #if defined BOOST_THREAD_USES_DATETIME
558 bool timed_lock_shared(T const & abs_or_rel_time);
560 void unlock_shared();
565 bool try_lock_upgrade();
566 #ifdef BOOST_THREAD_USES_CHRONO
567 template <class Rep, class Period>
568 bool try_lock_upgrade_for(
569 const boost::chrono::duration<Rep, Period>& rel_time)
571 return try_lock_upgrade_until(chrono::steady_clock::now() + rel_time);
573 template <class Clock, class Duration>
574 bool try_lock_upgrade_until(
575 const boost::chrono::time_point<Clock, Duration>& abs_time);
577 #if defined BOOST_THREAD_USES_DATETIME
579 bool timed_lock_upgrade(T const & abs_or_rel_time);
581 void unlock_upgrade();
583 // Shared <-> Exclusive
585 #ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
586 //bool unlock_shared_and_lock(); // can cause a deadlock if used
587 bool try_unlock_shared_and_lock();
588 #ifdef BOOST_THREAD_USES_CHRONO
589 template <class Rep, class Period>
590 bool try_unlock_shared_and_lock_for(
591 const boost::chrono::duration<Rep, Period>& rel_time)
593 return try_unlock_shared_and_lock_until(chrono::steady_clock::now() + rel_time);
595 template <class Clock, class Duration>
596 bool try_unlock_shared_and_lock_until(
597 const boost::chrono::time_point<Clock, Duration>& abs_time);
600 void unlock_and_lock_shared();
602 // Shared <-> Upgrade
604 #ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
605 //bool unlock_shared_and_lock_upgrade(); // can cause a deadlock if used
606 bool try_unlock_shared_and_lock_upgrade();
607 #ifdef BOOST_THREAD_USES_CHRONO
608 template <class Rep, class Period>
609 bool try_unlock_shared_and_lock_upgrade_for(
610 const boost::chrono::duration<Rep, Period>& rel_time)
612 return try_unlock_shared_and_lock_upgrade_until(chrono::steady_clock::now() + rel_time);
614 template <class Clock, class Duration>
615 bool try_unlock_shared_and_lock_upgrade_until(
616 const boost::chrono::time_point<Clock, Duration>& abs_time);
619 void unlock_upgrade_and_lock_shared();
621 // Upgrade <-> Exclusive
623 void unlock_upgrade_and_lock();
624 bool try_unlock_upgrade_and_lock();
625 #ifdef BOOST_THREAD_USES_CHRONO
626 template <class Rep, class Period>
627 bool try_unlock_upgrade_and_lock_for(
628 const boost::chrono::duration<Rep, Period>& rel_time)
630 return try_unlock_upgrade_and_lock_until(chrono::steady_clock::now() + rel_time);
632 template <class Clock, class Duration>
633 bool try_unlock_upgrade_and_lock_until(
634 const boost::chrono::time_point<Clock, Duration>& abs_time);
636 void unlock_and_lock_upgrade();
639 inline upgrade_mutex::upgrade_mutex()
646 inline upgrade_mutex::~upgrade_mutex()
648 boost::lock_guard<mutex_t> _(mut_);
651 // Exclusive ownership
653 inline void upgrade_mutex::lock()
655 boost::unique_lock<mutex_t> lk(mut_);
656 gate1_.wait(lk, boost::bind(&upgrade_mutex::no_writer_no_upgrader, boost::ref(*this)));
657 state_ |= write_entered_;
658 gate2_.wait(lk, boost::bind(&upgrade_mutex::no_readers, boost::ref(*this)));
661 inline bool upgrade_mutex::try_lock()
663 boost::unique_lock<mutex_t> lk(mut_);
664 if (!no_writer_no_upgrader_no_readers())
668 state_ = write_entered_;
672 #ifdef BOOST_THREAD_USES_CHRONO
673 template <class Clock, class Duration>
674 bool upgrade_mutex::try_lock_until(
675 const boost::chrono::time_point<Clock, Duration>& abs_time)
677 boost::unique_lock<mutex_t> lk(mut_);
678 if (!gate1_.wait_until(lk, abs_time, boost::bind(
679 &upgrade_mutex::no_writer_no_upgrader, boost::ref(*this))))
683 state_ |= write_entered_;
684 if (!gate2_.wait_until(lk, abs_time, boost::bind(
685 &upgrade_mutex::no_readers, boost::ref(*this))))
687 state_ &= ~write_entered_;
694 #if defined BOOST_THREAD_USES_DATETIME
696 bool upgrade_mutex::timed_lock(T const & abs_or_rel_time)
698 boost::unique_lock<mutex_t> lk(mut_);
699 if (!gate1_.timed_wait(lk, abs_or_rel_time, boost::bind(
700 &upgrade_mutex::no_writer_no_upgrader, boost::ref(*this))))
704 state_ |= write_entered_;
705 if (!gate2_.timed_wait(lk, abs_or_rel_time, boost::bind(
706 &upgrade_mutex::no_readers, boost::ref(*this))))
708 state_ &= ~write_entered_;
715 inline void upgrade_mutex::unlock()
717 boost::lock_guard<mutex_t> _(mut_);
718 BOOST_ASSERT(one_writer());
719 BOOST_ASSERT(no_upgrader());
720 BOOST_ASSERT(no_readers());
722 // notify all since multiple *lock_shared*() calls and a *lock_upgrade*()
723 // call may be able to proceed in response to this notification
729 inline void upgrade_mutex::lock_shared()
731 boost::unique_lock<mutex_t> lk(mut_);
732 gate1_.wait(lk, boost::bind(&upgrade_mutex::no_writer_no_max_readers, boost::ref(*this)));
733 count_t num_readers = (state_ & n_readers_) + 1;
734 state_ &= ~n_readers_;
735 state_ |= num_readers;
738 inline bool upgrade_mutex::try_lock_shared()
740 boost::unique_lock<mutex_t> lk(mut_);
741 if (!no_writer_no_max_readers())
745 count_t num_readers = (state_ & n_readers_) + 1;
746 state_ &= ~n_readers_;
747 state_ |= num_readers;
751 #ifdef BOOST_THREAD_USES_CHRONO
752 template <class Clock, class Duration>
753 bool upgrade_mutex::try_lock_shared_until(
754 const boost::chrono::time_point<Clock, Duration>& abs_time)
756 boost::unique_lock<mutex_t> lk(mut_);
757 if (!gate1_.wait_until(lk, abs_time, boost::bind(
758 &upgrade_mutex::no_writer_no_max_readers, boost::ref(*this))))
762 count_t num_readers = (state_ & n_readers_) + 1;
763 state_ &= ~n_readers_;
764 state_ |= num_readers;
769 #if defined BOOST_THREAD_USES_DATETIME
771 bool upgrade_mutex::timed_lock_shared(T const & abs_or_rel_time)
773 boost::unique_lock<mutex_t> lk(mut_);
774 if (!gate1_.timed_wait(lk, abs_or_rel_time, boost::bind(
775 &upgrade_mutex::no_writer_no_max_readers, boost::ref(*this))))
779 count_t num_readers = (state_ & n_readers_) + 1;
780 state_ &= ~n_readers_;
781 state_ |= num_readers;
786 inline void upgrade_mutex::unlock_shared()
788 boost::lock_guard<mutex_t> _(mut_);
789 BOOST_ASSERT(one_or_more_readers());
790 count_t num_readers = (state_ & n_readers_) - 1;
791 state_ &= ~n_readers_;
792 state_ |= num_readers;
795 if (num_readers == n_readers_ - 1)
800 if (num_readers == 0)
807 inline void upgrade_mutex::lock_upgrade()
809 boost::unique_lock<mutex_t> lk(mut_);
810 gate1_.wait(lk, boost::bind(&upgrade_mutex::no_writer_no_upgrader_no_max_readers, boost::ref(*this)));
811 count_t num_readers = (state_ & n_readers_) + 1;
812 state_ &= ~n_readers_;
813 state_ |= upgradable_entered_ | num_readers;
816 inline bool upgrade_mutex::try_lock_upgrade()
818 boost::unique_lock<mutex_t> lk(mut_);
819 if (!no_writer_no_upgrader_no_max_readers())
823 count_t num_readers = (state_ & n_readers_) + 1;
824 state_ &= ~n_readers_;
825 state_ |= upgradable_entered_ | num_readers;
829 #ifdef BOOST_THREAD_USES_CHRONO
830 template <class Clock, class Duration>
831 bool upgrade_mutex::try_lock_upgrade_until(
832 const boost::chrono::time_point<Clock, Duration>& abs_time)
834 boost::unique_lock<mutex_t> lk(mut_);
835 if (!gate1_.wait_until(lk, abs_time, boost::bind(
836 &upgrade_mutex::no_writer_no_upgrader_no_max_readers, boost::ref(*this))))
840 count_t num_readers = (state_ & n_readers_) + 1;
841 state_ &= ~n_readers_;
842 state_ |= upgradable_entered_ | num_readers;
847 #if defined BOOST_THREAD_USES_DATETIME
849 bool upgrade_mutex::timed_lock_upgrade(T const & abs_or_rel_time)
851 boost::unique_lock<mutex_t> lk(mut_);
852 if (!gate1_.timed_wait(lk, abs_or_rel_time, boost::bind(
853 &upgrade_mutex::no_writer_no_upgrader_no_max_readers, boost::ref(*this))))
857 count_t num_readers = (state_ & n_readers_) + 1;
858 state_ &= ~n_readers_;
859 state_ |= upgradable_entered_ | num_readers;
864 inline void upgrade_mutex::unlock_upgrade()
866 boost::lock_guard<mutex_t> _(mut_);
867 BOOST_ASSERT(no_writer());
868 BOOST_ASSERT(one_upgrader());
869 BOOST_ASSERT(one_or_more_readers());
870 count_t num_readers = (state_ & n_readers_) - 1;
871 state_ &= ~(upgradable_entered_ | n_readers_);
872 state_ |= num_readers;
873 // notify all since both a *lock*() and a *lock_shared*() call
874 // may be able to proceed in response to this notification
878 // Shared <-> Exclusive
880 #ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
881 inline bool upgrade_mutex::try_unlock_shared_and_lock()
883 boost::unique_lock<mutex_t> lk(mut_);
884 BOOST_ASSERT(one_or_more_readers());
885 if (!no_writer_no_upgrader_one_reader())
889 state_ = write_entered_;
893 #ifdef BOOST_THREAD_USES_CHRONO
894 template <class Clock, class Duration>
895 bool upgrade_mutex::try_unlock_shared_and_lock_until(
896 const boost::chrono::time_point<Clock, Duration>& abs_time)
898 boost::unique_lock<mutex_t> lk(mut_);
899 BOOST_ASSERT(one_or_more_readers());
900 if (!gate1_.wait_until(lk, abs_time, boost::bind(
901 &upgrade_mutex::no_writer_no_upgrader, boost::ref(*this))))
905 count_t num_readers = (state_ & n_readers_) - 1;
906 state_ &= ~n_readers_;
907 state_ |= (write_entered_ | num_readers);
908 if (!gate2_.wait_until(lk, abs_time, boost::bind(
909 &upgrade_mutex::no_readers, boost::ref(*this))))
912 state_ &= ~(write_entered_ | n_readers_);
913 state_ |= num_readers;
921 inline void upgrade_mutex::unlock_and_lock_shared()
923 boost::lock_guard<mutex_t> _(mut_);
924 BOOST_ASSERT(one_writer());
925 BOOST_ASSERT(no_upgrader());
926 BOOST_ASSERT(no_readers());
928 // notify all since multiple *lock_shared*() calls and a *lock_upgrade*()
929 // call may be able to proceed in response to this notification
933 // Shared <-> Upgrade
935 #ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
936 inline bool upgrade_mutex::try_unlock_shared_and_lock_upgrade()
938 boost::unique_lock<mutex_t> lk(mut_);
939 BOOST_ASSERT(one_or_more_readers());
940 if (!no_writer_no_upgrader())
944 state_ |= upgradable_entered_;
948 #ifdef BOOST_THREAD_USES_CHRONO
949 template <class Clock, class Duration>
950 bool upgrade_mutex::try_unlock_shared_and_lock_upgrade_until(
951 const boost::chrono::time_point<Clock, Duration>& abs_time)
953 boost::unique_lock<mutex_t> lk(mut_);
954 BOOST_ASSERT(one_or_more_readers());
955 if (!gate1_.wait_until(lk, abs_time, boost::bind(
956 &upgrade_mutex::no_writer_no_upgrader, boost::ref(*this))))
960 state_ |= upgradable_entered_;
966 inline void upgrade_mutex::unlock_upgrade_and_lock_shared()
968 boost::lock_guard<mutex_t> _(mut_);
969 BOOST_ASSERT(no_writer());
970 BOOST_ASSERT(one_upgrader());
971 BOOST_ASSERT(one_or_more_readers());
972 state_ &= ~upgradable_entered_;
973 // notify all since only one *lock*() or *lock_upgrade*() call can win and
974 // proceed in response to this notification, but a *lock_shared*() call may
975 // also be waiting and could steal the notification
979 // Upgrade <-> Exclusive
981 inline void upgrade_mutex::unlock_upgrade_and_lock()
983 boost::unique_lock<mutex_t> lk(mut_);
984 BOOST_ASSERT(no_writer());
985 BOOST_ASSERT(one_upgrader());
986 BOOST_ASSERT(one_or_more_readers());
987 count_t num_readers = (state_ & n_readers_) - 1;
988 state_ &= ~(upgradable_entered_ | n_readers_);
989 state_ |= write_entered_ | num_readers;
990 gate2_.wait(lk, boost::bind(&upgrade_mutex::no_readers, boost::ref(*this)));
993 inline bool upgrade_mutex::try_unlock_upgrade_and_lock()
995 boost::unique_lock<mutex_t> lk(mut_);
996 BOOST_ASSERT(no_writer());
997 BOOST_ASSERT(one_upgrader());
998 BOOST_ASSERT(one_or_more_readers());
1003 state_ = write_entered_;
1007 #ifdef BOOST_THREAD_USES_CHRONO
1008 template <class Clock, class Duration>
1009 bool upgrade_mutex::try_unlock_upgrade_and_lock_until(
1010 const boost::chrono::time_point<Clock, Duration>& abs_time)
1012 boost::unique_lock<mutex_t> lk(mut_);
1013 BOOST_ASSERT(no_writer());
1014 BOOST_ASSERT(one_upgrader());
1015 BOOST_ASSERT(one_or_more_readers());
1016 count_t num_readers = (state_ & n_readers_) - 1;
1017 state_ &= ~(upgradable_entered_ | n_readers_);
1018 state_ |= (write_entered_ | num_readers);
1019 if (!gate2_.wait_until(lk, abs_time, boost::bind(
1020 &upgrade_mutex::no_readers, boost::ref(*this))))
1023 state_ &= ~(write_entered_ | n_readers_);
1024 state_ |= (upgradable_entered_ | num_readers);
1031 inline void upgrade_mutex::unlock_and_lock_upgrade()
1033 boost::lock_guard<mutex_t> _(mut_);
1034 BOOST_ASSERT(one_writer());
1035 BOOST_ASSERT(no_upgrader());
1036 BOOST_ASSERT(no_readers());
1037 state_ = upgradable_entered_ | 1;
1038 // notify all since multiple *lock_shared*() calls may be able
1039 // to proceed in response to this notification
1040 gate1_.notify_all();
1047 //using thread_v2::shared_mutex;
1048 using thread_v2::upgrade_mutex;
1049 typedef thread_v2::upgrade_mutex shared_mutex;