You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase.
1585 lines
44 KiB
1585 lines
44 KiB
// Distributed under the Boost Software License, Version 1.0. (See |
|
// accompanying file LICENSE_1_0.txt or copy at |
|
// http://www.boost.org/LICENSE_1_0.txt) |
|
// (C) Copyright 2007 Anthony Williams |
|
#ifndef BOOST_THREAD_LOCKS_HPP |
|
#define BOOST_THREAD_LOCKS_HPP |
|
#include <boost/thread/detail/config.hpp> |
|
#include <boost/thread/exceptions.hpp> |
|
#include <boost/thread/detail/move.hpp> |
|
#include <algorithm> |
|
#include <iterator> |
|
#include <boost/thread/thread_time.hpp> |
|
#include <boost/detail/workaround.hpp> |
|
#include <boost/type_traits/is_class.hpp> |
|
|
|
#include <boost/config/abi_prefix.hpp> |
|
|
|
namespace boost |
|
{ |
|
struct xtime; |
|
|
|
#if defined(BOOST_NO_SFINAE) || \ |
|
BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600)) || \ |
|
BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590)) |
|
#define BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES |
|
#endif |
|
|
|
#ifndef BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES |
|
namespace detail |
|
{ |
|
#define BOOST_DEFINE_HAS_MEMBER_CALLED(member_name) \ |
|
template<typename T, bool=boost::is_class<T>::value> \ |
|
struct has_member_called_##member_name \ |
|
{ \ |
|
BOOST_STATIC_CONSTANT(bool, value=false); \ |
|
}; \ |
|
\ |
|
template<typename T> \ |
|
struct has_member_called_##member_name<T,true> \ |
|
{ \ |
|
typedef char true_type; \ |
|
struct false_type \ |
|
{ \ |
|
true_type dummy[2]; \ |
|
}; \ |
|
\ |
|
struct fallback { int member_name; }; \ |
|
struct derived: \ |
|
T, fallback \ |
|
{ \ |
|
derived(); \ |
|
}; \ |
|
\ |
|
template<int fallback::*> struct tester; \ |
|
\ |
|
template<typename U> \ |
|
static false_type has_member(tester<&U::member_name>*); \ |
|
template<typename U> \ |
|
static true_type has_member(...); \ |
|
\ |
|
BOOST_STATIC_CONSTANT( \ |
|
bool, value=sizeof(has_member<derived>(0))==sizeof(true_type)); \ |
|
} |
|
|
|
BOOST_DEFINE_HAS_MEMBER_CALLED(lock); |
|
BOOST_DEFINE_HAS_MEMBER_CALLED(unlock); |
|
BOOST_DEFINE_HAS_MEMBER_CALLED(try_lock); |
|
|
|
template<typename T,bool=has_member_called_lock<T>::value > |
|
struct has_member_lock |
|
{ |
|
BOOST_STATIC_CONSTANT(bool, value=false); |
|
}; |
|
|
|
template<typename T> |
|
struct has_member_lock<T,true> |
|
{ |
|
typedef char true_type; |
|
struct false_type |
|
{ |
|
true_type dummy[2]; |
|
}; |
|
|
|
template<typename U,typename V> |
|
static true_type has_member(V (U::*)()); |
|
template<typename U> |
|
static false_type has_member(U); |
|
|
|
BOOST_STATIC_CONSTANT( |
|
bool,value=sizeof(has_member_lock<T>::has_member(&T::lock))==sizeof(true_type)); |
|
}; |
|
|
|
template<typename T,bool=has_member_called_unlock<T>::value > |
|
struct has_member_unlock |
|
{ |
|
BOOST_STATIC_CONSTANT(bool, value=false); |
|
}; |
|
|
|
template<typename T> |
|
struct has_member_unlock<T,true> |
|
{ |
|
typedef char true_type; |
|
struct false_type |
|
{ |
|
true_type dummy[2]; |
|
}; |
|
|
|
template<typename U,typename V> |
|
static true_type has_member(V (U::*)()); |
|
template<typename U> |
|
static false_type has_member(U); |
|
|
|
BOOST_STATIC_CONSTANT( |
|
bool,value=sizeof(has_member_unlock<T>::has_member(&T::unlock))==sizeof(true_type)); |
|
}; |
|
|
|
template<typename T,bool=has_member_called_try_lock<T>::value > |
|
struct has_member_try_lock |
|
{ |
|
BOOST_STATIC_CONSTANT(bool, value=false); |
|
}; |
|
|
|
template<typename T> |
|
struct has_member_try_lock<T,true> |
|
{ |
|
typedef char true_type; |
|
struct false_type |
|
{ |
|
true_type dummy[2]; |
|
}; |
|
|
|
template<typename U> |
|
static true_type has_member(bool (U::*)()); |
|
template<typename U> |
|
static false_type has_member(U); |
|
|
|
BOOST_STATIC_CONSTANT( |
|
bool,value=sizeof(has_member_try_lock<T>::has_member(&T::try_lock))==sizeof(true_type)); |
|
}; |
|
|
|
} |
|
|
|
|
|
template<typename T> |
|
struct is_mutex_type |
|
{ |
|
BOOST_STATIC_CONSTANT(bool, value = detail::has_member_lock<T>::value && |
|
detail::has_member_unlock<T>::value && |
|
detail::has_member_try_lock<T>::value); |
|
|
|
}; |
|
#else |
|
template<typename T> |
|
struct is_mutex_type |
|
{ |
|
BOOST_STATIC_CONSTANT(bool, value = false); |
|
}; |
|
#endif |
|
|
|
struct defer_lock_t |
|
{}; |
|
struct try_to_lock_t |
|
{}; |
|
struct adopt_lock_t |
|
{}; |
|
|
|
const defer_lock_t defer_lock={}; |
|
const try_to_lock_t try_to_lock={}; |
|
const adopt_lock_t adopt_lock={}; |
|
|
|
template<typename Mutex> |
|
class shared_lock; |
|
|
|
template<typename Mutex> |
|
class upgrade_lock; |
|
|
|
template<typename Mutex> |
|
class unique_lock; |
|
|
|
namespace detail |
|
{ |
|
template<typename Mutex> |
|
class try_lock_wrapper; |
|
} |
|
|
|
#ifdef BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES |
|
template<typename T> |
|
struct is_mutex_type<unique_lock<T> > |
|
{ |
|
BOOST_STATIC_CONSTANT(bool, value = true); |
|
}; |
|
|
|
template<typename T> |
|
struct is_mutex_type<shared_lock<T> > |
|
{ |
|
BOOST_STATIC_CONSTANT(bool, value = true); |
|
}; |
|
|
|
template<typename T> |
|
struct is_mutex_type<upgrade_lock<T> > |
|
{ |
|
BOOST_STATIC_CONSTANT(bool, value = true); |
|
}; |
|
|
|
template<typename T> |
|
struct is_mutex_type<detail::try_lock_wrapper<T> > |
|
{ |
|
BOOST_STATIC_CONSTANT(bool, value = true); |
|
}; |
|
|
|
class mutex; |
|
class timed_mutex; |
|
class recursive_mutex; |
|
class recursive_timed_mutex; |
|
class shared_mutex; |
|
|
|
template<> |
|
struct is_mutex_type<mutex> |
|
{ |
|
BOOST_STATIC_CONSTANT(bool, value = true); |
|
}; |
|
template<> |
|
struct is_mutex_type<timed_mutex> |
|
{ |
|
BOOST_STATIC_CONSTANT(bool, value = true); |
|
}; |
|
template<> |
|
struct is_mutex_type<recursive_mutex> |
|
{ |
|
BOOST_STATIC_CONSTANT(bool, value = true); |
|
}; |
|
template<> |
|
struct is_mutex_type<recursive_timed_mutex> |
|
{ |
|
BOOST_STATIC_CONSTANT(bool, value = true); |
|
}; |
|
template<> |
|
struct is_mutex_type<shared_mutex> |
|
{ |
|
BOOST_STATIC_CONSTANT(bool, value = true); |
|
}; |
|
|
|
#endif |
|
|
|
template<typename Mutex> |
|
class lock_guard |
|
{ |
|
private: |
|
Mutex& m; |
|
|
|
explicit lock_guard(lock_guard&); |
|
lock_guard& operator=(lock_guard&); |
|
public: |
|
explicit lock_guard(Mutex& m_): |
|
m(m_) |
|
{ |
|
m.lock(); |
|
} |
|
lock_guard(Mutex& m_,adopt_lock_t): |
|
m(m_) |
|
{} |
|
~lock_guard() |
|
{ |
|
m.unlock(); |
|
} |
|
}; |
|
|
|
|
|
template<typename Mutex> |
|
class unique_lock |
|
{ |
|
private: |
|
Mutex* m; |
|
bool is_locked; |
|
unique_lock(unique_lock&); |
|
explicit unique_lock(upgrade_lock<Mutex>&); |
|
unique_lock& operator=(unique_lock&); |
|
unique_lock& operator=(upgrade_lock<Mutex>& other); |
|
public: |
|
#if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100) |
|
unique_lock(const volatile unique_lock&); |
|
#endif |
|
unique_lock(): |
|
m(0),is_locked(false) |
|
{} |
|
|
|
explicit unique_lock(Mutex& m_): |
|
m(&m_),is_locked(false) |
|
{ |
|
lock(); |
|
} |
|
unique_lock(Mutex& m_,adopt_lock_t): |
|
m(&m_),is_locked(true) |
|
{} |
|
unique_lock(Mutex& m_,defer_lock_t): |
|
m(&m_),is_locked(false) |
|
{} |
|
unique_lock(Mutex& m_,try_to_lock_t): |
|
m(&m_),is_locked(false) |
|
{ |
|
try_lock(); |
|
} |
|
template<typename TimeDuration> |
|
unique_lock(Mutex& m_,TimeDuration const& target_time): |
|
m(&m_),is_locked(false) |
|
{ |
|
timed_lock(target_time); |
|
} |
|
unique_lock(Mutex& m_,system_time const& target_time): |
|
m(&m_),is_locked(false) |
|
{ |
|
timed_lock(target_time); |
|
} |
|
#ifndef BOOST_NO_RVALUE_REFERENCES |
|
unique_lock(unique_lock&& other): |
|
m(other.m),is_locked(other.is_locked) |
|
{ |
|
other.is_locked=false; |
|
other.m=0; |
|
} |
|
explicit unique_lock(upgrade_lock<Mutex>&& other); |
|
|
|
unique_lock<Mutex>&& move() |
|
{ |
|
return static_cast<unique_lock<Mutex>&&>(*this); |
|
} |
|
|
|
|
|
unique_lock& operator=(unique_lock&& other) |
|
{ |
|
unique_lock temp(other.move()); |
|
swap(temp); |
|
return *this; |
|
} |
|
|
|
unique_lock& operator=(upgrade_lock<Mutex>&& other) |
|
{ |
|
unique_lock temp(other.move()); |
|
swap(temp); |
|
return *this; |
|
} |
|
void swap(unique_lock&& other) |
|
{ |
|
std::swap(m,other.m); |
|
std::swap(is_locked,other.is_locked); |
|
} |
|
#else |
|
unique_lock(detail::thread_move_t<unique_lock<Mutex> > other): |
|
m(other->m),is_locked(other->is_locked) |
|
{ |
|
other->is_locked=false; |
|
other->m=0; |
|
} |
|
unique_lock(detail::thread_move_t<upgrade_lock<Mutex> > other); |
|
|
|
operator detail::thread_move_t<unique_lock<Mutex> >() |
|
{ |
|
return move(); |
|
} |
|
|
|
detail::thread_move_t<unique_lock<Mutex> > move() |
|
{ |
|
return detail::thread_move_t<unique_lock<Mutex> >(*this); |
|
} |
|
|
|
#if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100) |
|
unique_lock& operator=(unique_lock<Mutex> other) |
|
{ |
|
swap(other); |
|
return *this; |
|
} |
|
#else |
|
unique_lock& operator=(detail::thread_move_t<unique_lock<Mutex> > other) |
|
{ |
|
unique_lock temp(other); |
|
swap(temp); |
|
return *this; |
|
} |
|
#endif |
|
|
|
unique_lock& operator=(detail::thread_move_t<upgrade_lock<Mutex> > other) |
|
{ |
|
unique_lock temp(other); |
|
swap(temp); |
|
return *this; |
|
} |
|
void swap(detail::thread_move_t<unique_lock<Mutex> > other) |
|
{ |
|
std::swap(m,other->m); |
|
std::swap(is_locked,other->is_locked); |
|
} |
|
#endif |
|
void swap(unique_lock& other) |
|
{ |
|
std::swap(m,other.m); |
|
std::swap(is_locked,other.is_locked); |
|
} |
|
|
|
~unique_lock() |
|
{ |
|
if(owns_lock()) |
|
{ |
|
m->unlock(); |
|
} |
|
} |
|
void lock() |
|
{ |
|
if(owns_lock()) |
|
{ |
|
boost::throw_exception(boost::lock_error()); |
|
} |
|
m->lock(); |
|
is_locked=true; |
|
} |
|
bool try_lock() |
|
{ |
|
if(owns_lock()) |
|
{ |
|
boost::throw_exception(boost::lock_error()); |
|
} |
|
is_locked=m->try_lock(); |
|
return is_locked; |
|
} |
|
template<typename TimeDuration> |
|
bool timed_lock(TimeDuration const& relative_time) |
|
{ |
|
is_locked=m->timed_lock(relative_time); |
|
return is_locked; |
|
} |
|
|
|
bool timed_lock(::boost::system_time const& absolute_time) |
|
{ |
|
is_locked=m->timed_lock(absolute_time); |
|
return is_locked; |
|
} |
|
bool timed_lock(::boost::xtime const& absolute_time) |
|
{ |
|
is_locked=m->timed_lock(absolute_time); |
|
return is_locked; |
|
} |
|
void unlock() |
|
{ |
|
if(!owns_lock()) |
|
{ |
|
boost::throw_exception(boost::lock_error()); |
|
} |
|
m->unlock(); |
|
is_locked=false; |
|
} |
|
|
|
typedef void (unique_lock::*bool_type)(); |
|
operator bool_type() const |
|
{ |
|
return is_locked?&unique_lock::lock:0; |
|
} |
|
bool operator!() const |
|
{ |
|
return !owns_lock(); |
|
} |
|
bool owns_lock() const |
|
{ |
|
return is_locked; |
|
} |
|
|
|
Mutex* mutex() const |
|
{ |
|
return m; |
|
} |
|
|
|
Mutex* release() |
|
{ |
|
Mutex* const res=m; |
|
m=0; |
|
is_locked=false; |
|
return res; |
|
} |
|
|
|
friend class shared_lock<Mutex>; |
|
friend class upgrade_lock<Mutex>; |
|
}; |
|
|
|
#ifndef BOOST_NO_RVALUE_REFERENCES |
|
template<typename Mutex> |
|
void swap(unique_lock<Mutex>&& lhs,unique_lock<Mutex>&& rhs) |
|
{ |
|
lhs.swap(rhs); |
|
} |
|
|
|
template<typename Mutex> |
|
inline upgrade_lock<Mutex>&& move(upgrade_lock<Mutex>&& ul) |
|
{ |
|
return static_cast<upgrade_lock<Mutex>&&>(ul); |
|
} |
|
|
|
template<typename Mutex> |
|
inline upgrade_lock<Mutex>&& move(upgrade_lock<Mutex>& ul) |
|
{ |
|
return static_cast<upgrade_lock<Mutex>&&>(ul); |
|
} |
|
#endif |
|
template<typename Mutex> |
|
void swap(unique_lock<Mutex>& lhs,unique_lock<Mutex>& rhs) |
|
{ |
|
lhs.swap(rhs); |
|
} |
|
|
|
#ifndef BOOST_NO_RVALUE_REFERENCES |
|
template<typename Mutex> |
|
inline unique_lock<Mutex>&& move(unique_lock<Mutex>&& ul) |
|
{ |
|
return static_cast<unique_lock<Mutex>&&>(ul); |
|
} |
|
|
|
template<typename Mutex> |
|
inline unique_lock<Mutex>&& move(unique_lock<Mutex>& ul) |
|
{ |
|
return static_cast<unique_lock<Mutex>&&>(ul); |
|
} |
|
#endif |
|
|
|
template<typename Mutex> |
|
class shared_lock |
|
{ |
|
protected: |
|
Mutex* m; |
|
bool is_locked; |
|
private: |
|
explicit shared_lock(shared_lock&); |
|
shared_lock& operator=(shared_lock&); |
|
public: |
|
shared_lock(): |
|
m(0),is_locked(false) |
|
{} |
|
|
|
explicit shared_lock(Mutex& m_): |
|
m(&m_),is_locked(false) |
|
{ |
|
lock(); |
|
} |
|
shared_lock(Mutex& m_,adopt_lock_t): |
|
m(&m_),is_locked(true) |
|
{} |
|
shared_lock(Mutex& m_,defer_lock_t): |
|
m(&m_),is_locked(false) |
|
{} |
|
shared_lock(Mutex& m_,try_to_lock_t): |
|
m(&m_),is_locked(false) |
|
{ |
|
try_lock(); |
|
} |
|
shared_lock(Mutex& m_,system_time const& target_time): |
|
m(&m_),is_locked(false) |
|
{ |
|
timed_lock(target_time); |
|
} |
|
|
|
shared_lock(detail::thread_move_t<shared_lock<Mutex> > other): |
|
m(other->m),is_locked(other->is_locked) |
|
{ |
|
other->is_locked=false; |
|
other->m=0; |
|
} |
|
|
|
shared_lock(detail::thread_move_t<unique_lock<Mutex> > other): |
|
m(other->m),is_locked(other->is_locked) |
|
{ |
|
if(is_locked) |
|
{ |
|
m->unlock_and_lock_shared(); |
|
} |
|
other->is_locked=false; |
|
other->m=0; |
|
} |
|
|
|
shared_lock(detail::thread_move_t<upgrade_lock<Mutex> > other): |
|
m(other->m),is_locked(other->is_locked) |
|
{ |
|
if(is_locked) |
|
{ |
|
m->unlock_upgrade_and_lock_shared(); |
|
} |
|
other->is_locked=false; |
|
other->m=0; |
|
} |
|
|
|
operator detail::thread_move_t<shared_lock<Mutex> >() |
|
{ |
|
return move(); |
|
} |
|
|
|
detail::thread_move_t<shared_lock<Mutex> > move() |
|
{ |
|
return detail::thread_move_t<shared_lock<Mutex> >(*this); |
|
} |
|
|
|
|
|
shared_lock& operator=(detail::thread_move_t<shared_lock<Mutex> > other) |
|
{ |
|
shared_lock temp(other); |
|
swap(temp); |
|
return *this; |
|
} |
|
|
|
shared_lock& operator=(detail::thread_move_t<unique_lock<Mutex> > other) |
|
{ |
|
shared_lock temp(other); |
|
swap(temp); |
|
return *this; |
|
} |
|
|
|
shared_lock& operator=(detail::thread_move_t<upgrade_lock<Mutex> > other) |
|
{ |
|
shared_lock temp(other); |
|
swap(temp); |
|
return *this; |
|
} |
|
|
|
#ifndef BOOST_NO_RVALUE_REFERENCES |
|
void swap(shared_lock&& other) |
|
{ |
|
std::swap(m,other.m); |
|
std::swap(is_locked,other.is_locked); |
|
} |
|
#else |
|
void swap(boost::detail::thread_move_t<shared_lock<Mutex> > other) |
|
{ |
|
std::swap(m,other->m); |
|
std::swap(is_locked,other->is_locked); |
|
} |
|
#endif |
|
void swap(shared_lock& other) |
|
{ |
|
std::swap(m,other.m); |
|
std::swap(is_locked,other.is_locked); |
|
} |
|
|
|
Mutex* mutex() const |
|
{ |
|
return m; |
|
} |
|
|
|
~shared_lock() |
|
{ |
|
if(owns_lock()) |
|
{ |
|
m->unlock_shared(); |
|
} |
|
} |
|
void lock() |
|
{ |
|
if(owns_lock()) |
|
{ |
|
boost::throw_exception(boost::lock_error()); |
|
} |
|
m->lock_shared(); |
|
is_locked=true; |
|
} |
|
bool try_lock() |
|
{ |
|
if(owns_lock()) |
|
{ |
|
boost::throw_exception(boost::lock_error()); |
|
} |
|
is_locked=m->try_lock_shared(); |
|
return is_locked; |
|
} |
|
bool timed_lock(boost::system_time const& target_time) |
|
{ |
|
if(owns_lock()) |
|
{ |
|
boost::throw_exception(boost::lock_error()); |
|
} |
|
is_locked=m->timed_lock_shared(target_time); |
|
return is_locked; |
|
} |
|
template<typename Duration> |
|
bool timed_lock(Duration const& target_time) |
|
{ |
|
if(owns_lock()) |
|
{ |
|
boost::throw_exception(boost::lock_error()); |
|
} |
|
is_locked=m->timed_lock_shared(target_time); |
|
return is_locked; |
|
} |
|
void unlock() |
|
{ |
|
if(!owns_lock()) |
|
{ |
|
boost::throw_exception(boost::lock_error()); |
|
} |
|
m->unlock_shared(); |
|
is_locked=false; |
|
} |
|
|
|
typedef void (shared_lock<Mutex>::*bool_type)(); |
|
operator bool_type() const |
|
{ |
|
return is_locked?&shared_lock::lock:0; |
|
} |
|
bool operator!() const |
|
{ |
|
return !owns_lock(); |
|
} |
|
bool owns_lock() const |
|
{ |
|
return is_locked; |
|
} |
|
|
|
}; |
|
|
|
#ifndef BOOST_NO_RVALUE_REFERENCES |
|
template<typename Mutex> |
|
void swap(shared_lock<Mutex>&& lhs,shared_lock<Mutex>&& rhs) |
|
{ |
|
lhs.swap(rhs); |
|
} |
|
#else |
|
template<typename Mutex> |
|
void swap(shared_lock<Mutex>& lhs,shared_lock<Mutex>& rhs) |
|
{ |
|
lhs.swap(rhs); |
|
} |
|
#endif |
|
|
|
template<typename Mutex> |
|
class upgrade_lock |
|
{ |
|
protected: |
|
Mutex* m; |
|
bool is_locked; |
|
private: |
|
explicit upgrade_lock(upgrade_lock&); |
|
upgrade_lock& operator=(upgrade_lock&); |
|
public: |
|
upgrade_lock(): |
|
m(0),is_locked(false) |
|
{} |
|
|
|
explicit upgrade_lock(Mutex& m_): |
|
m(&m_),is_locked(false) |
|
{ |
|
lock(); |
|
} |
|
upgrade_lock(Mutex& m_,adopt_lock_t): |
|
m(&m_),is_locked(true) |
|
{} |
|
upgrade_lock(Mutex& m_,defer_lock_t): |
|
m(&m_),is_locked(false) |
|
{} |
|
upgrade_lock(Mutex& m_,try_to_lock_t): |
|
m(&m_),is_locked(false) |
|
{ |
|
try_lock(); |
|
} |
|
#ifdef BOOST_HAS_RVALUE_REFS |
|
upgrade_lock(upgrade_lock<Mutex>&& other): |
|
m(other.m),is_locked(other.is_locked) |
|
{ |
|
other.is_locked=false; |
|
other.m=0; |
|
} |
|
|
|
upgrade_lock(unique_lock<Mutex>&& other): |
|
m(other.m),is_locked(other.is_locked) |
|
{ |
|
if(is_locked) |
|
{ |
|
m->unlock_and_lock_upgrade(); |
|
} |
|
other.is_locked=false; |
|
other.m=0; |
|
} |
|
|
|
upgrade_lock& operator=(upgrade_lock<Mutex>&& other) |
|
{ |
|
upgrade_lock temp(static_cast<upgrade_lock<Mutex>&&>(other)); |
|
swap(temp); |
|
return *this; |
|
} |
|
|
|
upgrade_lock& operator=(unique_lock<Mutex>&& other) |
|
{ |
|
upgrade_lock temp(static_cast<unique_lock<Mutex>&&>(other)); |
|
swap(temp); |
|
return *this; |
|
} |
|
#else |
|
upgrade_lock(detail::thread_move_t<upgrade_lock<Mutex> > other): |
|
m(other->m),is_locked(other->is_locked) |
|
{ |
|
other->is_locked=false; |
|
other->m=0; |
|
} |
|
|
|
upgrade_lock(detail::thread_move_t<unique_lock<Mutex> > other): |
|
m(other->m),is_locked(other->is_locked) |
|
{ |
|
if(is_locked) |
|
{ |
|
m->unlock_and_lock_upgrade(); |
|
} |
|
other->is_locked=false; |
|
other->m=0; |
|
} |
|
|
|
operator detail::thread_move_t<upgrade_lock<Mutex> >() |
|
{ |
|
return move(); |
|
} |
|
|
|
detail::thread_move_t<upgrade_lock<Mutex> > move() |
|
{ |
|
return detail::thread_move_t<upgrade_lock<Mutex> >(*this); |
|
} |
|
|
|
|
|
upgrade_lock& operator=(detail::thread_move_t<upgrade_lock<Mutex> > other) |
|
{ |
|
upgrade_lock temp(other); |
|
swap(temp); |
|
return *this; |
|
} |
|
|
|
upgrade_lock& operator=(detail::thread_move_t<unique_lock<Mutex> > other) |
|
{ |
|
upgrade_lock temp(other); |
|
swap(temp); |
|
return *this; |
|
} |
|
#endif |
|
|
|
void swap(upgrade_lock& other) |
|
{ |
|
std::swap(m,other.m); |
|
std::swap(is_locked,other.is_locked); |
|
} |
|
|
|
~upgrade_lock() |
|
{ |
|
if(owns_lock()) |
|
{ |
|
m->unlock_upgrade(); |
|
} |
|
} |
|
void lock() |
|
{ |
|
if(owns_lock()) |
|
{ |
|
boost::throw_exception(boost::lock_error()); |
|
} |
|
m->lock_upgrade(); |
|
is_locked=true; |
|
} |
|
bool try_lock() |
|
{ |
|
if(owns_lock()) |
|
{ |
|
boost::throw_exception(boost::lock_error()); |
|
} |
|
is_locked=m->try_lock_upgrade(); |
|
return is_locked; |
|
} |
|
void unlock() |
|
{ |
|
if(!owns_lock()) |
|
{ |
|
boost::throw_exception(boost::lock_error()); |
|
} |
|
m->unlock_upgrade(); |
|
is_locked=false; |
|
} |
|
|
|
typedef void (upgrade_lock::*bool_type)(); |
|
operator bool_type() const |
|
{ |
|
return is_locked?&upgrade_lock::lock:0; |
|
} |
|
bool operator!() const |
|
{ |
|
return !owns_lock(); |
|
} |
|
bool owns_lock() const |
|
{ |
|
return is_locked; |
|
} |
|
friend class shared_lock<Mutex>; |
|
friend class unique_lock<Mutex>; |
|
}; |
|
|
|
|
|
#ifndef BOOST_NO_RVALUE_REFERENCES |
|
template<typename Mutex> |
|
unique_lock<Mutex>::unique_lock(upgrade_lock<Mutex>&& other): |
|
m(other.m),is_locked(other.is_locked) |
|
{ |
|
other.is_locked=false; |
|
if(is_locked) |
|
{ |
|
m->unlock_upgrade_and_lock(); |
|
} |
|
} |
|
#else |
|
template<typename Mutex> |
|
unique_lock<Mutex>::unique_lock(detail::thread_move_t<upgrade_lock<Mutex> > other): |
|
m(other->m),is_locked(other->is_locked) |
|
{ |
|
other->is_locked=false; |
|
if(is_locked) |
|
{ |
|
m->unlock_upgrade_and_lock(); |
|
} |
|
} |
|
#endif |
|
template <class Mutex> |
|
class upgrade_to_unique_lock |
|
{ |
|
private: |
|
upgrade_lock<Mutex>* source; |
|
unique_lock<Mutex> exclusive; |
|
|
|
explicit upgrade_to_unique_lock(upgrade_to_unique_lock&); |
|
upgrade_to_unique_lock& operator=(upgrade_to_unique_lock&); |
|
public: |
|
explicit upgrade_to_unique_lock(upgrade_lock<Mutex>& m_): |
|
source(&m_),exclusive(move(*source)) |
|
{} |
|
~upgrade_to_unique_lock() |
|
{ |
|
if(source) |
|
{ |
|
*source=move(exclusive); |
|
} |
|
} |
|
|
|
#ifdef BOOST_HAS_RVALUE_REFS |
|
upgrade_to_unique_lock(upgrade_to_unique_lock<Mutex>&& other): |
|
source(other.source),exclusive(move(other.exclusive)) |
|
{ |
|
other.source=0; |
|
} |
|
|
|
upgrade_to_unique_lock& operator=(upgrade_to_unique_lock<Mutex>&& other) |
|
{ |
|
upgrade_to_unique_lock temp(other); |
|
swap(temp); |
|
return *this; |
|
} |
|
#else |
|
upgrade_to_unique_lock(detail::thread_move_t<upgrade_to_unique_lock<Mutex> > other): |
|
source(other->source),exclusive(move(other->exclusive)) |
|
{ |
|
other->source=0; |
|
} |
|
|
|
upgrade_to_unique_lock& operator=(detail::thread_move_t<upgrade_to_unique_lock<Mutex> > other) |
|
{ |
|
upgrade_to_unique_lock temp(other); |
|
swap(temp); |
|
return *this; |
|
} |
|
#endif |
|
void swap(upgrade_to_unique_lock& other) |
|
{ |
|
std::swap(source,other.source); |
|
exclusive.swap(other.exclusive); |
|
} |
|
typedef void (upgrade_to_unique_lock::*bool_type)(upgrade_to_unique_lock&); |
|
operator bool_type() const |
|
{ |
|
return exclusive.owns_lock()?&upgrade_to_unique_lock::swap:0; |
|
} |
|
bool operator!() const |
|
{ |
|
return !owns_lock(); |
|
} |
|
bool owns_lock() const |
|
{ |
|
return exclusive.owns_lock(); |
|
} |
|
}; |
|
|
|
namespace detail |
|
{ |
|
template<typename Mutex> |
|
class try_lock_wrapper: |
|
private unique_lock<Mutex> |
|
{ |
|
typedef unique_lock<Mutex> base; |
|
public: |
|
try_lock_wrapper() |
|
{} |
|
|
|
explicit try_lock_wrapper(Mutex& m): |
|
base(m,try_to_lock) |
|
{} |
|
|
|
try_lock_wrapper(Mutex& m_,adopt_lock_t): |
|
base(m_,adopt_lock) |
|
{} |
|
try_lock_wrapper(Mutex& m_,defer_lock_t): |
|
base(m_,defer_lock) |
|
{} |
|
try_lock_wrapper(Mutex& m_,try_to_lock_t): |
|
base(m_,try_to_lock) |
|
{} |
|
#ifndef BOOST_NO_RVALUE_REFERENCES |
|
try_lock_wrapper(try_lock_wrapper&& other): |
|
base(other.move()) |
|
{} |
|
|
|
try_lock_wrapper&& move() |
|
{ |
|
return static_cast<try_lock_wrapper&&>(*this); |
|
} |
|
|
|
try_lock_wrapper& operator=(try_lock_wrapper<Mutex>&& other) |
|
{ |
|
try_lock_wrapper temp(other.move()); |
|
swap(temp); |
|
return *this; |
|
} |
|
|
|
void swap(try_lock_wrapper&& other) |
|
{ |
|
base::swap(other); |
|
} |
|
#else |
|
try_lock_wrapper(detail::thread_move_t<try_lock_wrapper<Mutex> > other): |
|
base(detail::thread_move_t<base>(*other)) |
|
{} |
|
|
|
operator detail::thread_move_t<try_lock_wrapper<Mutex> >() |
|
{ |
|
return move(); |
|
} |
|
|
|
detail::thread_move_t<try_lock_wrapper<Mutex> > move() |
|
{ |
|
return detail::thread_move_t<try_lock_wrapper<Mutex> >(*this); |
|
} |
|
|
|
try_lock_wrapper& operator=(detail::thread_move_t<try_lock_wrapper<Mutex> > other) |
|
{ |
|
try_lock_wrapper temp(other); |
|
swap(temp); |
|
return *this; |
|
} |
|
|
|
void swap(detail::thread_move_t<try_lock_wrapper<Mutex> > other) |
|
{ |
|
base::swap(*other); |
|
} |
|
#endif |
|
void swap(try_lock_wrapper& other) |
|
{ |
|
base::swap(other); |
|
} |
|
void lock() |
|
{ |
|
base::lock(); |
|
} |
|
bool try_lock() |
|
{ |
|
return base::try_lock(); |
|
} |
|
void unlock() |
|
{ |
|
base::unlock(); |
|
} |
|
bool owns_lock() const |
|
{ |
|
return base::owns_lock(); |
|
} |
|
Mutex* mutex() const |
|
{ |
|
return base::mutex(); |
|
} |
|
Mutex* release() |
|
{ |
|
return base::release(); |
|
} |
|
bool operator!() const |
|
{ |
|
return !this->owns_lock(); |
|
} |
|
|
|
typedef typename base::bool_type bool_type; |
|
operator bool_type() const |
|
{ |
|
return base::operator bool_type(); |
|
} |
|
}; |
|
|
|
#ifndef BOOST_NO_RVALUE_REFERENCES |
|
template<typename Mutex> |
|
void swap(try_lock_wrapper<Mutex>&& lhs,try_lock_wrapper<Mutex>&& rhs) |
|
{ |
|
lhs.swap(rhs); |
|
} |
|
#else |
|
template<typename Mutex> |
|
void swap(try_lock_wrapper<Mutex>& lhs,try_lock_wrapper<Mutex>& rhs) |
|
{ |
|
lhs.swap(rhs); |
|
} |
|
#endif |
|
|
|
template<typename MutexType1,typename MutexType2> |
|
unsigned try_lock_internal(MutexType1& m1,MutexType2& m2) |
|
{ |
|
boost::unique_lock<MutexType1> l1(m1,boost::try_to_lock); |
|
if(!l1) |
|
{ |
|
return 1; |
|
} |
|
if(!m2.try_lock()) |
|
{ |
|
return 2; |
|
} |
|
l1.release(); |
|
return 0; |
|
} |
|
|
|
template<typename MutexType1,typename MutexType2,typename MutexType3> |
|
unsigned try_lock_internal(MutexType1& m1,MutexType2& m2,MutexType3& m3) |
|
{ |
|
boost::unique_lock<MutexType1> l1(m1,boost::try_to_lock); |
|
if(!l1) |
|
{ |
|
return 1; |
|
} |
|
if(unsigned const failed_lock=try_lock_internal(m2,m3)) |
|
{ |
|
return failed_lock+1; |
|
} |
|
l1.release(); |
|
return 0; |
|
} |
|
|
|
|
|
template<typename MutexType1,typename MutexType2,typename MutexType3, |
|
typename MutexType4> |
|
unsigned try_lock_internal(MutexType1& m1,MutexType2& m2,MutexType3& m3, |
|
MutexType4& m4) |
|
{ |
|
boost::unique_lock<MutexType1> l1(m1,boost::try_to_lock); |
|
if(!l1) |
|
{ |
|
return 1; |
|
} |
|
if(unsigned const failed_lock=try_lock_internal(m2,m3,m4)) |
|
{ |
|
return failed_lock+1; |
|
} |
|
l1.release(); |
|
return 0; |
|
} |
|
|
|
template<typename MutexType1,typename MutexType2,typename MutexType3, |
|
typename MutexType4,typename MutexType5> |
|
unsigned try_lock_internal(MutexType1& m1,MutexType2& m2,MutexType3& m3, |
|
MutexType4& m4,MutexType5& m5) |
|
{ |
|
boost::unique_lock<MutexType1> l1(m1,boost::try_to_lock); |
|
if(!l1) |
|
{ |
|
return 1; |
|
} |
|
if(unsigned const failed_lock=try_lock_internal(m2,m3,m4,m5)) |
|
{ |
|
return failed_lock+1; |
|
} |
|
l1.release(); |
|
return 0; |
|
} |
|
|
|
|
|
template<typename MutexType1,typename MutexType2> |
|
unsigned lock_helper(MutexType1& m1,MutexType2& m2) |
|
{ |
|
boost::unique_lock<MutexType1> l1(m1); |
|
if(!m2.try_lock()) |
|
{ |
|
return 1; |
|
} |
|
l1.release(); |
|
return 0; |
|
} |
|
|
|
template<typename MutexType1,typename MutexType2,typename MutexType3> |
|
unsigned lock_helper(MutexType1& m1,MutexType2& m2,MutexType3& m3) |
|
{ |
|
boost::unique_lock<MutexType1> l1(m1); |
|
if(unsigned const failed_lock=try_lock_internal(m2,m3)) |
|
{ |
|
return failed_lock; |
|
} |
|
l1.release(); |
|
return 0; |
|
} |
|
|
|
template<typename MutexType1,typename MutexType2,typename MutexType3, |
|
typename MutexType4> |
|
unsigned lock_helper(MutexType1& m1,MutexType2& m2,MutexType3& m3, |
|
MutexType4& m4) |
|
{ |
|
boost::unique_lock<MutexType1> l1(m1); |
|
if(unsigned const failed_lock=try_lock_internal(m2,m3,m4)) |
|
{ |
|
return failed_lock; |
|
} |
|
l1.release(); |
|
return 0; |
|
} |
|
|
|
template<typename MutexType1,typename MutexType2,typename MutexType3, |
|
typename MutexType4,typename MutexType5> |
|
unsigned lock_helper(MutexType1& m1,MutexType2& m2,MutexType3& m3, |
|
MutexType4& m4,MutexType5& m5) |
|
{ |
|
boost::unique_lock<MutexType1> l1(m1); |
|
if(unsigned const failed_lock=try_lock_internal(m2,m3,m4,m5)) |
|
{ |
|
return failed_lock; |
|
} |
|
l1.release(); |
|
return 0; |
|
} |
|
} |
|
|
|
namespace detail |
|
{ |
|
template<bool x> |
|
struct is_mutex_type_wrapper |
|
{}; |
|
|
|
template<typename MutexType1,typename MutexType2> |
|
void lock_impl(MutexType1& m1,MutexType2& m2,is_mutex_type_wrapper<true>) |
|
{ |
|
unsigned const lock_count=2; |
|
unsigned lock_first=0; |
|
for(;;) |
|
{ |
|
switch(lock_first) |
|
{ |
|
case 0: |
|
lock_first=detail::lock_helper(m1,m2); |
|
if(!lock_first) |
|
return; |
|
break; |
|
case 1: |
|
lock_first=detail::lock_helper(m2,m1); |
|
if(!lock_first) |
|
return; |
|
lock_first=(lock_first+1)%lock_count; |
|
break; |
|
} |
|
} |
|
} |
|
|
|
template<typename Iterator> |
|
void lock_impl(Iterator begin,Iterator end,is_mutex_type_wrapper<false>); |
|
} |
|
|
|
|
|
template<typename MutexType1,typename MutexType2> |
|
void lock(MutexType1& m1,MutexType2& m2) |
|
{ |
|
detail::lock_impl(m1,m2,detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>()); |
|
} |
|
|
|
template<typename MutexType1,typename MutexType2> |
|
void lock(const MutexType1& m1,MutexType2& m2) |
|
{ |
|
detail::lock_impl(m1,m2,detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>()); |
|
} |
|
|
|
template<typename MutexType1,typename MutexType2> |
|
void lock(MutexType1& m1,const MutexType2& m2) |
|
{ |
|
detail::lock_impl(m1,m2,detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>()); |
|
} |
|
|
|
template<typename MutexType1,typename MutexType2> |
|
void lock(const MutexType1& m1,const MutexType2& m2) |
|
{ |
|
detail::lock_impl(m1,m2,detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>()); |
|
} |
|
|
|
template<typename MutexType1,typename MutexType2,typename MutexType3> |
|
void lock(MutexType1& m1,MutexType2& m2,MutexType3& m3) |
|
{ |
|
unsigned const lock_count=3; |
|
unsigned lock_first=0; |
|
for(;;) |
|
{ |
|
switch(lock_first) |
|
{ |
|
case 0: |
|
lock_first=detail::lock_helper(m1,m2,m3); |
|
if(!lock_first) |
|
return; |
|
break; |
|
case 1: |
|
lock_first=detail::lock_helper(m2,m3,m1); |
|
if(!lock_first) |
|
return; |
|
lock_first=(lock_first+1)%lock_count; |
|
break; |
|
case 2: |
|
lock_first=detail::lock_helper(m3,m1,m2); |
|
if(!lock_first) |
|
return; |
|
lock_first=(lock_first+2)%lock_count; |
|
break; |
|
} |
|
} |
|
} |
|
|
|
template<typename MutexType1,typename MutexType2,typename MutexType3, |
|
typename MutexType4> |
|
void lock(MutexType1& m1,MutexType2& m2,MutexType3& m3, |
|
MutexType4& m4) |
|
{ |
|
unsigned const lock_count=4; |
|
unsigned lock_first=0; |
|
for(;;) |
|
{ |
|
switch(lock_first) |
|
{ |
|
case 0: |
|
lock_first=detail::lock_helper(m1,m2,m3,m4); |
|
if(!lock_first) |
|
return; |
|
break; |
|
case 1: |
|
lock_first=detail::lock_helper(m2,m3,m4,m1); |
|
if(!lock_first) |
|
return; |
|
lock_first=(lock_first+1)%lock_count; |
|
break; |
|
case 2: |
|
lock_first=detail::lock_helper(m3,m4,m1,m2); |
|
if(!lock_first) |
|
return; |
|
lock_first=(lock_first+2)%lock_count; |
|
break; |
|
case 3: |
|
lock_first=detail::lock_helper(m4,m1,m2,m3); |
|
if(!lock_first) |
|
return; |
|
lock_first=(lock_first+3)%lock_count; |
|
break; |
|
} |
|
} |
|
} |
|
|
|
template<typename MutexType1,typename MutexType2,typename MutexType3, |
|
typename MutexType4,typename MutexType5> |
|
void lock(MutexType1& m1,MutexType2& m2,MutexType3& m3, |
|
MutexType4& m4,MutexType5& m5) |
|
{ |
|
unsigned const lock_count=5; |
|
unsigned lock_first=0; |
|
for(;;) |
|
{ |
|
switch(lock_first) |
|
{ |
|
case 0: |
|
lock_first=detail::lock_helper(m1,m2,m3,m4,m5); |
|
if(!lock_first) |
|
return; |
|
break; |
|
case 1: |
|
lock_first=detail::lock_helper(m2,m3,m4,m5,m1); |
|
if(!lock_first) |
|
return; |
|
lock_first=(lock_first+1)%lock_count; |
|
break; |
|
case 2: |
|
lock_first=detail::lock_helper(m3,m4,m5,m1,m2); |
|
if(!lock_first) |
|
return; |
|
lock_first=(lock_first+2)%lock_count; |
|
break; |
|
case 3: |
|
lock_first=detail::lock_helper(m4,m5,m1,m2,m3); |
|
if(!lock_first) |
|
return; |
|
lock_first=(lock_first+3)%lock_count; |
|
break; |
|
case 4: |
|
lock_first=detail::lock_helper(m5,m1,m2,m3,m4); |
|
if(!lock_first) |
|
return; |
|
lock_first=(lock_first+4)%lock_count; |
|
break; |
|
} |
|
} |
|
} |
|
|
|
namespace detail |
|
{ |
|
template<typename Mutex,bool x=is_mutex_type<Mutex>::value> |
|
struct try_lock_impl_return |
|
{ |
|
typedef int type; |
|
}; |
|
|
|
template<typename Iterator> |
|
struct try_lock_impl_return<Iterator,false> |
|
{ |
|
typedef Iterator type; |
|
}; |
|
|
|
template<typename MutexType1,typename MutexType2> |
|
int try_lock_impl(MutexType1& m1,MutexType2& m2,is_mutex_type_wrapper<true>) |
|
{ |
|
return ((int)detail::try_lock_internal(m1,m2))-1; |
|
} |
|
|
|
template<typename Iterator> |
|
Iterator try_lock_impl(Iterator begin,Iterator end,is_mutex_type_wrapper<false>); |
|
} |
|
|
|
template<typename MutexType1,typename MutexType2> |
|
typename detail::try_lock_impl_return<MutexType1>::type try_lock(MutexType1& m1,MutexType2& m2) |
|
{ |
|
return detail::try_lock_impl(m1,m2,detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>()); |
|
} |
|
|
|
template<typename MutexType1,typename MutexType2> |
|
typename detail::try_lock_impl_return<MutexType1>::type try_lock(const MutexType1& m1,MutexType2& m2) |
|
{ |
|
return detail::try_lock_impl(m1,m2,detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>()); |
|
} |
|
|
|
template<typename MutexType1,typename MutexType2> |
|
typename detail::try_lock_impl_return<MutexType1>::type try_lock(MutexType1& m1,const MutexType2& m2) |
|
{ |
|
return detail::try_lock_impl(m1,m2,detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>()); |
|
} |
|
|
|
template<typename MutexType1,typename MutexType2> |
|
typename detail::try_lock_impl_return<MutexType1>::type try_lock(const MutexType1& m1,const MutexType2& m2) |
|
{ |
|
return detail::try_lock_impl(m1,m2,detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>()); |
|
} |
|
|
|
template<typename MutexType1,typename MutexType2,typename MutexType3> |
|
int try_lock(MutexType1& m1,MutexType2& m2,MutexType3& m3) |
|
{ |
|
return ((int)detail::try_lock_internal(m1,m2,m3))-1; |
|
} |
|
|
|
template<typename MutexType1,typename MutexType2,typename MutexType3,typename MutexType4> |
|
int try_lock(MutexType1& m1,MutexType2& m2,MutexType3& m3,MutexType4& m4) |
|
{ |
|
return ((int)detail::try_lock_internal(m1,m2,m3,m4))-1; |
|
} |
|
|
|
template<typename MutexType1,typename MutexType2,typename MutexType3,typename MutexType4,typename MutexType5> |
|
int try_lock(MutexType1& m1,MutexType2& m2,MutexType3& m3,MutexType4& m4,MutexType5& m5) |
|
{ |
|
return ((int)detail::try_lock_internal(m1,m2,m3,m4,m5))-1; |
|
} |
|
|
|
|
|
namespace detail |
|
{ |
|
template<typename Iterator> |
|
struct range_lock_guard |
|
{ |
|
Iterator begin; |
|
Iterator end; |
|
|
|
range_lock_guard(Iterator begin_,Iterator end_): |
|
begin(begin_),end(end_) |
|
{ |
|
lock(begin,end); |
|
} |
|
|
|
void release() |
|
{ |
|
begin=end; |
|
} |
|
|
|
~range_lock_guard() |
|
{ |
|
for(;begin!=end;++begin) |
|
{ |
|
begin->unlock(); |
|
} |
|
} |
|
}; |
|
|
|
template<typename Iterator> |
|
Iterator try_lock_impl(Iterator begin,Iterator end,is_mutex_type_wrapper<false>) |
|
|
|
{ |
|
if(begin==end) |
|
{ |
|
return end; |
|
} |
|
typedef typename std::iterator_traits<Iterator>::value_type lock_type; |
|
unique_lock<lock_type> guard(*begin,try_to_lock); |
|
|
|
if(!guard.owns_lock()) |
|
{ |
|
return begin; |
|
} |
|
Iterator const failed=try_lock(++begin,end); |
|
if(failed==end) |
|
{ |
|
guard.release(); |
|
} |
|
|
|
return failed; |
|
} |
|
} |
|
|
|
|
|
namespace detail |
|
{ |
|
template<typename Iterator> |
|
void lock_impl(Iterator begin,Iterator end,is_mutex_type_wrapper<false>) |
|
{ |
|
typedef typename std::iterator_traits<Iterator>::value_type lock_type; |
|
|
|
if(begin==end) |
|
{ |
|
return; |
|
} |
|
bool start_with_begin=true; |
|
Iterator second=begin; |
|
++second; |
|
Iterator next=second; |
|
|
|
for(;;) |
|
{ |
|
unique_lock<lock_type> begin_lock(*begin,defer_lock); |
|
if(start_with_begin) |
|
{ |
|
begin_lock.lock(); |
|
Iterator const failed_lock=try_lock(next,end); |
|
if(failed_lock==end) |
|
{ |
|
begin_lock.release(); |
|
return; |
|
} |
|
start_with_begin=false; |
|
next=failed_lock; |
|
} |
|
else |
|
{ |
|
detail::range_lock_guard<Iterator> guard(next,end); |
|
if(begin_lock.try_lock()) |
|
{ |
|
Iterator const failed_lock=try_lock(second,next); |
|
if(failed_lock==next) |
|
{ |
|
begin_lock.release(); |
|
guard.release(); |
|
return; |
|
} |
|
start_with_begin=false; |
|
next=failed_lock; |
|
} |
|
else |
|
{ |
|
start_with_begin=true; |
|
next=second; |
|
} |
|
} |
|
} |
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
#include <boost/config/abi_suffix.hpp> |
|
|
|
#endif
|
|
|