First inclusion in repository

[SVN r34901]
This commit is contained in:
Ion Gaztañaga
2006-08-18 13:14:03 +00:00
parent 5573eac65f
commit f5d47cff17
7 changed files with 1544 additions and 0 deletions

View File

@@ -0,0 +1,60 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztañaga 2005-2006. 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)
//
// See http://www.boost.org/libs/interprocess for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTERPROCESS_MOVE_HPP
#define BOOST_INTERPROCESS_MOVE_HPP
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
/*!\file
Describes a function and a type to emulate move semantics.
*/
namespace boost {
namespace interprocess {
namespace detail {
/*!An object that represents a moved object.*/
template<class Object>
struct moved_object
{
moved_object(const Object &obj)
: m_obj(const_cast<Object *>(&obj))
{}
Object &get()
{ return *m_obj; }
private:
Object *m_obj;
};
} //namespace detail {
/*!A function that converts an object to a moved object so that
it can match a function taking a detail::moved_object object.*/
template<class Object>
detail::moved_object<Object> move
(/*const */Object &lock)
{ return detail::moved_object<Object>(lock); }
} //namespace interprocess {
} //namespace boost {
#include <boost/interprocess/detail/config_end.hpp>
#endif

View File

@@ -0,0 +1,69 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztañaga 2005-2006. 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)
//
// See http://www.boost.org/libs/interprocess for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTERPROCESS_DETAIL_OS_THREAD_FUNCTIONS_HPP
#define BOOST_INTERPROCESS_DETAIL_OS_THREAD_FUNCTIONS_HPP
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
# include <boost/interprocess/sync/win32/win32_sync_primitives.hpp>
#else
# ifdef BOOST_HAS_UNISTD_H
# include <pthread.h>
# include <unistd.h>
# else
# error Unknown platform
# endif
#endif
namespace boost {
namespace interprocess {
namespace detail{
#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
typedef unsigned long OS_thread_id_t;
inline OS_thread_id_t get_current_thread_id()
{ return winapi::get_current_thread_id(); }
inline OS_thread_id_t get_invalid_thread_id()
{ return OS_thread_id_t(0xffffffff); }
inline OS_thread_id_t equal_thread_id(OS_thread_id_t id1, OS_thread_id_t id2)
{ return id1 == id2; }
#else //#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
typedef pthread_t OS_thread_id_t;
inline pthread_t get_current_thread_id()
{ return pthread_self(); }
inline OS_thread_id_t invalid_thread_id()
{
static pthread_t invalid_id;
return invalid_id;
}
inline OS_thread_id_t equal_thread_id(OS_thread_id_t id1, OS_thread_id_t id2)
{ return 0 != pthread_equal(id1, id2); }
#endif //#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
} //namespace detail{
} //namespace interprocess {
} //namespace boost {
#include <boost/interprocess/detail/config_end.hpp>
#endif //BOOST_INTERPROCESS_DETAIL_OS_THREAD_FUNCTIONS_HPP

View File

