Chris@16: #ifndef BOOST_SMART_PTR_DETAIL_SHARED_COUNT_HPP_INCLUDED Chris@16: #define BOOST_SMART_PTR_DETAIL_SHARED_COUNT_HPP_INCLUDED Chris@16: Chris@16: // MS compatible compilers support #pragma once Chris@16: Chris@16: #if defined(_MSC_VER) && (_MSC_VER >= 1020) Chris@16: # pragma once Chris@16: #endif Chris@16: Chris@16: // Chris@16: // detail/shared_count.hpp Chris@16: // Chris@16: // Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. Chris@16: // Copyright 2004-2005 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: Chris@16: #ifdef __BORLANDC__ Chris@16: # pragma warn -8027 // Functions containing try are not expanded inline Chris@16: #endif Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: // In order to avoid circular dependencies with Boost.TR1 Chris@16: // we make sure that our include of doesn't try to Chris@16: // pull in the TR1 headers: that's why we use this header Chris@16: // rather than including directly: Chris@16: #include // std::auto_ptr Chris@16: #include // std::less Chris@16: Chris@16: #ifdef BOOST_NO_EXCEPTIONS Chris@16: # include // std::bad_alloc Chris@16: #endif Chris@16: Chris@16: #if !defined( BOOST_NO_CXX11_SMART_PTR ) Chris@16: # include Chris@16: #endif Chris@16: Chris@16: namespace boost Chris@16: { Chris@16: Chris@16: namespace detail Chris@16: { Chris@16: Chris@16: #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) Chris@16: Chris@16: int const shared_count_id = 0x2C35F101; Chris@16: int const weak_count_id = 0x298C38A4; Chris@16: Chris@16: #endif Chris@16: Chris@16: struct sp_nothrow_tag {}; Chris@16: Chris@16: template< class D > struct sp_inplace_tag Chris@16: { Chris@16: }; Chris@16: Chris@16: #if !defined( BOOST_NO_CXX11_SMART_PTR ) Chris@16: Chris@16: template< class T > class sp_reference_wrapper Chris@16: { Chris@16: public: Chris@16: Chris@16: explicit sp_reference_wrapper( T & t): t_( boost::addressof( t ) ) Chris@16: { Chris@16: } Chris@16: Chris@16: template< class Y > void operator()( Y * p ) const Chris@16: { Chris@16: (*t_)( p ); Chris@16: } Chris@16: Chris@16: private: Chris@16: Chris@16: T * t_; Chris@16: }; Chris@16: Chris@16: template< class D > struct sp_convert_reference Chris@16: { Chris@16: typedef D type; Chris@16: }; Chris@16: Chris@16: template< class D > struct sp_convert_reference< D& > Chris@16: { Chris@16: typedef sp_reference_wrapper< D > type; Chris@16: }; Chris@16: Chris@16: #endif Chris@16: Chris@16: class weak_count; Chris@16: Chris@16: class shared_count Chris@16: { Chris@16: private: Chris@16: Chris@16: sp_counted_base * pi_; Chris@16: Chris@16: #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) Chris@16: int id_; Chris@16: #endif Chris@16: Chris@16: friend class weak_count; Chris@16: Chris@16: public: Chris@16: Chris@16: shared_count(): pi_(0) // nothrow Chris@16: #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) Chris@16: , id_(shared_count_id) Chris@16: #endif Chris@16: { Chris@16: } Chris@16: Chris@16: template explicit shared_count( Y * p ): pi_( 0 ) Chris@16: #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) Chris@16: , id_(shared_count_id) Chris@16: #endif Chris@16: { Chris@16: #ifndef BOOST_NO_EXCEPTIONS Chris@16: Chris@16: try Chris@16: { Chris@16: pi_ = new sp_counted_impl_p( p ); Chris@16: } Chris@16: catch(...) Chris@16: { Chris@16: boost::checked_delete( p ); Chris@16: throw; Chris@16: } Chris@16: Chris@16: #else Chris@16: Chris@16: pi_ = new sp_counted_impl_p( p ); Chris@16: Chris@16: if( pi_ == 0 ) Chris@16: { Chris@16: boost::checked_delete( p ); Chris@16: boost::throw_exception( std::bad_alloc() ); Chris@16: } Chris@16: Chris@16: #endif Chris@16: } Chris@16: Chris@16: #if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1200 ) Chris@16: template shared_count( Y * p, D d ): pi_(0) Chris@16: #else Chris@16: template shared_count( P p, D d ): pi_(0) Chris@16: #endif Chris@16: #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) Chris@16: , id_(shared_count_id) Chris@16: #endif Chris@16: { Chris@16: #if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1200 ) Chris@16: typedef Y* P; Chris@16: #endif Chris@16: #ifndef BOOST_NO_EXCEPTIONS Chris@16: Chris@16: try Chris@16: { Chris@16: pi_ = new sp_counted_impl_pd(p, d); Chris@16: } Chris@16: catch(...) Chris@16: { Chris@16: d(p); // delete p Chris@16: throw; Chris@16: } Chris@16: Chris@16: #else Chris@16: Chris@16: pi_ = new sp_counted_impl_pd(p, d); Chris@16: Chris@16: if(pi_ == 0) Chris@16: { Chris@16: d(p); // delete p Chris@16: boost::throw_exception(std::bad_alloc()); Chris@16: } Chris@16: Chris@16: #endif Chris@16: } Chris@16: Chris@16: #if !defined( BOOST_NO_FUNCTION_TEMPLATE_ORDERING ) Chris@16: Chris@16: template< class P, class D > shared_count( P p, sp_inplace_tag ): pi_( 0 ) Chris@16: #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) Chris@16: , id_(shared_count_id) Chris@16: #endif Chris@16: { Chris@16: #ifndef BOOST_NO_EXCEPTIONS Chris@16: Chris@16: try Chris@16: { Chris@16: pi_ = new sp_counted_impl_pd< P, D >( p ); Chris@16: } Chris@16: catch( ... ) Chris@16: { Chris@16: D::operator_fn( p ); // delete p Chris@16: throw; Chris@16: } Chris@16: Chris@16: #else Chris@16: Chris@16: pi_ = new sp_counted_impl_pd< P, D >( p ); Chris@16: Chris@16: if( pi_ == 0 ) Chris@16: { Chris@16: D::operator_fn( p ); // delete p Chris@16: boost::throw_exception( std::bad_alloc() ); Chris@16: } Chris@16: Chris@16: #endif // #ifndef BOOST_NO_EXCEPTIONS Chris@16: } Chris@16: Chris@16: #endif // !defined( BOOST_NO_FUNCTION_TEMPLATE_ORDERING ) Chris@16: Chris@16: template shared_count( P p, D d, A a ): pi_( 0 ) Chris@16: #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) Chris@16: , id_(shared_count_id) Chris@16: #endif Chris@16: { Chris@16: typedef sp_counted_impl_pda impl_type; Chris@101: Chris@101: #if !defined( BOOST_NO_CXX11_ALLOCATOR ) Chris@101: Chris@101: typedef typename std::allocator_traits::template rebind_alloc< impl_type > A2; Chris@101: Chris@101: #else Chris@101: Chris@16: typedef typename A::template rebind< impl_type >::other A2; Chris@16: Chris@101: #endif Chris@101: Chris@16: A2 a2( a ); Chris@16: Chris@16: #ifndef BOOST_NO_EXCEPTIONS Chris@16: Chris@16: try Chris@16: { Chris@101: #if !defined( BOOST_NO_CXX11_ALLOCATOR ) Chris@101: Chris@101: impl_type * pi = std::allocator_traits::allocate( a2, 1 ); Chris@101: pi_ = pi; Chris@101: std::allocator_traits::construct( a2, pi, p, d, a ); Chris@101: Chris@101: #else Chris@101: Chris@16: pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) ); Chris@101: ::new( static_cast< void* >( pi_ ) ) impl_type( p, d, a ); Chris@101: Chris@101: #endif Chris@16: } Chris@16: catch(...) Chris@16: { Chris@16: d( p ); Chris@16: Chris@16: if( pi_ != 0 ) Chris@16: { Chris@16: a2.deallocate( static_cast< impl_type* >( pi_ ), 1 ); Chris@16: } Chris@16: Chris@16: throw; Chris@16: } Chris@16: Chris@16: #else Chris@16: Chris@101: #if !defined( BOOST_NO_CXX11_ALLOCATOR ) Chris@101: Chris@101: impl_type * pi = std::allocator_traits::allocate( a2, 1 ); Chris@101: pi_ = pi; Chris@101: Chris@101: #else Chris@101: Chris@16: pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) ); Chris@16: Chris@101: #endif Chris@101: Chris@16: if( pi_ != 0 ) Chris@16: { Chris@101: #if !defined( BOOST_NO_CXX11_ALLOCATOR ) Chris@101: Chris@101: std::allocator_traits::construct( a2, pi, p, d, a ); Chris@101: Chris@101: #else Chris@101: Chris@101: ::new( static_cast< void* >( pi_ ) ) impl_type( p, d, a ); Chris@101: Chris@101: #endif Chris@16: } Chris@16: else Chris@16: { Chris@16: d( p ); Chris@16: boost::throw_exception( std::bad_alloc() ); Chris@16: } Chris@16: Chris@16: #endif Chris@16: } Chris@16: Chris@16: #if !defined( BOOST_NO_FUNCTION_TEMPLATE_ORDERING ) Chris@16: Chris@16: template< class P, class D, class A > shared_count( P p, sp_inplace_tag< D >, A a ): pi_( 0 ) Chris@16: #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) Chris@16: , id_(shared_count_id) Chris@16: #endif Chris@16: { Chris@16: typedef sp_counted_impl_pda< P, D, A > impl_type; Chris@101: Chris@101: #if !defined( BOOST_NO_CXX11_ALLOCATOR ) Chris@101: Chris@101: typedef typename std::allocator_traits::template rebind_alloc< impl_type > A2; Chris@101: Chris@101: #else Chris@101: Chris@16: typedef typename A::template rebind< impl_type >::other A2; Chris@16: Chris@101: #endif Chris@101: Chris@16: A2 a2( a ); Chris@16: Chris@16: #ifndef BOOST_NO_EXCEPTIONS Chris@16: Chris@16: try Chris@16: { Chris@101: #if !defined( BOOST_NO_CXX11_ALLOCATOR ) Chris@101: Chris@101: impl_type * pi = std::allocator_traits::allocate( a2, 1 ); Chris@101: pi_ = pi; Chris@101: std::allocator_traits::construct( a2, pi, p, a ); Chris@101: Chris@101: #else Chris@101: Chris@16: pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) ); Chris@101: ::new( static_cast< void* >( pi_ ) ) impl_type( p, a ); Chris@101: Chris@101: #endif Chris@16: } Chris@16: catch(...) Chris@16: { Chris@16: D::operator_fn( p ); Chris@16: Chris@16: if( pi_ != 0 ) Chris@16: { Chris@16: a2.deallocate( static_cast< impl_type* >( pi_ ), 1 ); Chris@16: } Chris@16: Chris@16: throw; Chris@16: } Chris@16: Chris@16: #else Chris@16: Chris@101: #if !defined( BOOST_NO_CXX11_ALLOCATOR ) Chris@101: Chris@101: impl_type * pi = std::allocator_traits::allocate( a2, 1 ); Chris@101: pi_ = pi; Chris@101: Chris@101: #else Chris@101: Chris@16: pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) ); Chris@16: Chris@101: #endif Chris@101: Chris@16: if( pi_ != 0 ) Chris@16: { Chris@101: #if !defined( BOOST_NO_CXX11_ALLOCATOR ) Chris@101: Chris@101: std::allocator_traits::construct( a2, pi, p, a ); Chris@101: Chris@101: #else Chris@101: Chris@101: ::new( static_cast< void* >( pi_ ) ) impl_type( p, a ); Chris@101: Chris@101: #endif Chris@16: } Chris@16: else Chris@16: { Chris@16: D::operator_fn( p ); Chris@16: boost::throw_exception( std::bad_alloc() ); Chris@16: } Chris@16: Chris@16: #endif // #ifndef BOOST_NO_EXCEPTIONS Chris@16: } Chris@16: Chris@16: #endif // !defined( BOOST_NO_FUNCTION_TEMPLATE_ORDERING ) Chris@16: Chris@16: #ifndef BOOST_NO_AUTO_PTR Chris@16: Chris@16: // auto_ptr is special cased to provide the strong guarantee Chris@16: Chris@16: template Chris@16: explicit shared_count( std::auto_ptr & r ): pi_( new sp_counted_impl_p( r.get() ) ) Chris@16: #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) Chris@16: , id_(shared_count_id) Chris@16: #endif Chris@16: { Chris@16: #ifdef BOOST_NO_EXCEPTIONS Chris@16: Chris@16: if( pi_ == 0 ) Chris@16: { Chris@16: boost::throw_exception(std::bad_alloc()); Chris@16: } Chris@16: Chris@16: #endif Chris@16: Chris@16: r.release(); Chris@16: } Chris@16: Chris@16: #endif Chris@16: Chris@16: #if !defined( BOOST_NO_CXX11_SMART_PTR ) Chris@16: Chris@16: template Chris@16: explicit shared_count( std::unique_ptr & r ): pi_( 0 ) Chris@16: #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) Chris@16: , id_(shared_count_id) Chris@16: #endif Chris@16: { Chris@16: typedef typename sp_convert_reference::type D2; Chris@16: Chris@16: D2 d2( r.get_deleter() ); Chris@16: pi_ = new sp_counted_impl_pd< typename std::unique_ptr::pointer, D2 >( r.get(), d2 ); Chris@16: Chris@16: #ifdef BOOST_NO_EXCEPTIONS Chris@16: Chris@16: if( pi_ == 0 ) Chris@16: { Chris@16: boost::throw_exception( std::bad_alloc() ); Chris@16: } Chris@16: Chris@16: #endif Chris@16: Chris@16: r.release(); Chris@16: } Chris@16: Chris@16: #endif Chris@16: Chris@16: ~shared_count() // nothrow Chris@16: { Chris@16: if( pi_ != 0 ) pi_->release(); Chris@16: #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) Chris@16: id_ = 0; Chris@16: #endif Chris@16: } Chris@16: Chris@16: shared_count(shared_count const & r): pi_(r.pi_) // nothrow Chris@16: #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) Chris@16: , id_(shared_count_id) Chris@16: #endif Chris@16: { Chris@16: if( pi_ != 0 ) pi_->add_ref_copy(); Chris@16: } Chris@16: Chris@16: #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) Chris@16: Chris@16: shared_count(shared_count && r): pi_(r.pi_) // nothrow Chris@16: #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) Chris@16: , id_(shared_count_id) Chris@16: #endif Chris@16: { Chris@16: r.pi_ = 0; Chris@16: } Chris@16: Chris@16: #endif Chris@16: Chris@16: explicit shared_count(weak_count const & r); // throws bad_weak_ptr when r.use_count() == 0 Chris@16: shared_count( weak_count const & r, sp_nothrow_tag ); // constructs an empty *this when r.use_count() == 0 Chris@16: Chris@16: shared_count & operator= (shared_count const & r) // nothrow Chris@16: { Chris@16: sp_counted_base * tmp = r.pi_; Chris@16: Chris@16: if( tmp != pi_ ) Chris@16: { Chris@16: if( tmp != 0 ) tmp->add_ref_copy(); Chris@16: if( pi_ != 0 ) pi_->release(); Chris@16: pi_ = tmp; Chris@16: } Chris@16: Chris@16: return *this; Chris@16: } Chris@16: Chris@16: void swap(shared_count & r) // nothrow Chris@16: { Chris@16: sp_counted_base * tmp = r.pi_; Chris@16: r.pi_ = pi_; Chris@16: pi_ = tmp; Chris@16: } Chris@16: Chris@16: long use_count() const // nothrow Chris@16: { Chris@16: return pi_ != 0? pi_->use_count(): 0; Chris@16: } Chris@16: Chris@16: bool unique() const // nothrow Chris@16: { Chris@16: return use_count() == 1; Chris@16: } Chris@16: Chris@16: bool empty() const // nothrow Chris@16: { Chris@16: return pi_ == 0; Chris@16: } Chris@16: Chris@16: friend inline bool operator==(shared_count const & a, shared_count const & b) Chris@16: { Chris@16: return a.pi_ == b.pi_; Chris@16: } Chris@16: Chris@16: friend inline bool operator<(shared_count const & a, shared_count const & b) Chris@16: { Chris@16: return std::less()( a.pi_, b.pi_ ); Chris@16: } Chris@16: Chris@16: void * get_deleter( sp_typeinfo const & ti ) const Chris@16: { Chris@16: return pi_? pi_->get_deleter( ti ): 0; Chris@16: } Chris@16: Chris@16: void * get_untyped_deleter() const Chris@16: { Chris@16: return pi_? pi_->get_untyped_deleter(): 0; Chris@16: } Chris@16: }; Chris@16: Chris@16: Chris@16: class weak_count Chris@16: { Chris@16: private: Chris@16: Chris@16: sp_counted_base * pi_; Chris@16: Chris@16: #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) Chris@16: int id_; Chris@16: #endif Chris@16: Chris@16: friend class shared_count; Chris@16: Chris@16: public: Chris@16: Chris@16: weak_count(): pi_(0) // nothrow Chris@16: #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) Chris@16: , id_(weak_count_id) Chris@16: #endif Chris@16: { Chris@16: } Chris@16: Chris@16: weak_count(shared_count const & r): pi_(r.pi_) // nothrow Chris@16: #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) Chris@16: , id_(weak_count_id) Chris@16: #endif Chris@16: { Chris@16: if(pi_ != 0) pi_->weak_add_ref(); Chris@16: } Chris@16: Chris@16: weak_count(weak_count const & r): pi_(r.pi_) // nothrow Chris@16: #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) Chris@16: , id_(weak_count_id) Chris@16: #endif Chris@16: { Chris@16: if(pi_ != 0) pi_->weak_add_ref(); Chris@16: } Chris@16: Chris@16: // Move support Chris@16: Chris@16: #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) Chris@16: Chris@16: weak_count(weak_count && r): pi_(r.pi_) // nothrow Chris@16: #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) Chris@16: , id_(weak_count_id) Chris@16: #endif Chris@16: { Chris@16: r.pi_ = 0; Chris@16: } Chris@16: Chris@16: #endif Chris@16: Chris@16: ~weak_count() // nothrow Chris@16: { Chris@16: if(pi_ != 0) pi_->weak_release(); Chris@16: #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) Chris@16: id_ = 0; Chris@16: #endif Chris@16: } Chris@16: Chris@16: weak_count & operator= (shared_count const & r) // nothrow Chris@16: { Chris@16: sp_counted_base * tmp = r.pi_; Chris@16: Chris@16: if( tmp != pi_ ) Chris@16: { Chris@16: if(tmp != 0) tmp->weak_add_ref(); Chris@16: if(pi_ != 0) pi_->weak_release(); Chris@16: pi_ = tmp; Chris@16: } Chris@16: Chris@16: return *this; Chris@16: } Chris@16: Chris@16: weak_count & operator= (weak_count const & r) // nothrow Chris@16: { Chris@16: sp_counted_base * tmp = r.pi_; Chris@16: Chris@16: if( tmp != pi_ ) Chris@16: { Chris@16: if(tmp != 0) tmp->weak_add_ref(); Chris@16: if(pi_ != 0) pi_->weak_release(); Chris@16: pi_ = tmp; Chris@16: } Chris@16: Chris@16: return *this; Chris@16: } Chris@16: Chris@16: void swap(weak_count & r) // nothrow Chris@16: { Chris@16: sp_counted_base * tmp = r.pi_; Chris@16: r.pi_ = pi_; Chris@16: pi_ = tmp; Chris@16: } Chris@16: Chris@16: long use_count() const // nothrow Chris@16: { Chris@16: return pi_ != 0? pi_->use_count(): 0; Chris@16: } Chris@16: Chris@16: bool empty() const // nothrow Chris@16: { Chris@16: return pi_ == 0; Chris@16: } Chris@16: Chris@16: friend inline bool operator==(weak_count const & a, weak_count const & b) Chris@16: { Chris@16: return a.pi_ == b.pi_; Chris@16: } Chris@16: Chris@16: friend inline bool operator<(weak_count const & a, weak_count const & b) Chris@16: { Chris@16: return std::less()(a.pi_, b.pi_); Chris@16: } Chris@16: }; Chris@16: Chris@16: inline shared_count::shared_count( weak_count const & r ): pi_( r.pi_ ) Chris@16: #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) Chris@16: , id_(shared_count_id) Chris@16: #endif Chris@16: { Chris@16: if( pi_ == 0 || !pi_->add_ref_lock() ) Chris@16: { Chris@16: boost::throw_exception( boost::bad_weak_ptr() ); Chris@16: } Chris@16: } Chris@16: Chris@16: inline shared_count::shared_count( weak_count const & r, sp_nothrow_tag ): pi_( r.pi_ ) Chris@16: #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) Chris@16: , id_(shared_count_id) Chris@16: #endif Chris@16: { Chris@16: if( pi_ != 0 && !pi_->add_ref_lock() ) Chris@16: { Chris@16: pi_ = 0; Chris@16: } Chris@16: } Chris@16: Chris@16: } // namespace detail Chris@16: Chris@16: } // namespace boost Chris@16: Chris@16: #ifdef __BORLANDC__ Chris@16: # pragma warn .8027 // Functions containing try are not expanded inline Chris@16: #endif Chris@16: Chris@16: #endif // #ifndef BOOST_SMART_PTR_DETAIL_SHARED_COUNT_HPP_INCLUDED