boost/thread/locks.hpp
// 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 <boost/thread/thread_time.hpp>
namespace boost
{
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 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;
explicit unique_lock(unique_lock&);
unique_lock& operator=(unique_lock&);
public:
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();
}
unique_lock(Mutex& m_,system_time const& target_time):
m(&m_),is_locked(false)
{
timed_lock(target_time);
}
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);
}
unique_lock& operator=(detail::thread_move_t<unique_lock<Mutex> > other)
{
unique_lock temp(other);
swap(temp);
return *this;
}
unique_lock& operator=(detail::thread_move_t<upgrade_lock<Mutex> > other)
{
unique_lock temp(other);
swap(temp);
return *this;
}
void swap(unique_lock& other)
{
std::swap(m,other.m);
std::swap(is_locked,other.is_locked);
}
void swap(detail::thread_move_t<unique_lock<Mutex> > 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())
{
throw boost::lock_error();
}
m->lock();
is_locked=true;
}
bool try_lock()
{
if(owns_lock())
{
throw 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;
}
void unlock()
{
if(!owns_lock())
{
throw 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>;
};
template<typename Mutex>
inline detail::thread_move_t<unique_lock<Mutex> > move(unique_lock<Mutex> & x)
{
return x.move();
}
template<typename Mutex>
inline detail::thread_move_t<unique_lock<Mutex> > move(detail::thread_move_t<unique_lock<Mutex> > x)
{
return x;
}
template<typename Mutex>
class shared_lock
{
protected:
Mutex* m;
bool is_locked;
private:
explicit shared_lock(shared_lock&);
shared_lock& operator=(shared_lock&);
public:
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;
}
shared_lock(detail::thread_move_t<unique_lock<Mutex> > other):
m(other->m),is_locked(other->is_locked)
{
other->is_locked=false;
if(is_locked)
{
m->unlock_and_lock_shared();
}
}
shared_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_shared();
}
}
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;
}
void swap(shared_lock& other)
{
std::swap(m,other.m);
std::swap(is_locked,other.is_locked);
}
~shared_lock()
{
if(owns_lock())
{
m->unlock_shared();
}
}
void lock()
{
if(owns_lock())
{
throw boost::lock_error();
}
m->lock_shared();
is_locked=true;
}
bool try_lock()
{
if(owns_lock())
{
throw boost::lock_error();
}
is_locked=m->try_lock_shared();
return is_locked;
}
bool timed_lock(boost::system_time const& target_time)
{
if(owns_lock())
{
throw boost::lock_error();
}
is_locked=m->timed_lock_shared(target_time);
return is_locked;
}
void unlock()
{
if(!owns_lock())
{
throw boost::lock_error();
}
m->unlock_shared();
is_locked=false;
}
typedef void (shared_lock::*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;
}
};
template<typename Mutex>
inline detail::thread_move_t<shared_lock<Mutex> > move(shared_lock<Mutex> & x)
{
return x.move();
}
template<typename Mutex>
inline detail::thread_move_t<shared_lock<Mutex> > move(detail::thread_move_t<shared_lock<Mutex> > x)
{
return x;
}
template<typename Mutex>
class upgrade_lock
{
protected:
Mutex* m;
bool is_locked;
private:
explicit upgrade_lock(upgrade_lock&);
upgrade_lock& operator=(upgrade_lock&);
public:
explicit upgrade_lock(Mutex& m_):
m(&m_),is_locked(false)
{
lock();
}
upgrade_lock(Mutex& m_,bool do_lock):
m(&m_),is_locked(false)
{
if(do_lock)
{
lock();
}
}
upgrade_lock(detail::thread_move_t<upgrade_lock<Mutex> > other):
m(other->m),is_locked(other->is_locked)
{
other->is_locked=false;
}
upgrade_lock(detail::thread_move_t<unique_lock<Mutex> > other):
m(other->m),is_locked(other->is_locked)
{
other->is_locked=false;
if(is_locked)
{
m->unlock_and_lock_upgrade();
}
}
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;
}
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())
{
throw boost::lock_error();
}
m->lock_upgrade();
is_locked=true;
}
bool try_lock()
{
if(owns_lock())
{
throw boost::lock_error();
}
is_locked=m->try_lock_upgrade();
return is_locked;
}
void unlock()
{
if(!owns_lock())
{
throw 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>;
};
template<typename Mutex>
inline detail::thread_move_t<upgrade_lock<Mutex> > move(upgrade_lock<Mutex> & x)
{
return x.move();
}
template<typename Mutex>
inline detail::thread_move_t<upgrade_lock<Mutex> > move(detail::thread_move_t<upgrade_lock<Mutex> > x)
{
return x;
}
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();
}
}
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);
}
}
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;
}
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();
}
};
}
#endif