@@ -0,0 +1,390 @@
//////////////////////////////////////////////////////////////////////////////
// I, Howard Hinnant, hereby place this code in the public domain.
//////////////////////////////////////////////////////////////////////////////
//
// This file is the adaptation for Interprocess of
// Howard Hinnant's unique_ptr emulation
//
// (C) Copyright Ion Gaztañaga 2006. 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)
//
// See http://www.boost.org/libs/interprocess for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTERPROCESS_UNIQUE_PTR_HPP_INCLUDED
#define BOOST_INTERPROCESS_UNIQUE_PTR_HPP_INCLUDED
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/assert.hpp>
#include <boost/interprocess/detail/utilities.hpp>
#include <boost/interprocess/detail/move.hpp>
#include <boost/compressed_pair.hpp>
#include <boost/static_assert.hpp>
#include <boost/mpl/if.hpp>
#include <boost/type_traits.hpp>
#include <boost/utility/enable_if.hpp>
#include <cstddef>
namespace boost{
namespace interprocess{
template <class T>
struct default_delete
{
default_delete() {}
template <class U> default_delete(const default_delete<U>&) {}
void operator() (T* ptr) const
{
BOOST_STATIC_ASSERT(sizeof(T) > 0);
delete ptr;
}
};
template <class T>
struct default_delete<T[]>
{
void operator() (T* ptr) const
{
BOOST_STATIC_ASSERT(sizeof(T) > 0);
delete [] ptr;
}
};
template <class T, std::size_t N>
struct default_delete<T[N]>
{
void operator() (T* ptr, std::size_t) const
{
BOOST_STATIC_ASSERT(sizeof(T) > 0);
delete [] ptr;
}
};
template <class T, class D> class unique_ptr;
namespace detail {
template <class T> struct unique_ptr_error;
template <class T, class D>
struct unique_ptr_error<const unique_ptr<T, D> >
{
typedef unique_ptr<T, D> type;
};
} //namespace detail {
template <class T, class D = default_delete<T> >
class unique_ptr
{
struct nat {int for_bool_;};
typedef typename boost::add_reference<D>::type deleter_reference;
typedef typename boost::add_reference<const D>::type deleter_const_reference;
public:
typedef T element_type;
typedef D deleter_type;
typedef typename detail::pointer_type<T, D>::type pointer;
// constructors
unique_ptr() : ptr_(pointer()) {}
explicit unique_ptr(pointer p) : ptr_(p) {}
unique_ptr(pointer p
,typename boost::mpl::if_<boost::is_reference<D>
,D
,typename boost::add_reference<const D>::type>::type d)
: ptr_(p, d)
{}
/*
unique_ptr(const unique_ptr& u)
: ptr_(const_cast<unique_ptr&>(u).release(), u.get_deleter())
{}
*/
unique_ptr(detail::moved_object<unique_ptr> u)
: ptr_(u.get().release(), u.get().get_deleter())
{}
template <class U, class E>
unique_ptr(const unique_ptr<U, E>& u,
typename boost::enable_if_c<
boost::is_convertible<typename unique_ptr<U, E>::pointer, pointer>::value &&
boost::is_convertible<E, D>::value &&
(
!boost::is_reference<D>::value ||
boost::is_same<D, E>::value
)
,
nat
>::type = nat())
: ptr_(const_cast<unique_ptr<U,E>&>(u).release(), u.get_deleter())
{}
// destructor
~unique_ptr()
{ reset(); }
// assignment
unique_ptr& operator=(const unique_ptr& cu)
{
unique_ptr& u = const_cast<unique_ptr&>(cu);
reset(u.release());
ptr_.second() = u.get_deleter();
return *this;
}
template <class U, class E>
unique_ptr& operator=(const unique_ptr<U, E>& cu)
{
unique_ptr<U, E>& u = const_cast<unique_ptr<U, E>&>(cu);
reset(u.release());
ptr_.second() = u.get_deleter();
return *this;
}
unique_ptr& operator=(int nat::*)
{
reset();
return *this;
}
// observers
typename boost::add_reference<T>::type operator*() const {return *ptr_.first();}
pointer operator->() const {return ptr_.first();}
pointer get() const {return ptr_.first();}
deleter_reference get_deleter() {return ptr_.second();}
deleter_const_reference get_deleter() const {return ptr_.second();}
operator int nat::*() const {return ptr_.first() ? &nat::for_bool_ : 0;}
// modifiers
pointer release()
{
pointer tmp = ptr_.first();
ptr_.first() = pointer();
return tmp;
}
void reset(pointer p = pointer())
{
if (ptr_.first() != p)
{
if (ptr_.first())
ptr_.second()(ptr_.first());
ptr_.first() = p;
}
}
void swap(unique_ptr& u) {ptr_.swap(u.ptr_);}
private:
boost::compressed_pair<pointer, D> ptr_;
//This private constructor avoids moving from non-const lvalues
unique_ptr(const unique_ptr&);
template <class U, class E> unique_ptr(unique_ptr<U, E>&);
template <class U> unique_ptr(U&, typename detail::unique_ptr_error<U>::type = 0);
unique_ptr& operator=(unique_ptr&);
template <class U, class E> unique_ptr& operator=(unique_ptr<U, E>&);
template <class U> typename detail::unique_ptr_error<U>::type operator=(U&);
};
/*
template <class T, class D>
class unique_ptr<T[], D>
{
struct nat {int for_bool_;};
typedef typename boost::add_reference<D>::type deleter_reference;
typedef typename boost::add_reference<const D>::type deleter_const_reference;
public:
typedef T element_type;
typedef D deleter_type;
typedef typename detail::pointer_type<T, D>::type pointer;
// constructors
unique_ptr() : ptr_(pointer()) {}
explicit unique_ptr(pointer p) : ptr_(p) {}
unique_ptr(pointer p, typename boost::mpl::if_<
boost::is_reference<D>,
D,
typename boost::add_reference<const D>::type>::type d)
: ptr_(p, d) {}
unique_ptr(const unique_ptr& u)
: ptr_(const_cast<unique_ptr&>(u).release(), u.get_deleter()) {}
// destructor
~unique_ptr() {reset();}
// assignment
unique_ptr& operator=(const unique_ptr& cu)
{
unique_ptr& u = const_cast<unique_ptr&>(cu);
reset(u.release());
ptr_.second() = u.get_deleter();
return *this;
}
unique_ptr& operator=(int nat::*)
{
reset();
return *this;
}
// observers
typename boost::add_reference<T>::type operator[](std::size_t i) const {return ptr_.first()[i];}
pointer get() const {return ptr_.first();}
deleter_reference get_deleter() {return ptr_.second();}
deleter_const_reference get_deleter() const {return ptr_.second();}
operator int nat::*() const {return ptr_.first() ? &nat::for_bool_ : 0;}
// modifiers
pointer release()
{
pointer tmp = ptr_.first();
ptr_.first() = pointer();
return tmp;
}
void reset(pointer p = pointer())
{
if (ptr_.first() != p)
{
if (ptr_.first())
ptr_.second()(ptr_.first());
ptr_.first() = p;
}
}
void swap(unique_ptr& u) {ptr_.swap(u.ptr_);}
private:
boost::compressed_pair<pointer, D> ptr_;
template <class U, class E> unique_ptr(U p, E,
typename boost::enable_if<boost::is_convertible<U, pointer> >::type* = 0);
template <class U> explicit unique_ptr(U,
typename boost::enable_if<boost::is_convertible<U, pointer> >::type* = 0);
unique_ptr(unique_ptr&);
template <class U> unique_ptr(U&, typename detail::unique_ptr_error<U>::type = 0);
unique_ptr& operator=(unique_ptr&);
template <class U> typename detail::unique_ptr_error<U>::type operator=(U&);
};
template <class T, class D, std::size_t N>
class unique_ptr<T[N], D>
{
struct nat {int for_bool_;};
typedef typename boost::add_reference<D>::type deleter_reference;
typedef typename boost::add_reference<const D>::type deleter_const_reference;
public:
typedef T element_type;
typedef D deleter_type;
typedef typename detail::pointer_type<T, D>::type pointer;
static const std::size_t size = N;
// constructors
unique_ptr() : ptr_(pointer()) {}
explicit unique_ptr(pointer p) : ptr_(p) {}
unique_ptr(pointer p, typename boost::mpl::if_<
boost::is_reference<D>,
D,
typename boost::add_reference<const D>::type>::type d)
: ptr_(p, d) {}
unique_ptr(const unique_ptr& u)
: ptr_(const_cast<unique_ptr&>(u).release(), u.get_deleter()) {}
// destructor
~unique_ptr() {reset();}
// assignment
unique_ptr& operator=(const unique_ptr& cu)
{
unique_ptr& u = const_cast<unique_ptr&>(cu);
reset(u.release());
ptr_.second() = u.get_deleter();
return *this;
}
unique_ptr& operator=(int nat::*)
{
reset();
return *this;
}
// observers
typename boost::add_reference<T>::type operator[](std::size_t i) const {return ptr_.first()[i];}
pointer get() const {return ptr_.first();}
deleter_reference get_deleter() {return ptr_.second();}
deleter_const_reference get_deleter() const {return ptr_.second();}
operator int nat::*() const {return ptr_.first() ? &nat::for_bool_ : 0;}
// modifiers
pointer release()
{
pointer tmp = ptr_.first();
ptr_.first() = pointer();
return tmp;
}
void reset(pointer p = pointer())
{
if (ptr_.first() != p)
{
if (ptr_.first())
ptr_.second()(ptr_.first(), N);
ptr_.first() = p;
}
}
void swap(unique_ptr& u) {ptr_.swap(u.ptr_);}
private:
boost::compressed_pair<pointer, D> ptr_;
template <class U, class E> unique_ptr(U p, E,
typename boost::enable_if<boost::is_convertible<U, pointer> >::type* = 0);
template <class U> explicit unique_ptr(U,
typename boost::enable_if<boost::is_convertible<U, pointer> >::type* = 0);
unique_ptr(unique_ptr&);
template <class U> unique_ptr(U&, typename detail::unique_ptr_error<U>::type = 0);
unique_ptr& operator=(unique_ptr&);
template <class U> typename detail::unique_ptr_error<U>::type operator=(U&);
};
*/
template <class T, class D> inline
void swap(unique_ptr<T, D>& x, unique_ptr<T, D>& y)
{ x.swap(y); }
template <class T1, class D1, class T2, class D2> inline
bool operator==(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y)
{ return x.get() == y.get(); }
template <class T1, class D1, class T2, class D2> inline
bool operator!=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y)
{ return x.get() != y.get(); }
template <class T1, class D1, class T2, class D2> inline
bool operator <(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y)
{ return x.get() < y.get(); }
template <class T1, class D1, class T2, class D2> inline
bool operator<=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y)
{ return x.get() <= y.get(); }
template <class T1, class D1, class T2, class D2> inline
bool operator >(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y)
{ return x.get() > y.get(); }
template <class T1, class D1, class T2, class D2> inline
bool operator>=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y)
{ return x.get() >= y.get(); }
/*
template <class T, class D> inline
unique_ptr<T, D> move(unique_ptr<T, D>& p)
{
return unique_ptr<T, D>(p.release(), p.get_deleter());
}
*/
} //namespace interprocess{
} //namespace boost{
#include <boost/interprocess/detail/config_end.hpp>
#endif //#ifndef BOOST_INTERPROCESS_UNIQUE_PTR_HPP_INCLUDED

