File indexing completed on 2025-01-18 09:52:49
0001 #ifndef BOOST_THREAD_V2_SHARED_MUTEX_HPP
0002 #define BOOST_THREAD_V2_SHARED_MUTEX_HPP
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152 #include <boost/thread/detail/config.hpp>
0153 #include <boost/thread/mutex.hpp>
0154 #include <boost/thread/condition_variable.hpp>
0155 #include <boost/thread/mutex.hpp>
0156 #ifdef BOOST_THREAD_USES_CHRONO
0157 #include <boost/chrono.hpp>
0158 #endif
0159 #include <climits>
0160 #include <boost/system/system_error.hpp>
0161 #include <boost/bind/bind.hpp>
0162
0163 namespace boost {
0164 namespace thread_v2 {
0165
0166 class shared_mutex
0167 {
0168 typedef boost::mutex mutex_t;
0169 typedef boost::condition_variable cond_t;
0170 typedef unsigned count_t;
0171
0172 mutex_t mut_;
0173 cond_t gate1_;
0174
0175
0176 cond_t gate2_;
0177 count_t state_;
0178
0179 static const count_t write_entered_ = 1U << (sizeof(count_t)*CHAR_BIT - 1);
0180 static const count_t n_readers_ = ~write_entered_;
0181
0182 bool no_writer() const
0183 {
0184 return (state_ & write_entered_) == 0;
0185 }
0186
0187 bool one_writer() const
0188 {
0189 return (state_ & write_entered_) != 0;
0190 }
0191
0192 bool no_writer_no_readers() const
0193 {
0194
0195
0196 return state_ == 0;
0197 }
0198
0199 bool no_writer_no_max_readers() const
0200 {
0201 return (state_ & write_entered_) == 0 &&
0202 (state_ & n_readers_) != n_readers_;
0203 }
0204
0205 bool no_readers() const
0206 {
0207 return (state_ & n_readers_) == 0;
0208 }
0209
0210 bool one_or_more_readers() const
0211 {
0212 return (state_ & n_readers_) > 0;
0213 }
0214
0215 shared_mutex(shared_mutex const&);
0216 shared_mutex& operator=(shared_mutex const&);
0217
0218 public:
0219 shared_mutex();
0220 ~shared_mutex();
0221
0222
0223
0224 void lock();
0225 bool try_lock();
0226 #ifdef BOOST_THREAD_USES_CHRONO
0227 template <class Rep, class Period>
0228 bool try_lock_for(const boost::chrono::duration<Rep, Period>& rel_time)
0229 {
0230 return try_lock_until(chrono::steady_clock::now() + rel_time);
0231 }
0232 template <class Clock, class Duration>
0233 bool try_lock_until(
0234 const boost::chrono::time_point<Clock, Duration>& abs_time);
0235 #endif
0236 #if defined BOOST_THREAD_USES_DATETIME
0237 template<typename T>
0238 bool timed_lock(T const & abs_or_rel_time);
0239 #endif
0240 void unlock();
0241
0242
0243
0244 void lock_shared();
0245 bool try_lock_shared();
0246 #ifdef BOOST_THREAD_USES_CHRONO
0247 template <class Rep, class Period>
0248 bool try_lock_shared_for(const boost::chrono::duration<Rep, Period>& rel_time)
0249 {
0250 return try_lock_shared_until(chrono::steady_clock::now() + rel_time);
0251 }
0252 template <class Clock, class Duration>
0253 bool try_lock_shared_until(
0254 const boost::chrono::time_point<Clock, Duration>& abs_time);
0255 #endif
0256 #if defined BOOST_THREAD_USES_DATETIME
0257 template<typename T>
0258 bool timed_lock_shared(T const & abs_or_rel_time);
0259 #endif
0260 void unlock_shared();
0261 };
0262
0263 inline shared_mutex::shared_mutex()
0264 : state_(0)
0265 {
0266 }
0267
0268 inline shared_mutex::~shared_mutex()
0269 {
0270 boost::lock_guard<mutex_t> _(mut_);
0271 }
0272
0273
0274
0275 inline void shared_mutex::lock()
0276 {
0277 boost::unique_lock<mutex_t> lk(mut_);
0278 gate1_.wait(lk, boost::bind(&shared_mutex::no_writer, boost::ref(*this)));
0279 state_ |= write_entered_;
0280 gate2_.wait(lk, boost::bind(&shared_mutex::no_readers, boost::ref(*this)));
0281 }
0282
0283 inline bool shared_mutex::try_lock()
0284 {
0285 boost::unique_lock<mutex_t> lk(mut_);
0286 if (!no_writer_no_readers())
0287 {
0288 return false;
0289 }
0290 state_ = write_entered_;
0291 return true;
0292 }
0293
0294 #ifdef BOOST_THREAD_USES_CHRONO
0295 template <class Clock, class Duration>
0296 bool shared_mutex::try_lock_until(
0297 const boost::chrono::time_point<Clock, Duration>& abs_time)
0298 {
0299 boost::unique_lock<mutex_t> lk(mut_);
0300 if (!gate1_.wait_until(lk, abs_time, boost::bind(
0301 &shared_mutex::no_writer, boost::ref(*this))))
0302 {
0303 return false;
0304 }
0305 state_ |= write_entered_;
0306 if (!gate2_.wait_until(lk, abs_time, boost::bind(
0307 &shared_mutex::no_readers, boost::ref(*this))))
0308 {
0309 state_ &= ~write_entered_;
0310 return false;
0311 }
0312 return true;
0313 }
0314 #endif
0315
0316 #if defined BOOST_THREAD_USES_DATETIME
0317 template<typename T>
0318 bool shared_mutex::timed_lock(T const & abs_or_rel_time)
0319 {
0320 boost::unique_lock<mutex_t> lk(mut_);
0321 if (!gate1_.timed_wait(lk, abs_or_rel_time, boost::bind(
0322 &shared_mutex::no_writer, boost::ref(*this))))
0323 {
0324 return false;
0325 }
0326 state_ |= write_entered_;
0327 if (!gate2_.timed_wait(lk, abs_or_rel_time, boost::bind(
0328 &shared_mutex::no_readers, boost::ref(*this))))
0329 {
0330 state_ &= ~write_entered_;
0331 return false;
0332 }
0333 return true;
0334 }
0335 #endif
0336
0337 inline void shared_mutex::unlock()
0338 {
0339 boost::lock_guard<mutex_t> _(mut_);
0340 BOOST_ASSERT(one_writer());
0341 BOOST_ASSERT(no_readers());
0342 state_ = 0;
0343
0344
0345 gate1_.notify_all();
0346 }
0347
0348
0349
0350 inline void shared_mutex::lock_shared()
0351 {
0352 boost::unique_lock<mutex_t> lk(mut_);
0353 gate1_.wait(lk, boost::bind(&shared_mutex::no_writer_no_max_readers, boost::ref(*this)));
0354 count_t num_readers = (state_ & n_readers_) + 1;
0355 state_ &= ~n_readers_;
0356 state_ |= num_readers;
0357 }
0358
0359 inline bool shared_mutex::try_lock_shared()
0360 {
0361 boost::unique_lock<mutex_t> lk(mut_);
0362 if (!no_writer_no_max_readers())
0363 {
0364 return false;
0365 }
0366 count_t num_readers = (state_ & n_readers_) + 1;
0367 state_ &= ~n_readers_;
0368 state_ |= num_readers;
0369 return true;
0370 }
0371
0372 #ifdef BOOST_THREAD_USES_CHRONO
0373 template <class Clock, class Duration>
0374 bool shared_mutex::try_lock_shared_until(
0375 const boost::chrono::time_point<Clock, Duration>& abs_time)
0376 {
0377 boost::unique_lock<mutex_t> lk(mut_);
0378 if (!gate1_.wait_until(lk, abs_time, boost::bind(
0379 &shared_mutex::no_writer_no_max_readers, boost::ref(*this))))
0380 {
0381 return false;
0382 }
0383 count_t num_readers = (state_ & n_readers_) + 1;
0384 state_ &= ~n_readers_;
0385 state_ |= num_readers;
0386 return true;
0387 }
0388 #endif
0389
0390 #if defined BOOST_THREAD_USES_DATETIME
0391 template<typename T>
0392 bool shared_mutex::timed_lock_shared(T const & abs_or_rel_time)
0393 {
0394 boost::unique_lock<mutex_t> lk(mut_);
0395 if (!gate1_.timed_wait(lk, abs_or_rel_time, boost::bind(
0396 &shared_mutex::no_writer_no_max_readers, boost::ref(*this))))
0397 {
0398 return false;
0399 }
0400 count_t num_readers = (state_ & n_readers_) + 1;
0401 state_ &= ~n_readers_;
0402 state_ |= num_readers;
0403 return true;
0404 }
0405 #endif
0406
0407 inline void shared_mutex::unlock_shared()
0408 {
0409 boost::lock_guard<mutex_t> _(mut_);
0410 BOOST_ASSERT(one_or_more_readers());
0411 count_t num_readers = (state_ & n_readers_) - 1;
0412 state_ &= ~n_readers_;
0413 state_ |= num_readers;
0414 if (no_writer())
0415 {
0416 if (num_readers == n_readers_ - 1)
0417 gate1_.notify_one();
0418 }
0419 else
0420 {
0421 if (num_readers == 0)
0422 gate2_.notify_one();
0423 }
0424 }
0425
0426 }
0427 }
0428
0429 namespace boost {
0430 namespace thread_v2 {
0431
0432 class upgrade_mutex
0433 {
0434 typedef boost::mutex mutex_t;
0435 typedef boost::condition_variable cond_t;
0436 typedef unsigned count_t;
0437
0438 mutex_t mut_;
0439 cond_t gate1_;
0440
0441
0442 cond_t gate2_;
0443 count_t state_;
0444
0445 static const unsigned write_entered_ = 1U << (sizeof(count_t)*CHAR_BIT - 1);
0446 static const unsigned upgradable_entered_ = write_entered_ >> 1;
0447 static const unsigned n_readers_ = ~(write_entered_ | upgradable_entered_);
0448
0449 bool no_writer() const
0450 {
0451 return (state_ & write_entered_) == 0;
0452 }
0453
0454 bool one_writer() const
0455 {
0456 return (state_ & write_entered_) != 0;
0457 }
0458
0459 bool no_writer_no_max_readers() const
0460 {
0461 return (state_ & write_entered_) == 0 &&
0462 (state_ & n_readers_) != n_readers_;
0463 }
0464
0465 bool no_writer_no_upgrader() const
0466 {
0467 return (state_ & (write_entered_ | upgradable_entered_)) == 0;
0468 }
0469
0470 bool no_writer_no_upgrader_no_readers() const
0471 {
0472
0473
0474 return state_ == 0;
0475 }
0476
0477 bool no_writer_no_upgrader_one_reader() const
0478 {
0479
0480
0481 return state_ == 1;
0482 }
0483
0484 bool no_writer_no_upgrader_no_max_readers() const
0485 {
0486 return (state_ & (write_entered_ | upgradable_entered_)) == 0 &&
0487 (state_ & n_readers_) != n_readers_;
0488 }
0489
0490 bool no_upgrader() const
0491 {
0492 return (state_ & upgradable_entered_) == 0;
0493 }
0494
0495 bool one_upgrader() const
0496 {
0497 return (state_ & upgradable_entered_) != 0;
0498 }
0499
0500 bool no_readers() const
0501 {
0502 return (state_ & n_readers_) == 0;
0503 }
0504
0505 bool one_reader() const
0506 {
0507 return (state_ & n_readers_) == 1;
0508 }
0509
0510 bool one_or_more_readers() const
0511 {
0512 return (state_ & n_readers_) > 0;
0513 }
0514
0515 upgrade_mutex(const upgrade_mutex&);
0516 upgrade_mutex& operator=(const upgrade_mutex&);
0517
0518 public:
0519 upgrade_mutex();
0520 ~upgrade_mutex();
0521
0522
0523
0524 void lock();
0525 bool try_lock();
0526 #ifdef BOOST_THREAD_USES_CHRONO
0527 template <class Rep, class Period>
0528 bool try_lock_for(const boost::chrono::duration<Rep, Period>& rel_time)
0529 {
0530 return try_lock_until(chrono::steady_clock::now() + rel_time);
0531 }
0532 template <class Clock, class Duration>
0533 bool try_lock_until(
0534 const boost::chrono::time_point<Clock, Duration>& abs_time);
0535 #endif
0536 #if defined BOOST_THREAD_USES_DATETIME
0537 template<typename T>
0538 bool timed_lock(T const & abs_or_rel_time);
0539 #endif
0540 void unlock();
0541
0542
0543
0544 void lock_shared();
0545 bool try_lock_shared();
0546 #ifdef BOOST_THREAD_USES_CHRONO
0547 template <class Rep, class Period>
0548 bool try_lock_shared_for(const boost::chrono::duration<Rep, Period>& rel_time)
0549 {
0550 return try_lock_shared_until(chrono::steady_clock::now() + rel_time);
0551 }
0552 template <class Clock, class Duration>
0553 bool try_lock_shared_until(
0554 const boost::chrono::time_point<Clock, Duration>& abs_time);
0555 #endif
0556 #if defined BOOST_THREAD_USES_DATETIME
0557 template<typename T>
0558 bool timed_lock_shared(T const & abs_or_rel_time);
0559 #endif
0560 void unlock_shared();
0561
0562
0563
0564 void lock_upgrade();
0565 bool try_lock_upgrade();
0566 #ifdef BOOST_THREAD_USES_CHRONO
0567 template <class Rep, class Period>
0568 bool try_lock_upgrade_for(
0569 const boost::chrono::duration<Rep, Period>& rel_time)
0570 {
0571 return try_lock_upgrade_until(chrono::steady_clock::now() + rel_time);
0572 }
0573 template <class Clock, class Duration>
0574 bool try_lock_upgrade_until(
0575 const boost::chrono::time_point<Clock, Duration>& abs_time);
0576 #endif
0577 #if defined BOOST_THREAD_USES_DATETIME
0578 template<typename T>
0579 bool timed_lock_upgrade(T const & abs_or_rel_time);
0580 #endif
0581 void unlock_upgrade();
0582
0583
0584
0585 #ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
0586
0587 bool try_unlock_shared_and_lock();
0588 #ifdef BOOST_THREAD_USES_CHRONO
0589 template <class Rep, class Period>
0590 bool try_unlock_shared_and_lock_for(
0591 const boost::chrono::duration<Rep, Period>& rel_time)
0592 {
0593 return try_unlock_shared_and_lock_until(chrono::steady_clock::now() + rel_time);
0594 }
0595 template <class Clock, class Duration>
0596 bool try_unlock_shared_and_lock_until(
0597 const boost::chrono::time_point<Clock, Duration>& abs_time);
0598 #endif
0599 #endif
0600 void unlock_and_lock_shared();
0601
0602
0603
0604 #ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
0605
0606 bool try_unlock_shared_and_lock_upgrade();
0607 #ifdef BOOST_THREAD_USES_CHRONO
0608 template <class Rep, class Period>
0609 bool try_unlock_shared_and_lock_upgrade_for(
0610 const boost::chrono::duration<Rep, Period>& rel_time)
0611 {
0612 return try_unlock_shared_and_lock_upgrade_until(chrono::steady_clock::now() + rel_time);
0613 }
0614 template <class Clock, class Duration>
0615 bool try_unlock_shared_and_lock_upgrade_until(
0616 const boost::chrono::time_point<Clock, Duration>& abs_time);
0617 #endif
0618 #endif
0619 void unlock_upgrade_and_lock_shared();
0620
0621
0622
0623 void unlock_upgrade_and_lock();
0624 bool try_unlock_upgrade_and_lock();
0625 #ifdef BOOST_THREAD_USES_CHRONO
0626 template <class Rep, class Period>
0627 bool try_unlock_upgrade_and_lock_for(
0628 const boost::chrono::duration<Rep, Period>& rel_time)
0629 {
0630 return try_unlock_upgrade_and_lock_until(chrono::steady_clock::now() + rel_time);
0631 }
0632 template <class Clock, class Duration>
0633 bool try_unlock_upgrade_and_lock_until(
0634 const boost::chrono::time_point<Clock, Duration>& abs_time);
0635 #endif
0636 void unlock_and_lock_upgrade();
0637 };
0638
0639 inline upgrade_mutex::upgrade_mutex()
0640 : gate1_(),
0641 gate2_(),
0642 state_(0)
0643 {
0644 }
0645
0646 inline upgrade_mutex::~upgrade_mutex()
0647 {
0648 boost::lock_guard<mutex_t> _(mut_);
0649 }
0650
0651
0652
0653 inline void upgrade_mutex::lock()
0654 {
0655 boost::unique_lock<mutex_t> lk(mut_);
0656 gate1_.wait(lk, boost::bind(&upgrade_mutex::no_writer_no_upgrader, boost::ref(*this)));
0657 state_ |= write_entered_;
0658 gate2_.wait(lk, boost::bind(&upgrade_mutex::no_readers, boost::ref(*this)));
0659 }
0660
0661 inline bool upgrade_mutex::try_lock()
0662 {
0663 boost::unique_lock<mutex_t> lk(mut_);
0664 if (!no_writer_no_upgrader_no_readers())
0665 {
0666 return false;
0667 }
0668 state_ = write_entered_;
0669 return true;
0670 }
0671
0672 #ifdef BOOST_THREAD_USES_CHRONO
0673 template <class Clock, class Duration>
0674 bool upgrade_mutex::try_lock_until(
0675 const boost::chrono::time_point<Clock, Duration>& abs_time)
0676 {
0677 boost::unique_lock<mutex_t> lk(mut_);
0678 if (!gate1_.wait_until(lk, abs_time, boost::bind(
0679 &upgrade_mutex::no_writer_no_upgrader, boost::ref(*this))))
0680 {
0681 return false;
0682 }
0683 state_ |= write_entered_;
0684 if (!gate2_.wait_until(lk, abs_time, boost::bind(
0685 &upgrade_mutex::no_readers, boost::ref(*this))))
0686 {
0687 state_ &= ~write_entered_;
0688 return false;
0689 }
0690 return true;
0691 }
0692 #endif
0693
0694 #if defined BOOST_THREAD_USES_DATETIME
0695 template<typename T>
0696 bool upgrade_mutex::timed_lock(T const & abs_or_rel_time)
0697 {
0698 boost::unique_lock<mutex_t> lk(mut_);
0699 if (!gate1_.timed_wait(lk, abs_or_rel_time, boost::bind(
0700 &upgrade_mutex::no_writer_no_upgrader, boost::ref(*this))))
0701 {
0702 return false;
0703 }
0704 state_ |= write_entered_;
0705 if (!gate2_.timed_wait(lk, abs_or_rel_time, boost::bind(
0706 &upgrade_mutex::no_readers, boost::ref(*this))))
0707 {
0708 state_ &= ~write_entered_;
0709 return false;
0710 }
0711 return true;
0712 }
0713 #endif
0714
0715 inline void upgrade_mutex::unlock()
0716 {
0717 boost::lock_guard<mutex_t> _(mut_);
0718 BOOST_ASSERT(one_writer());
0719 BOOST_ASSERT(no_upgrader());
0720 BOOST_ASSERT(no_readers());
0721 state_ = 0;
0722
0723
0724 gate1_.notify_all();
0725 }
0726
0727
0728
0729 inline void upgrade_mutex::lock_shared()
0730 {
0731 boost::unique_lock<mutex_t> lk(mut_);
0732 gate1_.wait(lk, boost::bind(&upgrade_mutex::no_writer_no_max_readers, boost::ref(*this)));
0733 count_t num_readers = (state_ & n_readers_) + 1;
0734 state_ &= ~n_readers_;
0735 state_ |= num_readers;
0736 }
0737
0738 inline bool upgrade_mutex::try_lock_shared()
0739 {
0740 boost::unique_lock<mutex_t> lk(mut_);
0741 if (!no_writer_no_max_readers())
0742 {
0743 return false;
0744 }
0745 count_t num_readers = (state_ & n_readers_) + 1;
0746 state_ &= ~n_readers_;
0747 state_ |= num_readers;
0748 return true;
0749 }
0750
0751 #ifdef BOOST_THREAD_USES_CHRONO
0752 template <class Clock, class Duration>
0753 bool upgrade_mutex::try_lock_shared_until(
0754 const boost::chrono::time_point<Clock, Duration>& abs_time)
0755 {
0756 boost::unique_lock<mutex_t> lk(mut_);
0757 if (!gate1_.wait_until(lk, abs_time, boost::bind(
0758 &upgrade_mutex::no_writer_no_max_readers, boost::ref(*this))))
0759 {
0760 return false;
0761 }
0762 count_t num_readers = (state_ & n_readers_) + 1;
0763 state_ &= ~n_readers_;
0764 state_ |= num_readers;
0765 return true;
0766 }
0767 #endif
0768
0769 #if defined BOOST_THREAD_USES_DATETIME
0770 template<typename T>
0771 bool upgrade_mutex::timed_lock_shared(T const & abs_or_rel_time)
0772 {
0773 boost::unique_lock<mutex_t> lk(mut_);
0774 if (!gate1_.timed_wait(lk, abs_or_rel_time, boost::bind(
0775 &upgrade_mutex::no_writer_no_max_readers, boost::ref(*this))))
0776 {
0777 return false;
0778 }
0779 count_t num_readers = (state_ & n_readers_) + 1;
0780 state_ &= ~n_readers_;
0781 state_ |= num_readers;
0782 return true;
0783 }
0784 #endif
0785
0786 inline void upgrade_mutex::unlock_shared()
0787 {
0788 boost::lock_guard<mutex_t> _(mut_);
0789 BOOST_ASSERT(one_or_more_readers());
0790 count_t num_readers = (state_ & n_readers_) - 1;
0791 state_ &= ~n_readers_;
0792 state_ |= num_readers;
0793 if (no_writer())
0794 {
0795 if (num_readers == n_readers_ - 1)
0796 gate1_.notify_one();
0797 }
0798 else
0799 {
0800 if (num_readers == 0)
0801 gate2_.notify_one();
0802 }
0803 }
0804
0805
0806
0807 inline void upgrade_mutex::lock_upgrade()
0808 {
0809 boost::unique_lock<mutex_t> lk(mut_);
0810 gate1_.wait(lk, boost::bind(&upgrade_mutex::no_writer_no_upgrader_no_max_readers, boost::ref(*this)));
0811 count_t num_readers = (state_ & n_readers_) + 1;
0812 state_ &= ~n_readers_;
0813 state_ |= upgradable_entered_ | num_readers;
0814 }
0815
0816 inline bool upgrade_mutex::try_lock_upgrade()
0817 {
0818 boost::unique_lock<mutex_t> lk(mut_);
0819 if (!no_writer_no_upgrader_no_max_readers())
0820 {
0821 return false;
0822 }
0823 count_t num_readers = (state_ & n_readers_) + 1;
0824 state_ &= ~n_readers_;
0825 state_ |= upgradable_entered_ | num_readers;
0826 return true;
0827 }
0828
0829 #ifdef BOOST_THREAD_USES_CHRONO
0830 template <class Clock, class Duration>
0831 bool upgrade_mutex::try_lock_upgrade_until(
0832 const boost::chrono::time_point<Clock, Duration>& abs_time)
0833 {
0834 boost::unique_lock<mutex_t> lk(mut_);
0835 if (!gate1_.wait_until(lk, abs_time, boost::bind(
0836 &upgrade_mutex::no_writer_no_upgrader_no_max_readers, boost::ref(*this))))
0837 {
0838 return false;
0839 }
0840 count_t num_readers = (state_ & n_readers_) + 1;
0841 state_ &= ~n_readers_;
0842 state_ |= upgradable_entered_ | num_readers;
0843 return true;
0844 }
0845 #endif
0846
0847 #if defined BOOST_THREAD_USES_DATETIME
0848 template<typename T>
0849 bool upgrade_mutex::timed_lock_upgrade(T const & abs_or_rel_time)
0850 {
0851 boost::unique_lock<mutex_t> lk(mut_);
0852 if (!gate1_.timed_wait(lk, abs_or_rel_time, boost::bind(
0853 &upgrade_mutex::no_writer_no_upgrader_no_max_readers, boost::ref(*this))))
0854 {
0855 return false;
0856 }
0857 count_t num_readers = (state_ & n_readers_) + 1;
0858 state_ &= ~n_readers_;
0859 state_ |= upgradable_entered_ | num_readers;
0860 return true;
0861 }
0862 #endif
0863
0864 inline void upgrade_mutex::unlock_upgrade()
0865 {
0866 boost::lock_guard<mutex_t> _(mut_);
0867 BOOST_ASSERT(no_writer());
0868 BOOST_ASSERT(one_upgrader());
0869 BOOST_ASSERT(one_or_more_readers());
0870 count_t num_readers = (state_ & n_readers_) - 1;
0871 state_ &= ~(upgradable_entered_ | n_readers_);
0872 state_ |= num_readers;
0873
0874
0875 gate1_.notify_all();
0876 }
0877
0878
0879
0880 #ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
0881 inline bool upgrade_mutex::try_unlock_shared_and_lock()
0882 {
0883 boost::unique_lock<mutex_t> lk(mut_);
0884 BOOST_ASSERT(one_or_more_readers());
0885 if (!no_writer_no_upgrader_one_reader())
0886 {
0887 return false;
0888 }
0889 state_ = write_entered_;
0890 return true;
0891 }
0892
0893 #ifdef BOOST_THREAD_USES_CHRONO
0894 template <class Clock, class Duration>
0895 bool upgrade_mutex::try_unlock_shared_and_lock_until(
0896 const boost::chrono::time_point<Clock, Duration>& abs_time)
0897 {
0898 boost::unique_lock<mutex_t> lk(mut_);
0899 BOOST_ASSERT(one_or_more_readers());
0900 if (!gate1_.wait_until(lk, abs_time, boost::bind(
0901 &upgrade_mutex::no_writer_no_upgrader, boost::ref(*this))))
0902 {
0903 return false;
0904 }
0905 count_t num_readers = (state_ & n_readers_) - 1;
0906 state_ &= ~n_readers_;
0907 state_ |= (write_entered_ | num_readers);
0908 if (!gate2_.wait_until(lk, abs_time, boost::bind(
0909 &upgrade_mutex::no_readers, boost::ref(*this))))
0910 {
0911 ++num_readers;
0912 state_ &= ~(write_entered_ | n_readers_);
0913 state_ |= num_readers;
0914 return false;
0915 }
0916 return true;
0917 }
0918 #endif
0919 #endif
0920
0921 inline void upgrade_mutex::unlock_and_lock_shared()
0922 {
0923 boost::lock_guard<mutex_t> _(mut_);
0924 BOOST_ASSERT(one_writer());
0925 BOOST_ASSERT(no_upgrader());
0926 BOOST_ASSERT(no_readers());
0927 state_ = 1;
0928
0929
0930 gate1_.notify_all();
0931 }
0932
0933
0934
0935 #ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
0936 inline bool upgrade_mutex::try_unlock_shared_and_lock_upgrade()
0937 {
0938 boost::unique_lock<mutex_t> lk(mut_);
0939 BOOST_ASSERT(one_or_more_readers());
0940 if (!no_writer_no_upgrader())
0941 {
0942 return false;
0943 }
0944 state_ |= upgradable_entered_;
0945 return true;
0946 }
0947
0948 #ifdef BOOST_THREAD_USES_CHRONO
0949 template <class Clock, class Duration>
0950 bool upgrade_mutex::try_unlock_shared_and_lock_upgrade_until(
0951 const boost::chrono::time_point<Clock, Duration>& abs_time)
0952 {
0953 boost::unique_lock<mutex_t> lk(mut_);
0954 BOOST_ASSERT(one_or_more_readers());
0955 if (!gate1_.wait_until(lk, abs_time, boost::bind(
0956 &upgrade_mutex::no_writer_no_upgrader, boost::ref(*this))))
0957 {
0958 return false;
0959 }
0960 state_ |= upgradable_entered_;
0961 return true;
0962 }
0963 #endif
0964 #endif
0965
0966 inline void upgrade_mutex::unlock_upgrade_and_lock_shared()
0967 {
0968 boost::lock_guard<mutex_t> _(mut_);
0969 BOOST_ASSERT(no_writer());
0970 BOOST_ASSERT(one_upgrader());
0971 BOOST_ASSERT(one_or_more_readers());
0972 state_ &= ~upgradable_entered_;
0973
0974
0975
0976 gate1_.notify_all();
0977 }
0978
0979
0980
0981 inline void upgrade_mutex::unlock_upgrade_and_lock()
0982 {
0983 boost::unique_lock<mutex_t> lk(mut_);
0984 BOOST_ASSERT(no_writer());
0985 BOOST_ASSERT(one_upgrader());
0986 BOOST_ASSERT(one_or_more_readers());
0987 count_t num_readers = (state_ & n_readers_) - 1;
0988 state_ &= ~(upgradable_entered_ | n_readers_);
0989 state_ |= write_entered_ | num_readers;
0990 gate2_.wait(lk, boost::bind(&upgrade_mutex::no_readers, boost::ref(*this)));
0991 }
0992
0993 inline bool upgrade_mutex::try_unlock_upgrade_and_lock()
0994 {
0995 boost::unique_lock<mutex_t> lk(mut_);
0996 BOOST_ASSERT(no_writer());
0997 BOOST_ASSERT(one_upgrader());
0998 BOOST_ASSERT(one_or_more_readers());
0999 if (!one_reader())
1000 {
1001 return false;
1002 }
1003 state_ = write_entered_;
1004 return true;
1005 }
1006
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)
1011 {
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))))
1021 {
1022 ++num_readers;
1023 state_ &= ~(write_entered_ | n_readers_);
1024 state_ |= (upgradable_entered_ | num_readers);
1025 return false;
1026 }
1027 return true;
1028 }
1029 #endif
1030
1031 inline void upgrade_mutex::unlock_and_lock_upgrade()
1032 {
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
1039
1040 gate1_.notify_all();
1041 }
1042
1043 }
1044 }
1045
1046 namespace boost {
1047
1048 using thread_v2::upgrade_mutex;
1049 typedef thread_v2::upgrade_mutex shared_mutex;
1050 }
1051
1052 #endif