////////////////////////////////////////////////////////////////////////////// | |
// | |
// 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-2009. | |
// 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 | |
#include <boost/interprocess/detail/config_begin.hpp> | |
#include <boost/interprocess/detail/workaround.hpp> | |
#include <boost/interprocess/detail/utilities.hpp> | |
#include <boost/interprocess/detail/cast_tags.hpp> | |
#include <boost/assert.hpp> | |
#include <boost/interprocess/smart_ptr/detail/shared_count.hpp> | |
#include <boost/interprocess/detail/mpl.hpp> | |
#include <boost/interprocess/detail/move.hpp> | |
#include <boost/interprocess/detail/type_traits.hpp> | |
#include <boost/interprocess/allocators/allocator.hpp> | |
#include <boost/interprocess/smart_ptr/deleter.hpp> | |
#include <boost/static_assert.hpp> | |
#include <boost/pointer_to_other.hpp> | |
#include <algorithm> // for std::swap | |
#include <functional> // for std::less | |
#include <typeinfo> // for std::bad_cast | |
#include <iosfwd> // for std::basic_ostream | |
//!\file | |
//!Describes the smart pointer shared_ptr | |
namespace boost{ | |
namespace interprocess{ | |
template<class T, class VoidAllocator, class Deleter> class weak_ptr; | |
template<class T, class VoidAllocator, class Deleter> class enable_shared_from_this; | |
namespace detail{ | |
template<class T, class VoidAllocator, class Deleter> | |
inline void sp_enable_shared_from_this | |
(shared_count<T, VoidAllocator, Deleter> const & pn | |
,enable_shared_from_this<T, VoidAllocator, Deleter> *pe | |
,T *ptr) | |
{ | |
(void)ptr; | |
if(pe != 0){ | |
pe->_internal_weak_this._internal_assign(pn); | |
} | |
} | |
template<class T, class VoidAllocator, class Deleter> | |
inline void sp_enable_shared_from_this(shared_count<T, VoidAllocator, Deleter> const &, ...) | |
{} | |
} // namespace detail | |
//!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<void>, the internal pointer will be offset_ptr<T>). | |
//! | |
//!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 T, class VoidAllocator, class Deleter> | |
class shared_ptr | |
{ | |
/// @cond | |
private: | |
typedef shared_ptr<T, VoidAllocator, Deleter> this_type; | |
/// @endcond | |
public: | |
typedef T element_type; | |
typedef T value_type; | |
typedef typename boost::pointer_to_other | |
<typename VoidAllocator::pointer, T>::type pointer; | |
typedef typename detail::add_reference | |
<value_type>::type reference; | |
typedef typename detail::add_reference | |
<const value_type>::type const_reference; | |
typedef typename boost::pointer_to_other | |
<typename VoidAllocator::pointer, const Deleter>::type const_deleter_pointer; | |
typedef typename boost::pointer_to_other | |
<typename VoidAllocator::pointer, const VoidAllocator>::type const_allocator_pointer; | |
BOOST_INTERPROCESS_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::pointer_to_other<pointer, T>::type ParameterPointer; | |
BOOST_STATIC_ASSERT((detail::is_same<pointer, ParameterPointer>::value) || | |
(detail::is_pointer<pointer>::value)); | |
detail::sp_enable_shared_from_this<T, VoidAllocator, Deleter>( m_pn, detail::get_pointer(p), detail::get_pointer(p) ); | |
} | |
//!Constructs a shared_ptr that shares ownership with r 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<class Y> | |
shared_ptr(shared_ptr<Y, VoidAllocator, Deleter> 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<class Y> | |
explicit shared_ptr(weak_ptr<Y, VoidAllocator, Deleter> 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_INTERPROCESS_RV_REF(shared_ptr) other) | |
: m_pn() | |
{ this->swap(other); } | |
/// @cond | |
template<class Y> | |
shared_ptr(shared_ptr<Y, VoidAllocator, Deleter> const & r, detail::static_cast_tag) | |
: m_pn( pointer(static_cast<T*>(detail::get_pointer(r.m_pn.get_pointer()))) | |
, r.m_pn) | |
{} | |
template<class Y> | |
shared_ptr(shared_ptr<Y, VoidAllocator, Deleter> const & r, detail::const_cast_tag) | |
: m_pn( pointer(const_cast<T*>(detail::get_pointer(r.m_pn.get_pointer()))) | |
, r.m_pn) | |
{} | |
template<class Y> | |
shared_ptr(shared_ptr<Y, VoidAllocator, Deleter> const & r, detail::dynamic_cast_tag) | |
: m_pn( pointer(dynamic_cast<T*>(detail::get_pointer(r.m_pn.get_pointer()))) | |
, r.m_pn) | |
{ | |
if(!m_pn.get_pointer()){ // need to allocate new counter -- the cast failed | |
m_pn = detail::shared_count<T, VoidAllocator, Deleter>(); | |
} | |
} | |
/// @endcond | |
//!Equivalent to shared_ptr(r).swap(*this). | |
//!Never throws | |
template<class Y> | |
shared_ptr & operator=(shared_ptr<Y, VoidAllocator, Deleter> 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_INTERPROCESS_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_INTERPROCESS_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<class Pointer> | |
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::pointer_to_other<Pointer, T>::type ParameterPointer; | |
BOOST_STATIC_ASSERT((detail::is_same<pointer, ParameterPointer>::value) || | |
(detail::is_pointer<Pointer>::value)); | |
this_type(p, a, d).swap(*this); | |
} | |
template<class Y> | |
void reset(shared_ptr<Y, VoidAllocator, Deleter> 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.get_pointer() != 0); return *m_pn.get_pointer(); } | |
//!Returns the pointer pointing | |
//!to the owned object | |
pointer operator-> () const // never throws | |
{ BOOST_ASSERT(m_pn.get_pointer() != 0); return m_pn.get_pointer(); } | |
//!Returns the pointer pointing | |
//!to the owned object | |
pointer get() const // never throws | |
{ return m_pn.get_pointer(); } | |
/// @cond | |
// 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.get_pointer() ? 0 : &this_type::unspecified_bool_type_func; } | |
/// @endcond | |
//!Not operator. | |
//!Returns true if this->get() != 0, false otherwise | |
bool operator! () const // never throws | |
{ return !m_pn.get_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<T, VoidAllocator, Deleter> & other) // never throws | |
{ m_pn.swap(other.m_pn); } | |
/// @cond | |
template<class T2, class A2, class Deleter2> | |
bool _internal_less(shared_ptr<T2, A2, Deleter2> 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<class T2, class A2, class Deleter2> friend class shared_ptr; | |
template<class T2, class A2, class Deleter2> friend class weak_ptr; | |
detail::shared_count<T, VoidAllocator, Deleter> m_pn; // reference counter | |
/// @endcond | |
}; // shared_ptr | |
template<class T, class VoidAllocator, class Deleter, class U, class VoidAllocator2, class Deleter2> inline | |
bool operator==(shared_ptr<T, VoidAllocator, Deleter> const & a, shared_ptr<U, VoidAllocator2, Deleter2> const & b) | |
{ return a.get() == b.get(); } | |
template<class T, class VoidAllocator, class Deleter, class U, class VoidAllocator2, class Deleter2> inline | |
bool operator!=(shared_ptr<T, VoidAllocator, Deleter> const & a, shared_ptr<U, VoidAllocator2, Deleter2> const & b) | |
{ return a.get() != b.get(); } | |
template<class T, class VoidAllocator, class Deleter, class U, class VoidAllocator2, class Deleter2> inline | |
bool operator<(shared_ptr<T, VoidAllocator, Deleter> const & a, shared_ptr<U, VoidAllocator2, Deleter2> const & b) | |
{ return a._internal_less(b); } | |
template<class T, class VoidAllocator, class Deleter> inline | |
void swap(shared_ptr<T, VoidAllocator, Deleter> & a, shared_ptr<T, VoidAllocator, Deleter> & b) | |
{ a.swap(b); } | |
template<class T, class VoidAllocator, class Deleter, class U> inline | |
shared_ptr<T, VoidAllocator, Deleter> static_pointer_cast(shared_ptr<U, VoidAllocator, Deleter> const & r) | |
{ return shared_ptr<T, VoidAllocator, Deleter>(r, detail::static_cast_tag()); } | |
template<class T, class VoidAllocator, class Deleter, class U> inline | |
shared_ptr<T, VoidAllocator, Deleter> const_pointer_cast(shared_ptr<U, VoidAllocator, Deleter> const & r) | |
{ return shared_ptr<T, VoidAllocator, Deleter>(r, detail::const_cast_tag()); } | |
template<class T, class VoidAllocator, class Deleter, class U> inline | |
shared_ptr<T, VoidAllocator, Deleter> dynamic_pointer_cast(shared_ptr<U, VoidAllocator, Deleter> const & r) | |
{ return shared_ptr<T, VoidAllocator, Deleter>(r, detail::dynamic_cast_tag()); } | |
// get_pointer() enables boost::mem_fn to recognize shared_ptr | |
template<class T, class VoidAllocator, class Deleter> inline | |
T * get_pointer(shared_ptr<T, VoidAllocator, Deleter> const & p) | |
{ return p.get(); } | |
// operator<< | |
template<class E, class T, class Y, class VoidAllocator, class Deleter> inline | |
std::basic_ostream<E, T> & operator<< | |
(std::basic_ostream<E, T> & os, shared_ptr<Y, VoidAllocator, Deleter> 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<class T, class ManagedMemory> | |
struct managed_shared_ptr | |
{ | |
typedef typename ManagedMemory::template allocator<void>::type void_allocator; | |
typedef typename ManagedMemory::template deleter<T>::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<class T, class ManagedMemory> | |
inline typename managed_shared_ptr<T, ManagedMemory>::type | |
make_managed_shared_ptr(T *constructed_object, ManagedMemory &managed_memory) | |
{ | |
return typename managed_shared_ptr<T, ManagedMemory>::type | |
( constructed_object | |
, managed_memory.template get_allocator<void>() | |
, managed_memory.template get_deleter<T>() | |
); | |
} | |
} // namespace interprocess | |
/// @cond | |
#if defined(_MSC_VER) && (_MSC_VER < 1400) | |
// get_pointer() enables boost::mem_fn to recognize shared_ptr | |
template<class T, class VoidAllocator, class Deleter> inline | |
T * get_pointer(boost::interprocess::shared_ptr<T, VoidAllocator, Deleter> const & p) | |
{ return p.get(); } | |
#endif | |
/// @endcond | |
} // namespace boost | |
#include <boost/interprocess/detail/config_end.hpp> | |
#endif // #ifndef BOOST_INTERPROCESS_SHARED_PTR_HPP_INCLUDED |