View File

@@ -0,0 +1,111 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztañaga 2005-2006. 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)
//
// See http://www.boost.org/libs/interprocess for documentation.
//
//////////////////////////////////////////////////////////////////////////////
//
// Parts of the pthread code come from Boost Threads code:
//
//////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001-2003
// William E. Kempf
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
//////////////////////////////////////////////////////////////////////////////
#include <boost/date_time/posix_time/posix_time_types.hpp>
#include <boost/interprocess/detail/os_thread_functions.hpp>
#include <boost/interprocess/exceptions.hpp>
namespace boost {
namespace interprocess {
inline interprocess_recursive_mutex::interprocess_recursive_mutex()
: m_nLockCount(0), m_nOwner(detail::get_invalid_thread_id()){}
inline interprocess_recursive_mutex::~interprocess_recursive_mutex(){}
inline void interprocess_recursive_mutex::lock()
{
unsigned long pNumber = detail::get_current_thread_id();
if(pNumber == m_nOwner){
if((unsigned int)(m_nLockCount+1) == 0){
//Overflow, throw an exception
throw interprocess_exception();
}
++m_nLockCount;
}
else{
m_mutex.lock();
m_nOwner = pNumber;
m_nLockCount = 1;
}
}
inline bool interprocess_recursive_mutex::try_lock()
{
unsigned long pNumber = detail::get_current_thread_id();
if(pNumber == m_nOwner) { // we own it
if((unsigned int)(m_nLockCount+1) == 0){
//Overflow, throw an exception
throw interprocess_exception();
}
++m_nLockCount;
return true;
}
if(m_mutex.try_lock()){
m_nOwner = pNumber;
m_nLockCount = 1;
return true;
}
return false;
}
inline bool interprocess_recursive_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
{
unsigned long pNumber = detail::get_current_thread_id();
if(pNumber == m_nOwner) { // we own it
if((unsigned int)(m_nLockCount+1) == 0){
//Overflow, throw an exception
throw interprocess_exception();
}
++m_nLockCount;
return true;
}
if(m_mutex.timed_lock(abs_time)){
m_nOwner = pNumber;
m_nLockCount = 1;
return true;
}
return false;
}
inline void interprocess_recursive_mutex::unlock()
{
#ifndef NDEBUG
unsigned long pNumber = detail::get_current_thread_id();
assert(pNumber == m_nOwner);
#endif
--m_nLockCount;
if(!m_nLockCount){
m_nOwner = detail::get_invalid_thread_id();
m_mutex.unlock();
}
}
} //namespace interprocess {
} //namespace boost {

View File

