fix doc example typo
[boost.git] / boost / thread / locks.hpp
blobabbfd75b4eb8d354e2414e40a543f7dbc993b1cf
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>
15 #include <boost/config/abi_prefix.hpp>
17 namespace boost
19 struct xtime;
21 #if defined(BOOST_NO_SFINAE) || \
22 BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600)) || \
23 BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590))
24 #define BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES
25 #endif
27 #ifndef BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES
28 namespace detail
30 template<typename T>
31 struct has_member_lock
33 typedef char true_type;
34 struct false_type
36 true_type dummy[2];
39 template<typename U>
40 static true_type has_member(U*,void (U::*dummy)()=&U::lock);
41 static false_type has_member(void*);
43 BOOST_STATIC_CONSTANT(bool, value=sizeof(has_member_lock<T>::has_member((T*)NULL))==sizeof(true_type));
46 template<typename T>
47 struct has_member_unlock
49 typedef char true_type;
50 struct false_type
52 true_type dummy[2];
55 template<typename U>
56 static true_type has_member(U*,void (U::*dummy)()=&U::unlock);
57 static false_type has_member(void*);
59 BOOST_STATIC_CONSTANT(bool, value=sizeof(has_member_unlock<T>::has_member((T*)NULL))==sizeof(true_type));
62 template<typename T>
63 struct has_member_try_lock
65 typedef char true_type;
66 struct false_type
68 true_type dummy[2];
71 template<typename U>
72 static true_type has_member(U*,bool (U::*dummy)()=&U::try_lock);
73 static false_type has_member(void*);
75 BOOST_STATIC_CONSTANT(bool, value=sizeof(has_member_try_lock<T>::has_member((T*)NULL))==sizeof(true_type));
81 template<typename T>
82 struct is_mutex_type
84 BOOST_STATIC_CONSTANT(bool, value = detail::has_member_lock<T>::value &&
85 detail::has_member_unlock<T>::value &&
86 detail::has_member_try_lock<T>::value);
89 #else
90 template<typename T>
91 struct is_mutex_type
93 BOOST_STATIC_CONSTANT(bool, value = false);
95 #endif
97 struct defer_lock_t
98 {};
99 struct try_to_lock_t
101 struct adopt_lock_t
104 const defer_lock_t defer_lock={};
105 const try_to_lock_t try_to_lock={};
106 const adopt_lock_t adopt_lock={};
108 template<typename Mutex>
109 class shared_lock;
111 template<typename Mutex>
112 class upgrade_lock;
114 template<typename Mutex>
115 class unique_lock;
117 namespace detail
119 template<typename Mutex>
120 class try_lock_wrapper;
123 #ifdef BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES
124 template<typename T>
125 struct is_mutex_type<unique_lock<T> >
127 BOOST_STATIC_CONSTANT(bool, value = true);
130 template<typename T>
131 struct is_mutex_type<shared_lock<T> >
133 BOOST_STATIC_CONSTANT(bool, value = true);
136 template<typename T>
137 struct is_mutex_type<upgrade_lock<T> >
139 BOOST_STATIC_CONSTANT(bool, value = true);
142 template<typename T>
143 struct is_mutex_type<detail::try_lock_wrapper<T> >
145 BOOST_STATIC_CONSTANT(bool, value = true);
148 class mutex;
149 class timed_mutex;
150 class recursive_mutex;
151 class recursive_timed_mutex;
152 class shared_mutex;
154 template<>
155 struct is_mutex_type<mutex>
157 BOOST_STATIC_CONSTANT(bool, value = true);
159 template<>
160 struct is_mutex_type<timed_mutex>
162 BOOST_STATIC_CONSTANT(bool, value = true);
164 template<>
165 struct is_mutex_type<recursive_mutex>
167 BOOST_STATIC_CONSTANT(bool, value = true);
169 template<>
170 struct is_mutex_type<recursive_timed_mutex>
172 BOOST_STATIC_CONSTANT(bool, value = true);
174 template<>
175 struct is_mutex_type<shared_mutex>
177 BOOST_STATIC_CONSTANT(bool, value = true);
180 #endif
182 template<typename Mutex>
183 class lock_guard
185 private:
186 Mutex& m;
188 explicit lock_guard(lock_guard&);
189 lock_guard& operator=(lock_guard&);
190 public:
191 explicit lock_guard(Mutex& m_):
192 m(m_)
194 m.lock();
196 lock_guard(Mutex& m_,adopt_lock_t):
197 m(m_)
199 ~lock_guard()
201 m.unlock();
206 template<typename Mutex>
207 class unique_lock
209 private:
210 Mutex* m;
211 bool is_locked;
212 unique_lock(unique_lock&);
213 explicit unique_lock(upgrade_lock<Mutex>&);
214 unique_lock& operator=(unique_lock&);
215 unique_lock& operator=(upgrade_lock<Mutex>& other);
216 public:
217 unique_lock():
218 m(0),is_locked(false)
221 explicit unique_lock(Mutex& m_):
222 m(&m_),is_locked(false)
224 lock();
226 unique_lock(Mutex& m_,adopt_lock_t):
227 m(&m_),is_locked(true)
229 unique_lock(Mutex& m_,defer_lock_t):
230 m(&m_),is_locked(false)
232 unique_lock(Mutex& m_,try_to_lock_t):
233 m(&m_),is_locked(false)
235 try_lock();
237 template<typename TimeDuration>
238 unique_lock(Mutex& m_,TimeDuration const& target_time):
239 m(&m_),is_locked(false)
241 timed_lock(target_time);
243 unique_lock(Mutex& m_,system_time const& target_time):
244 m(&m_),is_locked(false)
246 timed_lock(target_time);
248 #ifdef BOOST_HAS_RVALUE_REFS
249 unique_lock(unique_lock&& other):
250 m(other.m),is_locked(other.is_locked)
252 other.is_locked=false;
253 other.m=0;
255 explicit unique_lock(upgrade_lock<Mutex>&& other);
257 unique_lock<Mutex>&& move()
259 return static_cast<unique_lock<Mutex>&&>(*this);
263 unique_lock& operator=(unique_lock<Mutex>&& other)
265 unique_lock temp(other);
266 swap(temp);
267 return *this;
270 unique_lock& operator=(upgrade_lock<Mutex>&& other)
272 unique_lock temp(other);
273 swap(temp);
274 return *this;
276 void swap(unique_lock&& other)
278 std::swap(m,other.m);
279 std::swap(is_locked,other.is_locked);
281 #else
282 unique_lock(detail::thread_move_t<unique_lock<Mutex> > other):
283 m(other->m),is_locked(other->is_locked)
285 other->is_locked=false;
286 other->m=0;
288 unique_lock(detail::thread_move_t<upgrade_lock<Mutex> > other);
290 operator detail::thread_move_t<unique_lock<Mutex> >()
292 return move();
295 detail::thread_move_t<unique_lock<Mutex> > move()
297 return detail::thread_move_t<unique_lock<Mutex> >(*this);
300 unique_lock& operator=(detail::thread_move_t<unique_lock<Mutex> > other)
302 unique_lock temp(other);
303 swap(temp);
304 return *this;
307 unique_lock& operator=(detail::thread_move_t<upgrade_lock<Mutex> > other)
309 unique_lock temp(other);
310 swap(temp);
311 return *this;
313 void swap(unique_lock& other)
315 std::swap(m,other.m);
316 std::swap(is_locked,other.is_locked);
318 void swap(detail::thread_move_t<unique_lock<Mutex> > other)
320 std::swap(m,other->m);
321 std::swap(is_locked,other->is_locked);
323 #endif
325 ~unique_lock()
327 if(owns_lock())
329 m->unlock();
332 void lock()
334 if(owns_lock())
336 throw boost::lock_error();
338 m->lock();
339 is_locked=true;
341 bool try_lock()
343 if(owns_lock())
345 throw boost::lock_error();
347 is_locked=m->try_lock();
348 return is_locked;
350 template<typename TimeDuration>
351 bool timed_lock(TimeDuration const& relative_time)
353 is_locked=m->timed_lock(relative_time);
354 return is_locked;
357 bool timed_lock(::boost::system_time const& absolute_time)
359 is_locked=m->timed_lock(absolute_time);
360 return is_locked;
362 bool timed_lock(::boost::xtime const& absolute_time)
364 is_locked=m->timed_lock(absolute_time);
365 return is_locked;
367 void unlock()
369 if(!owns_lock())
371 throw boost::lock_error();
373 m->unlock();
374 is_locked=false;
377 typedef void (unique_lock::*bool_type)();
378 operator bool_type() const
380 return is_locked?&unique_lock::lock:0;
382 bool operator!() const
384 return !owns_lock();
386 bool owns_lock() const
388 return is_locked;
391 Mutex* mutex() const
393 return m;
396 Mutex* release()
398 Mutex* const res=m;
399 m=0;
400 is_locked=false;
401 return res;
404 friend class shared_lock<Mutex>;
405 friend class upgrade_lock<Mutex>;
408 #ifdef BOOST_HAS_RVALUE_REFS
409 template<typename Mutex>
410 void swap(unique_lock<Mutex>&& lhs,unique_lock<Mutex>&& rhs)
412 lhs.swap(rhs);
414 #else
415 template<typename Mutex>
416 void swap(unique_lock<Mutex>& lhs,unique_lock<Mutex>& rhs)
418 lhs.swap(rhs);
420 #endif
422 #ifdef BOOST_HAS_RVALUE_REFS
423 template<typename Mutex>
424 inline unique_lock<Mutex>&& move(unique_lock<Mutex>&& ul)
426 return ul;
428 #endif
430 template<typename Mutex>
431 class shared_lock
433 protected:
434 Mutex* m;
435 bool is_locked;
436 private:
437 explicit shared_lock(shared_lock&);
438 shared_lock& operator=(shared_lock&);
439 public:
440 shared_lock():
441 m(0),is_locked(false)
444 explicit shared_lock(Mutex& m_):
445 m(&m_),is_locked(false)
447 lock();
449 shared_lock(Mutex& m_,adopt_lock_t):
450 m(&m_),is_locked(true)
452 shared_lock(Mutex& m_,defer_lock_t):
453 m(&m_),is_locked(false)
455 shared_lock(Mutex& m_,try_to_lock_t):
456 m(&m_),is_locked(false)
458 try_lock();
460 shared_lock(Mutex& m_,system_time const& target_time):
461 m(&m_),is_locked(false)
463 timed_lock(target_time);
466 shared_lock(detail::thread_move_t<shared_lock<Mutex> > other):
467 m(other->m),is_locked(other->is_locked)
469 other->is_locked=false;
470 other->m=0;
473 shared_lock(detail::thread_move_t<unique_lock<Mutex> > other):
474 m(other->m),is_locked(other->is_locked)
476 if(is_locked)
478 m->unlock_and_lock_shared();
480 other->is_locked=false;
481 other->m=0;
484 shared_lock(detail::thread_move_t<upgrade_lock<Mutex> > other):
485 m(other->m),is_locked(other->is_locked)
487 if(is_locked)
489 m->unlock_upgrade_and_lock_shared();
491 other->is_locked=false;
492 other->m=0;
495 operator detail::thread_move_t<shared_lock<Mutex> >()
497 return move();
500 detail::thread_move_t<shared_lock<Mutex> > move()
502 return detail::thread_move_t<shared_lock<Mutex> >(*this);
506 shared_lock& operator=(detail::thread_move_t<shared_lock<Mutex> > other)
508 shared_lock temp(other);
509 swap(temp);
510 return *this;
513 shared_lock& operator=(detail::thread_move_t<unique_lock<Mutex> > other)
515 shared_lock temp(other);
516 swap(temp);
517 return *this;
520 shared_lock& operator=(detail::thread_move_t<upgrade_lock<Mutex> > other)
522 shared_lock temp(other);
523 swap(temp);
524 return *this;
527 #ifdef BOOST_HAS_RVALUE_REFS
528 void swap(shared_lock&& other)
530 std::swap(m,other.m);
531 std::swap(is_locked,other.is_locked);
533 #else
534 void swap(shared_lock& other)
536 std::swap(m,other.m);
537 std::swap(is_locked,other.is_locked);
539 void swap(boost::detail::thread_move_t<shared_lock<Mutex> > other)
541 std::swap(m,other->m);
542 std::swap(is_locked,other->is_locked);
544 #endif
546 Mutex* mutex() const
548 return m;
551 ~shared_lock()
553 if(owns_lock())
555 m->unlock_shared();
558 void lock()
560 if(owns_lock())
562 throw boost::lock_error();
564 m->lock_shared();
565 is_locked=true;
567 bool try_lock()
569 if(owns_lock())
571 throw boost::lock_error();
573 is_locked=m->try_lock_shared();
574 return is_locked;
576 bool timed_lock(boost::system_time const& target_time)
578 if(owns_lock())
580 throw boost::lock_error();
582 is_locked=m->timed_lock_shared(target_time);
583 return is_locked;
585 template<typename Duration>
586 bool timed_lock(Duration const& target_time)
588 if(owns_lock())
590 throw boost::lock_error();
592 is_locked=m->timed_lock_shared(target_time);
593 return is_locked;
595 void unlock()
597 if(!owns_lock())
599 throw boost::lock_error();
601 m->unlock_shared();
602 is_locked=false;
605 typedef void (shared_lock<Mutex>::*bool_type)();
606 operator bool_type() const
608 return is_locked?&shared_lock::lock:0;
610 bool operator!() const
612 return !owns_lock();
614 bool owns_lock() const
616 return is_locked;
621 #ifdef BOOST_HAS_RVALUE_REFS
622 template<typename Mutex>
623 void swap(shared_lock<Mutex>&& lhs,shared_lock<Mutex>&& rhs)
625 lhs.swap(rhs);
627 #else
628 template<typename Mutex>
629 void swap(shared_lock<Mutex>& lhs,shared_lock<Mutex>& rhs)
631 lhs.swap(rhs);
633 #endif
635 template<typename Mutex>
636 class upgrade_lock
638 protected:
639 Mutex* m;
640 bool is_locked;
641 private:
642 explicit upgrade_lock(upgrade_lock&);
643 upgrade_lock& operator=(upgrade_lock&);
644 public:
645 upgrade_lock():
646 m(0),is_locked(false)
649 explicit upgrade_lock(Mutex& m_):
650 m(&m_),is_locked(false)
652 lock();
654 upgrade_lock(Mutex& m_,adopt_lock_t):
655 m(&m_),is_locked(true)
657 upgrade_lock(Mutex& m_,defer_lock_t):
658 m(&m_),is_locked(false)
660 upgrade_lock(Mutex& m_,try_to_lock_t):
661 m(&m_),is_locked(false)
663 try_lock();
665 upgrade_lock(detail::thread_move_t<upgrade_lock<Mutex> > other):
666 m(other->m),is_locked(other->is_locked)
668 other->is_locked=false;
669 other->m=0;
672 upgrade_lock(detail::thread_move_t<unique_lock<Mutex> > other):
673 m(other->m),is_locked(other->is_locked)
675 if(is_locked)
677 m->unlock_and_lock_upgrade();
679 other->is_locked=false;
680 other->m=0;
683 operator detail::thread_move_t<upgrade_lock<Mutex> >()
685 return move();
688 detail::thread_move_t<upgrade_lock<Mutex> > move()
690 return detail::thread_move_t<upgrade_lock<Mutex> >(*this);
694 upgrade_lock& operator=(detail::thread_move_t<upgrade_lock<Mutex> > other)
696 upgrade_lock temp(other);
697 swap(temp);
698 return *this;
701 upgrade_lock& operator=(detail::thread_move_t<unique_lock<Mutex> > other)
703 upgrade_lock temp(other);
704 swap(temp);
705 return *this;
708 void swap(upgrade_lock& other)
710 std::swap(m,other.m);
711 std::swap(is_locked,other.is_locked);
714 ~upgrade_lock()
716 if(owns_lock())
718 m->unlock_upgrade();
721 void lock()
723 if(owns_lock())
725 throw boost::lock_error();
727 m->lock_upgrade();
728 is_locked=true;
730 bool try_lock()
732 if(owns_lock())
734 throw boost::lock_error();
736 is_locked=m->try_lock_upgrade();
737 return is_locked;
739 void unlock()
741 if(!owns_lock())
743 throw boost::lock_error();
745 m->unlock_upgrade();
746 is_locked=false;
749 typedef void (upgrade_lock::*bool_type)();
750 operator bool_type() const
752 return is_locked?&upgrade_lock::lock:0;
754 bool operator!() const
756 return !owns_lock();
758 bool owns_lock() const
760 return is_locked;
762 friend class shared_lock<Mutex>;
763 friend class unique_lock<Mutex>;
767 #ifdef BOOST_HAS_RVALUE_REFS
768 template<typename Mutex>
769 unique_lock<Mutex>::unique_lock(upgrade_lock<Mutex>&& other):
770 m(other.m),is_locked(other.is_locked)
772 other.is_locked=false;
773 if(is_locked)
775 m.unlock_upgrade_and_lock();
778 #else
779 template<typename Mutex>
780 unique_lock<Mutex>::unique_lock(detail::thread_move_t<upgrade_lock<Mutex> > other):
781 m(other->m),is_locked(other->is_locked)
783 other->is_locked=false;
784 if(is_locked)
786 m->unlock_upgrade_and_lock();
789 #endif
790 template <class Mutex>
791 class upgrade_to_unique_lock
793 private:
794 upgrade_lock<Mutex>* source;
795 unique_lock<Mutex> exclusive;
797 explicit upgrade_to_unique_lock(upgrade_to_unique_lock&);
798 upgrade_to_unique_lock& operator=(upgrade_to_unique_lock&);
799 public:
800 explicit upgrade_to_unique_lock(upgrade_lock<Mutex>& m_):
801 source(&m_),exclusive(move(*source))
803 ~upgrade_to_unique_lock()
805 if(source)
807 *source=move(exclusive);
811 upgrade_to_unique_lock(detail::thread_move_t<upgrade_to_unique_lock<Mutex> > other):
812 source(other->source),exclusive(move(other->exclusive))
814 other->source=0;
817 upgrade_to_unique_lock& operator=(detail::thread_move_t<upgrade_to_unique_lock<Mutex> > other)
819 upgrade_to_unique_lock temp(other);
820 swap(temp);
821 return *this;
823 void swap(upgrade_to_unique_lock& other)
825 std::swap(source,other.source);
826 exclusive.swap(other.exclusive);
828 typedef void (upgrade_to_unique_lock::*bool_type)(upgrade_to_unique_lock&);
829 operator bool_type() const
831 return exclusive.owns_lock()?&upgrade_to_unique_lock::swap:0;
833 bool operator!() const
835 return !owns_lock();
837 bool owns_lock() const
839 return exclusive.owns_lock();
843 namespace detail
845 template<typename Mutex>
846 class try_lock_wrapper:
847 private unique_lock<Mutex>
849 typedef unique_lock<Mutex> base;
850 public:
851 try_lock_wrapper()
854 explicit try_lock_wrapper(Mutex& m):
855 base(m,try_to_lock)
858 try_lock_wrapper(Mutex& m_,adopt_lock_t):
859 base(m_,adopt_lock)
861 try_lock_wrapper(Mutex& m_,defer_lock_t):
862 base(m_,defer_lock)
864 try_lock_wrapper(Mutex& m_,try_to_lock_t):
865 base(m_,try_to_lock)
867 try_lock_wrapper(detail::thread_move_t<try_lock_wrapper<Mutex> > other):
868 base(detail::thread_move_t<base>(*other))
871 operator detail::thread_move_t<try_lock_wrapper<Mutex> >()
873 return move();
876 detail::thread_move_t<try_lock_wrapper<Mutex> > move()
878 return detail::thread_move_t<try_lock_wrapper<Mutex> >(*this);
881 try_lock_wrapper& operator=(detail::thread_move_t<try_lock_wrapper<Mutex> > other)
883 try_lock_wrapper temp(other);
884 swap(temp);
885 return *this;
888 #ifdef BOOST_HAS_RVALUE_REFS
889 void swap(try_lock_wrapper&& other)
891 base::swap(other);
893 #else
894 void swap(try_lock_wrapper& other)
896 base::swap(other);
898 void swap(detail::thread_move_t<try_lock_wrapper<Mutex> > other)
900 base::swap(*other);
902 #endif
904 void lock()
906 base::lock();
908 bool try_lock()
910 return base::try_lock();
912 void unlock()
914 base::unlock();
916 bool owns_lock() const
918 return base::owns_lock();
920 Mutex* mutex() const
922 return base::mutex();
924 Mutex* release()
926 return base::release();
928 bool operator!() const
930 return !this->owns_lock();
933 typedef typename base::bool_type bool_type;
934 operator bool_type() const
936 return base::operator bool_type();
940 #ifdef BOOST_HAS_RVALUE_REFS
941 template<typename Mutex>
942 void swap(try_lock_wrapper<Mutex>&& lhs,try_lock_wrapper<Mutex>&& rhs)
944 lhs.swap(rhs);
946 #else
947 template<typename Mutex>
948 void swap(try_lock_wrapper<Mutex>& lhs,try_lock_wrapper<Mutex>& rhs)
950 lhs.swap(rhs);
952 #endif
954 template<typename MutexType1,typename MutexType2>
955 unsigned try_lock_internal(MutexType1& m1,MutexType2& m2)
957 boost::unique_lock<MutexType1> l1(m1,boost::try_to_lock);
958 if(!l1)
960 return 1;
962 if(!m2.try_lock())
964 return 2;
966 l1.release();
967 return 0;
970 template<typename MutexType1,typename MutexType2,typename MutexType3>
971 unsigned try_lock_internal(MutexType1& m1,MutexType2& m2,MutexType3& m3)
973 boost::unique_lock<MutexType1> l1(m1,boost::try_to_lock);
974 if(!l1)
976 return 1;
978 if(unsigned const failed_lock=try_lock_internal(m2,m3))
980 return failed_lock+1;
982 l1.release();
983 return 0;
987 template<typename MutexType1,typename MutexType2,typename MutexType3,
988 typename MutexType4>
989 unsigned try_lock_internal(MutexType1& m1,MutexType2& m2,MutexType3& m3,
990 MutexType4& m4)
992 boost::unique_lock<MutexType1> l1(m1,boost::try_to_lock);
993 if(!l1)
995 return 1;
997 if(unsigned const failed_lock=try_lock_internal(m2,m3,m4))
999 return failed_lock+1;
1001 l1.release();
1002 return 0;
1005 template<typename MutexType1,typename MutexType2,typename MutexType3,
1006 typename MutexType4,typename MutexType5>
1007 unsigned try_lock_internal(MutexType1& m1,MutexType2& m2,MutexType3& m3,
1008 MutexType4& m4,MutexType5& m5)
1010 boost::unique_lock<MutexType1> l1(m1,boost::try_to_lock);
1011 if(!l1)
1013 return 1;
1015 if(unsigned const failed_lock=try_lock_internal(m2,m3,m4,m5))
1017 return failed_lock+1;
1019 l1.release();
1020 return 0;
1024 template<typename MutexType1,typename MutexType2>
1025 unsigned lock_helper(MutexType1& m1,MutexType2& m2)
1027 boost::unique_lock<MutexType1> l1(m1);
1028 if(!m2.try_lock())
1030 return 1;
1032 l1.release();
1033 return 0;
1036 template<typename MutexType1,typename MutexType2,typename MutexType3>
1037 unsigned lock_helper(MutexType1& m1,MutexType2& m2,MutexType3& m3)
1039 boost::unique_lock<MutexType1> l1(m1);
1040 if(unsigned const failed_lock=try_lock_internal(m2,m3))
1042 return failed_lock;
1044 l1.release();
1045 return 0;
1048 template<typename MutexType1,typename MutexType2,typename MutexType3,
1049 typename MutexType4>
1050 unsigned lock_helper(MutexType1& m1,MutexType2& m2,MutexType3& m3,
1051 MutexType4& m4)
1053 boost::unique_lock<MutexType1> l1(m1);
1054 if(unsigned const failed_lock=try_lock_internal(m2,m3,m4))
1056 return failed_lock;
1058 l1.release();
1059 return 0;
1062 template<typename MutexType1,typename MutexType2,typename MutexType3,
1063 typename MutexType4,typename MutexType5>
1064 unsigned lock_helper(MutexType1& m1,MutexType2& m2,MutexType3& m3,
1065 MutexType4& m4,MutexType5& m5)
1067 boost::unique_lock<MutexType1> l1(m1);
1068 if(unsigned const failed_lock=try_lock_internal(m2,m3,m4,m5))
1070 return failed_lock;
1072 l1.release();
1073 return 0;
1077 namespace detail
1079 template<bool x>
1080 struct is_mutex_type_wrapper
1083 template<typename MutexType1,typename MutexType2>
1084 void lock_impl(MutexType1& m1,MutexType2& m2,is_mutex_type_wrapper<true>)
1086 unsigned const lock_count=2;
1087 unsigned lock_first=0;
1088 while(true)
1090 switch(lock_first)
1092 case 0:
1093 lock_first=detail::lock_helper(m1,m2);
1094 if(!lock_first)
1095 return;
1096 break;
1097 case 1:
1098 lock_first=detail::lock_helper(m2,m1);
1099 if(!lock_first)
1100 return;
1101 lock_first=(lock_first+1)%lock_count;
1102 break;
1107 template<typename Iterator>
1108 void lock_impl(Iterator begin,Iterator end,is_mutex_type_wrapper<false>);
1112 template<typename MutexType1,typename MutexType2>
1113 void lock(MutexType1& m1,MutexType2& m2)
1115 detail::lock_impl(m1,m2,detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>());
1118 template<typename MutexType1,typename MutexType2>
1119 void lock(const MutexType1& m1,MutexType2& m2)
1121 detail::lock_impl(m1,m2,detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>());
1124 template<typename MutexType1,typename MutexType2>
1125 void lock(MutexType1& m1,const MutexType2& m2)
1127 detail::lock_impl(m1,m2,detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>());
1130 template<typename MutexType1,typename MutexType2>
1131 void lock(const MutexType1& m1,const MutexType2& m2)
1133 detail::lock_impl(m1,m2,detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>());
1136 template<typename MutexType1,typename MutexType2,typename MutexType3>
1137 void lock(MutexType1& m1,MutexType2& m2,MutexType3& m3)
1139 unsigned const lock_count=3;
1140 unsigned lock_first=0;
1141 while(true)
1143 switch(lock_first)
1145 case 0:
1146 lock_first=detail::lock_helper(m1,m2,m3);
1147 if(!lock_first)
1148 return;
1149 break;
1150 case 1:
1151 lock_first=detail::lock_helper(m2,m3,m1);
1152 if(!lock_first)
1153 return;
1154 lock_first=(lock_first+1)%lock_count;
1155 break;
1156 case 2:
1157 lock_first=detail::lock_helper(m3,m1,m2);
1158 if(!lock_first)
1159 return;
1160 lock_first=(lock_first+2)%lock_count;
1161 break;
1166 template<typename MutexType1,typename MutexType2,typename MutexType3,
1167 typename MutexType4>
1168 void lock(MutexType1& m1,MutexType2& m2,MutexType3& m3,
1169 MutexType4& m4)
1171 unsigned const lock_count=4;
1172 unsigned lock_first=0;
1173 while(true)
1175 switch(lock_first)
1177 case 0:
1178 lock_first=detail::lock_helper(m1,m2,m3,m4);
1179 if(!lock_first)
1180 return;
1181 break;
1182 case 1:
1183 lock_first=detail::lock_helper(m2,m3,m4,m1);
1184 if(!lock_first)
1185 return;
1186 lock_first=(lock_first+1)%lock_count;
1187 break;
1188 case 2:
1189 lock_first=detail::lock_helper(m3,m4,m1,m2);
1190 if(!lock_first)
1191 return;
1192 lock_first=(lock_first+2)%lock_count;
1193 break;
1194 case 3:
1195 lock_first=detail::lock_helper(m4,m1,m2,m3);
1196 if(!lock_first)
1197 return;
1198 lock_first=(lock_first+3)%lock_count;
1199 break;
1204 template<typename MutexType1,typename MutexType2,typename MutexType3,
1205 typename MutexType4,typename MutexType5>
1206 void lock(MutexType1& m1,MutexType2& m2,MutexType3& m3,
1207 MutexType4& m4,MutexType5& m5)
1209 unsigned const lock_count=5;
1210 unsigned lock_first=0;
1211 while(true)
1213 switch(lock_first)
1215 case 0:
1216 lock_first=detail::lock_helper(m1,m2,m3,m4,m5);
1217 if(!lock_first)
1218 return;
1219 break;
1220 case 1:
1221 lock_first=detail::lock_helper(m2,m3,m4,m5,m1);
1222 if(!lock_first)
1223 return;
1224 lock_first=(lock_first+1)%lock_count;
1225 break;
1226 case 2:
1227 lock_first=detail::lock_helper(m3,m4,m5,m1,m2);
1228 if(!lock_first)
1229 return;
1230 lock_first=(lock_first+2)%lock_count;
1231 break;
1232 case 3:
1233 lock_first=detail::lock_helper(m4,m5,m1,m2,m3);
1234 if(!lock_first)
1235 return;
1236 lock_first=(lock_first+3)%lock_count;
1237 break;
1238 case 4:
1239 lock_first=detail::lock_helper(m5,m1,m2,m3,m4);
1240 if(!lock_first)
1241 return;
1242 lock_first=(lock_first+4)%lock_count;
1243 break;
1248 namespace detail
1250 template<typename Mutex,bool x=is_mutex_type<Mutex>::value>
1251 struct try_lock_impl_return
1253 typedef int type;
1256 template<typename Iterator>
1257 struct try_lock_impl_return<Iterator,false>
1259 typedef Iterator type;
1262 template<typename MutexType1,typename MutexType2>
1263 int try_lock_impl(MutexType1& m1,MutexType2& m2,is_mutex_type_wrapper<true>)
1265 return ((int)detail::try_lock_internal(m1,m2))-1;
1268 template<typename Iterator>
1269 Iterator try_lock_impl(Iterator begin,Iterator end,is_mutex_type_wrapper<false>);
1272 template<typename MutexType1,typename MutexType2>
1273 typename detail::try_lock_impl_return<MutexType1>::type try_lock(MutexType1& m1,MutexType2& m2)
1275 return detail::try_lock_impl(m1,m2,detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>());
1278 template<typename MutexType1,typename MutexType2>
1279 typename detail::try_lock_impl_return<MutexType1>::type try_lock(const MutexType1& m1,MutexType2& m2)
1281 return detail::try_lock_impl(m1,m2,detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>());
1284 template<typename MutexType1,typename MutexType2>
1285 typename detail::try_lock_impl_return<MutexType1>::type try_lock(MutexType1& m1,const MutexType2& m2)
1287 return detail::try_lock_impl(m1,m2,detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>());
1290 template<typename MutexType1,typename MutexType2>
1291 typename detail::try_lock_impl_return<MutexType1>::type try_lock(const MutexType1& m1,const MutexType2& m2)
1293 return detail::try_lock_impl(m1,m2,detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>());
1296 template<typename MutexType1,typename MutexType2,typename MutexType3>
1297 int try_lock(MutexType1& m1,MutexType2& m2,MutexType3& m3)
1299 return ((int)detail::try_lock_internal(m1,m2,m3))-1;
1302 template<typename MutexType1,typename MutexType2,typename MutexType3,typename MutexType4>
1303 int try_lock(MutexType1& m1,MutexType2& m2,MutexType3& m3,MutexType4& m4)
1305 return ((int)detail::try_lock_internal(m1,m2,m3,m4))-1;
1308 template<typename MutexType1,typename MutexType2,typename MutexType3,typename MutexType4,typename MutexType5>
1309 int try_lock(MutexType1& m1,MutexType2& m2,MutexType3& m3,MutexType4& m4,MutexType5& m5)
1311 return ((int)detail::try_lock_internal(m1,m2,m3,m4,m5))-1;
1315 namespace detail
1317 template<typename Iterator>
1318 struct range_lock_guard
1320 Iterator begin;
1321 Iterator end;
1323 range_lock_guard(Iterator begin_,Iterator end_):
1324 begin(begin_),end(end_)
1326 lock(begin,end);
1329 void release()
1331 begin=end;
1334 ~range_lock_guard()
1336 for(;begin!=end;++begin)
1338 begin->unlock();
1343 template<typename Iterator>
1344 Iterator try_lock_impl(Iterator begin,Iterator end,is_mutex_type_wrapper<false>)
1347 if(begin==end)
1349 return end;
1351 typedef typename std::iterator_traits<Iterator>::value_type lock_type;
1352 unique_lock<lock_type> guard(*begin,try_to_lock);
1354 if(!guard.owns_lock())
1356 return begin;
1358 Iterator const failed=try_lock(++begin,end);
1359 if(failed==end)
1361 guard.release();
1364 return failed;
1369 namespace detail
1371 template<typename Iterator>
1372 void lock_impl(Iterator begin,Iterator end,is_mutex_type_wrapper<false>)
1374 typedef typename std::iterator_traits<Iterator>::value_type lock_type;
1376 if(begin==end)
1378 return;
1380 bool start_with_begin=true;
1381 Iterator second=begin;
1382 ++second;
1383 Iterator next=second;
1385 for(;;)
1387 unique_lock<lock_type> begin_lock(*begin,defer_lock);
1388 if(start_with_begin)
1390 begin_lock.lock();
1391 Iterator const failed_lock=try_lock(next,end);
1392 if(failed_lock==end)
1394 begin_lock.release();
1395 return;
1397 start_with_begin=false;
1398 next=failed_lock;
1400 else
1402 detail::range_lock_guard<Iterator> guard(next,end);
1403 if(begin_lock.try_lock())
1405 Iterator const failed_lock=try_lock(second,next);
1406 if(failed_lock==next)
1408 begin_lock.release();
1409 guard.release();
1410 return;
1412 start_with_begin=false;
1413 next=failed_lock;
1415 else
1417 start_with_begin=true;
1418 next=second;
1428 #include <boost/config/abi_suffix.hpp>
1430 #endif