From 25ca8551276d85840220c15f8bac80908a0907bc Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 9 Nov 2005 20:05:42 +0000 Subject: [PATCH] shared_ptr( p, d, a ) added. [SVN r31613] --- include/boost/detail/shared_count.hpp | 46 ++++++++++++++++++++++++ include/boost/detail/sp_counted_impl.hpp | 42 ++++++++++++++++++++++ include/boost/shared_ptr.hpp | 16 +++++++-- 3 files changed, 102 insertions(+), 2 deletions(-) diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index 49aca85..0395053 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -127,6 +127,52 @@ public: boost::throw_exception(std::bad_alloc()); } +#endif + } + + template shared_count( P p, D d, A a ): pi_( 0 ) +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + , id_(shared_count_id) +#endif + { + typedef sp_counted_impl_pda impl_type; + typedef typename A::template rebind< impl_type >::other A2; + + A2 a2( a ); + +#ifndef BOOST_NO_EXCEPTIONS + + try + { + pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) ); + new( static_cast< void* >( pi_ ) ) impl_type( p, d, a ); + } + catch(...) + { + d( p ); + + if( pi_ != 0 ) + { + a2.deallocate( static_cast< impl_type* >( pi_ ), 1 ); + } + + throw; + } + +#else + + pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) ); + + if( pi_ != 0 ) + { + new( static_cast< void* >( pi_ ) ) impl_type( p, d, a ); + } + else + { + d( p ); + boost::throw_exception( std::bad_alloc() ); + } + #endif } diff --git a/include/boost/detail/sp_counted_impl.hpp b/include/boost/detail/sp_counted_impl.hpp index 51093b5..51557db 100644 --- a/include/boost/detail/sp_counted_impl.hpp +++ b/include/boost/detail/sp_counted_impl.hpp @@ -176,6 +176,48 @@ public: #endif }; +template class sp_counted_impl_pda: public sp_counted_base +{ +private: + + P p_; // copy constructor must not throw + D d_; // copy constructor must not throw + A a_; // copy constructor must not throw + + sp_counted_impl_pda( sp_counted_impl_pda const & ); + sp_counted_impl_pda & operator= ( sp_counted_impl_pda const & ); + + typedef sp_counted_impl_pda this_type; + +public: + + // pre: d( p ) must not throw + + sp_counted_impl_pda( P p, D d, A a ): p_( p ), d_( d ), a_( a ) + { + } + + virtual void dispose() // nothrow + { + d_( p_ ); + } + + virtual void destroy() // nothrow + { + typedef typename A::template rebind< this_type >::other A2; + + A2 a2( a_ ); + + this->~this_type(); + a2.deallocate( this, 1 ); + } + + virtual void * get_deleter( std::type_info const & ti ) + { + return ti == typeid( D )? &d_: 0; + } +}; + #ifdef __CODEGUARD__ # pragma option pop #endif diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index de8c112..cb94325 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -146,6 +146,13 @@ public: boost::detail::sp_enable_shared_from_this( pn, p, p ); } + // As above, but with allocator. A's copy constructor shall not throw. + + template shared_ptr( Y * p, D d, A a ): px( p ), pn( p, d, a ) + { + boost::detail::sp_enable_shared_from_this( pn, p, p ); + } + // generated copy constructor, assignment, destructor are fine... // except that Borland C++ has a bug, and g++ with -Wsynth warns @@ -246,9 +253,14 @@ public: this_type(p).swap(*this); } - template void reset(Y * p, D d) + template void reset( Y * p, D d ) { - this_type(p, d).swap(*this); + this_type( p, d ).swap( *this ); + } + + template void reset( Y * p, D d, A a ) + { + this_type( p, d, a ).swap( *this ); } reference operator* () const // never throws