@@ -0,0 +1,250 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztañaga 2005-2006. 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)
//
// See http://www.boost.org/libs/interprocess for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_NAMED_CONDITION_HPP
#define BOOST_NAMED_CONDITION_HPP
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/detail/creation_tags.hpp>
#include <boost/interprocess/exceptions.hpp>
#include <boost/interprocess/shared_memory.hpp>
#include <boost/interprocess/sync/interprocess_condition.hpp>
#include <boost/date_time/posix_time/ptime.hpp>
#include <boost/date_time/posix_time/posix_time_types.hpp>
/*!\file
Describes process-shared variables interprocess_condition class
*/
namespace boost {
namespace interprocess {
class named_condition
{
//Non-copyable
named_condition();
named_condition(const named_condition &);
named_condition &operator=(const named_condition &);
public:
/*!Creates a global condition with a name.*/
named_condition(detail::create_only_t create_only, const char *name);
/*!Opens or creates a global condition with a name.
If the condition is created, this call is equivalent to create().
If the condition is already created, this call is equivalent to open().
Does not throw*/
named_condition(detail::open_or_create_t open_or_create, const char *name);
/*!Opens a global condition with a name if that condition is previously.
created. If it is not previously created this function return false.
Does not throw*/
named_condition(detail::open_only_t open_only, const char *name);
/*!Destroys *this*/
~named_condition();
/*!If there is a thread waiting on *this, change that
thread's state to ready. Otherwise there is no effect.*/
void notify_one();
/*!Change the state of all threads waiting on *this to ready.
If there are no waiting threads, notify_all() has no effect.*/
void notify_all();
/*!Releases the lock on the interprocess_mutex object associated with lock, blocks
the current thread of execution until readied by a call to
this->notify_one() or this->notify_all(), and then reacquires the lock.*/
template <typename L>
void wait(L& lock);
/*!The same as: while (!pred()) wait(lock)*/
template <typename L, typename Pr>
void wait(L& lock, Pr pred);
/*!Releases the lock on the interprocess_mutex object associated with lock, blocks
the current thread of execution until readied by a call to
this->notify_one() or this->notify_all(), or until time abs_time is reached,
and then reacquires the lock.
Returns: false if time abs_time is reached, otherwise true.*/
template <typename L>
bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time);
/*!The same as: while (!pred()) {
if (!timed_wait(lock, abs_time)) return false;
} return true;*/
template <typename L, typename Pr>
bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred);
static bool remove(const char *name);
private:
interprocess_condition *condition() const
{ return static_cast<interprocess_condition*>(m_shmem.get_address()); }
shared_memory m_shmem;
class construct_func_t;
};
class named_condition::construct_func_t
{
public:
enum CreationType { open_only, open_or_create, create_only };
construct_func_t(CreationType type)
: m_creation_type(type){}
bool operator()(const mapped_region &region, bool created) const
{
switch(m_creation_type){
case open_only:
return true;
break;
case create_only:
case open_or_create:
if(created){
new(region.get_address())interprocess_condition;
}
return true;
break;
default:
return false;
break;
}
return true;
}
private:
CreationType m_creation_type;
};
inline named_condition::~named_condition()
{}
inline named_condition::named_condition(detail::create_only_t, const char *name)
: m_shmem (create_only
,name
,sizeof(interprocess_condition)
,memory_mappable::read_write
,0
,construct_func_t(construct_func_t::create_only))
{}
inline named_condition::named_condition(detail::open_or_create_t, const char *name)
: m_shmem (open_or_create
,name
,sizeof(interprocess_condition)
,memory_mappable::read_write
,0
,construct_func_t(construct_func_t::open_or_create))
{}
inline named_condition::named_condition(detail::open_only_t, const char *name)
: m_shmem (open_only
,name
,memory_mappable::read_write
,0
,construct_func_t(construct_func_t::open_only))
{}
inline void named_condition::notify_one()
{ this->condition()->notify_one(); }
inline void named_condition::notify_all()
{ this->condition()->notify_all(); }
template <typename L>
inline void named_condition::wait(L& lock)
{
if (!lock)
throw lock_exception();
this->condition()->do_wait(*lock.mutex()->mutex());
}
template <typename L, typename Pr>
inline void named_condition::wait
(L& lock, Pr pred)
{
if (!lock)
throw lock_exception();
while (!pred())
this->condition()->do_wait(*lock.mutex()->mutex());
}
template <typename L>
inline bool named_condition::timed_wait
(L& lock, const boost::posix_time::ptime &abs_time)
{
if (!lock)
throw lock_exception();
return this->condition()->do_timed_wait(abs_time, *lock.mutex()->mutex());
}
template <typename L, typename Pr>
inline bool named_condition::timed_wait
(L& lock, const boost::posix_time::ptime &abs_time, Pr pred)
{
if (!lock)
throw lock_exception();
while (!pred()){
if (!this->condition()->do_timed_wait(abs_time, *lock.mutex()->mutex()))
return false;
}
return true;
}
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/*
template <typename L>
inline void named_condition::wait(L& lock)
{ this->condition()->wait(lock); }
template <typename L, typename Pr>
inline void named_condition::wait(L& lock, Pr pred)
{ this->condition()->wait(lock, pred); }
template <typename L>
inline bool named_condition::timed_wait
(L& lock, const boost::posix_time::ptime &abs_time)
{ this->condition()->timed_wait(lock, abs_time); }
template <typename L, typename Pr>
inline bool named_condition::timed_wait
(L& lock, const boost::posix_time::ptime &abs_time, Pr pred)
{ this->condition()->timed_wait(lock, abs_time, pred); }
*/
inline bool named_condition::remove(const char *name)
{ return shared_memory_object::remove(name); }
} //namespace interprocess
} // namespace boost
#include <boost/interprocess/detail/config_end.hpp>
#endif // BOOST_NAMED_CONDITION_HPP

View File

