diff --git a/include/boost/smart_ptr/detail/local_counted_base.hpp b/include/boost/smart_ptr/detail/local_counted_base.hpp index 94a9b02..20ba3c2 100644 --- a/include/boost/smart_ptr/detail/local_counted_base.hpp +++ b/include/boost/smart_ptr/detail/local_counted_base.hpp @@ -32,7 +32,6 @@ class local_counted_base { private: - local_counted_base( local_counted_base const & ); local_counted_base & operator= ( local_counted_base const & ); private: @@ -48,11 +47,17 @@ public: { } - virtual ~local_counted_base() /*BOOST_NOEXCEPT*/ + BOOST_CONSTEXPR local_counted_base( local_counted_base const & ) BOOST_SP_NOEXCEPT: local_use_count_( initial_ ) { } - void add_ref() + virtual ~local_counted_base() /*BOOST_SP_NOEXCEPT*/ + { + } + + virtual void destroy() BOOST_SP_NOEXCEPT = 0; + + void add_ref() BOOST_SP_NOEXCEPT { #if defined( __has_builtin ) # if __has_builtin( __builtin_assume ) @@ -65,13 +70,13 @@ public: local_use_count_ = static_cast( local_use_count_ + 1 ); } - void release() + void release() BOOST_SP_NOEXCEPT { local_use_count_ = static_cast( local_use_count_ - 1 ); if( local_use_count_ == 0 ) { - delete this; + destroy(); } } @@ -83,6 +88,10 @@ public: class local_counted_impl: public local_counted_base { +private: + + local_counted_impl( local_counted_impl const & ); + private: boost::shared_ptr pn_; @@ -100,6 +109,23 @@ public: } #endif + + virtual void destroy() BOOST_SP_NOEXCEPT + { + delete this; + } +}; + +class local_counted_impl_em: public local_counted_base +{ +public: + + boost::shared_ptr pn_; + + virtual void destroy() BOOST_SP_NOEXCEPT + { + pn_.reset(); + } }; } // namespace detail diff --git a/include/boost/smart_ptr/local_shared_ptr.hpp b/include/boost/smart_ptr/local_shared_ptr.hpp index dcf2128..b2566b5 100644 --- a/include/boost/smart_ptr/local_shared_ptr.hpp +++ b/include/boost/smart_ptr/local_shared_ptr.hpp @@ -17,9 +17,86 @@ namespace boost { +template class local_shared_ptr; + namespace detail { +template class local_sp_deleter: public local_counted_impl_em +{ +private: + + D d_; + +public: + + local_sp_deleter(): d_() + { + } + + explicit local_sp_deleter( D const& d ) BOOST_SP_NOEXCEPT: d_( d ) + { + } + +#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) + + explicit local_sp_deleter( D&& d ) BOOST_SP_NOEXCEPT: d_( std::move(d) ) + { + } + +#endif + + template void operator()( Y* p ) const BOOST_SP_NOEXCEPT + { + d_( p ); + } +}; + +template< class E, class Y > inline void lsp_pointer_construct( boost::local_shared_ptr< E > * ppx, Y * p, boost::detail::local_counted_base * & pn ) +{ + boost::detail::sp_assert_convertible< Y, E >(); + + typedef boost::detail::local_sp_deleter< boost::checked_deleter > D; + + boost::shared_ptr p2( p, D() ); + + D * pd = static_cast< D * >( p2._internal_get_untyped_deleter() ); + + pd->pn_ = p2; + + pn = pd; +} + +template< class E, class Y > inline void lsp_pointer_construct( boost::local_shared_ptr< E[] > * ppx, Y * p, boost::detail::local_counted_base * & pn ) +{ + boost::detail::sp_assert_convertible< Y[], E[] >(); + + typedef boost::detail::local_sp_deleter< boost::checked_array_deleter > D; + + boost::shared_ptr p2( p, D() ); + + D * pd = static_cast< D * >( p2._internal_get_untyped_deleter() ); + + pd->pn_ = p2; + + pn = pd; +} + +template< class E, std::size_t N, class Y > inline void lsp_pointer_construct( boost::local_shared_ptr< E[N] > * ppx, Y * p, boost::detail::local_counted_base * & pn ) +{ + boost::detail::sp_assert_convertible< Y[N], E[N] >(); + + typedef boost::detail::local_sp_deleter< boost::checked_array_deleter > D; + + boost::shared_ptr p2( p, D() ); + + D * pd = static_cast< D * >( p2._internal_get_untyped_deleter() ); + + pd->pn_ = p2; + + pn = pd; +} + } // namespace detail // @@ -73,9 +150,9 @@ public: #endif template - explicit local_shared_ptr( Y * p ): px( p ), - pn( new boost::detail::local_counted_impl( shared_ptr( p ) ) ) + explicit local_shared_ptr( Y * p ): px( p ), pn( 0 ) { + boost::detail::lsp_pointer_construct( this, p, pn ); } template local_shared_ptr( Y * p, D d ): px( p ),