williamr@2: #ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED williamr@2: #define BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED williamr@2: williamr@2: // MS compatible compilers support #pragma once williamr@2: williamr@2: #if defined(_MSC_VER) && (_MSC_VER >= 1020) williamr@2: # pragma once williamr@2: #endif williamr@2: williamr@2: // williamr@2: // detail/shared_count.hpp williamr@2: // williamr@2: // Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. williamr@2: // Copyright 2004-2005 Peter Dimov williamr@2: // williamr@2: // Distributed under the Boost Software License, Version 1.0. (See williamr@2: // accompanying file LICENSE_1_0.txt or copy at williamr@2: // http://www.boost.org/LICENSE_1_0.txt) williamr@2: // williamr@2: williamr@2: #ifdef __BORLANDC__ williamr@2: # pragma warn -8027 // Functions containing try are not expanded inline williamr@2: #endif williamr@2: williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: williamr@2: #include // std::auto_ptr williamr@2: #include // std::less williamr@2: #include // std::bad_alloc williamr@2: #include // std::type_info in get_deleter williamr@2: williamr@2: namespace boost williamr@2: { williamr@2: williamr@2: namespace detail williamr@2: { williamr@2: williamr@2: #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) williamr@2: williamr@2: int const shared_count_id = 0x2C35F101; williamr@2: int const weak_count_id = 0x298C38A4; williamr@2: williamr@2: #endif williamr@2: williamr@2: class weak_count; williamr@2: williamr@2: class shared_count williamr@2: { williamr@2: private: williamr@2: williamr@2: sp_counted_base * pi_; williamr@2: williamr@2: #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) williamr@2: int id_; williamr@2: #endif williamr@2: williamr@2: friend class weak_count; williamr@2: williamr@2: public: williamr@2: williamr@2: shared_count(): pi_(0) // nothrow williamr@2: #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) williamr@2: , id_(shared_count_id) williamr@2: #endif williamr@2: { williamr@2: } williamr@2: williamr@2: template explicit shared_count( Y * p ): pi_( 0 ) williamr@2: #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) williamr@2: , id_(shared_count_id) williamr@2: #endif williamr@2: { williamr@2: #ifndef BOOST_NO_EXCEPTIONS williamr@2: williamr@2: try williamr@2: { williamr@2: pi_ = new sp_counted_impl_p( p ); williamr@2: } williamr@2: catch(...) williamr@2: { williamr@2: boost::checked_delete( p ); williamr@2: throw; williamr@2: } williamr@2: williamr@2: #else williamr@2: williamr@2: pi_ = new sp_counted_impl_p( p ); williamr@2: williamr@2: if( pi_ == 0 ) williamr@2: { williamr@2: boost::checked_delete( p ); williamr@2: boost::throw_exception( std::bad_alloc() ); williamr@2: } williamr@2: williamr@2: #endif williamr@2: } williamr@2: williamr@2: template shared_count(P p, D d): pi_(0) williamr@2: #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) williamr@2: , id_(shared_count_id) williamr@2: #endif williamr@2: { williamr@2: #ifndef BOOST_NO_EXCEPTIONS williamr@2: williamr@2: try williamr@2: { williamr@2: pi_ = new sp_counted_impl_pd(p, d); williamr@2: } williamr@2: catch(...) williamr@2: { williamr@2: d(p); // delete p williamr@2: throw; williamr@2: } williamr@2: williamr@2: #else williamr@2: williamr@2: pi_ = new sp_counted_impl_pd(p, d); williamr@2: williamr@2: if(pi_ == 0) williamr@2: { williamr@2: d(p); // delete p williamr@2: boost::throw_exception(std::bad_alloc()); williamr@2: } williamr@2: williamr@2: #endif williamr@2: } williamr@2: williamr@2: template shared_count( P p, D d, A a ): pi_( 0 ) williamr@2: #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) williamr@2: , id_(shared_count_id) williamr@2: #endif williamr@2: { williamr@2: typedef sp_counted_impl_pda impl_type; williamr@2: typedef typename A::template rebind< impl_type >::other A2; williamr@2: williamr@2: A2 a2( a ); williamr@2: williamr@2: #ifndef BOOST_NO_EXCEPTIONS williamr@2: williamr@2: try williamr@2: { williamr@2: pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) ); williamr@2: new( static_cast< void* >( pi_ ) ) impl_type( p, d, a ); williamr@2: } williamr@2: catch(...) williamr@2: { williamr@2: d( p ); williamr@2: williamr@2: if( pi_ != 0 ) williamr@2: { williamr@2: a2.deallocate( static_cast< impl_type* >( pi_ ), 1 ); williamr@2: } williamr@2: williamr@2: throw; williamr@2: } williamr@2: williamr@2: #else williamr@2: williamr@2: pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) ); williamr@2: williamr@2: if( pi_ != 0 ) williamr@2: { williamr@2: new( static_cast< void* >( pi_ ) ) impl_type( p, d, a ); williamr@2: } williamr@2: else williamr@2: { williamr@2: d( p ); williamr@2: boost::throw_exception( std::bad_alloc() ); williamr@2: } williamr@2: williamr@2: #endif williamr@2: } williamr@2: williamr@2: #ifndef BOOST_NO_AUTO_PTR williamr@2: williamr@2: // auto_ptr is special cased to provide the strong guarantee williamr@2: williamr@2: template williamr@2: explicit shared_count( std::auto_ptr & r ): pi_( new sp_counted_impl_p( r.get() ) ) williamr@2: #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) williamr@2: , id_(shared_count_id) williamr@2: #endif williamr@2: { williamr@2: #ifdef BOOST_NO_EXCEPTIONS williamr@2: williamr@2: if( pi_ == 0 ) williamr@2: { williamr@2: boost::throw_exception(std::bad_alloc()); williamr@2: } williamr@2: williamr@2: #endif williamr@2: williamr@2: r.release(); williamr@2: } williamr@2: williamr@2: #endif williamr@2: williamr@2: ~shared_count() // nothrow williamr@2: { williamr@2: if( pi_ != 0 ) pi_->release(); williamr@2: #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) williamr@2: id_ = 0; williamr@2: #endif williamr@2: } williamr@2: williamr@2: shared_count(shared_count const & r): pi_(r.pi_) // nothrow williamr@2: #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) williamr@2: , id_(shared_count_id) williamr@2: #endif williamr@2: { williamr@2: if( pi_ != 0 ) pi_->add_ref_copy(); williamr@2: } williamr@2: williamr@2: explicit shared_count(weak_count const & r); // throws bad_weak_ptr when r.use_count() == 0 williamr@2: williamr@2: shared_count & operator= (shared_count const & r) // nothrow williamr@2: { williamr@2: sp_counted_base * tmp = r.pi_; williamr@2: williamr@2: if( tmp != pi_ ) williamr@2: { williamr@2: if( tmp != 0 ) tmp->add_ref_copy(); williamr@2: if( pi_ != 0 ) pi_->release(); williamr@2: pi_ = tmp; williamr@2: } williamr@2: williamr@2: return *this; williamr@2: } williamr@2: williamr@2: void swap(shared_count & r) // nothrow williamr@2: { williamr@2: sp_counted_base * tmp = r.pi_; williamr@2: r.pi_ = pi_; williamr@2: pi_ = tmp; williamr@2: } williamr@2: williamr@2: long use_count() const // nothrow williamr@2: { williamr@2: return pi_ != 0? pi_->use_count(): 0; williamr@2: } williamr@2: williamr@2: bool unique() const // nothrow williamr@2: { williamr@2: return use_count() == 1; williamr@2: } williamr@2: williamr@2: friend inline bool operator==(shared_count const & a, shared_count const & b) williamr@2: { williamr@2: return a.pi_ == b.pi_; williamr@2: } williamr@2: williamr@2: friend inline bool operator<(shared_count const & a, shared_count const & b) williamr@2: { williamr@2: return std::less()( a.pi_, b.pi_ ); williamr@2: } williamr@2: williamr@2: void * get_deleter(std::type_info const & ti) const williamr@2: { williamr@2: return pi_? pi_->get_deleter( ti ): 0; williamr@2: } williamr@2: }; williamr@2: williamr@2: williamr@2: class weak_count williamr@2: { williamr@2: private: williamr@2: williamr@2: sp_counted_base * pi_; williamr@2: williamr@2: #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) williamr@2: int id_; williamr@2: #endif williamr@2: williamr@2: friend class shared_count; williamr@2: williamr@2: public: williamr@2: williamr@2: weak_count(): pi_(0) // nothrow williamr@2: #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) williamr@2: , id_(weak_count_id) williamr@2: #endif williamr@2: { williamr@2: } williamr@2: williamr@2: weak_count(shared_count const & r): pi_(r.pi_) // nothrow williamr@2: #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) williamr@2: , id_(shared_count_id) williamr@2: #endif williamr@2: { williamr@2: if(pi_ != 0) pi_->weak_add_ref(); williamr@2: } williamr@2: williamr@2: weak_count(weak_count const & r): pi_(r.pi_) // nothrow williamr@2: #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) williamr@2: , id_(shared_count_id) williamr@2: #endif williamr@2: { williamr@2: if(pi_ != 0) pi_->weak_add_ref(); williamr@2: } williamr@2: williamr@2: ~weak_count() // nothrow williamr@2: { williamr@2: if(pi_ != 0) pi_->weak_release(); williamr@2: #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) williamr@2: id_ = 0; williamr@2: #endif williamr@2: } williamr@2: williamr@2: weak_count & operator= (shared_count const & r) // nothrow williamr@2: { williamr@2: sp_counted_base * tmp = r.pi_; williamr@2: if(tmp != 0) tmp->weak_add_ref(); williamr@2: if(pi_ != 0) pi_->weak_release(); williamr@2: pi_ = tmp; williamr@2: williamr@2: return *this; williamr@2: } williamr@2: williamr@2: weak_count & operator= (weak_count const & r) // nothrow williamr@2: { williamr@2: sp_counted_base * tmp = r.pi_; williamr@2: if(tmp != 0) tmp->weak_add_ref(); williamr@2: if(pi_ != 0) pi_->weak_release(); williamr@2: pi_ = tmp; williamr@2: williamr@2: return *this; williamr@2: } williamr@2: williamr@2: void swap(weak_count & r) // nothrow williamr@2: { williamr@2: sp_counted_base * tmp = r.pi_; williamr@2: r.pi_ = pi_; williamr@2: pi_ = tmp; williamr@2: } williamr@2: williamr@2: long use_count() const // nothrow williamr@2: { williamr@2: return pi_ != 0? pi_->use_count(): 0; williamr@2: } williamr@2: williamr@2: friend inline bool operator==(weak_count const & a, weak_count const & b) williamr@2: { williamr@2: return a.pi_ == b.pi_; williamr@2: } williamr@2: williamr@2: friend inline bool operator<(weak_count const & a, weak_count const & b) williamr@2: { williamr@2: return std::less()(a.pi_, b.pi_); williamr@2: } williamr@2: }; williamr@2: williamr@2: inline shared_count::shared_count( weak_count const & r ): pi_( r.pi_ ) williamr@2: #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) williamr@2: , id_(shared_count_id) williamr@2: #endif williamr@2: { williamr@2: if( pi_ == 0 || !pi_->add_ref_lock() ) williamr@2: { williamr@2: boost::throw_exception( boost::bad_weak_ptr() ); williamr@2: } williamr@2: } williamr@2: williamr@2: } // namespace detail williamr@2: williamr@2: } // namespace boost williamr@2: williamr@2: #ifdef __BORLANDC__ williamr@2: # pragma warn .8027 // Functions containing try are not expanded inline williamr@2: #endif williamr@2: williamr@2: #endif // #ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED