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 // (C) Copyright 2011-2012 Vicente J. Botet Escriba
7 #ifndef BOOST_THREAD_LOCK_ALGORITHMS_HPP
8 #define BOOST_THREAD_LOCK_ALGORITHMS_HPP
10 #include <boost/thread/detail/config.hpp>
11 #include <boost/thread/lock_types.hpp>
12 #include <boost/thread/lockable_traits.hpp>
17 #include <boost/config/abi_prefix.hpp>
23 template <typename MutexType1, typename MutexType2>
24 unsigned try_lock_internal(MutexType1& m1, MutexType2& m2)
26 boost::unique_lock<MutexType1> l1(m1, boost::try_to_lock);
39 template <typename MutexType1, typename MutexType2, typename MutexType3>
40 unsigned try_lock_internal(MutexType1& m1, MutexType2& m2, MutexType3& m3)
42 boost::unique_lock<MutexType1> l1(m1, boost::try_to_lock);
47 if (unsigned const failed_lock=try_lock_internal(m2,m3))
49 return failed_lock + 1;
55 template <typename MutexType1, typename MutexType2, typename MutexType3, typename MutexType4>
56 unsigned try_lock_internal(MutexType1& m1, MutexType2& m2, MutexType3& m3, MutexType4& m4)
58 boost::unique_lock<MutexType1> l1(m1, boost::try_to_lock);
63 if (unsigned const failed_lock=try_lock_internal(m2,m3,m4))
65 return failed_lock + 1;
71 template <typename MutexType1, typename MutexType2, typename MutexType3, typename MutexType4, typename MutexType5>
72 unsigned try_lock_internal(MutexType1& m1, MutexType2& m2, MutexType3& m3, MutexType4& m4, MutexType5& m5)
74 boost::unique_lock<MutexType1> l1(m1, boost::try_to_lock);
79 if (unsigned const failed_lock=try_lock_internal(m2,m3,m4,m5))
81 return failed_lock + 1;
87 template <typename MutexType1, typename MutexType2>
88 unsigned lock_helper(MutexType1& m1, MutexType2& m2)
90 boost::unique_lock<MutexType1> l1(m1);
99 template <typename MutexType1, typename MutexType2, typename MutexType3>
100 unsigned lock_helper(MutexType1& m1, MutexType2& m2, MutexType3& m3)
102 boost::unique_lock<MutexType1> l1(m1);
103 if (unsigned const failed_lock=try_lock_internal(m2,m3))
111 template <typename MutexType1, typename MutexType2, typename MutexType3, typename MutexType4>
112 unsigned lock_helper(MutexType1& m1, MutexType2& m2, MutexType3& m3, MutexType4& m4)
114 boost::unique_lock<MutexType1> l1(m1);
115 if (unsigned const failed_lock=try_lock_internal(m2,m3,m4))
123 template <typename MutexType1, typename MutexType2, typename MutexType3, typename MutexType4, typename MutexType5>
124 unsigned lock_helper(MutexType1& m1, MutexType2& m2, MutexType3& m3, MutexType4& m4, MutexType5& m5)
126 boost::unique_lock<MutexType1> l1(m1);
127 if (unsigned const failed_lock=try_lock_internal(m2,m3,m4,m5))
139 struct is_mutex_type_wrapper
143 template <typename MutexType1, typename MutexType2>
144 void lock_impl(MutexType1& m1, MutexType2& m2, is_mutex_type_wrapper<true> )
146 unsigned const lock_count = 2;
147 unsigned lock_first = 0;
153 lock_first = detail::lock_helper(m1, m2);
154 if (!lock_first) return;
157 lock_first = detail::lock_helper(m2, m1);
158 if (!lock_first) return;
159 lock_first = (lock_first + 1) % lock_count;
165 template <typename Iterator>
166 void lock_impl(Iterator begin, Iterator end, is_mutex_type_wrapper<false> );
169 template <typename MutexType1, typename MutexType2>
170 void lock(MutexType1& m1, MutexType2& m2)
172 detail::lock_impl(m1, m2, detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>());
175 template <typename MutexType1, typename MutexType2>
176 void lock(const MutexType1& m1, MutexType2& m2)
178 detail::lock_impl(m1, m2, detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>());
181 template <typename MutexType1, typename MutexType2>
182 void lock(MutexType1& m1, const MutexType2& m2)
184 detail::lock_impl(m1, m2, detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>());
187 template <typename MutexType1, typename MutexType2>
188 void lock(const MutexType1& m1, const MutexType2& m2)
190 detail::lock_impl(m1, m2, detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>());
193 template <typename MutexType1, typename MutexType2, typename MutexType3>
194 void lock(MutexType1& m1, MutexType2& m2, MutexType3& m3)
196 unsigned const lock_count = 3;
197 unsigned lock_first = 0;
203 lock_first = detail::lock_helper(m1, m2, m3);
204 if (!lock_first) return;
207 lock_first = detail::lock_helper(m2, m3, m1);
208 if (!lock_first) return;
209 lock_first = (lock_first + 1) % lock_count;
212 lock_first = detail::lock_helper(m3, m1, m2);
213 if (!lock_first) return;
214 lock_first = (lock_first + 2) % lock_count;
220 template <typename MutexType1, typename MutexType2, typename MutexType3, typename MutexType4>
221 void lock(MutexType1& m1, MutexType2& m2, MutexType3& m3, MutexType4& m4)
223 unsigned const lock_count = 4;
224 unsigned lock_first = 0;
230 lock_first = detail::lock_helper(m1, m2, m3, m4);
231 if (!lock_first) return;
234 lock_first = detail::lock_helper(m2, m3, m4, m1);
235 if (!lock_first) return;
236 lock_first = (lock_first + 1) % lock_count;
239 lock_first = detail::lock_helper(m3, m4, m1, m2);
240 if (!lock_first) return;
241 lock_first = (lock_first + 2) % lock_count;
244 lock_first = detail::lock_helper(m4, m1, m2, m3);
245 if (!lock_first) return;
246 lock_first = (lock_first + 3) % lock_count;
252 template <typename MutexType1, typename MutexType2, typename MutexType3, typename MutexType4, typename MutexType5>
253 void lock(MutexType1& m1, MutexType2& m2, MutexType3& m3, MutexType4& m4, MutexType5& m5)
255 unsigned const lock_count = 5;
256 unsigned lock_first = 0;
262 lock_first = detail::lock_helper(m1, m2, m3, m4, m5);
263 if (!lock_first) return;
266 lock_first = detail::lock_helper(m2, m3, m4, m5, m1);
267 if (!lock_first) return;
268 lock_first = (lock_first + 1) % lock_count;
271 lock_first = detail::lock_helper(m3, m4, m5, m1, m2);
272 if (!lock_first) return;
273 lock_first = (lock_first + 2) % lock_count;
276 lock_first = detail::lock_helper(m4, m5, m1, m2, m3);
277 if (!lock_first) return;
278 lock_first = (lock_first + 3) % lock_count;
281 lock_first = detail::lock_helper(m5, m1, m2, m3, m4);
282 if (!lock_first) return;
283 lock_first = (lock_first + 4) % lock_count;
291 template <typename Mutex, bool x = is_mutex_type<Mutex>::value>
292 struct try_lock_impl_return
297 template <typename Iterator>
298 struct try_lock_impl_return<Iterator, false>
300 typedef Iterator type;
303 template <typename MutexType1, typename MutexType2>
304 int try_lock_impl(MutexType1& m1, MutexType2& m2, is_mutex_type_wrapper<true> )
306 return ((int) detail::try_lock_internal(m1, m2)) - 1;
309 template <typename Iterator>
310 Iterator try_lock_impl(Iterator begin, Iterator end, is_mutex_type_wrapper<false> );
313 template <typename MutexType1, typename MutexType2>
314 typename detail::try_lock_impl_return<MutexType1>::type try_lock(MutexType1& m1, MutexType2& m2)
316 return detail::try_lock_impl(m1, m2, detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>());
319 template <typename MutexType1, typename MutexType2>
320 typename detail::try_lock_impl_return<MutexType1>::type try_lock(const MutexType1& m1, MutexType2& m2)
322 return detail::try_lock_impl(m1, m2, detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>());
325 template <typename MutexType1, typename MutexType2>
326 typename detail::try_lock_impl_return<MutexType1>::type try_lock(MutexType1& m1, const MutexType2& m2)
328 return detail::try_lock_impl(m1, m2, detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>());
331 template <typename MutexType1, typename MutexType2>
332 typename detail::try_lock_impl_return<MutexType1>::type try_lock(const MutexType1& m1, const MutexType2& m2)
334 return detail::try_lock_impl(m1, m2, detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>());
337 template <typename MutexType1, typename MutexType2, typename MutexType3>
338 int try_lock(MutexType1& m1, MutexType2& m2, MutexType3& m3)
340 return ((int) detail::try_lock_internal(m1, m2, m3)) - 1;
343 template <typename MutexType1, typename MutexType2, typename MutexType3, typename MutexType4>
344 int try_lock(MutexType1& m1, MutexType2& m2, MutexType3& m3, MutexType4& m4)
346 return ((int) detail::try_lock_internal(m1, m2, m3, m4)) - 1;
349 template <typename MutexType1, typename MutexType2, typename MutexType3, typename MutexType4, typename MutexType5>
350 int try_lock(MutexType1& m1, MutexType2& m2, MutexType3& m3, MutexType4& m4, MutexType5& m5)
352 return ((int) detail::try_lock_internal(m1, m2, m3, m4, m5)) - 1;
357 template <typename Iterator>
358 struct range_lock_guard
363 range_lock_guard(Iterator begin_, Iterator end_) :
364 begin(begin_), end(end_)
366 boost::lock(begin, end);
376 for (; begin != end; ++begin)
383 template <typename Iterator>
384 Iterator try_lock_impl(Iterator begin, Iterator end, is_mutex_type_wrapper<false> )
391 typedef typename std::iterator_traits<Iterator>::value_type lock_type;
392 unique_lock<lock_type> guard(*begin, try_to_lock);
394 if (!guard.owns_lock())
398 Iterator const failed = boost::try_lock(++begin, end);
410 template <typename Iterator>
411 void lock_impl(Iterator begin, Iterator end, is_mutex_type_wrapper<false> )
413 typedef typename std::iterator_traits<Iterator>::value_type lock_type;
419 bool start_with_begin = true;
420 Iterator second = begin;
422 Iterator next = second;
426 unique_lock<lock_type> begin_lock(*begin, defer_lock);
427 if (start_with_begin)
430 Iterator const failed_lock = boost::try_lock(next, end);
431 if (failed_lock == end)
433 begin_lock.release();
436 start_with_begin = false;
441 detail::range_lock_guard<Iterator> guard(next, end);
442 if (begin_lock.try_lock())
444 Iterator const failed_lock = boost::try_lock(second, next);
445 if (failed_lock == next)
447 begin_lock.release();
451 start_with_begin = false;
456 start_with_begin = true;
466 #include <boost/config/abi_suffix.hpp>