1 // Distributed under the Boost Software License, Version 1.0. (See 2 // accompanying file LICENSE_1_0.txt or copy at 3 // http://www.boost.org/LICENSE_1_0.txt) 4 // (C) Copyright 2007 Anthony Williams 5 #ifndef BOOST_THREAD_LOCKS_HPP 6 #define BOOST_THREAD_LOCKS_HPP 7 #include <boost/thread/detail/config.hpp> 8 #include <boost/thread/exceptions.hpp> 9 #include <boost/thread/detail/move.hpp> 10 #include <algorithm> 11 #include <iterator> 12 #include <boost/thread/thread_time.hpp> 13 #include <boost/detail/workaround.hpp> 14 #include <boost/type_traits/is_class.hpp> 15 16 #include <boost/config/abi_prefix.hpp> 17 18 namespace boost 19 { 20 struct xtime; 21 22 #if defined(BOOST_NO_SFINAE) || \ 23 BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600)) || \ 24 BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590)) 25 #define BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES 26 #endif 27 28 #ifndef BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES 29 namespace detail 30 { 31 #define BOOST_DEFINE_HAS_MEMBER_CALLED(member_name) \ 32 template<typename T, bool=boost::is_class<T>::value> \ 33 struct has_member_called_##member_name \ 34 { \ 35 BOOST_STATIC_CONSTANT(bool, value=false); \ 36 }; \ 37 \ 38 template<typename T> \ 39 struct has_member_called_##member_name<T,true> \ 40 { \ 41 typedef char true_type; \ 42 struct false_type \ 43 { \ 44 true_type dummy[2]; \ 45 }; \ 46 \ 47 struct fallback { int member_name; }; \ 48 struct derived: \ 49 T, fallback \ 50 { \ 51 derived(); \ 52 }; \ 53 \ 54 template<int fallback::*> struct tester; \ 55 \ 56 template<typename U> \ 57 static false_type has_member(tester<&U::member_name>*); \ 58 template<typename U> \ 59 static true_type has_member(...); \ 60 \ 61 BOOST_STATIC_CONSTANT( \ 62 bool, value=sizeof(has_member<derived>(0))==sizeof(true_type)); \ 63 } 64 65 BOOST_DEFINE_HAS_MEMBER_CALLED(lock); 66 BOOST_DEFINE_HAS_MEMBER_CALLED(unlock); 67 BOOST_DEFINE_HAS_MEMBER_CALLED(try_lock); 68 69 template<typename T,bool=has_member_called_lock<T>::value > 70 struct has_member_lock 71 { 72 BOOST_STATIC_CONSTANT(bool, value=false); 73 }; 74 75 template<typename T> 76 struct has_member_lock<T,true> 77 { 78 typedef char true_type; 79 struct false_type 80 { 81 true_type dummy[2]; 82 }; 83 84 template<typename U,typename V> 85 static true_type has_member(V (U::*)()); 86 template<typename U> 87 static false_type has_member(U); 88 89 BOOST_STATIC_CONSTANT( 90 bool,value=sizeof(has_member_lock<T>::has_member(&T::lock))==sizeof(true_type)); 91 }; 92 93 template<typename T,bool=has_member_called_unlock<T>::value > 94 struct has_member_unlock 95 { 96 BOOST_STATIC_CONSTANT(bool, value=false); 97 }; 98 99 template<typename T> 100 struct has_member_unlock<T,true> 101 { 102 typedef char true_type; 103 struct false_type 104 { 105 true_type dummy[2]; 106 }; 107 108 template<typename U,typename V> 109 static true_type has_member(V (U::*)()); 110 template<typename U> 111 static false_type has_member(U); 112 113 BOOST_STATIC_CONSTANT( 114 bool,value=sizeof(has_member_unlock<T>::has_member(&T::unlock))==sizeof(true_type)); 115 }; 116 117 template<typename T,bool=has_member_called_try_lock<T>::value > 118 struct has_member_try_lock 119 { 120 BOOST_STATIC_CONSTANT(bool, value=false); 121 }; 122 123 template<typename T> 124 struct has_member_try_lock<T,true> 125 { 126 typedef char true_type; 127 struct false_type 128 { 129 true_type dummy[2]; 130 }; 131 132 template<typename U> 133 static true_type has_member(bool (U::*)()); 134 template<typename U> 135 static false_type has_member(U); 136 137 BOOST_STATIC_CONSTANT( 138 bool,value=sizeof(has_member_try_lock<T>::has_member(&T::try_lock))==sizeof(true_type)); 139 }; 140 141 } 142 143 144 template<typename T> 145 struct is_mutex_type 146 { 147 BOOST_STATIC_CONSTANT(bool, value = detail::has_member_lock<T>::value && 148 detail::has_member_unlock<T>::value && 149 detail::has_member_try_lock<T>::value); 150 151 }; 152 #else 153 template<typename T> 154 struct is_mutex_type 155 { 156 BOOST_STATIC_CONSTANT(bool, value = false); 157 }; 158 #endif 159 160 struct defer_lock_t 161 {}; 162 struct try_to_lock_t 163 {}; 164 struct adopt_lock_t 165 {}; 166 167 const defer_lock_t defer_lock={}; 168 const try_to_lock_t try_to_lock={}; 169 const adopt_lock_t adopt_lock={}; 170 171 template<typename Mutex> 172 class shared_lock; 173 174 template<typename Mutex> 175 class upgrade_lock; 176 177 template<typename Mutex> 178 class unique_lock; 179 180 namespace detail 181 { 182 template<typename Mutex> 183 class try_lock_wrapper; 184 } 185 186 #ifdef BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES 187 template<typename T> 188 struct is_mutex_type<unique_lock<T> > 189 { 190 BOOST_STATIC_CONSTANT(bool, value = true); 191 }; 192 193 template<typename T> 194 struct is_mutex_type<shared_lock<T> > 195 { 196 BOOST_STATIC_CONSTANT(bool, value = true); 197 }; 198 199 template<typename T> 200 struct is_mutex_type<upgrade_lock<T> > 201 { 202 BOOST_STATIC_CONSTANT(bool, value = true); 203 }; 204 205 template<typename T> 206 struct is_mutex_type<detail::try_lock_wrapper<T> > 207 { 208 BOOST_STATIC_CONSTANT(bool, value = true); 209 }; 210 211 class mutex; 212 class timed_mutex; 213 class recursive_mutex; 214 class recursive_timed_mutex; 215 class shared_mutex; 216 217 template<> 218 struct is_mutex_type<mutex> 219 { 220 BOOST_STATIC_CONSTANT(bool, value = true); 221 }; 222 template<> 223 struct is_mutex_type<timed_mutex> 224 { 225 BOOST_STATIC_CONSTANT(bool, value = true); 226 }; 227 template<> 228 struct is_mutex_type<recursive_mutex> 229 { 230 BOOST_STATIC_CONSTANT(bool, value = true); 231 }; 232 template<> 233 struct is_mutex_type<recursive_timed_mutex> 234 { 235 BOOST_STATIC_CONSTANT(bool, value = true); 236 }; 237 template<> 238 struct is_mutex_type<shared_mutex> 239 { 240 BOOST_STATIC_CONSTANT(bool, value = true); 241 }; 242 243 #endif 244 245 template<typename Mutex> 246 class lock_guard 247 { 248 private: 249 Mutex& m; 250 251 explicit lock_guard(lock_guard&); 252 lock_guard& operator=(lock_guard&); 253 public: lock_guard(Mutex & m_)254 explicit lock_guard(Mutex& m_): 255 m(m_) 256 { 257 m.lock(); 258 } lock_guard(Mutex & m_,adopt_lock_t)259 lock_guard(Mutex& m_,adopt_lock_t): 260 m(m_) 261 {} ~lock_guard()262 ~lock_guard() 263 { 264 m.unlock(); 265 } 266 }; 267 268 269 template<typename Mutex> 270 class unique_lock 271 { 272 private: 273 Mutex* m; 274 bool is_locked; 275 unique_lock(unique_lock&); 276 explicit unique_lock(upgrade_lock<Mutex>&); 277 unique_lock& operator=(unique_lock&); 278 unique_lock& operator=(upgrade_lock<Mutex>& other); 279 public: 280 #if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100) 281 unique_lock(const volatile unique_lock&); 282 #endif unique_lock()283 unique_lock(): 284 m(0),is_locked(false) 285 {} 286 unique_lock(Mutex & m_)287 explicit unique_lock(Mutex& m_): 288 m(&m_),is_locked(false) 289 { 290 lock(); 291 } unique_lock(Mutex & m_,adopt_lock_t)292 unique_lock(Mutex& m_,adopt_lock_t): 293 m(&m_),is_locked(true) 294 {} unique_lock(Mutex & m_,defer_lock_t)295 unique_lock(Mutex& m_,defer_lock_t): 296 m(&m_),is_locked(false) 297 {} unique_lock(Mutex & m_,try_to_lock_t)298 unique_lock(Mutex& m_,try_to_lock_t): 299 m(&m_),is_locked(false) 300 { 301 try_lock(); 302 } 303 template<typename TimeDuration> unique_lock(Mutex & m_,TimeDuration const & target_time)304 unique_lock(Mutex& m_,TimeDuration const& target_time): 305 m(&m_),is_locked(false) 306 { 307 timed_lock(target_time); 308 } unique_lock(Mutex & m_,system_time const & target_time)309 unique_lock(Mutex& m_,system_time const& target_time): 310 m(&m_),is_locked(false) 311 { 312 timed_lock(target_time); 313 } 314 #ifndef BOOST_NO_RVALUE_REFERENCES unique_lock(unique_lock && other)315 unique_lock(unique_lock&& other): 316 m(other.m),is_locked(other.is_locked) 317 { 318 other.is_locked=false; 319 other.m=0; 320 } 321 explicit unique_lock(upgrade_lock<Mutex>&& other); 322 move()323 unique_lock<Mutex>&& move() 324 { 325 return static_cast<unique_lock<Mutex>&&>(*this); 326 } 327 328 operator =(unique_lock && other)329 unique_lock& operator=(unique_lock&& other) 330 { 331 unique_lock temp(other.move()); 332 swap(temp); 333 return *this; 334 } 335 operator =(upgrade_lock<Mutex> && other)336 unique_lock& operator=(upgrade_lock<Mutex>&& other) 337 { 338 unique_lock temp(other.move()); 339 swap(temp); 340 return *this; 341 } swap(unique_lock && other)342 void swap(unique_lock&& other) 343 { 344 std::swap(m,other.m); 345 std::swap(is_locked,other.is_locked); 346 } 347 #else unique_lock(detail::thread_move_t<unique_lock<Mutex>> other)348 unique_lock(detail::thread_move_t<unique_lock<Mutex> > other): 349 m(other->m),is_locked(other->is_locked) 350 { 351 other->is_locked=false; 352 other->m=0; 353 } 354 unique_lock(detail::thread_move_t<upgrade_lock<Mutex> > other); 355 operator detail::thread_move_t<unique_lock<Mutex>>()356 operator detail::thread_move_t<unique_lock<Mutex> >() 357 { 358 return move(); 359 } 360 move()361 detail::thread_move_t<unique_lock<Mutex> > move() 362 { 363 return detail::thread_move_t<unique_lock<Mutex> >(*this); 364 } 365 366 #if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100) operator =(unique_lock<Mutex> other)367 unique_lock& operator=(unique_lock<Mutex> other) 368 { 369 swap(other); 370 return *this; 371 } 372 #else operator =(detail::thread_move_t<unique_lock<Mutex>> other)373 unique_lock& operator=(detail::thread_move_t<unique_lock<Mutex> > other) 374 { 375 unique_lock temp(other); 376 swap(temp); 377 return *this; 378 } 379 #endif 380 operator =(detail::thread_move_t<upgrade_lock<Mutex>> other)381 unique_lock& operator=(detail::thread_move_t<upgrade_lock<Mutex> > other) 382 { 383 unique_lock temp(other); 384 swap(temp); 385 return *this; 386 } swap(detail::thread_move_t<unique_lock<Mutex>> other)387 void swap(detail::thread_move_t<unique_lock<Mutex> > other) 388 { 389 std::swap(m,other->m); 390 std::swap(is_locked,other->is_locked); 391 } 392 #endif swap(unique_lock & other)393 void swap(unique_lock& other) 394 { 395 std::swap(m,other.m); 396 std::swap(is_locked,other.is_locked); 397 } 398 ~unique_lock()399 ~unique_lock() 400 { 401 if(owns_lock()) 402 { 403 m->unlock(); 404 } 405 } lock()406 void lock() 407 { 408 if(owns_lock()) 409 { 410 boost::throw_exception(boost::lock_error()); 411 } 412 m->lock(); 413 is_locked=true; 414 } try_lock()415 bool try_lock() 416 { 417 if(owns_lock()) 418 { 419 boost::throw_exception(boost::lock_error()); 420 } 421 is_locked=m->try_lock(); 422 return is_locked; 423 } 424 template<typename TimeDuration> timed_lock(TimeDuration const & relative_time)425 bool timed_lock(TimeDuration const& relative_time) 426 { 427 is_locked=m->timed_lock(relative_time); 428 return is_locked; 429 } 430 timed_lock(::boost::system_time const & absolute_time)431 bool timed_lock(::boost::system_time const& absolute_time) 432 { 433 is_locked=m->timed_lock(absolute_time); 434 return is_locked; 435 } timed_lock(::boost::xtime const & absolute_time)436 bool timed_lock(::boost::xtime const& absolute_time) 437 { 438 is_locked=m->timed_lock(absolute_time); 439 return is_locked; 440 } unlock()441 void unlock() 442 { 443 if(!owns_lock()) 444 { 445 boost::throw_exception(boost::lock_error()); 446 } 447 m->unlock(); 448 is_locked=false; 449 } 450 451 typedef void (unique_lock::*bool_type)(); operator bool_type() const452 operator bool_type() const 453 { 454 return is_locked?&unique_lock::lock:0; 455 } operator !() const456 bool operator!() const 457 { 458 return !owns_lock(); 459 } owns_lock() const460 bool owns_lock() const 461 { 462 return is_locked; 463 } 464 mutex() const465 Mutex* mutex() const 466 { 467 return m; 468 } 469 release()470 Mutex* release() 471 { 472 Mutex* const res=m; 473 m=0; 474 is_locked=false; 475 return res; 476 } 477 478 friend class shared_lock<Mutex>; 479 friend class upgrade_lock<Mutex>; 480 }; 481 482 #ifndef BOOST_NO_RVALUE_REFERENCES 483 template<typename Mutex> swap(unique_lock<Mutex> && lhs,unique_lock<Mutex> && rhs)484 void swap(unique_lock<Mutex>&& lhs,unique_lock<Mutex>&& rhs) 485 { 486 lhs.swap(rhs); 487 } 488 489 template<typename Mutex> move(upgrade_lock<Mutex> && ul)490 inline upgrade_lock<Mutex>&& move(upgrade_lock<Mutex>&& ul) 491 { 492 return static_cast<upgrade_lock<Mutex>&&>(ul); 493 } 494 495 template<typename Mutex> move(upgrade_lock<Mutex> & ul)496 inline upgrade_lock<Mutex>&& move(upgrade_lock<Mutex>& ul) 497 { 498 return static_cast<upgrade_lock<Mutex>&&>(ul); 499 } 500 #endif 501 template<typename Mutex> swap(unique_lock<Mutex> & lhs,unique_lock<Mutex> & rhs)502 void swap(unique_lock<Mutex>& lhs,unique_lock<Mutex>& rhs) 503 { 504 lhs.swap(rhs); 505 } 506 507 #ifndef BOOST_NO_RVALUE_REFERENCES 508 template<typename Mutex> move(unique_lock<Mutex> && ul)509 inline unique_lock<Mutex>&& move(unique_lock<Mutex>&& ul) 510 { 511 return static_cast<unique_lock<Mutex>&&>(ul); 512 } 513 514 template<typename Mutex> move(unique_lock<Mutex> & ul)515 inline unique_lock<Mutex>&& move(unique_lock<Mutex>& ul) 516 { 517 return static_cast<unique_lock<Mutex>&&>(ul); 518 } 519 #endif 520 521 template<typename Mutex> 522 class shared_lock 523 { 524 protected: 525 Mutex* m; 526 bool is_locked; 527 private: 528 explicit shared_lock(shared_lock&); 529 shared_lock& operator=(shared_lock&); 530 public: shared_lock()531 shared_lock(): 532 m(0),is_locked(false) 533 {} 534 shared_lock(Mutex & m_)535 explicit shared_lock(Mutex& m_): 536 m(&m_),is_locked(false) 537 { 538 lock(); 539 } shared_lock(Mutex & m_,adopt_lock_t)540 shared_lock(Mutex& m_,adopt_lock_t): 541 m(&m_),is_locked(true) 542 {} shared_lock(Mutex & m_,defer_lock_t)543 shared_lock(Mutex& m_,defer_lock_t): 544 m(&m_),is_locked(false) 545 {} shared_lock(Mutex & m_,try_to_lock_t)546 shared_lock(Mutex& m_,try_to_lock_t): 547 m(&m_),is_locked(false) 548 { 549 try_lock(); 550 } shared_lock(Mutex & m_,system_time const & target_time)551 shared_lock(Mutex& m_,system_time const& target_time): 552 m(&m_),is_locked(false) 553 { 554 timed_lock(target_time); 555 } 556 shared_lock(detail::thread_move_t<shared_lock<Mutex>> other)557 shared_lock(detail::thread_move_t<shared_lock<Mutex> > other): 558 m(other->m),is_locked(other->is_locked) 559 { 560 other->is_locked=false; 561 other->m=0; 562 } 563 shared_lock(detail::thread_move_t<unique_lock<Mutex>> other)564 shared_lock(detail::thread_move_t<unique_lock<Mutex> > other): 565 m(other->m),is_locked(other->is_locked) 566 { 567 if(is_locked) 568 { 569 m->unlock_and_lock_shared(); 570 } 571 other->is_locked=false; 572 other->m=0; 573 } 574 shared_lock(detail::thread_move_t<upgrade_lock<Mutex>> other)575 shared_lock(detail::thread_move_t<upgrade_lock<Mutex> > other): 576 m(other->m),is_locked(other->is_locked) 577 { 578 if(is_locked) 579 { 580 m->unlock_upgrade_and_lock_shared(); 581 } 582 other->is_locked=false; 583 other->m=0; 584 } 585 operator detail::thread_move_t<shared_lock<Mutex>>()586 operator detail::thread_move_t<shared_lock<Mutex> >() 587 { 588 return move(); 589 } 590 move()591 detail::thread_move_t<shared_lock<Mutex> > move() 592 { 593 return detail::thread_move_t<shared_lock<Mutex> >(*this); 594 } 595 596 operator =(detail::thread_move_t<shared_lock<Mutex>> other)597 shared_lock& operator=(detail::thread_move_t<shared_lock<Mutex> > other) 598 { 599 shared_lock temp(other); 600 swap(temp); 601 return *this; 602 } 603 operator =(detail::thread_move_t<unique_lock<Mutex>> other)604 shared_lock& operator=(detail::thread_move_t<unique_lock<Mutex> > other) 605 { 606 shared_lock temp(other); 607 swap(temp); 608 return *this; 609 } 610 operator =(detail::thread_move_t<upgrade_lock<Mutex>> other)611 shared_lock& operator=(detail::thread_move_t<upgrade_lock<Mutex> > other) 612 { 613 shared_lock temp(other); 614 swap(temp); 615 return *this; 616 } 617 618 #ifndef BOOST_NO_RVALUE_REFERENCES swap(shared_lock && other)619 void swap(shared_lock&& other) 620 { 621 std::swap(m,other.m); 622 std::swap(is_locked,other.is_locked); 623 } 624 #else swap(boost::detail::thread_move_t<shared_lock<Mutex>> other)625 void swap(boost::detail::thread_move_t<shared_lock<Mutex> > other) 626 { 627 std::swap(m,other->m); 628 std::swap(is_locked,other->is_locked); 629 } 630 #endif swap(shared_lock & other)631 void swap(shared_lock& other) 632 { 633 std::swap(m,other.m); 634 std::swap(is_locked,other.is_locked); 635 } 636 mutex() const637 Mutex* mutex() const 638 { 639 return m; 640 } 641 ~shared_lock()642 ~shared_lock() 643 { 644 if(owns_lock()) 645 { 646 m->unlock_shared(); 647 } 648 } lock()649 void lock() 650 { 651 if(owns_lock()) 652 { 653 boost::throw_exception(boost::lock_error()); 654 } 655 m->lock_shared(); 656 is_locked=true; 657 } try_lock()658 bool try_lock() 659 { 660 if(owns_lock()) 661 { 662 boost::throw_exception(boost::lock_error()); 663 } 664 is_locked=m->try_lock_shared(); 665 return is_locked; 666 } timed_lock(boost::system_time const & target_time)667 bool timed_lock(boost::system_time const& target_time) 668 { 669 if(owns_lock()) 670 { 671 boost::throw_exception(boost::lock_error()); 672 } 673 is_locked=m->timed_lock_shared(target_time); 674 return is_locked; 675 } 676 template<typename Duration> timed_lock(Duration const & target_time)677 bool timed_lock(Duration const& target_time) 678 { 679 if(owns_lock()) 680 { 681 boost::throw_exception(boost::lock_error()); 682 } 683 is_locked=m->timed_lock_shared(target_time); 684 return is_locked; 685 } unlock()686 void unlock() 687 { 688 if(!owns_lock()) 689 { 690 boost::throw_exception(boost::lock_error()); 691 } 692 m->unlock_shared(); 693 is_locked=false; 694 } 695 696 typedef void (shared_lock<Mutex>::*bool_type)(); operator bool_type() const697 operator bool_type() const 698 { 699 return is_locked?&shared_lock::lock:0; 700 } operator !() const701 bool operator!() const 702 { 703 return !owns_lock(); 704 } owns_lock() const705 bool owns_lock() const 706 { 707 return is_locked; 708 } 709 710 }; 711 712 #ifndef BOOST_NO_RVALUE_REFERENCES 713 template<typename Mutex> swap(shared_lock<Mutex> && lhs,shared_lock<Mutex> && rhs)714 void swap(shared_lock<Mutex>&& lhs,shared_lock<Mutex>&& rhs) 715 { 716 lhs.swap(rhs); 717 } 718 #else 719 template<typename Mutex> swap(shared_lock<Mutex> & lhs,shared_lock<Mutex> & rhs)720 void swap(shared_lock<Mutex>& lhs,shared_lock<Mutex>& rhs) 721 { 722 lhs.swap(rhs); 723 } 724 #endif 725 726 template<typename Mutex> 727 class upgrade_lock 728 { 729 protected: 730 Mutex* m; 731 bool is_locked; 732 private: 733 explicit upgrade_lock(upgrade_lock&); 734 upgrade_lock& operator=(upgrade_lock&); 735 public: upgrade_lock()736 upgrade_lock(): 737 m(0),is_locked(false) 738 {} 739 upgrade_lock(Mutex & m_)740 explicit upgrade_lock(Mutex& m_): 741 m(&m_),is_locked(false) 742 { 743 lock(); 744 } upgrade_lock(Mutex & m_,adopt_lock_t)745 upgrade_lock(Mutex& m_,adopt_lock_t): 746 m(&m_),is_locked(true) 747 {} upgrade_lock(Mutex & m_,defer_lock_t)748 upgrade_lock(Mutex& m_,defer_lock_t): 749 m(&m_),is_locked(false) 750 {} upgrade_lock(Mutex & m_,try_to_lock_t)751 upgrade_lock(Mutex& m_,try_to_lock_t): 752 m(&m_),is_locked(false) 753 { 754 try_lock(); 755 } 756 #ifdef BOOST_HAS_RVALUE_REFS upgrade_lock(upgrade_lock<Mutex> && other)757 upgrade_lock(upgrade_lock<Mutex>&& other): 758 m(other.m),is_locked(other.is_locked) 759 { 760 other.is_locked=false; 761 other.m=0; 762 } 763 upgrade_lock(unique_lock<Mutex> && other)764 upgrade_lock(unique_lock<Mutex>&& other): 765 m(other.m),is_locked(other.is_locked) 766 { 767 if(is_locked) 768 { 769 m->unlock_and_lock_upgrade(); 770 } 771 other.is_locked=false; 772 other.m=0; 773 } 774 operator =(upgrade_lock<Mutex> && other)775 upgrade_lock& operator=(upgrade_lock<Mutex>&& other) 776 { 777 upgrade_lock temp(static_cast<upgrade_lock<Mutex>&&>(other)); 778 swap(temp); 779 return *this; 780 } 781 operator =(unique_lock<Mutex> && other)782 upgrade_lock& operator=(unique_lock<Mutex>&& other) 783 { 784 upgrade_lock temp(static_cast<unique_lock<Mutex>&&>(other)); 785 swap(temp); 786 return *this; 787 } 788 #else upgrade_lock(detail::thread_move_t<upgrade_lock<Mutex>> other)789 upgrade_lock(detail::thread_move_t<upgrade_lock<Mutex> > other): 790 m(other->m),is_locked(other->is_locked) 791 { 792 other->is_locked=false; 793 other->m=0; 794 } 795 upgrade_lock(detail::thread_move_t<unique_lock<Mutex>> other)796 upgrade_lock(detail::thread_move_t<unique_lock<Mutex> > other): 797 m(other->m),is_locked(other->is_locked) 798 { 799 if(is_locked) 800 { 801 m->unlock_and_lock_upgrade(); 802 } 803 other->is_locked=false; 804 other->m=0; 805 } 806 operator detail::thread_move_t<upgrade_lock<Mutex>>()807 operator detail::thread_move_t<upgrade_lock<Mutex> >() 808 { 809 return move(); 810 } 811 move()812 detail::thread_move_t<upgrade_lock<Mutex> > move() 813 { 814 return detail::thread_move_t<upgrade_lock<Mutex> >(*this); 815 } 816 817 operator =(detail::thread_move_t<upgrade_lock<Mutex>> other)818 upgrade_lock& operator=(detail::thread_move_t<upgrade_lock<Mutex> > other) 819 { 820 upgrade_lock temp(other); 821 swap(temp); 822 return *this; 823 } 824 operator =(detail::thread_move_t<unique_lock<Mutex>> other)825 upgrade_lock& operator=(detail::thread_move_t<unique_lock<Mutex> > other) 826 { 827 upgrade_lock temp(other); 828 swap(temp); 829 return *this; 830 } 831 #endif 832 swap(upgrade_lock & other)833 void swap(upgrade_lock& other) 834 { 835 std::swap(m,other.m); 836 std::swap(is_locked,other.is_locked); 837 } 838 ~upgrade_lock()839 ~upgrade_lock() 840 { 841 if(owns_lock()) 842 { 843 m->unlock_upgrade(); 844 } 845 } lock()846 void lock() 847 { 848 if(owns_lock()) 849 { 850 boost::throw_exception(boost::lock_error()); 851 } 852 m->lock_upgrade(); 853 is_locked=true; 854 } try_lock()855 bool try_lock() 856 { 857 if(owns_lock()) 858 { 859 boost::throw_exception(boost::lock_error()); 860 } 861 is_locked=m->try_lock_upgrade(); 862 return is_locked; 863 } unlock()864 void unlock() 865 { 866 if(!owns_lock()) 867 { 868 boost::throw_exception(boost::lock_error()); 869 } 870 m->unlock_upgrade(); 871 is_locked=false; 872 } 873 874 typedef void (upgrade_lock::*bool_type)(); operator bool_type() const875 operator bool_type() const 876 { 877 return is_locked?&upgrade_lock::lock:0; 878 } operator !() const879 bool operator!() const 880 { 881 return !owns_lock(); 882 } owns_lock() const883 bool owns_lock() const 884 { 885 return is_locked; 886 } 887 friend class shared_lock<Mutex>; 888 friend class unique_lock<Mutex>; 889 }; 890 891 892 #ifndef BOOST_NO_RVALUE_REFERENCES 893 template<typename Mutex> unique_lock(upgrade_lock<Mutex> && other)894 unique_lock<Mutex>::unique_lock(upgrade_lock<Mutex>&& other): 895 m(other.m),is_locked(other.is_locked) 896 { 897 other.is_locked=false; 898 if(is_locked) 899 { 900 m->unlock_upgrade_and_lock(); 901 } 902 } 903 #else 904 template<typename Mutex> unique_lock(detail::thread_move_t<upgrade_lock<Mutex>> other)905 unique_lock<Mutex>::unique_lock(detail::thread_move_t<upgrade_lock<Mutex> > other): 906 m(other->m),is_locked(other->is_locked) 907 { 908 other->is_locked=false; 909 if(is_locked) 910 { 911 m->unlock_upgrade_and_lock(); 912 } 913 } 914 #endif 915 template <class Mutex> 916 class upgrade_to_unique_lock 917 { 918 private: 919 upgrade_lock<Mutex>* source; 920 unique_lock<Mutex> exclusive; 921 922 explicit upgrade_to_unique_lock(upgrade_to_unique_lock&); 923 upgrade_to_unique_lock& operator=(upgrade_to_unique_lock&); 924 public: upgrade_to_unique_lock(upgrade_lock<Mutex> & m_)925 explicit upgrade_to_unique_lock(upgrade_lock<Mutex>& m_): 926 source(&m_),exclusive(move(*source)) 927 {} ~upgrade_to_unique_lock()928 ~upgrade_to_unique_lock() 929 { 930 if(source) 931 { 932 *source=move(exclusive); 933 } 934 } 935 936 #ifdef BOOST_HAS_RVALUE_REFS upgrade_to_unique_lock(upgrade_to_unique_lock<Mutex> && other)937 upgrade_to_unique_lock(upgrade_to_unique_lock<Mutex>&& other): 938 source(other.source),exclusive(move(other.exclusive)) 939 { 940 other.source=0; 941 } 942 operator =(upgrade_to_unique_lock<Mutex> && other)943 upgrade_to_unique_lock& operator=(upgrade_to_unique_lock<Mutex>&& other) 944 { 945 upgrade_to_unique_lock temp(other); 946 swap(temp); 947 return *this; 948 } 949 #else upgrade_to_unique_lock(detail::thread_move_t<upgrade_to_unique_lock<Mutex>> other)950 upgrade_to_unique_lock(detail::thread_move_t<upgrade_to_unique_lock<Mutex> > other): 951 source(other->source),exclusive(move(other->exclusive)) 952 { 953 other->source=0; 954 } 955 operator =(detail::thread_move_t<upgrade_to_unique_lock<Mutex>> other)956 upgrade_to_unique_lock& operator=(detail::thread_move_t<upgrade_to_unique_lock<Mutex> > other) 957 { 958 upgrade_to_unique_lock temp(other); 959 swap(temp); 960 return *this; 961 } 962 #endif swap(upgrade_to_unique_lock & other)963 void swap(upgrade_to_unique_lock& other) 964 { 965 std::swap(source,other.source); 966 exclusive.swap(other.exclusive); 967 } 968 typedef void (upgrade_to_unique_lock::*bool_type)(upgrade_to_unique_lock&); operator bool_type() const969 operator bool_type() const 970 { 971 return exclusive.owns_lock()?&upgrade_to_unique_lock::swap:0; 972 } operator !() const973 bool operator!() const 974 { 975 return !owns_lock(); 976 } owns_lock() const977 bool owns_lock() const 978 { 979 return exclusive.owns_lock(); 980 } 981 }; 982 983 namespace detail 984 { 985 template<typename Mutex> 986 class try_lock_wrapper: 987 private unique_lock<Mutex> 988 { 989 typedef unique_lock<Mutex> base; 990 public: try_lock_wrapper()991 try_lock_wrapper() 992 {} 993 try_lock_wrapper(Mutex & m)994 explicit try_lock_wrapper(Mutex& m): 995 base(m,try_to_lock) 996 {} 997 try_lock_wrapper(Mutex & m_,adopt_lock_t)998 try_lock_wrapper(Mutex& m_,adopt_lock_t): 999 base(m_,adopt_lock) 1000 {} try_lock_wrapper(Mutex & m_,defer_lock_t)1001 try_lock_wrapper(Mutex& m_,defer_lock_t): 1002 base(m_,defer_lock) 1003 {} try_lock_wrapper(Mutex & m_,try_to_lock_t)1004 try_lock_wrapper(Mutex& m_,try_to_lock_t): 1005 base(m_,try_to_lock) 1006 {} 1007 #ifndef BOOST_NO_RVALUE_REFERENCES try_lock_wrapper(try_lock_wrapper && other)1008 try_lock_wrapper(try_lock_wrapper&& other): 1009 base(other.move()) 1010 {} 1011 move()1012 try_lock_wrapper&& move() 1013 { 1014 return static_cast<try_lock_wrapper&&>(*this); 1015 } 1016 operator =(try_lock_wrapper<Mutex> && other)1017 try_lock_wrapper& operator=(try_lock_wrapper<Mutex>&& other) 1018 { 1019 try_lock_wrapper temp(other.move()); 1020 swap(temp); 1021 return *this; 1022 } 1023 swap(try_lock_wrapper && other)1024 void swap(try_lock_wrapper&& other) 1025 { 1026 base::swap(other); 1027 } 1028 #else try_lock_wrapper(detail::thread_move_t<try_lock_wrapper<Mutex>> other)1029 try_lock_wrapper(detail::thread_move_t<try_lock_wrapper<Mutex> > other): 1030 base(detail::thread_move_t<base>(*other)) 1031 {} 1032 operator detail::thread_move_t<try_lock_wrapper<Mutex>>()1033 operator detail::thread_move_t<try_lock_wrapper<Mutex> >() 1034 { 1035 return move(); 1036 } 1037 move()1038 detail::thread_move_t<try_lock_wrapper<Mutex> > move() 1039 { 1040 return detail::thread_move_t<try_lock_wrapper<Mutex> >(*this); 1041 } 1042 operator =(detail::thread_move_t<try_lock_wrapper<Mutex>> other)1043 try_lock_wrapper& operator=(detail::thread_move_t<try_lock_wrapper<Mutex> > other) 1044 { 1045 try_lock_wrapper temp(other); 1046 swap(temp); 1047 return *this; 1048 } 1049 swap(detail::thread_move_t<try_lock_wrapper<Mutex>> other)1050 void swap(detail::thread_move_t<try_lock_wrapper<Mutex> > other) 1051 { 1052 base::swap(*other); 1053 } 1054 #endif swap(try_lock_wrapper & other)1055 void swap(try_lock_wrapper& other) 1056 { 1057 base::swap(other); 1058 } lock()1059 void lock() 1060 { 1061 base::lock(); 1062 } try_lock()1063 bool try_lock() 1064 { 1065 return base::try_lock(); 1066 } unlock()1067 void unlock() 1068 { 1069 base::unlock(); 1070 } owns_lock() const1071 bool owns_lock() const 1072 { 1073 return base::owns_lock(); 1074 } mutex() const1075 Mutex* mutex() const 1076 { 1077 return base::mutex(); 1078 } release()1079 Mutex* release() 1080 { 1081 return base::release(); 1082 } operator !() const1083 bool operator!() const 1084 { 1085 return !this->owns_lock(); 1086 } 1087 1088 typedef typename base::bool_type bool_type; operator bool_type() const1089 operator bool_type() const 1090 { 1091 return base::operator bool_type(); 1092 } 1093 }; 1094 1095 #ifndef BOOST_NO_RVALUE_REFERENCES 1096 template<typename Mutex> swap(try_lock_wrapper<Mutex> && lhs,try_lock_wrapper<Mutex> && rhs)1097 void swap(try_lock_wrapper<Mutex>&& lhs,try_lock_wrapper<Mutex>&& rhs) 1098 { 1099 lhs.swap(rhs); 1100 } 1101 #else 1102 template<typename Mutex> swap(try_lock_wrapper<Mutex> & lhs,try_lock_wrapper<Mutex> & rhs)1103 void swap(try_lock_wrapper<Mutex>& lhs,try_lock_wrapper<Mutex>& rhs) 1104 { 1105 lhs.swap(rhs); 1106 } 1107 #endif 1108 1109 template<typename MutexType1,typename MutexType2> try_lock_internal(MutexType1 & m1,MutexType2 & m2)1110 unsigned try_lock_internal(MutexType1& m1,MutexType2& m2) 1111 { 1112 boost::unique_lock<MutexType1> l1(m1,boost::try_to_lock); 1113 if(!l1) 1114 { 1115 return 1; 1116 } 1117 if(!m2.try_lock()) 1118 { 1119 return 2; 1120 } 1121 l1.release(); 1122 return 0; 1123 } 1124 1125 template<typename MutexType1,typename MutexType2,typename MutexType3> try_lock_internal(MutexType1 & m1,MutexType2 & m2,MutexType3 & m3)1126 unsigned try_lock_internal(MutexType1& m1,MutexType2& m2,MutexType3& m3) 1127 { 1128 boost::unique_lock<MutexType1> l1(m1,boost::try_to_lock); 1129 if(!l1) 1130 { 1131 return 1; 1132 } 1133 if(unsigned const failed_lock=try_lock_internal(m2,m3)) 1134 { 1135 return failed_lock+1; 1136 } 1137 l1.release(); 1138 return 0; 1139 } 1140 1141 1142 template<typename MutexType1,typename MutexType2,typename MutexType3, 1143 typename MutexType4> try_lock_internal(MutexType1 & m1,MutexType2 & m2,MutexType3 & m3,MutexType4 & m4)1144 unsigned try_lock_internal(MutexType1& m1,MutexType2& m2,MutexType3& m3, 1145 MutexType4& m4) 1146 { 1147 boost::unique_lock<MutexType1> l1(m1,boost::try_to_lock); 1148 if(!l1) 1149 { 1150 return 1; 1151 } 1152 if(unsigned const failed_lock=try_lock_internal(m2,m3,m4)) 1153 { 1154 return failed_lock+1; 1155 } 1156 l1.release(); 1157 return 0; 1158 } 1159 1160 template<typename MutexType1,typename MutexType2,typename MutexType3, 1161 typename MutexType4,typename MutexType5> try_lock_internal(MutexType1 & m1,MutexType2 & m2,MutexType3 & m3,MutexType4 & m4,MutexType5 & m5)1162 unsigned try_lock_internal(MutexType1& m1,MutexType2& m2,MutexType3& m3, 1163 MutexType4& m4,MutexType5& m5) 1164 { 1165 boost::unique_lock<MutexType1> l1(m1,boost::try_to_lock); 1166 if(!l1) 1167 { 1168 return 1; 1169 } 1170 if(unsigned const failed_lock=try_lock_internal(m2,m3,m4,m5)) 1171 { 1172 return failed_lock+1; 1173 } 1174 l1.release(); 1175 return 0; 1176 } 1177 1178 1179 template<typename MutexType1,typename MutexType2> lock_helper(MutexType1 & m1,MutexType2 & m2)1180 unsigned lock_helper(MutexType1& m1,MutexType2& m2) 1181 { 1182 boost::unique_lock<MutexType1> l1(m1); 1183 if(!m2.try_lock()) 1184 { 1185 return 1; 1186 } 1187 l1.release(); 1188 return 0; 1189 } 1190 1191 template<typename MutexType1,typename MutexType2,typename MutexType3> lock_helper(MutexType1 & m1,MutexType2 & m2,MutexType3 & m3)1192 unsigned lock_helper(MutexType1& m1,MutexType2& m2,MutexType3& m3) 1193 { 1194 boost::unique_lock<MutexType1> l1(m1); 1195 if(unsigned const failed_lock=try_lock_internal(m2,m3)) 1196 { 1197 return failed_lock; 1198 } 1199 l1.release(); 1200 return 0; 1201 } 1202 1203 template<typename MutexType1,typename MutexType2,typename MutexType3, 1204 typename MutexType4> lock_helper(MutexType1 & m1,MutexType2 & m2,MutexType3 & m3,MutexType4 & m4)1205 unsigned lock_helper(MutexType1& m1,MutexType2& m2,MutexType3& m3, 1206 MutexType4& m4) 1207 { 1208 boost::unique_lock<MutexType1> l1(m1); 1209 if(unsigned const failed_lock=try_lock_internal(m2,m3,m4)) 1210 { 1211 return failed_lock; 1212 } 1213 l1.release(); 1214 return 0; 1215 } 1216 1217 template<typename MutexType1,typename MutexType2,typename MutexType3, 1218 typename MutexType4,typename MutexType5> lock_helper(MutexType1 & m1,MutexType2 & m2,MutexType3 & m3,MutexType4 & m4,MutexType5 & m5)1219 unsigned lock_helper(MutexType1& m1,MutexType2& m2,MutexType3& m3, 1220 MutexType4& m4,MutexType5& m5) 1221 { 1222 boost::unique_lock<MutexType1> l1(m1); 1223 if(unsigned const failed_lock=try_lock_internal(m2,m3,m4,m5)) 1224 { 1225 return failed_lock; 1226 } 1227 l1.release(); 1228 return 0; 1229 } 1230 } 1231 1232 namespace detail 1233 { 1234 template<bool x> 1235 struct is_mutex_type_wrapper 1236 {}; 1237 1238 template<typename MutexType1,typename MutexType2> lock_impl(MutexType1 & m1,MutexType2 & m2,is_mutex_type_wrapper<true>)1239 void lock_impl(MutexType1& m1,MutexType2& m2,is_mutex_type_wrapper<true>) 1240 { 1241 unsigned const lock_count=2; 1242 unsigned lock_first=0; 1243 for(;;) 1244 { 1245 switch(lock_first) 1246 { 1247 case 0: 1248 lock_first=detail::lock_helper(m1,m2); 1249 if(!lock_first) 1250 return; 1251 break; 1252 case 1: 1253 lock_first=detail::lock_helper(m2,m1); 1254 if(!lock_first) 1255 return; 1256 lock_first=(lock_first+1)%lock_count; 1257 break; 1258 } 1259 } 1260 } 1261 1262 template<typename Iterator> 1263 void lock_impl(Iterator begin,Iterator end,is_mutex_type_wrapper<false>); 1264 } 1265 1266 1267 template<typename MutexType1,typename MutexType2> lock(MutexType1 & m1,MutexType2 & m2)1268 void lock(MutexType1& m1,MutexType2& m2) 1269 { 1270 detail::lock_impl(m1,m2,detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>()); 1271 } 1272 1273 template<typename MutexType1,typename MutexType2> lock(const MutexType1 & m1,MutexType2 & m2)1274 void lock(const MutexType1& m1,MutexType2& m2) 1275 { 1276 detail::lock_impl(m1,m2,detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>()); 1277 } 1278 1279 template<typename MutexType1,typename MutexType2> lock(MutexType1 & m1,const MutexType2 & m2)1280 void lock(MutexType1& m1,const MutexType2& m2) 1281 { 1282 detail::lock_impl(m1,m2,detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>()); 1283 } 1284 1285 template<typename MutexType1,typename MutexType2> lock(const MutexType1 & m1,const MutexType2 & m2)1286 void lock(const MutexType1& m1,const MutexType2& m2) 1287 { 1288 detail::lock_impl(m1,m2,detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>()); 1289 } 1290 1291 template<typename MutexType1,typename MutexType2,typename MutexType3> lock(MutexType1 & m1,MutexType2 & m2,MutexType3 & m3)1292 void lock(MutexType1& m1,MutexType2& m2,MutexType3& m3) 1293 { 1294 unsigned const lock_count=3; 1295 unsigned lock_first=0; 1296 for(;;) 1297 { 1298 switch(lock_first) 1299 { 1300 case 0: 1301 lock_first=detail::lock_helper(m1,m2,m3); 1302 if(!lock_first) 1303 return; 1304 break; 1305 case 1: 1306 lock_first=detail::lock_helper(m2,m3,m1); 1307 if(!lock_first) 1308 return; 1309 lock_first=(lock_first+1)%lock_count; 1310 break; 1311 case 2: 1312 lock_first=detail::lock_helper(m3,m1,m2); 1313 if(!lock_first) 1314 return; 1315 lock_first=(lock_first+2)%lock_count; 1316 break; 1317 } 1318 } 1319 } 1320 1321 template<typename MutexType1,typename MutexType2,typename MutexType3, 1322 typename MutexType4> lock(MutexType1 & m1,MutexType2 & m2,MutexType3 & m3,MutexType4 & m4)1323 void lock(MutexType1& m1,MutexType2& m2,MutexType3& m3, 1324 MutexType4& m4) 1325 { 1326 unsigned const lock_count=4; 1327 unsigned lock_first=0; 1328 for(;;) 1329 { 1330 switch(lock_first) 1331 { 1332 case 0: 1333 lock_first=detail::lock_helper(m1,m2,m3,m4); 1334 if(!lock_first) 1335 return; 1336 break; 1337 case 1: 1338 lock_first=detail::lock_helper(m2,m3,m4,m1); 1339 if(!lock_first) 1340 return; 1341 lock_first=(lock_first+1)%lock_count; 1342 break; 1343 case 2: 1344 lock_first=detail::lock_helper(m3,m4,m1,m2); 1345 if(!lock_first) 1346 return; 1347 lock_first=(lock_first+2)%lock_count; 1348 break; 1349 case 3: 1350 lock_first=detail::lock_helper(m4,m1,m2,m3); 1351 if(!lock_first) 1352 return; 1353 lock_first=(lock_first+3)%lock_count; 1354 break; 1355 } 1356 } 1357 } 1358 1359 template<typename MutexType1,typename MutexType2,typename MutexType3, 1360 typename MutexType4,typename MutexType5> lock(MutexType1 & m1,MutexType2 & m2,MutexType3 & m3,MutexType4 & m4,MutexType5 & m5)1361 void lock(MutexType1& m1,MutexType2& m2,MutexType3& m3, 1362 MutexType4& m4,MutexType5& m5) 1363 { 1364 unsigned const lock_count=5; 1365 unsigned lock_first=0; 1366 for(;;) 1367 { 1368 switch(lock_first) 1369 { 1370 case 0: 1371 lock_first=detail::lock_helper(m1,m2,m3,m4,m5); 1372 if(!lock_first) 1373 return; 1374 break; 1375 case 1: 1376 lock_first=detail::lock_helper(m2,m3,m4,m5,m1); 1377 if(!lock_first) 1378 return; 1379 lock_first=(lock_first+1)%lock_count; 1380 break; 1381 case 2: 1382 lock_first=detail::lock_helper(m3,m4,m5,m1,m2); 1383 if(!lock_first) 1384 return; 1385 lock_first=(lock_first+2)%lock_count; 1386 break; 1387 case 3: 1388 lock_first=detail::lock_helper(m4,m5,m1,m2,m3); 1389 if(!lock_first) 1390 return; 1391 lock_first=(lock_first+3)%lock_count; 1392 break; 1393 case 4: 1394 lock_first=detail::lock_helper(m5,m1,m2,m3,m4); 1395 if(!lock_first) 1396 return; 1397 lock_first=(lock_first+4)%lock_count; 1398 break; 1399 } 1400 } 1401 } 1402 1403 namespace detail 1404 { 1405 template<typename Mutex,bool x=is_mutex_type<Mutex>::value> 1406 struct try_lock_impl_return 1407 { 1408 typedef int type; 1409 }; 1410 1411 template<typename Iterator> 1412 struct try_lock_impl_return<Iterator,false> 1413 { 1414 typedef Iterator type; 1415 }; 1416 1417 template<typename MutexType1,typename MutexType2> try_lock_impl(MutexType1 & m1,MutexType2 & m2,is_mutex_type_wrapper<true>)1418 int try_lock_impl(MutexType1& m1,MutexType2& m2,is_mutex_type_wrapper<true>) 1419 { 1420 return ((int)detail::try_lock_internal(m1,m2))-1; 1421 } 1422 1423 template<typename Iterator> 1424 Iterator try_lock_impl(Iterator begin,Iterator end,is_mutex_type_wrapper<false>); 1425 } 1426 1427 template<typename MutexType1,typename MutexType2> try_lock(MutexType1 & m1,MutexType2 & m2)1428 typename detail::try_lock_impl_return<MutexType1>::type try_lock(MutexType1& m1,MutexType2& m2) 1429 { 1430 return detail::try_lock_impl(m1,m2,detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>()); 1431 } 1432 1433 template<typename MutexType1,typename MutexType2> try_lock(const MutexType1 & m1,MutexType2 & m2)1434 typename detail::try_lock_impl_return<MutexType1>::type try_lock(const MutexType1& m1,MutexType2& m2) 1435 { 1436 return detail::try_lock_impl(m1,m2,detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>()); 1437 } 1438 1439 template<typename MutexType1,typename MutexType2> try_lock(MutexType1 & m1,const MutexType2 & m2)1440 typename detail::try_lock_impl_return<MutexType1>::type try_lock(MutexType1& m1,const MutexType2& m2) 1441 { 1442 return detail::try_lock_impl(m1,m2,detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>()); 1443 } 1444 1445 template<typename MutexType1,typename MutexType2> try_lock(const MutexType1 & m1,const MutexType2 & m2)1446 typename detail::try_lock_impl_return<MutexType1>::type try_lock(const MutexType1& m1,const MutexType2& m2) 1447 { 1448 return detail::try_lock_impl(m1,m2,detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>()); 1449 } 1450 1451 template<typename MutexType1,typename MutexType2,typename MutexType3> try_lock(MutexType1 & m1,MutexType2 & m2,MutexType3 & m3)1452 int try_lock(MutexType1& m1,MutexType2& m2,MutexType3& m3) 1453 { 1454 return ((int)detail::try_lock_internal(m1,m2,m3))-1; 1455 } 1456 1457 template<typename MutexType1,typename MutexType2,typename MutexType3,typename MutexType4> try_lock(MutexType1 & m1,MutexType2 & m2,MutexType3 & m3,MutexType4 & m4)1458 int try_lock(MutexType1& m1,MutexType2& m2,MutexType3& m3,MutexType4& m4) 1459 { 1460 return ((int)detail::try_lock_internal(m1,m2,m3,m4))-1; 1461 } 1462 1463 template<typename MutexType1,typename MutexType2,typename MutexType3,typename MutexType4,typename MutexType5> try_lock(MutexType1 & m1,MutexType2 & m2,MutexType3 & m3,MutexType4 & m4,MutexType5 & m5)1464 int try_lock(MutexType1& m1,MutexType2& m2,MutexType3& m3,MutexType4& m4,MutexType5& m5) 1465 { 1466 return ((int)detail::try_lock_internal(m1,m2,m3,m4,m5))-1; 1467 } 1468 1469 1470 namespace detail 1471 { 1472 template<typename Iterator> 1473 struct range_lock_guard 1474 { 1475 Iterator begin; 1476 Iterator end; 1477 range_lock_guardboost::detail::range_lock_guard1478 range_lock_guard(Iterator begin_,Iterator end_): 1479 begin(begin_),end(end_) 1480 { 1481 lock(begin,end); 1482 } 1483 releaseboost::detail::range_lock_guard1484 void release() 1485 { 1486 begin=end; 1487 } 1488 ~range_lock_guardboost::detail::range_lock_guard1489 ~range_lock_guard() 1490 { 1491 for(;begin!=end;++begin) 1492 { 1493 begin->unlock(); 1494 } 1495 } 1496 }; 1497 1498 template<typename Iterator> try_lock_impl(Iterator begin,Iterator end,is_mutex_type_wrapper<false>)1499 Iterator try_lock_impl(Iterator begin,Iterator end,is_mutex_type_wrapper<false>) 1500 1501 { 1502 if(begin==end) 1503 { 1504 return end; 1505 } 1506 typedef typename std::iterator_traits<Iterator>::value_type lock_type; 1507 unique_lock<lock_type> guard(*begin,try_to_lock); 1508 1509 if(!guard.owns_lock()) 1510 { 1511 return begin; 1512 } 1513 Iterator const failed=try_lock(++begin,end); 1514 if(failed==end) 1515 { 1516 guard.release(); 1517 } 1518 1519 return failed; 1520 } 1521 } 1522 1523 1524 namespace detail 1525 { 1526 template<typename Iterator> lock_impl(Iterator begin,Iterator end,is_mutex_type_wrapper<false>)1527 void lock_impl(Iterator begin,Iterator end,is_mutex_type_wrapper<false>) 1528 { 1529 typedef typename std::iterator_traits<Iterator>::value_type lock_type; 1530 1531 if(begin==end) 1532 { 1533 return; 1534 } 1535 bool start_with_begin=true; 1536 Iterator second=begin; 1537 ++second; 1538 Iterator next=second; 1539 1540 for(;;) 1541 { 1542 unique_lock<lock_type> begin_lock(*begin,defer_lock); 1543 if(start_with_begin) 1544 { 1545 begin_lock.lock(); 1546 Iterator const failed_lock=try_lock(next,end); 1547 if(failed_lock==end) 1548 { 1549 begin_lock.release(); 1550 return; 1551 } 1552 start_with_begin=false; 1553 next=failed_lock; 1554 } 1555 else 1556 { 1557 detail::range_lock_guard<Iterator> guard(next,end); 1558 if(begin_lock.try_lock()) 1559 { 1560 Iterator const failed_lock=try_lock(second,next); 1561 if(failed_lock==next) 1562 { 1563 begin_lock.release(); 1564 guard.release(); 1565 return; 1566 } 1567 start_with_begin=false; 1568 next=failed_lock; 1569 } 1570 else 1571 { 1572 start_with_begin=true; 1573 next=second; 1574 } 1575 } 1576 } 1577 } 1578 1579 } 1580 1581 } 1582 1583 #include <boost/config/abi_suffix.hpp> 1584 1585 #endif 1586