@@ -0,0 +1,356 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztañaga 2005-2006. 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)
//
// See http://www.boost.org/libs/interprocess for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTERPROCESS_named_upgradable_mutex_HPP
#define BOOST_INTERPROCESS_named_upgradable_mutex_HPP
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/detail/creation_tags.hpp>
#include <boost/interprocess/exceptions.hpp>
#include <boost/interprocess/shared_memory.hpp>
#include <boost/interprocess/sync/interprocess_upgradable_mutex.hpp>
#include <boost/date_time/posix_time/ptime.hpp>
#include <boost/date_time/posix_time/posix_time_types.hpp>
/*!\file
Describes a named upgradable mutex class for inter-process synchronization
*/
namespace boost {
namespace interprocess {
class named_condition;
/*!A upgradable mutex with a global name, so it can be found from different
processes. This mutex can't be placed in shared memory, and
each process should have it's own named upgradable mutex.*/
class named_upgradable_mutex
{
//Non-copyable
named_upgradable_mutex();
named_upgradable_mutex(const named_upgradable_mutex &);
named_upgradable_mutex &operator=(const named_upgradable_mutex &);
friend class named_condition;
public:
/*!Creates a global interprocess_mutex with a name.*/
named_upgradable_mutex(detail::create_only_t create_only, const char *name);
/*!Opens or creates a global upgradable mutex with a name.
If the upgradable mutex is created, this call is equivalent to create().
If the upgradable mutex is already created, this call is equivalent to open().
Throws interprocess_exception on error.*/
named_upgradable_mutex(detail::open_or_create_t open_or_create, const char *name);
/*!Opens a global upgradable mutex with a name if that mutex is previously.
created. If it is not previously created this function return false.
Throws interprocess_exception on error.*/
named_upgradable_mutex(detail::open_only_t open_only, const char *name);
/*!Closes the named upgradable mutex. Does not throw*/
~named_upgradable_mutex();
//Exclusive locking
/*!Effects: The calling thread tries to obtain exclusive ownership of the mutex,
and if another thread has exclusive, sharable or upgradable ownership of
the mutex, it waits until it can obtain the ownership.
Throws: interprocess_exception on error.*/
void lock();
/*!Effects: The calling thread tries to acquire exclusive ownership of the mutex
without waiting. If no other thread has exclusive, sharable or upgradable
ownership of the mutex this succeeds.
Returns: If it can acquire exclusive ownership immediately returns true.
If it has to wait, returns false.
Throws: interprocess_exception on error.*/
bool try_lock();
/*!Effects: The calling thread tries to acquire exclusive ownership of the mutex
waiting if necessary until no other thread has has exclusive, sharable or
upgradable ownership of the mutex or abs_time is reached.
Returns: If acquires exclusive ownership, returns true. Otherwise returns false.
Throws: interprocess_exception on error.*/
bool timed_lock(const boost::posix_time::ptime &abs_time);
/*!Precondition: The thread must have exclusive ownership of the mutex.
Effects: The calling thread releases the exclusive ownership of the mutex.
Throws: An exception derived from interprocess_exception on error.*/
void unlock();
//Sharable locking
/*!Effects: The calling thread tries to obtain sharable ownership of the mutex,
and if another thread has exclusive or upgradable ownership of the mutex,
waits until it can obtain the ownership.
Throws: interprocess_exception on error.*/
void lock_sharable();
/*!Effects: The calling thread tries to acquire sharable ownership of the mutex
without waiting. If no other thread has has exclusive or upgradable ownership
of the mutex this succeeds.
Returns: If it can acquire sharable ownership immediately returns true. If it
has to wait, returns false.
Throws: interprocess_exception on error.*/
bool try_lock_sharable();
/*!Effects: The calling thread tries to acquire sharable ownership of the mutex
waiting if necessary until no other thread has has exclusive or upgradable
ownership of the mutex or abs_time is reached.
Returns: If acquires sharable ownership, returns true. Otherwise returns false.
Throws: interprocess_exception on error.*/
bool timed_lock_sharable(const boost::posix_time::ptime &abs_time);
/*!Precondition: The thread must have sharable ownership of the mutex.
Effects: The calling thread releases the sharable ownership of the mutex.
Throws: An exception derived from interprocess_exception on error.*/
void unlock_sharable();
//Upgradable locking
/*!Effects: The calling thread tries to obtain upgradable ownership of the mutex,
and if another thread has exclusive or upgradable ownership of the mutex,
waits until it can obtain the ownership.
Throws: interprocess_exception on error.*/
void lock_upgradable();
/*!Effects: The calling thread tries to acquire upgradable ownership of the mutex
without waiting. If no other thread has has exclusive or upgradable ownership
of the mutex this succeeds.
Returns: If it can acquire upgradable ownership immediately returns true.
If it has to wait, returns false.
Throws: interprocess_exception on error.*/
bool try_lock_upgradable();
/*!Effects: The calling thread tries to acquire upgradable ownership of the mutex
waiting if necessary until no other thread has has exclusive or upgradable
ownership of the mutex or abs_time is reached.
Returns: If acquires upgradable ownership, returns true. Otherwise returns false.
Throws: interprocess_exception on error.*/
bool timed_lock_upgradable(const boost::posix_time::ptime &abs_time);
/*!Precondition: The thread must have upgradable ownership of the mutex.
Effects: The calling thread releases the upgradable ownership of the mutex.
Throws: An exception derived from interprocess_exception on error.*/
void unlock_upgradable();
//Demotions
/*!Precondition: The thread must have exclusive ownership of the mutex.
Effects: The thread atomically releases exclusive ownership and acquires
upgradable ownership. This operation is non-blocking.
Throws: An exception derived from interprocess_exception on error.*/
void unlock_and_lock_upgradable();
/*!Precondition: The thread must have exclusive ownership of the mutex.
Effects: The thread atomically releases exclusive ownership and acquires
sharable ownership. This operation is non-blocking.
Throws: An exception derived from interprocess_exception on error.*/
void unlock_and_lock_sharable();
/*!Precondition: The thread must have upgradable ownership of the mutex.
Effects: The thread atomically releases upgradable ownership and acquires
sharable ownership. This operation is non-blocking.
Throws: An exception derived from interprocess_exception on error.*/
void unlock_upgradable_and_lock_sharable();
//Promotions
/*!Precondition: The thread must have upgradable ownership of the mutex.
Effects: The thread atomically releases upgradable ownership and acquires
exclusive ownership. This operation will block until all threads with
sharable ownership releas it.
Throws: An exception derived from interprocess_exception on error.*/
void unlock_upgradable_and_lock();
/*!Precondition: The thread must have upgradable ownership of the mutex.
Effects: The thread atomically releases upgradable ownership and tries to
acquire exclusive ownership. This operation will fail if there are threads
with sharable ownership, but it will maintain upgradable ownership.
Returns: If acquires exclusive ownership, returns true. Otherwise returns false.
Throws: An exception derived from interprocess_exception on error.*/
bool try_unlock_upgradable_and_lock();
/*!Precondition: The thread must have upgradable ownership of the mutex.
Effects: The thread atomically releases upgradable ownership and tries to acquire
exclusive ownership, waiting if necessary until abs_time. This operation will
fail if there are threads with sharable ownership or timeout reaches, but it
will maintain upgradable ownership.
Returns: If acquires exclusive ownership, returns true. Otherwise returns false.
Throws: An exception derived from interprocess_exception on error. */
bool timed_unlock_upgradable_and_lock(const boost::posix_time::ptime &abs_time);
/*!Precondition: The thread must have sharable ownership of the mutex.
Effects: The thread atomically releases sharable ownership and tries to acquire
exclusive ownership. This operation will fail if there are threads with sharable
or upgradable ownership, but it will maintain sharable ownership.
Returns: If acquires exclusive ownership, returns true. Otherwise returns false.
Throws: An exception derived from interprocess_exception on error.*/
bool try_unlock_sharable_and_lock();
bool try_unlock_sharable_and_lock_upgradable();
/*! Erases a named upgradable mutex from the system*/
static bool remove(const char *name);
private:
interprocess_upgradable_mutex *mutex() const
{ return static_cast<interprocess_upgradable_mutex*>(m_shmem.get_address()); }
shared_memory m_shmem;
class construct_func_t;
};
class named_upgradable_mutex::construct_func_t
{
public:
enum CreationType { open_only, open_or_create, create_only };
construct_func_t(CreationType type)
: m_creation_type(type){}
bool operator()(const mapped_region &region, bool created) const
{
switch(m_creation_type){
case open_only:
return true;
break;
case create_only:
case open_or_create:
if(created){
new(region.get_address())interprocess_upgradable_mutex;
}
return true;
break;
default:
return false;
break;
}
return true;
}
private:
CreationType m_creation_type;
};
inline named_upgradable_mutex::~named_upgradable_mutex()
{}
inline named_upgradable_mutex::named_upgradable_mutex
(detail::create_only_t, const char *name)
: m_shmem (create_only
,name
,sizeof(interprocess_upgradable_mutex)
,memory_mappable::read_write
,0
,construct_func_t(construct_func_t::create_only))
{}
inline named_upgradable_mutex::named_upgradable_mutex
(detail::open_or_create_t, const char *name)
: m_shmem (open_or_create
,name
,sizeof(interprocess_upgradable_mutex)
,memory_mappable::read_write
,0
,construct_func_t(construct_func_t::open_or_create))
{}
inline named_upgradable_mutex::named_upgradable_mutex
(detail::open_only_t, const char *name)
: m_shmem (open_only
,name
,memory_mappable::read_write
,0
,construct_func_t(construct_func_t::open_only))
{}
inline void named_upgradable_mutex::lock()
{ this->mutex()->lock(); }
inline void named_upgradable_mutex::unlock()
{ this->mutex()->unlock(); }
inline bool named_upgradable_mutex::try_lock()
{ return this->mutex()->try_lock(); }
inline bool named_upgradable_mutex::timed_lock
(const boost::posix_time::ptime &abs_time)
{ return this->mutex()->timed_lock(abs_time); }
inline void named_upgradable_mutex::lock_upgradable()
{ this->mutex()->lock_upgradable(); }
inline void named_upgradable_mutex::unlock_upgradable()
{ this->mutex()->unlock_upgradable(); }
inline bool named_upgradable_mutex::try_lock_upgradable()
{ return this->mutex()->try_lock_upgradable(); }
inline bool named_upgradable_mutex::timed_lock_upgradable
(const boost::posix_time::ptime &abs_time)
{ return this->mutex()->timed_lock_upgradable(abs_time); }
inline void named_upgradable_mutex::lock_sharable()
{ this->mutex()->lock_sharable(); }
inline void named_upgradable_mutex::unlock_sharable()
{ this->mutex()->unlock_sharable(); }
inline bool named_upgradable_mutex::try_lock_sharable()
{ return this->mutex()->try_lock_sharable(); }
inline bool named_upgradable_mutex::timed_lock_sharable
(const boost::posix_time::ptime &abs_time)
{ return this->mutex()->timed_lock_sharable(abs_time); }
inline void named_upgradable_mutex::unlock_and_lock_upgradable()
{ this->mutex()->unlock_and_lock_upgradable(); }
inline void named_upgradable_mutex::unlock_and_lock_sharable()
{ this->mutex()->unlock_and_lock_sharable(); }
inline void named_upgradable_mutex::unlock_upgradable_and_lock_sharable()
{ this->mutex()->unlock_upgradable_and_lock_sharable(); }
inline void named_upgradable_mutex::unlock_upgradable_and_lock()
{ this->mutex()->unlock_upgradable_and_lock(); }
inline bool named_upgradable_mutex::try_unlock_upgradable_and_lock()
{ return this->mutex()->try_unlock_upgradable_and_lock(); }
inline bool named_upgradable_mutex::timed_unlock_upgradable_and_lock
(const boost::posix_time::ptime &abs_time)
{ return this->mutex()->timed_unlock_upgradable_and_lock(abs_time); }
inline bool named_upgradable_mutex::try_unlock_sharable_and_lock()
{ return this->mutex()->try_unlock_sharable_and_lock(); }
inline bool named_upgradable_mutex::try_unlock_sharable_and_lock_upgradable()
{ return this->mutex()->try_unlock_sharable_and_lock_upgradable(); }
inline bool named_upgradable_mutex::remove(const char *name)
{ return shared_memory_object::remove(name); }
} //namespace interprocess {
} //namespace boost {
#include <boost/interprocess/detail/config_end.hpp>
#endif //BOOST_INTERPROCESS_named_upgradable_mutex_HPP

