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