File indexing completed on 2025-12-15 10:09:31
0001
0002
0003
0004
0005
0006
0007 #ifndef BOOST_THREAD_LOCK_TYPES_HPP
0008 #define BOOST_THREAD_LOCK_TYPES_HPP
0009
0010 #include <boost/thread/detail/config.hpp>
0011 #include <boost/thread/detail/move.hpp>
0012 #include <boost/thread/exceptions.hpp>
0013 #include <boost/thread/lock_options.hpp>
0014 #include <boost/thread/lockable_traits.hpp>
0015 #if ! defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
0016 #include <boost/thread/is_locked_by_this_thread.hpp>
0017 #endif
0018 #include <boost/thread/thread_time.hpp>
0019
0020 #include <boost/assert.hpp>
0021 #ifdef BOOST_THREAD_USES_CHRONO
0022 #include <boost/chrono/time_point.hpp>
0023 #include <boost/chrono/duration.hpp>
0024 #endif
0025 #include <boost/detail/workaround.hpp>
0026
0027 #include <boost/config/abi_prefix.hpp>
0028
0029 namespace boost
0030 {
0031 struct xtime;
0032
0033 template <typename Mutex>
0034 class shared_lock;
0035
0036 template <typename Mutex>
0037 class upgrade_lock;
0038
0039 template <typename Mutex>
0040 class unique_lock;
0041
0042 namespace detail
0043 {
0044 template <typename Mutex>
0045 class try_lock_wrapper;
0046 }
0047
0048 #ifdef BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES
0049 namespace sync
0050 {
0051 template<typename T>
0052 struct is_basic_lockable<unique_lock<T> >
0053 {
0054 BOOST_STATIC_CONSTANT(bool, value = true);
0055 };
0056 template<typename T>
0057 struct is_lockable<unique_lock<T> >
0058 {
0059 BOOST_STATIC_CONSTANT(bool, value = true);
0060 };
0061
0062 template<typename T>
0063 struct is_basic_lockable<shared_lock<T> >
0064 {
0065 BOOST_STATIC_CONSTANT(bool, value = true);
0066 };
0067 template<typename T>
0068 struct is_lockable<shared_lock<T> >
0069 {
0070 BOOST_STATIC_CONSTANT(bool, value = true);
0071 };
0072
0073 template<typename T>
0074 struct is_basic_lockable<upgrade_lock<T> >
0075 {
0076 BOOST_STATIC_CONSTANT(bool, value = true);
0077 };
0078 template<typename T>
0079 struct is_lockable<upgrade_lock<T> >
0080 {
0081 BOOST_STATIC_CONSTANT(bool, value = true);
0082 };
0083
0084 template<typename T>
0085 struct is_basic_lockable<detail::try_lock_wrapper<T> >
0086 {
0087 BOOST_STATIC_CONSTANT(bool, value = true);
0088 };
0089 template<typename T>
0090 struct is_lockable<detail::try_lock_wrapper<T> >
0091 {
0092 BOOST_STATIC_CONSTANT(bool, value = true);
0093 };
0094 }
0095 #endif
0096
0097
0098 template <typename Mutex>
0099 class unique_lock
0100 {
0101 private:
0102 Mutex* m;
0103 bool is_locked;
0104
0105 private:
0106 explicit unique_lock(upgrade_lock<Mutex>&);
0107 unique_lock& operator=(upgrade_lock<Mutex>& other);
0108 public:
0109 typedef Mutex mutex_type;
0110 BOOST_THREAD_MOVABLE_ONLY( unique_lock)
0111
0112 #if 0
0113 #if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100)
0114 unique_lock(const volatile unique_lock&);
0115 #endif
0116 #endif
0117 unique_lock()BOOST_NOEXCEPT :
0118 m(0),is_locked(false)
0119 {}
0120
0121 explicit unique_lock(Mutex& m_) :
0122 m(&m_), is_locked(false)
0123 {
0124 lock();
0125 }
0126 unique_lock(Mutex& m_, adopt_lock_t) :
0127 m(&m_), is_locked(true)
0128 {
0129 #if ! defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
0130 BOOST_ASSERT(is_locked_by_this_thread(m));
0131 #endif
0132 }
0133 unique_lock(Mutex& m_, defer_lock_t)BOOST_NOEXCEPT:
0134 m(&m_),is_locked(false)
0135 {}
0136 unique_lock(Mutex& m_, try_to_lock_t) :
0137 m(&m_), is_locked(false)
0138 {
0139 try_lock();
0140 }
0141 #if defined BOOST_THREAD_USES_DATETIME
0142 template<typename TimeDuration>
0143 unique_lock(Mutex& m_,TimeDuration const& target_time):
0144 m(&m_),is_locked(false)
0145 {
0146 timed_lock(target_time);
0147 }
0148 unique_lock(Mutex& m_,system_time const& target_time):
0149 m(&m_),is_locked(false)
0150 {
0151 timed_lock(target_time);
0152 }
0153 #endif
0154 #ifdef BOOST_THREAD_USES_CHRONO
0155 template <class Clock, class Duration>
0156 unique_lock(Mutex& mtx, const chrono::time_point<Clock, Duration>& t)
0157 : m(&mtx), is_locked(mtx.try_lock_until(t))
0158 {
0159 }
0160 template <class Rep, class Period>
0161 unique_lock(Mutex& mtx, const chrono::duration<Rep, Period>& d)
0162 : m(&mtx), is_locked(mtx.try_lock_for(d))
0163 {
0164 }
0165 #endif
0166
0167 unique_lock(BOOST_THREAD_RV_REF(unique_lock) other) BOOST_NOEXCEPT:
0168 m(BOOST_THREAD_RV(other).m),is_locked(BOOST_THREAD_RV(other).is_locked)
0169 {
0170 BOOST_THREAD_RV(other).is_locked=false;
0171 BOOST_THREAD_RV(other).m=0;
0172 }
0173
0174 BOOST_THREAD_EXPLICIT_LOCK_CONVERSION unique_lock(BOOST_THREAD_RV_REF_BEG upgrade_lock<Mutex> BOOST_THREAD_RV_REF_END other);
0175
0176 #ifndef BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION
0177
0178 unique_lock& operator=(BOOST_THREAD_RV_REF_BEG upgrade_lock<Mutex> BOOST_THREAD_RV_REF_END other)
0179 {
0180 unique_lock temp(::boost::move(other));
0181 swap(temp);
0182 return *this;
0183 }
0184 #endif
0185
0186
0187 unique_lock& operator=(BOOST_THREAD_RV_REF(unique_lock) other)
0188 {
0189 unique_lock temp(::boost::move(other));
0190 swap(temp);
0191 return *this;
0192 }
0193 #if 0
0194 #if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100)
0195 unique_lock& operator=(unique_lock<Mutex> other)
0196 {
0197 swap(other);
0198 return *this;
0199 }
0200 #endif
0201 #endif
0202
0203
0204 unique_lock(BOOST_THREAD_RV_REF_BEG upgrade_lock<mutex_type> BOOST_THREAD_RV_REF_END ul, try_to_lock_t)
0205 : m(0),is_locked(false)
0206 {
0207 if (BOOST_THREAD_RV(ul).owns_lock())
0208 {
0209 if (BOOST_THREAD_RV(ul).mutex()->try_unlock_upgrade_and_lock())
0210 {
0211 m = BOOST_THREAD_RV(ul).release();
0212 is_locked = true;
0213 }
0214 }
0215 else
0216 {
0217 m = BOOST_THREAD_RV(ul).release();
0218 }
0219 }
0220
0221 #ifdef BOOST_THREAD_USES_CHRONO
0222 template <class Clock, class Duration>
0223 unique_lock(BOOST_THREAD_RV_REF_BEG upgrade_lock<mutex_type> BOOST_THREAD_RV_REF_END ul,
0224 const chrono::time_point<Clock, Duration>& abs_time)
0225 : m(0),is_locked(false)
0226 {
0227 if (BOOST_THREAD_RV(ul).owns_lock())
0228 {
0229 if (BOOST_THREAD_RV(ul).mutex()->try_unlock_upgrade_and_lock_until(abs_time))
0230 {
0231 m = BOOST_THREAD_RV(ul).release();
0232 is_locked = true;
0233 }
0234 }
0235 else
0236 {
0237 m = BOOST_THREAD_RV(ul).release();
0238 }
0239 }
0240
0241 template <class Rep, class Period>
0242 unique_lock(BOOST_THREAD_RV_REF_BEG upgrade_lock<mutex_type> BOOST_THREAD_RV_REF_END ul,
0243 const chrono::duration<Rep, Period>& rel_time)
0244 : m(0),is_locked(false)
0245 {
0246 if (BOOST_THREAD_RV(ul).owns_lock())
0247 {
0248 if (BOOST_THREAD_RV(ul).mutex()->try_unlock_upgrade_and_lock_for(rel_time))
0249 {
0250 m = BOOST_THREAD_RV(ul).release();
0251 is_locked = true;
0252 }
0253 }
0254 else
0255 {
0256 m = BOOST_THREAD_RV(ul).release();
0257 }
0258 }
0259 #endif
0260
0261 #ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
0262
0263 unique_lock(BOOST_THREAD_RV_REF_BEG shared_lock<mutex_type> BOOST_THREAD_RV_REF_END sl, try_to_lock_t)
0264 : m(0),is_locked(false)
0265 {
0266 if (BOOST_THREAD_RV(sl).owns_lock())
0267 {
0268 if (BOOST_THREAD_RV(sl).mutex()->try_unlock_shared_and_lock())
0269 {
0270 m = BOOST_THREAD_RV(sl).release();
0271 is_locked = true;
0272 }
0273 }
0274 else
0275 {
0276 m = BOOST_THREAD_RV(sl).release();
0277 }
0278 }
0279
0280 #ifdef BOOST_THREAD_USES_CHRONO
0281 template <class Clock, class Duration>
0282 unique_lock(BOOST_THREAD_RV_REF_BEG shared_lock<mutex_type> BOOST_THREAD_RV_REF_END sl,
0283 const chrono::time_point<Clock, Duration>& abs_time)
0284 : m(0),is_locked(false)
0285 {
0286 if (BOOST_THREAD_RV(sl).owns_lock())
0287 {
0288 if (BOOST_THREAD_RV(sl).mutex()->try_unlock_shared_and_lock_until(abs_time))
0289 {
0290 m = BOOST_THREAD_RV(sl).release();
0291 is_locked = true;
0292 }
0293 }
0294 else
0295 {
0296 m = BOOST_THREAD_RV(sl).release();
0297 }
0298 }
0299
0300 template <class Rep, class Period>
0301 unique_lock(BOOST_THREAD_RV_REF_BEG shared_lock<mutex_type> BOOST_THREAD_RV_REF_END sl,
0302 const chrono::duration<Rep, Period>& rel_time)
0303 : m(0),is_locked(false)
0304 {
0305 if (BOOST_THREAD_RV(sl).owns_lock())
0306 {
0307 if (BOOST_THREAD_RV(sl).mutex()->try_unlock_shared_and_lock_for(rel_time))
0308 {
0309 m = BOOST_THREAD_RV(sl).release();
0310 is_locked = true;
0311 }
0312 }
0313 else
0314 {
0315 m = BOOST_THREAD_RV(sl).release();
0316 }
0317 }
0318 #endif
0319 #endif
0320
0321 void swap(unique_lock& other)BOOST_NOEXCEPT
0322 {
0323 std::swap(m,other.m);
0324 std::swap(is_locked,other.is_locked);
0325 }
0326
0327 ~unique_lock()
0328 {
0329 if (owns_lock())
0330 {
0331 m->unlock();
0332 }
0333 }
0334 void lock()
0335 {
0336 if (m == 0)
0337 {
0338 boost::throw_exception(
0339 boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost unique_lock has no mutex"));
0340 }
0341 if (owns_lock())
0342 {
0343 boost::throw_exception(
0344 boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost unique_lock owns already the mutex"));
0345 }
0346 m->lock();
0347 is_locked = true;
0348 }
0349 bool try_lock()
0350 {
0351 if (m == 0)
0352 {
0353 boost::throw_exception(
0354 boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost unique_lock has no mutex"));
0355 }
0356 if (owns_lock())
0357 {
0358 boost::throw_exception(
0359 boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost unique_lock owns already the mutex"));
0360 }
0361 is_locked = m->try_lock();
0362 return is_locked;
0363 }
0364 #if defined BOOST_THREAD_USES_DATETIME
0365 template<typename TimeDuration>
0366 bool timed_lock(TimeDuration const& relative_time)
0367 {
0368 if(m==0)
0369 {
0370 boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost unique_lock has no mutex"));
0371 }
0372 if(owns_lock())
0373 {
0374 boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost unique_lock owns already the mutex"));
0375 }
0376 is_locked=m->timed_lock(relative_time);
0377 return is_locked;
0378 }
0379
0380 bool timed_lock(::boost::system_time const& absolute_time)
0381 {
0382 if(m==0)
0383 {
0384 boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost unique_lock has no mutex"));
0385 }
0386 if(owns_lock())
0387 {
0388 boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost unique_lock owns already the mutex"));
0389 }
0390 is_locked=m->timed_lock(absolute_time);
0391 return is_locked;
0392 }
0393 bool timed_lock(::boost::xtime const& absolute_time)
0394 {
0395 if(m==0)
0396 {
0397 boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost unique_lock has no mutex"));
0398 }
0399 if(owns_lock())
0400 {
0401 boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost unique_lock owns already the mutex"));
0402 }
0403 is_locked=m->timed_lock(absolute_time);
0404 return is_locked;
0405 }
0406 #endif
0407 #ifdef BOOST_THREAD_USES_CHRONO
0408
0409 template <class Rep, class Period>
0410 bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
0411 {
0412 if(m==0)
0413 {
0414 boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost unique_lock has no mutex"));
0415 }
0416 if(owns_lock())
0417 {
0418 boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost unique_lock owns already the mutex"));
0419 }
0420 is_locked=m->try_lock_for(rel_time);
0421 return is_locked;
0422 }
0423 template <class Clock, class Duration>
0424 bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time)
0425 {
0426 if(m==0)
0427 {
0428 boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost unique_lock has no mutex"));
0429 }
0430 if(owns_lock())
0431 {
0432 boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost unique_lock owns already the mutex"));
0433 }
0434 is_locked=m->try_lock_until(abs_time);
0435 return is_locked;
0436 }
0437 #endif
0438
0439 void unlock()
0440 {
0441 if (m == 0)
0442 {
0443 boost::throw_exception(
0444 boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost unique_lock has no mutex"));
0445 }
0446 if (!owns_lock())
0447 {
0448 boost::throw_exception(
0449 boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost unique_lock doesn't own the mutex"));
0450 }
0451 m->unlock();
0452 is_locked = false;
0453 }
0454
0455 #if defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
0456 typedef void (unique_lock::*bool_type)();
0457 operator bool_type() const BOOST_NOEXCEPT
0458 {
0459 return is_locked?&unique_lock::lock:0;
0460 }
0461 bool operator!() const BOOST_NOEXCEPT
0462 {
0463 return !owns_lock();
0464 }
0465 #else
0466 explicit operator bool() const BOOST_NOEXCEPT
0467 {
0468 return owns_lock();
0469 }
0470 #endif
0471 bool owns_lock() const BOOST_NOEXCEPT
0472 {
0473 return is_locked;
0474 }
0475
0476 Mutex* mutex() const BOOST_NOEXCEPT
0477 {
0478 return m;
0479 }
0480
0481 Mutex* release()BOOST_NOEXCEPT
0482 {
0483 Mutex* const res=m;
0484 m=0;
0485 is_locked=false;
0486 return res;
0487 }
0488
0489 friend class shared_lock<Mutex> ;
0490 friend class upgrade_lock<Mutex> ;
0491 };
0492
0493 template<typename Mutex>
0494 void swap(unique_lock<Mutex>& lhs, unique_lock<Mutex>& rhs)
0495 BOOST_NOEXCEPT
0496 {
0497 lhs.swap(rhs);
0498 }
0499
0500 BOOST_THREAD_DCL_MOVABLE_BEG(Mutex) unique_lock<Mutex> BOOST_THREAD_DCL_MOVABLE_END
0501
0502 template<typename Mutex>
0503 class shared_lock
0504 {
0505 protected:
0506 Mutex* m;
0507 bool is_locked;
0508
0509 public:
0510 typedef Mutex mutex_type;
0511 BOOST_THREAD_MOVABLE_ONLY(shared_lock)
0512
0513 shared_lock() BOOST_NOEXCEPT:
0514 m(0),is_locked(false)
0515 {}
0516
0517 explicit shared_lock(Mutex& m_):
0518 m(&m_),is_locked(false)
0519 {
0520 lock();
0521 }
0522 shared_lock(Mutex& m_,adopt_lock_t):
0523 m(&m_),is_locked(true)
0524 {
0525 #if ! defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
0526 BOOST_ASSERT(is_locked_by_this_thread(m));
0527 #endif
0528 }
0529 shared_lock(Mutex& m_,defer_lock_t) BOOST_NOEXCEPT:
0530 m(&m_),is_locked(false)
0531 {}
0532 shared_lock(Mutex& m_,try_to_lock_t):
0533 m(&m_),is_locked(false)
0534 {
0535 try_lock();
0536 }
0537 #if defined BOOST_THREAD_USES_DATETIME
0538 shared_lock(Mutex& m_,system_time const& target_time):
0539 m(&m_),is_locked(false)
0540 {
0541 timed_lock(target_time);
0542 }
0543 #endif
0544 #ifdef BOOST_THREAD_USES_CHRONO
0545 template <class Clock, class Duration>
0546 shared_lock(Mutex& mtx, const chrono::time_point<Clock, Duration>& t)
0547 : m(&mtx), is_locked(mtx.try_lock_shared_until(t))
0548 {
0549 }
0550 template <class Rep, class Period>
0551 shared_lock(Mutex& mtx, const chrono::duration<Rep, Period>& d)
0552 : m(&mtx), is_locked(mtx.try_lock_shared_for(d))
0553 {
0554 }
0555 #endif
0556
0557 shared_lock(BOOST_THREAD_RV_REF_BEG shared_lock<Mutex> BOOST_THREAD_RV_REF_END other) BOOST_NOEXCEPT:
0558 m(BOOST_THREAD_RV(other).m),is_locked(BOOST_THREAD_RV(other).is_locked)
0559 {
0560 BOOST_THREAD_RV(other).is_locked=false;
0561 BOOST_THREAD_RV(other).m=0;
0562 }
0563
0564 BOOST_THREAD_EXPLICIT_LOCK_CONVERSION shared_lock(BOOST_THREAD_RV_REF_BEG unique_lock<Mutex> BOOST_THREAD_RV_REF_END other):
0565 m(BOOST_THREAD_RV(other).m),is_locked(BOOST_THREAD_RV(other).is_locked)
0566 {
0567 if(is_locked)
0568 {
0569 m->unlock_and_lock_shared();
0570 }
0571 BOOST_THREAD_RV(other).is_locked=false;
0572 BOOST_THREAD_RV(other).m=0;
0573 }
0574
0575 BOOST_THREAD_EXPLICIT_LOCK_CONVERSION shared_lock(BOOST_THREAD_RV_REF_BEG upgrade_lock<Mutex> BOOST_THREAD_RV_REF_END other):
0576 m(BOOST_THREAD_RV(other).m),is_locked(BOOST_THREAD_RV(other).is_locked)
0577 {
0578 if(is_locked)
0579 {
0580 m->unlock_upgrade_and_lock_shared();
0581 }
0582 BOOST_THREAD_RV(other).is_locked=false;
0583 BOOST_THREAD_RV(other).m=0;
0584 }
0585
0586
0587 shared_lock& operator=(BOOST_THREAD_RV_REF_BEG shared_lock<Mutex> BOOST_THREAD_RV_REF_END other)
0588 {
0589 shared_lock temp(::boost::move(other));
0590 swap(temp);
0591 return *this;
0592 }
0593 #ifndef BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION
0594 shared_lock& operator=(BOOST_THREAD_RV_REF_BEG unique_lock<Mutex> BOOST_THREAD_RV_REF_END other)
0595 {
0596 shared_lock temp(::boost::move(other));
0597 swap(temp);
0598 return *this;
0599 }
0600
0601 shared_lock& operator=(BOOST_THREAD_RV_REF_BEG upgrade_lock<Mutex> BOOST_THREAD_RV_REF_END other)
0602 {
0603 shared_lock temp(::boost::move(other));
0604 swap(temp);
0605 return *this;
0606 }
0607 #endif
0608
0609 void swap(shared_lock& other) BOOST_NOEXCEPT
0610 {
0611 std::swap(m,other.m);
0612 std::swap(is_locked,other.is_locked);
0613 }
0614
0615 Mutex* mutex() const BOOST_NOEXCEPT
0616 {
0617 return m;
0618 }
0619
0620 Mutex* release() BOOST_NOEXCEPT
0621 {
0622 Mutex* const res=m;
0623 m=0;
0624 is_locked=false;
0625 return res;
0626 }
0627
0628 ~shared_lock()
0629 {
0630 if(owns_lock())
0631 {
0632 m->unlock_shared();
0633 }
0634 }
0635 void lock()
0636 {
0637 if(m==0)
0638 {
0639 boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock has no mutex"));
0640 }
0641 if(owns_lock())
0642 {
0643 boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost shared_lock owns already the mutex"));
0644 }
0645 m->lock_shared();
0646 is_locked=true;
0647 }
0648 bool try_lock()
0649 {
0650 if(m==0)
0651 {
0652 boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock has no mutex"));
0653 }
0654 if(owns_lock())
0655 {
0656 boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost shared_lock owns already the mutex"));
0657 }
0658 is_locked=m->try_lock_shared();
0659 return is_locked;
0660 }
0661 #if defined BOOST_THREAD_USES_DATETIME
0662 bool timed_lock(boost::system_time const& target_time)
0663 {
0664 if(m==0)
0665 {
0666 boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock has no mutex"));
0667 }
0668 if(owns_lock())
0669 {
0670 boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost shared_lock owns already the mutex"));
0671 }
0672 is_locked=m->timed_lock_shared(target_time);
0673 return is_locked;
0674 }
0675 template<typename Duration>
0676 bool timed_lock(Duration const& target_time)
0677 {
0678 if(m==0)
0679 {
0680 boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock has no mutex"));
0681 }
0682 if(owns_lock())
0683 {
0684 boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost shared_lock owns already the mutex"));
0685 }
0686 is_locked=m->timed_lock_shared(target_time);
0687 return is_locked;
0688 }
0689 #endif
0690 #ifdef BOOST_THREAD_USES_CHRONO
0691 template <class Rep, class Period>
0692 bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
0693 {
0694 if(m==0)
0695 {
0696 boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock has no mutex"));
0697 }
0698 if(owns_lock())
0699 {
0700 boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost shared_lock owns already the mutex"));
0701 }
0702 is_locked=m->try_lock_shared_for(rel_time);
0703 return is_locked;
0704 }
0705 template <class Clock, class Duration>
0706 bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time)
0707 {
0708 if(m==0)
0709 {
0710 boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock has no mutex"));
0711 }
0712 if(owns_lock())
0713 {
0714 boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost shared_lock owns already the mutex"));
0715 }
0716 is_locked=m->try_lock_shared_until(abs_time);
0717 return is_locked;
0718 }
0719 #endif
0720 void unlock()
0721 {
0722 if(m==0)
0723 {
0724 boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock has no mutex"));
0725 }
0726 if(!owns_lock())
0727 {
0728 boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock doesn't own the mutex"));
0729 }
0730 m->unlock_shared();
0731 is_locked=false;
0732 }
0733
0734 #if defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
0735 typedef void (shared_lock<Mutex>::*bool_type)();
0736 operator bool_type() const BOOST_NOEXCEPT
0737 {
0738 return is_locked?&shared_lock::lock:0;
0739 }
0740 bool operator!() const BOOST_NOEXCEPT
0741 {
0742 return !owns_lock();
0743 }
0744 #else
0745 explicit operator bool() const BOOST_NOEXCEPT
0746 {
0747 return owns_lock();
0748 }
0749 #endif
0750 bool owns_lock() const BOOST_NOEXCEPT
0751 {
0752 return is_locked;
0753 }
0754
0755 };
0756
0757 BOOST_THREAD_DCL_MOVABLE_BEG(Mutex) shared_lock<Mutex> BOOST_THREAD_DCL_MOVABLE_END
0758
0759 template<typename Mutex>
0760 void swap(shared_lock<Mutex>& lhs,shared_lock<Mutex>& rhs) BOOST_NOEXCEPT
0761 {
0762 lhs.swap(rhs);
0763 }
0764
0765 template <typename Mutex>
0766 class upgrade_lock
0767 {
0768 protected:
0769 Mutex* m;
0770 bool is_locked;
0771
0772 public:
0773 typedef Mutex mutex_type;
0774 BOOST_THREAD_MOVABLE_ONLY( upgrade_lock)
0775
0776 upgrade_lock()BOOST_NOEXCEPT:
0777 m(0),is_locked(false)
0778 {}
0779
0780 explicit upgrade_lock(Mutex& m_) :
0781 m(&m_), is_locked(false)
0782 {
0783 lock();
0784 }
0785 upgrade_lock(Mutex& m_, adopt_lock_t) :
0786 m(&m_), is_locked(true)
0787 {
0788 #if ! defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
0789 BOOST_ASSERT(is_locked_by_this_thread(m));
0790 #endif
0791 }
0792 upgrade_lock(Mutex& m_, defer_lock_t)BOOST_NOEXCEPT:
0793 m(&m_),is_locked(false)
0794 {}
0795 upgrade_lock(Mutex& m_, try_to_lock_t) :
0796 m(&m_), is_locked(false)
0797 {
0798 try_lock();
0799 }
0800
0801 #ifdef BOOST_THREAD_USES_CHRONO
0802 template <class Clock, class Duration>
0803 upgrade_lock(Mutex& mtx, const chrono::time_point<Clock, Duration>& t)
0804 : m(&mtx), is_locked(mtx.try_lock_upgrade_until(t))
0805 {
0806 }
0807 template <class Rep, class Period>
0808 upgrade_lock(Mutex& mtx, const chrono::duration<Rep, Period>& d)
0809 : m(&mtx), is_locked(mtx.try_lock_upgrade_for(d))
0810 {
0811 }
0812 #endif
0813
0814 upgrade_lock(BOOST_THREAD_RV_REF_BEG upgrade_lock<Mutex> BOOST_THREAD_RV_REF_END other) BOOST_NOEXCEPT:
0815 m(BOOST_THREAD_RV(other).m),is_locked(BOOST_THREAD_RV(other).is_locked)
0816 {
0817 BOOST_THREAD_RV(other).is_locked=false;
0818 BOOST_THREAD_RV(other).m=0;
0819 }
0820
0821 BOOST_THREAD_EXPLICIT_LOCK_CONVERSION upgrade_lock(BOOST_THREAD_RV_REF_BEG unique_lock<Mutex> BOOST_THREAD_RV_REF_END other):
0822 m(BOOST_THREAD_RV(other).m),is_locked(BOOST_THREAD_RV(other).is_locked)
0823 {
0824 if(is_locked)
0825 {
0826 m->unlock_and_lock_upgrade();
0827 }
0828 BOOST_THREAD_RV(other).is_locked=false;
0829 BOOST_THREAD_RV(other).m=0;
0830 }
0831
0832
0833 upgrade_lock& operator=(BOOST_THREAD_RV_REF_BEG upgrade_lock<Mutex> BOOST_THREAD_RV_REF_END other)
0834 {
0835 upgrade_lock temp(::boost::move(other));
0836 swap(temp);
0837 return *this;
0838 }
0839
0840 #ifndef BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION
0841 upgrade_lock& operator=(BOOST_THREAD_RV_REF_BEG unique_lock<Mutex> BOOST_THREAD_RV_REF_END other)
0842 {
0843 upgrade_lock temp(::boost::move(other));
0844 swap(temp);
0845 return *this;
0846 }
0847 #endif
0848
0849 #ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
0850
0851 upgrade_lock(BOOST_THREAD_RV_REF_BEG shared_lock<mutex_type> BOOST_THREAD_RV_REF_END sl, try_to_lock_t)
0852 : m(0),is_locked(false)
0853 {
0854 if (BOOST_THREAD_RV(sl).owns_lock())
0855 {
0856 if (BOOST_THREAD_RV(sl).mutex()->try_unlock_shared_and_lock_upgrade())
0857 {
0858 m = BOOST_THREAD_RV(sl).release();
0859 is_locked = true;
0860 }
0861 }
0862 else
0863 {
0864 m = BOOST_THREAD_RV(sl).release();
0865 }
0866 }
0867
0868 #ifdef BOOST_THREAD_USES_CHRONO
0869 template <class Clock, class Duration>
0870 upgrade_lock(BOOST_THREAD_RV_REF_BEG shared_lock<mutex_type> BOOST_THREAD_RV_REF_END sl,
0871 const chrono::time_point<Clock, Duration>& abs_time)
0872 : m(0),is_locked(false)
0873 {
0874 if (BOOST_THREAD_RV(sl).owns_lock())
0875 {
0876 if (BOOST_THREAD_RV(sl).mutex()->try_unlock_shared_and_lock_upgrade_until(abs_time))
0877 {
0878 m = BOOST_THREAD_RV(sl).release();
0879 is_locked = true;
0880 }
0881 }
0882 else
0883 {
0884 m = BOOST_THREAD_RV(sl).release();
0885 }
0886 }
0887
0888 template <class Rep, class Period>
0889 upgrade_lock(BOOST_THREAD_RV_REF_BEG shared_lock<mutex_type> BOOST_THREAD_RV_REF_END sl,
0890 const chrono::duration<Rep, Period>& rel_time)
0891 : m(0),is_locked(false)
0892 {
0893 if (BOOST_THREAD_RV(sl).owns_lock())
0894 {
0895 if (BOOST_THREAD_RV(sl).mutex()->try_unlock_shared_and_lock_upgrade_for(rel_time))
0896 {
0897 m = BOOST_THREAD_RV(sl).release();
0898 is_locked = true;
0899 }
0900 }
0901 else
0902 {
0903 m = BOOST_THREAD_RV(sl).release();
0904 }
0905 }
0906 #endif
0907 #endif
0908 void swap(upgrade_lock& other)BOOST_NOEXCEPT
0909 {
0910 std::swap(m,other.m);
0911 std::swap(is_locked,other.is_locked);
0912 }
0913 Mutex* mutex() const BOOST_NOEXCEPT
0914 {
0915 return m;
0916 }
0917
0918 Mutex* release()BOOST_NOEXCEPT
0919 {
0920 Mutex* const res=m;
0921 m=0;
0922 is_locked=false;
0923 return res;
0924 }
0925 ~upgrade_lock()
0926 {
0927 if (owns_lock())
0928 {
0929 m->unlock_upgrade();
0930 }
0931 }
0932 void lock()
0933 {
0934 if (m == 0)
0935 {
0936 boost::throw_exception(
0937 boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost upgrade_lock has no mutex"));
0938 }
0939 if (owns_lock())
0940 {
0941 boost::throw_exception(
0942 boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost upgrade_lock owns already the mutex"));
0943 }
0944 m->lock_upgrade();
0945 is_locked = true;
0946 }
0947 bool try_lock()
0948 {
0949 if (m == 0)
0950 {
0951 boost::throw_exception(
0952 boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost upgrade_lock has no mutex"));
0953 }
0954 if (owns_lock())
0955 {
0956 boost::throw_exception(
0957 boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost upgrade_lock owns already the mutex"));
0958 }
0959 is_locked = m->try_lock_upgrade();
0960 return is_locked;
0961 }
0962 void unlock()
0963 {
0964 if (m == 0)
0965 {
0966 boost::throw_exception(
0967 boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost upgrade_lock has no mutex"));
0968 }
0969 if (!owns_lock())
0970 {
0971 boost::throw_exception(
0972 boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost upgrade_lock doesn't own the mutex"));
0973 }
0974 m->unlock_upgrade();
0975 is_locked = false;
0976 }
0977 #ifdef BOOST_THREAD_USES_CHRONO
0978 template <class Rep, class Period>
0979 bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
0980 {
0981 if(m==0)
0982 {
0983 boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost upgrade_lock has no mutex"));
0984 }
0985 if(owns_lock())
0986 {
0987 boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost upgrade_lock owns already the mutex"));
0988 }
0989 is_locked=m->try_lock_upgrade_for(rel_time);
0990 return is_locked;
0991 }
0992 template <class Clock, class Duration>
0993 bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time)
0994 {
0995 if(m==0)
0996 {
0997 boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost upgrade_lock has no mutex"));
0998 }
0999 if(owns_lock())
1000 {
1001 boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost upgrade_lock owns already the mutex"));
1002 }
1003 is_locked=m->try_lock_upgrade_until(abs_time);
1004 return is_locked;
1005 }
1006 #endif
1007 #if defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
1008 typedef void (upgrade_lock::*bool_type)();
1009 operator bool_type() const BOOST_NOEXCEPT
1010 {
1011 return is_locked?&upgrade_lock::lock:0;
1012 }
1013 bool operator!() const BOOST_NOEXCEPT
1014 {
1015 return !owns_lock();
1016 }
1017 #else
1018 explicit operator bool() const BOOST_NOEXCEPT
1019 {
1020 return owns_lock();
1021 }
1022 #endif
1023 bool owns_lock() const BOOST_NOEXCEPT
1024 {
1025 return is_locked;
1026 }
1027 friend class shared_lock<Mutex> ;
1028 friend class unique_lock<Mutex> ;
1029 };
1030
1031 template<typename Mutex>
1032 void swap(upgrade_lock<Mutex>& lhs, upgrade_lock<Mutex>& rhs)
1033 BOOST_NOEXCEPT
1034 {
1035 lhs.swap(rhs);
1036 }
1037
1038 BOOST_THREAD_DCL_MOVABLE_BEG(Mutex) upgrade_lock<Mutex> BOOST_THREAD_DCL_MOVABLE_END
1039
1040 template<typename Mutex>
1041 unique_lock<Mutex>::unique_lock(BOOST_THREAD_RV_REF_BEG upgrade_lock<Mutex> BOOST_THREAD_RV_REF_END other):
1042 m(BOOST_THREAD_RV(other).m),is_locked(BOOST_THREAD_RV(other).is_locked)
1043 {
1044 if(is_locked)
1045 {
1046 m->unlock_upgrade_and_lock();
1047 }
1048 BOOST_THREAD_RV(other).release();
1049 }
1050
1051 template <class Mutex>
1052 class upgrade_to_unique_lock
1053 {
1054 private:
1055 upgrade_lock<Mutex>* source;
1056 unique_lock<Mutex> exclusive;
1057
1058 public:
1059 typedef Mutex mutex_type;
1060 BOOST_THREAD_MOVABLE_ONLY( upgrade_to_unique_lock)
1061
1062 explicit upgrade_to_unique_lock(upgrade_lock<Mutex>& m_) :
1063 source(&m_), exclusive(::boost::move(*source))
1064 {
1065 }
1066 ~upgrade_to_unique_lock()
1067 {
1068 if (source)
1069 {
1070 *source = BOOST_THREAD_MAKE_RV_REF(upgrade_lock<Mutex> (::boost::move(exclusive)));
1071 }
1072 }
1073
1074 upgrade_to_unique_lock(BOOST_THREAD_RV_REF_BEG upgrade_to_unique_lock<Mutex> BOOST_THREAD_RV_REF_END other) BOOST_NOEXCEPT:
1075 source(BOOST_THREAD_RV(other).source),exclusive(::boost::move(BOOST_THREAD_RV(other).exclusive))
1076 {
1077 BOOST_THREAD_RV(other).source=0;
1078 }
1079
1080
1081 upgrade_to_unique_lock& operator=(BOOST_THREAD_RV_REF_BEG upgrade_to_unique_lock<Mutex> BOOST_THREAD_RV_REF_END other)
1082 {
1083 upgrade_to_unique_lock temp(::boost::move(other));
1084 swap(temp);
1085 return *this;
1086 }
1087
1088 void swap(upgrade_to_unique_lock& other)BOOST_NOEXCEPT
1089 {
1090 std::swap(source,other.source);
1091 exclusive.swap(other.exclusive);
1092 }
1093
1094 #if defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
1095 typedef void (upgrade_to_unique_lock::*bool_type)(upgrade_to_unique_lock&);
1096 operator bool_type() const BOOST_NOEXCEPT
1097 {
1098 return exclusive.owns_lock()?&upgrade_to_unique_lock::swap:0;
1099 }
1100 bool operator!() const BOOST_NOEXCEPT
1101 {
1102 return !owns_lock();
1103 }
1104 #else
1105 explicit operator bool() const BOOST_NOEXCEPT
1106 {
1107 return owns_lock();
1108 }
1109 #endif
1110
1111 bool owns_lock() const BOOST_NOEXCEPT
1112 {
1113 return exclusive.owns_lock();
1114 }
1115 Mutex* mutex() const BOOST_NOEXCEPT
1116 {
1117 return exclusive.mutex();
1118 }
1119 };
1120
1121 BOOST_THREAD_DCL_MOVABLE_BEG(Mutex) upgrade_to_unique_lock<Mutex> BOOST_THREAD_DCL_MOVABLE_END
1122
1123 namespace detail
1124 {
1125 template<typename Mutex>
1126 class try_lock_wrapper:
1127 private unique_lock<Mutex>
1128 {
1129 typedef unique_lock<Mutex> base;
1130 public:
1131 BOOST_THREAD_MOVABLE_ONLY(try_lock_wrapper)
1132
1133 try_lock_wrapper()
1134 {}
1135
1136 explicit try_lock_wrapper(Mutex& m):
1137 base(m,try_to_lock)
1138 {}
1139
1140 try_lock_wrapper(Mutex& m_,adopt_lock_t):
1141 base(m_,adopt_lock)
1142 {
1143 #if ! defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
1144 BOOST_ASSERT(is_locked_by_this_thread(m_));
1145 #endif
1146 }
1147 try_lock_wrapper(Mutex& m_,defer_lock_t):
1148 base(m_,defer_lock)
1149 {}
1150 try_lock_wrapper(Mutex& m_,try_to_lock_t):
1151 base(m_,try_to_lock)
1152 {}
1153 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1154 try_lock_wrapper(BOOST_THREAD_RV_REF(try_lock_wrapper) other):
1155 base(::boost::move(other))
1156 {}
1157
1158 #elif defined BOOST_THREAD_USES_MOVE
1159 try_lock_wrapper(BOOST_THREAD_RV_REF(try_lock_wrapper) other):
1160 base(::boost::move(static_cast<base&>(other)))
1161 {}
1162
1163 #else
1164 try_lock_wrapper(BOOST_THREAD_RV_REF(try_lock_wrapper) other):
1165 base(BOOST_THREAD_RV_REF(base)(*other))
1166 {}
1167 #endif
1168 try_lock_wrapper& operator=(BOOST_THREAD_RV_REF_BEG try_lock_wrapper<Mutex> BOOST_THREAD_RV_REF_END other)
1169 {
1170 try_lock_wrapper temp(::boost::move(other));
1171 swap(temp);
1172 return *this;
1173 }
1174 void swap(try_lock_wrapper& other)
1175 {
1176 base::swap(other);
1177 }
1178 void lock()
1179 {
1180 base::lock();
1181 }
1182 bool try_lock()
1183 {
1184 return base::try_lock();
1185 }
1186 void unlock()
1187 {
1188 base::unlock();
1189 }
1190 bool owns_lock() const
1191 {
1192 return base::owns_lock();
1193 }
1194 Mutex* mutex() const BOOST_NOEXCEPT
1195 {
1196 return base::mutex();
1197 }
1198 Mutex* release()
1199 {
1200 return base::release();
1201 }
1202
1203 #if defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
1204 typedef typename base::bool_type bool_type;
1205 operator bool_type() const
1206 {
1207 return base::operator bool_type();
1208 }
1209 bool operator!() const
1210 {
1211 return !this->owns_lock();
1212 }
1213 #else
1214 explicit operator bool() const
1215 {
1216 return owns_lock();
1217 }
1218 #endif
1219 };
1220
1221 template<typename Mutex>
1222 void swap(try_lock_wrapper<Mutex>& lhs,try_lock_wrapper<Mutex>& rhs)
1223 {
1224 lhs.swap(rhs);
1225 }
1226 }
1227 }
1228 #include <boost/config/abi_suffix.hpp>
1229
1230 #endif