//////////////////////////////////////////////////////////////////////////////
//
// This file is the adaptation for Interprocess of boost/shared_ptr.hpp
//
// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
// (C) Copyright Peter Dimov 2001, 2002, 2003
// (C) Copyright Ion Gaztanaga 2006-2012.
// 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_SHARED_PTR_HPP_INCLUDED
#define BOOST_INTERPROCESS_SHARED_PTR_HPP_INCLUDED
#ifndef BOOST_CONFIG_HPP
# include
#endif
#
#if defined(BOOST_HAS_PRAGMA_ONCE)
# pragma once
#endif
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include // for std::basic_ostream
//!\file
//!Describes the smart pointer shared_ptr
namespace boost{
namespace interprocess{
template class weak_ptr;
template class enable_shared_from_this;
namespace ipcdetail{
template
inline void sp_enable_shared_from_this
(shared_count const & pn
,enable_shared_from_this *pe
,T *ptr)
{
(void)ptr;
if(pe != 0){
pe->_internal_weak_this._internal_assign(pn);
}
}
template
inline void sp_enable_shared_from_this(shared_count const &, ...)
{}
} // namespace ipcdetail
//!shared_ptr stores a pointer to a dynamically allocated object.
//!The object pointed to is guaranteed to be deleted when the last shared_ptr pointing to
//!it is destroyed or reset.
//!
//!shared_ptr is parameterized on
//!T (the type of the object pointed to), VoidAllocator (the void allocator to be used
//!to allocate the auxiliary data) and Deleter (the deleter whose
//!operator() will be used to delete the object.
//!
//!The internal pointer will be of the same pointer type as typename
//!VoidAllocator::pointer type (that is, if typename VoidAllocator::pointer is
//!offset_ptr, the internal pointer will be offset_ptr).
//!
//!Because the implementation uses reference counting, cycles of shared_ptr
//!instances will not be reclaimed. For example, if main() holds a
//!shared_ptr to A, which directly or indirectly holds a shared_ptr back
//!to A, A's use count will be 2. Destruction of the original shared_ptr
//!will leave A dangling with a use count of 1.
//!Use weak_ptr to "break cycles."
template
class shared_ptr
{
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
typedef shared_ptr this_type;
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
typedef T element_type;
typedef T value_type;
typedef typename boost::intrusive::
pointer_traits::template
rebind_pointer::type pointer;
typedef typename ipcdetail::add_reference
::type reference;
typedef typename ipcdetail::add_reference
::type const_reference;
typedef typename boost::intrusive::
pointer_traits::template
rebind_pointer::type const_deleter_pointer;
typedef typename boost::intrusive::
pointer_traits::template
rebind_pointer::type const_allocator_pointer;
BOOST_COPYABLE_AND_MOVABLE(shared_ptr)
public:
//!Constructs an empty shared_ptr.
//!Use_count() == 0 && get()== 0.
shared_ptr()
: m_pn() // never throws
{}
//!Constructs a shared_ptr that owns the pointer p. Auxiliary data will be allocated
//!with a copy of a and the object will be deleted with a copy of d.
//!Requirements: Deleter and A's copy constructor must not throw.
explicit shared_ptr(const pointer&p, const VoidAllocator &a = VoidAllocator(), const Deleter &d = Deleter())
: m_pn(p, a, d)
{
//Check that the pointer passed is of the same type that
//the pointer the allocator defines or it's a raw pointer
typedef typename boost::intrusive::
pointer_traits::template
rebind_pointer::type ParameterPointer;
BOOST_STATIC_ASSERT((ipcdetail::is_same::value) ||
(ipcdetail::is_pointer::value));
ipcdetail::sp_enable_shared_from_this( m_pn, ipcdetail::to_raw_pointer(p), ipcdetail::to_raw_pointer(p) );
}
//!Copy constructs a shared_ptr. If r is empty, constructs an empty shared_ptr. Otherwise, constructs
//!a shared_ptr that shares ownership with r. Never throws.
shared_ptr(const shared_ptr &r)
: m_pn(r.m_pn) // never throws
{}
//!Constructs a shared_ptr that shares ownership with other and stores p.
//!Postconditions: get() == p && use_count() == r.use_count().
//!Throws: nothing.
shared_ptr(const shared_ptr &other, const pointer &p)
: m_pn(other.m_pn, p)
{}
//!If r is empty, constructs an empty shared_ptr. Otherwise, constructs
//!a shared_ptr that shares ownership with r. Never throws.
template
shared_ptr(shared_ptr const & r)
: m_pn(r.m_pn) // never throws
{}
//!Constructs a shared_ptr that shares ownership with r and stores
//!a copy of the pointer stored in r.
template
explicit shared_ptr(weak_ptr const & r)
: m_pn(r.m_pn) // may throw
{}
//!Move-Constructs a shared_ptr that takes ownership of other resource and
//!other is put in default-constructed state.
//!Throws: nothing.
explicit shared_ptr(BOOST_RV_REF(shared_ptr) other)
: m_pn()
{ this->swap(other); }
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
template
shared_ptr(shared_ptr const & r, ipcdetail::static_cast_tag)
: m_pn( pointer(static_cast(ipcdetail::to_raw_pointer(r.m_pn.to_raw_pointer())))
, r.m_pn)
{}
template
shared_ptr(shared_ptr const & r, ipcdetail::const_cast_tag)
: m_pn( pointer(const_cast(ipcdetail::to_raw_pointer(r.m_pn.to_raw_pointer())))
, r.m_pn)
{}
template
shared_ptr(shared_ptr const & r, ipcdetail::dynamic_cast_tag)
: m_pn( pointer(dynamic_cast(ipcdetail::to_raw_pointer(r.m_pn.to_raw_pointer())))
, r.m_pn)
{
if(!m_pn.to_raw_pointer()){ // need to allocate new counter -- the cast failed
m_pn = ipcdetail::shared_count();
}
}
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
//!Equivalent to shared_ptr(r).swap(*this).
//!Never throws
template
shared_ptr & operator=(shared_ptr const & r)
{
m_pn = r.m_pn; // shared_count::op= doesn't throw
return *this;
}
//!Equivalent to shared_ptr(r).swap(*this).
//!Never throws
shared_ptr & operator=(BOOST_COPY_ASSIGN_REF(shared_ptr) r)
{
m_pn = r.m_pn; // shared_count::op= doesn't throw
return *this;
}
//!Move-assignment. Equivalent to shared_ptr(other).swap(*this).
//!Never throws
shared_ptr & operator=(BOOST_RV_REF(shared_ptr) other) // never throws
{
this_type(other).swap(*this);
return *this;
}
//!This is equivalent to:
//!this_type().swap(*this);
void reset()
{
this_type().swap(*this);
}
//!This is equivalent to:
//!this_type(p, a, d).swap(*this);
template
void reset(const Pointer &p, const VoidAllocator &a = VoidAllocator(), const Deleter &d = Deleter())
{
//Check that the pointer passed is of the same type that
//the pointer the allocator defines or it's a raw pointer
typedef typename boost::intrusive::
pointer_traits::template
rebind_pointer::type ParameterPointer;
BOOST_STATIC_ASSERT((ipcdetail::is_same::value) ||
(ipcdetail::is_pointer::value));
this_type(p, a, d).swap(*this);
}
template
void reset(shared_ptr const & r, const pointer &p)
{
this_type(r, p).swap(*this);
}
//!Returns a reference to the
//!pointed type
reference operator* () const // never throws
{ BOOST_ASSERT(m_pn.to_raw_pointer() != 0); return *m_pn.to_raw_pointer(); }
//!Returns the pointer pointing
//!to the owned object
pointer operator-> () const // never throws
{ BOOST_ASSERT(m_pn.to_raw_pointer() != 0); return m_pn.to_raw_pointer(); }
//!Returns the pointer pointing
//!to the owned object
pointer get() const // never throws
{ return m_pn.to_raw_pointer(); }
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
// implicit conversion to "bool"
void unspecified_bool_type_func() const {}
typedef void (this_type::*unspecified_bool_type)() const;
operator unspecified_bool_type() const // never throws
{ return !m_pn.to_raw_pointer() ? 0 : &this_type::unspecified_bool_type_func; }
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
//!Not operator.
//!Returns true if this->get() != 0, false otherwise
bool operator! () const // never throws
{ return !m_pn.to_raw_pointer(); }
//!Returns use_count() == 1.
//!unique() might be faster than use_count()
bool unique() const // never throws
{ return m_pn.unique(); }
//!Returns the number of shared_ptr objects, *this included,
//!that share ownership with *this, or an unspecified nonnegative
//!value when *this is empty.
//!use_count() is not necessarily efficient. Use only for
//!debugging and testing purposes, not for production code.
long use_count() const // never throws
{ return m_pn.use_count(); }
//!Exchanges the contents of the two
//!smart pointers.
void swap(shared_ptr & other) // never throws
{ m_pn.swap(other.m_pn); }
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
template
bool _internal_less(shared_ptr const & rhs) const
{ return m_pn < rhs.m_pn; }
const_deleter_pointer get_deleter() const
{ return m_pn.get_deleter(); }
// const_allocator_pointer get_allocator() const
// { return m_pn.get_allocator(); }
private:
template friend class shared_ptr;
template friend class weak_ptr;
ipcdetail::shared_count m_pn; // reference counter
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
}; // shared_ptr
template inline
bool operator==(shared_ptr const & a, shared_ptr const & b)
{ return a.get() == b.get(); }
template inline
bool operator!=(shared_ptr const & a, shared_ptr const & b)
{ return a.get() != b.get(); }
template inline
bool operator<(shared_ptr const & a, shared_ptr const & b)
{ return a._internal_less(b); }
template inline
void swap(shared_ptr & a, shared_ptr & b)
{ a.swap(b); }
template inline
shared_ptr static_pointer_cast(shared_ptr const & r)
{ return shared_ptr(r, ipcdetail::static_cast_tag()); }
template inline
shared_ptr const_pointer_cast(shared_ptr const & r)
{ return shared_ptr(r, ipcdetail::const_cast_tag()); }
template inline
shared_ptr dynamic_pointer_cast(shared_ptr const & r)
{ return shared_ptr(r, ipcdetail::dynamic_cast_tag()); }
// to_raw_pointer() enables boost::mem_fn to recognize shared_ptr
template inline
T * to_raw_pointer(shared_ptr const & p)
{ return p.get(); }
// operator<<
template inline
std::basic_ostream & operator<<
(std::basic_ostream & os, shared_ptr const & p)
{ os << p.get(); return os; }
//!Returns the type of a shared pointer
//!of type T with the allocator boost::interprocess::allocator allocator
//!and boost::interprocess::deleter deleter
//!that can be constructed in the given managed segment type.
template
struct managed_shared_ptr
{
typedef typename ManagedMemory::template allocator::type void_allocator;
typedef typename ManagedMemory::template deleter::type deleter;
typedef shared_ptr< T, void_allocator, deleter> type;
};
//!Returns an instance of a shared pointer constructed
//!with the default allocator and deleter from a pointer
//!of type T that has been allocated in the passed managed segment
template
inline typename managed_shared_ptr::type
make_managed_shared_ptr(T *constructed_object, ManagedMemory &managed_memory)
{
return typename managed_shared_ptr::type
( constructed_object
, managed_memory.template get_allocator()
, managed_memory.template get_deleter()
);
}
//!Returns an instance of a shared pointer constructed
//!with the default allocator and deleter from a pointer
//!of type T that has been allocated in the passed managed segment.
//!Does not throw, return null shared pointer in error.
template
inline typename managed_shared_ptr::type
make_managed_shared_ptr(T *constructed_object, ManagedMemory &managed_memory, const std::nothrow_t &)
{
try{
return typename managed_shared_ptr::type
( constructed_object
, managed_memory.template get_allocator()
, managed_memory.template get_deleter()
);
}
catch(...){
return typename managed_shared_ptr::type();
}
}
} // namespace interprocess
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
#if defined(_MSC_VER) && (_MSC_VER < 1400)
// to_raw_pointer() enables boost::mem_fn to recognize shared_ptr
template inline
T * to_raw_pointer(boost::interprocess::shared_ptr const & p)
{ return p.get(); }
#endif
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
} // namespace boost
#include
#endif // #ifndef BOOST_INTERPROCESS_SHARED_PTR_HPP_INCLUDED