View File

@@ -0,0 +1,308 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztañaga 2005-2006. 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)
//
// See http://www.boost.org/libs/interprocess for documentation.
//
//////////////////////////////////////////////////////////////////////////////
//
// This interface is inspired by Howard Hinnant's lock proposal.
// http://home.twcny.rr.com/hinnant/cpp_extensions/threads_move.html
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTERPROCESS_UPGRADABLE_LOCK_HPP
#define BOOST_INTERPROCESS_UPGRADABLE_LOCK_HPP
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/sync/lock_options.hpp>
#include <boost/interprocess/exceptions.hpp>
#include <boost/interprocess/detail/move.hpp>
#include <boost/utility.hpp>
#include <boost/date_time/posix_time/ptime.hpp>
/*!\file
Describes the upgradable_lock class that serves to acquire the upgradable
lock of a mutex.
*/
namespace boost {
namespace interprocess {
template<class M>
class scoped_lock;
template<class M>
class sharable_lock;
/*!upgradable_lock is meant to carry out the tasks for read-locking, unlocking,
try-read-locking and timed-read-locking (recursive or not) for the Mutex.
Additionally the upgradable_lock can transfer ownership to a scoped_lock
using trasfer_lock syntax. The Mutex need not supply all of the functionality.
If the client of upgradable_lock<Mutex> does not use functionality which the
Mutex does not supply, no harm is done. Mutex ownership can be shared among
read_locks, and a single upgradable_lock. upgradable_lock does not support
copy semantics. However upgradable_lock supports ownership transfer from
a upgradable_locks or scoped_locks via trasfer_lock syntax.*/
template <class UpgradableMutex>
class upgradable_lock
{
public:
typedef UpgradableMutex mutex_type;
private:
typedef upgradable_lock<UpgradableMutex> this_type;
upgradable_lock(upgradable_lock const&);
explicit upgradable_lock(scoped_lock<mutex_type> const&);
typedef bool this_type::*unspecified_bool_type;
upgradable_lock& operator=(upgradable_lock const&);
upgradable_lock& operator=(scoped_lock<mutex_type> const&);
public:
/*!Effects: Default constructs a upgradable_lock.
Postconditions: owns() == false and mutex() == 0.*/
upgradable_lock()
: mp_mutex(0), m_locked(false)
{}
explicit upgradable_lock(mutex_type& m)
: mp_mutex(&m), m_locked(false)
{ mp_mutex->lock_upgradable(); m_locked = true; }
/*!Postconditions: owns() == false, and mutex() == &m.
Notes: The constructor will not take ownership of the mutex. There is no effect
required on the referenced mutex.*/
upgradable_lock(mutex_type& m, detail::defer_lock_type)
: mp_mutex(&m), m_locked(false)
{}
/*!Postconditions: owns() == true, and mutex() == &m.
Notes: The constructor will suppose that the mutex is already upgradable
locked. There is no effect required on the referenced mutex.*/
upgradable_lock(mutex_type& m, detail::accept_ownership_type)
: mp_mutex(&m), m_locked(true)
{}
/*!Effects: m.try_lock_upgradable().
Postconditions: mutex() == &m. owns() == the return value of the
m.try_lock_upgradable() executed within the constructor.
Notes: The constructor will take upgradable-ownership of the mutex
if it can do so without waiting. Whether or not this constructor
handles recursive locking depends upon the mutex. If the mutex_type
does not support try_lock_upgradable, this constructor will fail at
compile time if instantiated, but otherwise have no effect.*/
upgradable_lock(mutex_type& m, detail::try_to_lock_type)
: mp_mutex(&m), m_locked(false)
{ m_locked = mp_mutex->try_lock_upgradable(); }
/*!Effects: m.timed_lock_upgradable(abs_time)
Postconditions: mutex() == &m. owns() == the return value of the
m.timed_lock_upgradable() executed within the constructor.
Notes: The constructor will take upgradable-ownership of the mutex if it
can do so within the time specified. Whether or not this constructor
handles recursive locking depends upon the mutex. If the mutex_type
does not support timed_lock_upgradable, this constructor will fail
at compile time if instantiated, but otherwise have no effect.*/
upgradable_lock(mutex_type& m, const boost::posix_time::ptime& abs_time)
: mp_mutex(&m), m_locked(false)
{ m_locked = mp_mutex->timed_lock_upgradable(abs_time); }
/*!Effects: No effects on the underlying mutex.
Postconditions: mutex() == the value upgr.mutex() had before the
construction. upgr.mutex() == 0. owns() == upgr.owns() before the
construction. upgr.owns() == false.
Notes: If upgr is locked, this constructor will lock this upgradable_lock
while unlocking upgr. If upgr is unlocked, then this upgradable_lock will
be unlocked as well. Only a moved upgradable_lock's will match this
signature. An non-moved upgradable_lock can be moved with the
expression: "move(lock);". This constructor does not alter the
state of the mutex, only potentially who owns it.*/
explicit upgradable_lock(detail::moved_object<upgradable_lock<mutex_type> > upgr)
: mp_mutex(0), m_locked(upgr.get().owns())
{ mp_mutex = upgr.get().release(); }
/*!Effects: If scop.owns(), m_.unlock_and_lock_upgradable().
Postconditions: mutex() == the value scop.mutex() had before the construction.
scop.mutex() == 0. owns() == scop.owns() before the constructor. After the
construction, scop.owns() == false.
Notes: If scop is locked, this constructor will transfer the exclusive-ownership
to an upgradable-ownership of this upgradable_lock.
Only a moved sharable_lock's will match this
signature. An non-moved sharable_lock can be moved with the
expression: "move(lock);".*/
explicit upgradable_lock(detail::moved_object<scoped_lock<mutex_type> > scop)
: mp_mutex(0), m_locked(false)
{
scoped_lock<mutex_type> &u_lock = scop.get();
if(u_lock.owns()){
u_lock.mutex()->unlock_and_lock_upgradable();
m_locked = true;
}
mp_mutex = u_lock.release();
}
/*!Effects: If shar.owns() then calls try_unlock_sharable_and_lock_upgradable()
on the referenced mutex.
a)if try_unlock_sharable_and_lock_upgradable() returns true then mutex()
obtains the value from shar.release() and owns() is set to true.
b)if try_unlock_sharable_and_lock_upgradable() returns false then shar is
unaffected and this upgradable_lock construction has the same
effects as a default construction.
c)Else shar.owns() is false. mutex() obtains the value from shar.release()
and owns() is set to false.
Notes: This construction will not block. It will try to obtain mutex
ownership from shar immediately, while changing the lock type from a
"read lock" to an "upgradable lock". If the "read lock" isn't held
in the first place, the mutex merely changes type to an unlocked
"upgradable lock". If the "read lock" is held, then mutex transfer
occurs only if it can do so in a non-blocking manner.*/
upgradable_lock( detail::moved_object<sharable_lock<mutex_type> > shar
, detail::try_to_lock_type)
: mp_mutex(0), m_locked(false)
{
sharable_lock<mutex_type> &s_lock = shar.get();
if(s_lock.owns()){
if((m_locked = s_lock.mutex()->try_unlock_sharable_and_lock_upgradable()) == true){
mp_mutex = s_lock.release();
}
}
else{
s_lock.release();
}
}
/*!Effects: if (owns()) m_->unlock_upgradable().
Notes: The destructor behavior ensures that the mutex lock is not leaked.*/
~upgradable_lock()
{
try{
if(m_locked && mp_mutex) mp_mutex->unlock_upgradable();
}
catch(...){}
}
/*!Effects: If owns(), then unlock_upgradable() is called on mutex().
*this gets the state of upgr and upgr gets set to a default constructed state.
Notes: With a recursive mutex it is possible that both this and upgr own the
mutex before the assignment. In this case, this will own the mutex
after the assignment (and upgr will not), but the mutex's upgradable lock
count will be decremented by one.*/
upgradable_lock &operator=(detail::moved_object<upgradable_lock<mutex_type> > upgr)
{
if(this->owns())
this->unlock();
m_locked = upgr.get().owns();
mp_mutex = upgr.get().release();
return *this;
}
/*!Effects: If mutex() == 0 or if already locked, throws a lock_exception()
exception. Calls lock_upgradable() on the referenced mutex.
Postconditions: owns() == true.
Notes: The sharable_lock changes from a state of not owning the mutex,
to owning the mutex, blocking if necessary.*/
void lock()
{
if(!mp_mutex || m_locked)
throw lock_exception();
mp_mutex->lock_upgradable();
m_locked = true;
}
/*!Effects: If mutex() == 0 or if already locked, throws a lock_exception()
exception. Calls try_lock_upgradable() on the referenced mutex.
Postconditions: owns() == the value returned from
mutex()->try_lock_upgradable().
Notes: The upgradable_lock changes from a state of not owning the mutex,
to owning the mutex, but only if blocking was not required. If the
mutex_type does not support try_lock_upgradable(), this function will
fail at compile time if instantiated, but otherwise have no effect.*/
bool try_lock()
{
if(!mp_mutex || m_locked)
throw lock_exception();
m_locked = mp_mutex->try_lock_upgradable();
return m_locked;
}
/*!Effects: If mutex() == 0 or if already locked, throws a lock_exception()
exception. Calls timed_lock_upgradable(abs_time) on the referenced mutex.
Postconditions: owns() == the value returned from
mutex()->timed_lock_upgradable(abs_time).
Notes: The upgradable_lock changes from a state of not owning the mutex,
to owning the mutex, but only if it can obtain ownership within the
specified time. If the mutex_type does not support
timed_lock_upgradable(abs_time), this function will fail at compile
time if instantiated, but otherwise have no effect.*/
bool timed_lock(const boost::posix_time::ptime& abs_time)
{
if(!mp_mutex || m_locked)
throw lock_exception();
m_locked = mp_mutex->timed_lock_upgradable(abs_time);
return m_locked;
}
/*!Effects: If mutex() == 0 or if not locked, throws a lock_exception()
exception. Calls unlock_upgradable() on the referenced mutex.
Postconditions: owns() == false.
Notes: The upgradable_lock changes from a state of owning the mutex,
to not owning the mutex.*/
void unlock()
{
if(!mp_mutex || !m_locked)
throw lock_exception();
mp_mutex->unlock_upgradable();
m_locked = false;
}
/*!Effects: Returns true if this scoped_lock has acquired the referenced mutex.*/
bool owns() const
{ return m_locked && mp_mutex; }
/*!Conversion to bool. Returns owns().*/
operator unspecified_bool_type() const
{ return m_locked? &this_type::m_locked : 0; }
/*!Effects: Returns a pointer to the referenced mutex, or 0 if
there is no mutex to reference.*/
mutex_type* mutex() const
{ return mp_mutex; }
/*!Effects: Returns a pointer to the referenced mutex, or 0 if there is no
mutex to reference.
Postconditions: mutex() == 0 and owns() == false.*/
mutex_type* release()
{
mutex_type *mut = mp_mutex;
mp_mutex = 0;
m_locked = false;
return mut;
}
/*!Effects: Swaps state with moved lock.
Throws: Nothing.*/
void swap(detail::moved_object<upgradable_lock<mutex_type> > other)
{
std::swap(mp_mutex, other.get().mp_mutex);
std::swap(m_locked, other.get().m_locked);
}
private:
mutex_type *mp_mutex;
bool m_locked;
};
} // namespace interprocess
} // namespace boost
#include <boost/interprocess/detail/config_end.hpp>
#endif // BOOST_INTERPROCESS_UPGRADABLE_LOCK_HPP