mirror of
https://github.com/boostorg/interprocess.git
synced 2026-01-19 04:12:13 +00:00
First inclusion in repository
[SVN r34901]
This commit is contained in:
60
include/boost/interprocess/detail/move.hpp
Normal file
60
include/boost/interprocess/detail/move.hpp
Normal 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
|
||||
|
||||
|
||||
69
include/boost/interprocess/detail/os_thread_functions.hpp
Normal file
69
include/boost/interprocess/detail/os_thread_functions.hpp
Normal 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
|
||||
390
include/boost/interprocess/smart_ptr/unique_ptr.hpp
Normal file
390
include/boost/interprocess/smart_ptr/unique_ptr.hpp
Normal 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
|
||||
@@ -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 {
|
||||
|
||||
250
include/boost/interprocess/sync/named_condition.hpp
Normal file
250
include/boost/interprocess/sync/named_condition.hpp
Normal 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 ®ion, 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
|
||||
356
include/boost/interprocess/sync/named_upgradable_mutex.hpp
Normal file
356
include/boost/interprocess/sync/named_upgradable_mutex.hpp
Normal 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 ®ion, 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
|
||||
308
include/boost/interprocess/sync/upgradable_lock.hpp
Normal file
308
include/boost/interprocess/sync/upgradable_lock.hpp
Normal 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
|
||||
Reference in New Issue
Block a user