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