Chris@16: #ifndef BOOST_SMART_PTR_INTRUSIVE_PTR_HPP_INCLUDED Chris@16: #define BOOST_SMART_PTR_INTRUSIVE_PTR_HPP_INCLUDED Chris@16: Chris@16: // Chris@16: // intrusive_ptr.hpp Chris@16: // Chris@16: // Copyright (c) 2001, 2002 Peter Dimov Chris@16: // Chris@16: // Distributed under the Boost Software License, Version 1.0. (See Chris@16: // 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/smart_ptr/intrusive_ptr.html for documentation. Chris@16: // Chris@16: Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include // for std::less Chris@16: Chris@16: #if !defined(BOOST_NO_IOSTREAM) Chris@16: #if !defined(BOOST_NO_IOSFWD) Chris@16: #include // for std::basic_ostream Chris@16: #else Chris@16: #include Chris@16: #endif Chris@16: #endif Chris@16: Chris@16: Chris@16: namespace boost Chris@16: { Chris@16: Chris@16: // Chris@16: // intrusive_ptr Chris@16: // Chris@16: // A smart pointer that uses intrusive reference counting. Chris@16: // Chris@16: // Relies on unqualified calls to Chris@16: // Chris@16: // void intrusive_ptr_add_ref(T * p); Chris@16: // void intrusive_ptr_release(T * p); Chris@16: // Chris@16: // (p != 0) Chris@16: // Chris@16: // The object is responsible for destroying itself. Chris@16: // Chris@16: Chris@16: template class intrusive_ptr Chris@16: { Chris@16: private: Chris@16: Chris@16: typedef intrusive_ptr this_type; Chris@16: Chris@16: public: Chris@16: Chris@16: typedef T element_type; Chris@16: Chris@16: intrusive_ptr() BOOST_NOEXCEPT : px( 0 ) Chris@16: { Chris@16: } Chris@16: Chris@16: intrusive_ptr( T * p, bool add_ref = true ): px( p ) Chris@16: { Chris@16: if( px != 0 && add_ref ) intrusive_ptr_add_ref( px ); Chris@16: } Chris@16: Chris@16: #if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES) Chris@16: Chris@16: template Chris@16: #if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) Chris@16: Chris@16: intrusive_ptr( intrusive_ptr const & rhs, typename boost::detail::sp_enable_if_convertible::type = boost::detail::sp_empty() ) Chris@16: Chris@16: #else Chris@16: Chris@16: intrusive_ptr( intrusive_ptr const & rhs ) Chris@16: Chris@16: #endif Chris@16: : px( rhs.get() ) Chris@16: { Chris@16: if( px != 0 ) intrusive_ptr_add_ref( px ); Chris@16: } Chris@16: Chris@16: #endif Chris@16: Chris@16: intrusive_ptr(intrusive_ptr const & rhs): px( rhs.px ) Chris@16: { Chris@16: if( px != 0 ) intrusive_ptr_add_ref( px ); Chris@16: } Chris@16: Chris@16: ~intrusive_ptr() Chris@16: { Chris@16: if( px != 0 ) intrusive_ptr_release( px ); Chris@16: } Chris@16: Chris@16: #if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES) Chris@16: Chris@16: template intrusive_ptr & operator=(intrusive_ptr const & rhs) Chris@16: { Chris@16: this_type(rhs).swap(*this); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: #endif Chris@16: Chris@16: // Move support Chris@16: Chris@16: #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) Chris@16: Chris@16: intrusive_ptr(intrusive_ptr && rhs) BOOST_NOEXCEPT : px( rhs.px ) Chris@16: { Chris@16: rhs.px = 0; Chris@16: } Chris@16: Chris@16: intrusive_ptr & operator=(intrusive_ptr && rhs) BOOST_NOEXCEPT Chris@16: { Chris@16: this_type( static_cast< intrusive_ptr && >( rhs ) ).swap(*this); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: #endif Chris@16: Chris@16: intrusive_ptr & operator=(intrusive_ptr const & rhs) Chris@16: { Chris@16: this_type(rhs).swap(*this); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: intrusive_ptr & operator=(T * rhs) Chris@16: { Chris@16: this_type(rhs).swap(*this); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: void reset() BOOST_NOEXCEPT Chris@16: { Chris@16: this_type().swap( *this ); Chris@16: } Chris@16: Chris@16: void reset( T * rhs ) Chris@16: { Chris@16: this_type( rhs ).swap( *this ); Chris@16: } Chris@16: Chris@101: void reset( T * rhs, bool add_ref ) Chris@101: { Chris@101: this_type( rhs, add_ref ).swap( *this ); Chris@101: } Chris@101: Chris@16: T * get() const BOOST_NOEXCEPT Chris@16: { Chris@16: return px; Chris@16: } Chris@16: Chris@101: T * detach() BOOST_NOEXCEPT Chris@101: { Chris@101: T * ret = px; Chris@101: px = 0; Chris@101: return ret; Chris@101: } Chris@101: Chris@16: T & operator*() const Chris@16: { Chris@16: BOOST_ASSERT( px != 0 ); Chris@16: return *px; Chris@16: } Chris@16: Chris@16: T * operator->() const Chris@16: { Chris@16: BOOST_ASSERT( px != 0 ); Chris@16: return px; Chris@16: } Chris@16: Chris@16: // implicit conversion to "bool" Chris@16: #include Chris@16: Chris@16: void swap(intrusive_ptr & rhs) BOOST_NOEXCEPT Chris@16: { Chris@16: T * tmp = px; Chris@16: px = rhs.px; Chris@16: rhs.px = tmp; Chris@16: } Chris@16: Chris@16: private: Chris@16: Chris@16: T * px; Chris@16: }; Chris@16: Chris@16: template inline bool operator==(intrusive_ptr const & a, intrusive_ptr const & b) Chris@16: { Chris@16: return a.get() == b.get(); Chris@16: } Chris@16: Chris@16: template inline bool operator!=(intrusive_ptr const & a, intrusive_ptr const & b) Chris@16: { Chris@16: return a.get() != b.get(); Chris@16: } Chris@16: Chris@16: template inline bool operator==(intrusive_ptr const & a, U * b) Chris@16: { Chris@16: return a.get() == b; Chris@16: } Chris@16: Chris@16: template inline bool operator!=(intrusive_ptr const & a, U * b) Chris@16: { Chris@16: return a.get() != b; Chris@16: } Chris@16: Chris@16: template inline bool operator==(T * a, intrusive_ptr const & b) Chris@16: { Chris@16: return a == b.get(); Chris@16: } Chris@16: Chris@16: template inline bool operator!=(T * a, intrusive_ptr const & b) Chris@16: { Chris@16: return a != b.get(); Chris@16: } Chris@16: Chris@16: #if __GNUC__ == 2 && __GNUC_MINOR__ <= 96 Chris@16: Chris@16: // Resolve the ambiguity between our op!= and the one in rel_ops Chris@16: Chris@16: template inline bool operator!=(intrusive_ptr const & a, intrusive_ptr const & b) Chris@16: { Chris@16: return a.get() != b.get(); Chris@16: } Chris@16: Chris@16: #endif Chris@16: Chris@16: #if !defined( BOOST_NO_CXX11_NULLPTR ) Chris@16: Chris@16: template inline bool operator==( intrusive_ptr const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT Chris@16: { Chris@16: return p.get() == 0; Chris@16: } Chris@16: Chris@16: template inline bool operator==( boost::detail::sp_nullptr_t, intrusive_ptr const & p ) BOOST_NOEXCEPT Chris@16: { Chris@16: return p.get() == 0; Chris@16: } Chris@16: Chris@16: template inline bool operator!=( intrusive_ptr const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT Chris@16: { Chris@16: return p.get() != 0; Chris@16: } Chris@16: Chris@16: template inline bool operator!=( boost::detail::sp_nullptr_t, intrusive_ptr const & p ) BOOST_NOEXCEPT Chris@16: { Chris@16: return p.get() != 0; Chris@16: } Chris@16: Chris@16: #endif Chris@16: Chris@16: template inline bool operator<(intrusive_ptr const & a, intrusive_ptr const & b) Chris@16: { Chris@16: return std::less()(a.get(), b.get()); Chris@16: } Chris@16: Chris@16: template void swap(intrusive_ptr & lhs, intrusive_ptr & rhs) Chris@16: { Chris@16: lhs.swap(rhs); Chris@16: } Chris@16: Chris@16: // mem_fn support Chris@16: Chris@16: template T * get_pointer(intrusive_ptr const & p) Chris@16: { Chris@16: return p.get(); Chris@16: } Chris@16: Chris@16: template intrusive_ptr static_pointer_cast(intrusive_ptr const & p) Chris@16: { Chris@16: return static_cast(p.get()); Chris@16: } Chris@16: Chris@16: template intrusive_ptr const_pointer_cast(intrusive_ptr const & p) Chris@16: { Chris@16: return const_cast(p.get()); Chris@16: } Chris@16: Chris@16: template intrusive_ptr dynamic_pointer_cast(intrusive_ptr const & p) Chris@16: { Chris@16: return dynamic_cast(p.get()); Chris@16: } Chris@16: Chris@16: // operator<< Chris@16: Chris@16: #if !defined(BOOST_NO_IOSTREAM) Chris@16: Chris@16: #if defined(BOOST_NO_TEMPLATED_IOSTREAMS) || ( defined(__GNUC__) && (__GNUC__ < 3) ) Chris@16: Chris@16: template std::ostream & operator<< (std::ostream & os, intrusive_ptr const & p) Chris@16: { Chris@16: os << p.get(); Chris@16: return os; Chris@16: } Chris@16: Chris@16: #else Chris@16: Chris@16: // in STLport's no-iostreams mode no iostream symbols can be used Chris@16: #ifndef _STLP_NO_IOSTREAMS Chris@16: Chris@16: # if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300 && __SGI_STL_PORT) Chris@16: // MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL Chris@16: using std::basic_ostream; Chris@16: template basic_ostream & operator<< (basic_ostream & os, intrusive_ptr const & p) Chris@16: # else Chris@16: template std::basic_ostream & operator<< (std::basic_ostream & os, intrusive_ptr const & p) Chris@16: # endif Chris@16: { Chris@16: os << p.get(); Chris@16: return os; Chris@16: } Chris@16: Chris@16: #endif // _STLP_NO_IOSTREAMS Chris@16: Chris@16: #endif // __GNUC__ < 3 Chris@16: Chris@16: #endif // !defined(BOOST_NO_IOSTREAM) Chris@16: Chris@16: // hash_value Chris@16: Chris@16: template< class T > struct hash; Chris@16: Chris@16: template< class T > std::size_t hash_value( boost::intrusive_ptr const & p ) Chris@16: { Chris@16: return boost::hash< T* >()( p.get() ); Chris@16: } Chris@16: Chris@16: } // namespace boost Chris@16: Chris@16: #endif // #ifndef BOOST_SMART_PTR_INTRUSIVE_PTR_HPP_INCLUDED