Back to home page

EIC code displayed by LXR

 
 

    


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 //  shared_mutex.hpp
0005 //
0006 // Copyright Howard Hinnant 2007-2010.
0007 // Copyright Vicente J. Botet Escriba 2012.
0008 //
0009 //  Distributed under the Boost Software License, Version 1.0. (See
0010 //  accompanying file LICENSE_1_0.txt or copy at
0011 //  http://www.boost.org/LICENSE_1_0.txt)
0012 
0013 /*
0014 <shared_mutex> synopsis
0015 
0016 namespace boost
0017 {
0018 namespace thread_v2
0019 {
0020 
0021 class shared_mutex
0022 {
0023 public:
0024 
0025     shared_mutex();
0026     ~shared_mutex();
0027 
0028     shared_mutex(const shared_mutex&) = delete;
0029     shared_mutex& operator=(const shared_mutex&) = delete;
0030 
0031     // Exclusive ownership
0032 
0033     void lock();
0034     bool try_lock();
0035     template <class Rep, class Period>
0036         bool try_lock_for(const boost::chrono::duration<Rep, Period>& rel_time);
0037     template <class Clock, class Duration>
0038         bool
0039         try_lock_until(
0040                       const boost::chrono::time_point<Clock, Duration>& abs_time);
0041     void unlock();
0042 
0043     // Shared ownership
0044 
0045     void lock_shared();
0046     bool try_lock_shared();
0047     template <class Rep, class Period>
0048         bool
0049         try_lock_shared_for(const boost::chrono::duration<Rep, Period>& rel_time);
0050     template <class Clock, class Duration>
0051         bool
0052         try_lock_shared_until(
0053                       const boost::chrono::time_point<Clock, Duration>& abs_time);
0054     void unlock_shared();
0055 };
0056 
0057 class upgrade_mutex
0058 {
0059 public:
0060 
0061     upgrade_mutex();
0062     ~upgrade_mutex();
0063 
0064     upgrade_mutex(const upgrade_mutex&) = delete;
0065     upgrade_mutex& operator=(const upgrade_mutex&) = delete;
0066 
0067     // Exclusive ownership
0068 
0069     void lock();
0070     bool try_lock();
0071     template <class Rep, class Period>
0072         bool try_lock_for(const boost::chrono::duration<Rep, Period>& rel_time);
0073     template <class Clock, class Duration>
0074         bool
0075         try_lock_until(
0076                       const boost::chrono::time_point<Clock, Duration>& abs_time);
0077     void unlock();
0078 
0079     // Shared ownership
0080 
0081     void lock_shared();
0082     bool try_lock_shared();
0083     template <class Rep, class Period>
0084         bool
0085         try_lock_shared_for(const boost::chrono::duration<Rep, Period>& rel_time);
0086     template <class Clock, class Duration>
0087         bool
0088         try_lock_shared_until(
0089                       const boost::chrono::time_point<Clock, Duration>& abs_time);
0090     void unlock_shared();
0091 
0092     // Upgrade ownership
0093 
0094     void lock_upgrade();
0095     bool try_lock_upgrade();
0096     template <class Rep, class Period>
0097         bool
0098         try_lock_upgrade_for(
0099                             const boost::chrono::duration<Rep, Period>& rel_time);
0100     template <class Clock, class Duration>
0101         bool
0102         try_lock_upgrade_until(
0103                       const boost::chrono::time_point<Clock, Duration>& abs_time);
0104     void unlock_upgrade();
0105 
0106     // Shared <-> Exclusive
0107 
0108     bool try_unlock_shared_and_lock();
0109     template <class Rep, class Period>
0110         bool
0111         try_unlock_shared_and_lock_for(
0112                             const boost::chrono::duration<Rep, Period>& rel_time);
0113     template <class Clock, class Duration>
0114         bool
0115         try_unlock_shared_and_lock_until(
0116                       const boost::chrono::time_point<Clock, Duration>& abs_time);
0117     void unlock_and_lock_shared();
0118 
0119     // Shared <-> Upgrade
0120 
0121     bool try_unlock_shared_and_lock_upgrade();
0122     template <class Rep, class Period>
0123         bool
0124         try_unlock_shared_and_lock_upgrade_for(
0125                             const boost::chrono::duration<Rep, Period>& rel_time);
0126     template <class Clock, class Duration>
0127         bool
0128         try_unlock_shared_and_lock_upgrade_until(
0129                       const boost::chrono::time_point<Clock, Duration>& abs_time);
0130     void unlock_upgrade_and_lock_shared();
0131 
0132     // Upgrade <-> Exclusive
0133 
0134     void unlock_upgrade_and_lock();
0135     bool try_unlock_upgrade_and_lock();
0136     template <class Rep, class Period>
0137         bool
0138         try_unlock_upgrade_and_lock_for(
0139                             const boost::chrono::duration<Rep, Period>& rel_time);
0140     template <class Clock, class Duration>
0141         bool
0142         try_unlock_upgrade_and_lock_until(
0143                       const boost::chrono::time_point<Clock, Duration>& abs_time);
0144     void unlock_and_lock_upgrade();
0145 };
0146 
0147 }  // thread_v2
0148 }  // boost
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       // the gate2_ condition variable is only used by functions that
0175       // have taken write_entered_ but are waiting for no_readers()
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         //return (state_ & write_entered_) == 0 &&
0195         //       (state_ & n_readers_) == 0;
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       // Exclusive ownership
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       // Shared ownership
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     // Exclusive ownership
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       // notify all since multiple *lock_shared*() calls may be able
0344       // to proceed in response to this notification
0345       gate1_.notify_all();
0346     }
0347 
0348     // Shared ownership
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   }  // thread_v2
0427 }  // boost
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       // the gate2_ condition variable is only used by functions that
0441       // have taken write_entered_ but are waiting for no_readers()
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         //return (state_ & (write_entered_ | upgradable_entered_)) == 0 &&
0473         //       (state_ & n_readers_) == 0;
0474         return state_ == 0;
0475       }
0476 
0477       bool no_writer_no_upgrader_one_reader() const
0478       {
0479         //return (state_ & (write_entered_ | upgradable_entered_)) == 0 &&
0480         //       (state_ & n_readers_) == 1;
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       // Exclusive ownership
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       // Shared ownership
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       // Upgrade ownership
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       // Shared <-> Exclusive
0584 
0585 #ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
0586       //bool unlock_shared_and_lock(); // can cause a deadlock if used
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       // Shared <-> Upgrade
0603 
0604 #ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
0605       //bool unlock_shared_and_lock_upgrade(); // can cause a deadlock if used
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       // Upgrade <-> Exclusive
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     // Exclusive ownership
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       // notify all since multiple *lock_shared*() calls and a *lock_upgrade*()
0723       // call may be able to proceed in response to this notification
0724       gate1_.notify_all();
0725     }
0726 
0727     // Shared ownership
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     // Upgrade ownership
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       // notify all since both a *lock*() and a *lock_shared*() call
0874       // may be able to proceed in response to this notification
0875       gate1_.notify_all();
0876     }
0877 
0878     // Shared <-> Exclusive
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       // notify all since multiple *lock_shared*() calls and a *lock_upgrade*()
0929       // call may be able to proceed in response to this notification
0930       gate1_.notify_all();
0931     }
0932 
0933     // Shared <-> Upgrade
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       // notify all since only one *lock*() or *lock_upgrade*() call can win and
0974       // proceed in response to this notification, but a *lock_shared*() call may
0975       // also be waiting and could steal the notification
0976       gate1_.notify_all();
0977     }
0978 
0979     // Upgrade <-> Exclusive
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       // notify all since multiple *lock_shared*() calls may be able
1039       // to proceed in response to this notification
1040       gate1_.notify_all();
1041     }
1042 
1043   }  // thread_v2
1044 }  // boost
1045 
1046 namespace boost {
1047   //using thread_v2::shared_mutex;
1048   using thread_v2::upgrade_mutex;
1049   typedef thread_v2::upgrade_mutex shared_mutex;
1050 }
1051 
1052 #endif