#ifndef BOOST_SMART_PTR_LOCAL_SHARED_PTR_HPP_INCLUDED #define BOOST_SMART_PTR_LOCAL_SHARED_PTR_HPP_INCLUDED // local_shared_ptr.hpp // // Copyright 2017 Peter Dimov // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // See http://www.boost.org/libs/smart_ptr/ for documentation. #include namespace boost { template class local_shared_ptr; namespace detail { 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._internal_count(); 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._internal_count(); 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._internal_count(); pn = pd; } template< class E, class P, class D > inline void lsp_deleter_construct( boost::local_shared_ptr< E > * /*ppx*/, P p, D const& d, boost::detail::local_counted_base * & pn ) { typedef boost::detail::local_sp_deleter D2; boost::shared_ptr p2( p, D2( d ) ); D2 * pd = static_cast< D2 * >( p2._internal_get_untyped_deleter() ); pd->pn_ = p2._internal_count(); pn = pd; } template< class E, class P, class D, class A > inline void lsp_allocator_construct( boost::local_shared_ptr< E > * /*ppx*/, P p, D const& d, A const& a, boost::detail::local_counted_base * & pn ) { typedef boost::detail::local_sp_deleter D2; boost::shared_ptr p2( p, D2( d ), a ); D2 * pd = static_cast< D2 * >( p2._internal_get_untyped_deleter() ); pd->pn_ = p2._internal_count(); pn = pd; } struct lsp_internal_constructor_tag { }; } // namespace detail // // local_shared_ptr // // as shared_ptr, but local to a thread. // reference count manipulations are non-atomic. // template class local_shared_ptr { private: typedef local_shared_ptr this_type; public: typedef typename boost::detail::sp_element::type element_type; private: element_type * px; boost::detail::local_counted_base * pn; template friend class local_shared_ptr; public: // destructor ~local_shared_ptr() BOOST_SP_NOEXCEPT { if( pn ) { pn->release(); } } // constructors BOOST_CONSTEXPR local_shared_ptr() BOOST_SP_NOEXCEPT : px( 0 ), pn( 0 ) { } #if !defined( BOOST_NO_CXX11_NULLPTR ) BOOST_CONSTEXPR local_shared_ptr( boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT : px( 0 ), pn( 0 ) { } #endif // internal constructor, used by make_shared BOOST_CONSTEXPR local_shared_ptr( boost::detail::lsp_internal_constructor_tag, element_type * px_, boost::detail::local_counted_base * pn_ ) BOOST_SP_NOEXCEPT : px( px_ ), pn( pn_ ) { } template 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 ), pn( 0 ) { boost::detail::lsp_deleter_construct( this, p, d, pn ); } #if !defined( BOOST_NO_CXX11_NULLPTR ) template local_shared_ptr( boost::detail::sp_nullptr_t p, D d ): px( p ), pn( 0 ) { boost::detail::lsp_deleter_construct( this, p, d, pn ); } #endif template local_shared_ptr( Y * p, D d, A a ): px( p ), pn( 0 ) { boost::detail::lsp_allocator_construct( this, p, d, a, pn ); } #if !defined( BOOST_NO_CXX11_NULLPTR ) template local_shared_ptr( boost::detail::sp_nullptr_t p, D d, A a ): px( p ), pn( 0 ) { boost::detail::lsp_allocator_construct( this, p, d, a, pn ); } #endif // construction from shared_ptr template local_shared_ptr( shared_ptr const & r, typename boost::detail::sp_enable_if_convertible::type = boost::detail::sp_empty() ) : px( r.get() ), pn( 0 ) { boost::detail::sp_assert_convertible< Y, T >(); if( r.use_count() != 0 ) { pn = new boost::detail::local_counted_impl( r._internal_count() ); } } #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) template local_shared_ptr( shared_ptr && r, typename boost::detail::sp_enable_if_convertible::type = boost::detail::sp_empty() ) : px( r.get() ), pn( 0 ) { boost::detail::sp_assert_convertible< Y, T >(); if( r.use_count() != 0 ) { pn = new boost::detail::local_counted_impl( r._internal_count() ); r.reset(); } } #endif // construction from unique_ptr #if !defined( BOOST_NO_CXX11_SMART_PTR ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) template< class Y, class D > local_shared_ptr( std::unique_ptr< Y, D > && r, typename boost::detail::sp_enable_if_convertible::type = boost::detail::sp_empty() ) : px( r.get() ), pn( 0 ) { boost::detail::sp_assert_convertible< Y, T >(); if( px ) { pn = new boost::detail::local_counted_impl( shared_ptr( std::move(r) )._internal_count() ); } } #endif template< class Y, class D > local_shared_ptr( boost::movelib::unique_ptr< Y, D > r ); // ! // : px( r.get() ), pn( new boost::detail::local_counted_impl( shared_ptr( std::move(r) ) ) ) //{ // boost::detail::sp_assert_convertible< Y, T >(); //} // copy constructor local_shared_ptr( local_shared_ptr const & r ) BOOST_SP_NOEXCEPT : px( r.px ), pn( r.pn ) { if( pn ) { pn->add_ref(); } } // move constructor #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) local_shared_ptr( local_shared_ptr && r ) BOOST_SP_NOEXCEPT : px( r.px ), pn( r.pn ) { r.px = 0; r.pn = 0; } #endif // converting copy constructor template local_shared_ptr( local_shared_ptr const & r, typename boost::detail::sp_enable_if_convertible::type = boost::detail::sp_empty() ) BOOST_SP_NOEXCEPT : px( r.px ), pn( r.pn ) { boost::detail::sp_assert_convertible< Y, T >(); if( pn ) { pn->add_ref(); } } // converting move constructor #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) template local_shared_ptr( local_shared_ptr && r, typename boost::detail::sp_enable_if_convertible::type = boost::detail::sp_empty() ) BOOST_SP_NOEXCEPT : px( r.px ), pn( r.pn ) { boost::detail::sp_assert_convertible< Y, T >(); r.px = 0; r.pn = 0; } #endif // aliasing template local_shared_ptr( local_shared_ptr const & r, element_type * p ) BOOST_SP_NOEXCEPT : px( p ), pn( r.pn ) { if( pn ) { pn->add_ref(); } } #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) template local_shared_ptr( local_shared_ptr && r, element_type * p ) BOOST_SP_NOEXCEPT : px( p ), pn( r.pn ) { r.px = 0; r.pn = 0; } #endif // assignment local_shared_ptr & operator=( local_shared_ptr const & r ) BOOST_SP_NOEXCEPT { local_shared_ptr( r ).swap( *this ); return *this; } template local_shared_ptr & operator=( local_shared_ptr const & r ) BOOST_SP_NOEXCEPT { local_shared_ptr( r ).swap( *this ); return *this; } #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) local_shared_ptr & operator=( local_shared_ptr && r ) BOOST_SP_NOEXCEPT { local_shared_ptr( std::move( r ) ).swap( *this ); return *this; } template local_shared_ptr & operator=( local_shared_ptr && r ) BOOST_SP_NOEXCEPT { local_shared_ptr( std::move( r ) ).swap( *this ); return *this; } #endif #if !defined( BOOST_NO_CXX11_NULLPTR ) local_shared_ptr & operator=( boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT { local_shared_ptr().swap(*this); return *this; } #endif #if !defined( BOOST_NO_CXX11_SMART_PTR ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) template local_shared_ptr & operator=( std::unique_ptr && r ) { local_shared_ptr( std::move(r) ).swap( *this ); return *this; } #endif template local_shared_ptr & operator=( boost::movelib::unique_ptr r ); // ! // reset void reset() BOOST_SP_NOEXCEPT { local_shared_ptr().swap( *this ); } template void reset( Y * p ) // Y must be complete { local_shared_ptr( p ).swap( *this ); } template void reset( Y * p, D d ) { local_shared_ptr( p, d ).swap( *this ); } template void reset( Y * p, D d, A a ) { local_shared_ptr( p, d, a ).swap( *this ); } template void reset( local_shared_ptr const & r, element_type * p ) BOOST_SP_NOEXCEPT { local_shared_ptr( r, p ).swap( *this ); } #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) template void reset( local_shared_ptr && r, element_type * p ) BOOST_SP_NOEXCEPT { local_shared_ptr( std::move( r ), p ).swap( *this ); } #endif // accessors typename boost::detail::sp_dereference< T >::type operator* () const BOOST_SP_NOEXCEPT { return *px; } typename boost::detail::sp_member_access< T >::type operator-> () const BOOST_SP_NOEXCEPT { return px; } typename boost::detail::sp_array_access< T >::type operator[] ( std::ptrdiff_t i ) const BOOST_SP_NOEXCEPT_WITH_ASSERT { BOOST_ASSERT( px != 0 ); BOOST_ASSERT( i >= 0 && ( i < boost::detail::sp_extent< T >::value || boost::detail::sp_extent< T >::value == 0 ) ); return static_cast< typename boost::detail::sp_array_access< T >::type >( px[ i ] ); } element_type * get() const BOOST_SP_NOEXCEPT { return px; } // implicit conversion to "bool" #include long local_use_count() const BOOST_SP_NOEXCEPT { return pn? pn->local_use_count(): 0; } // conversions to shared_ptr, weak_ptr #if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) && !defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) template::type> operator shared_ptr() const BOOST_SP_NOEXCEPT #else template operator shared_ptr() const BOOST_SP_NOEXCEPT #endif { boost::detail::sp_assert_convertible(); if( pn ) { return shared_ptr( boost::detail::sp_internal_constructor_tag(), px, pn->local_cb_get_shared_count() ); } else { return shared_ptr(); } } #if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) && !defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) template::type> operator weak_ptr() const BOOST_SP_NOEXCEPT #else template operator weak_ptr() const BOOST_SP_NOEXCEPT #endif { boost::detail::sp_assert_convertible(); if( pn ) { return shared_ptr( boost::detail::sp_internal_constructor_tag(), px, pn->local_cb_get_shared_count() ); } else { return weak_ptr(); } } // swap void swap( local_shared_ptr & r ) BOOST_SP_NOEXCEPT { std::swap( px, r.px ); std::swap( pn, r.pn ); } // owner_before template bool owner_before( local_shared_ptr const & r ) const BOOST_SP_NOEXCEPT { return std::less< boost::detail::local_counted_base* >()( pn, r.pn ); } }; template inline bool operator==( local_shared_ptr const & a, local_shared_ptr const & b ) BOOST_SP_NOEXCEPT { return a.get() == b.get(); } template inline bool operator!=( local_shared_ptr const & a, local_shared_ptr const & b ) BOOST_SP_NOEXCEPT { return a.get() != b.get(); } #if !defined( BOOST_NO_CXX11_NULLPTR ) template inline bool operator==( local_shared_ptr const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT { return p.get() == 0; } template inline bool operator==( boost::detail::sp_nullptr_t, local_shared_ptr const & p ) BOOST_SP_NOEXCEPT { return p.get() == 0; } template inline bool operator!=( local_shared_ptr const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT { return p.get() != 0; } template inline bool operator!=( boost::detail::sp_nullptr_t, local_shared_ptr const & p ) BOOST_SP_NOEXCEPT { return p.get() != 0; } #endif template inline bool operator==( local_shared_ptr const & a, shared_ptr const & b ) BOOST_SP_NOEXCEPT { return a.get() == b.get(); } template inline bool operator!=( local_shared_ptr const & a, shared_ptr const & b ) BOOST_SP_NOEXCEPT { return a.get() != b.get(); } template inline bool operator==( shared_ptr const & a, local_shared_ptr const & b ) BOOST_SP_NOEXCEPT { return a.get() == b.get(); } template inline bool operator!=( shared_ptr const & a, local_shared_ptr const & b ) BOOST_SP_NOEXCEPT { return a.get() != b.get(); } template inline bool operator<(local_shared_ptr const & a, local_shared_ptr const & b) BOOST_SP_NOEXCEPT { return a.owner_before( b ); } template inline void swap( local_shared_ptr & a, local_shared_ptr & b ) BOOST_SP_NOEXCEPT { a.swap( b ); } template local_shared_ptr static_pointer_cast( local_shared_ptr const & r ) BOOST_SP_NOEXCEPT { (void) static_cast< T* >( static_cast< U* >( 0 ) ); typedef typename local_shared_ptr::element_type E; E * p = static_cast< E* >( r.get() ); return local_shared_ptr( r, p ); } template local_shared_ptr const_pointer_cast( local_shared_ptr const & r ) BOOST_SP_NOEXCEPT { (void) const_cast< T* >( static_cast< U* >( 0 ) ); typedef typename local_shared_ptr::element_type E; E * p = const_cast< E* >( r.get() ); return local_shared_ptr( r, p ); } template local_shared_ptr dynamic_pointer_cast( local_shared_ptr const & r ) BOOST_SP_NOEXCEPT { (void) dynamic_cast< T* >( static_cast< U* >( 0 ) ); typedef typename local_shared_ptr::element_type E; E * p = dynamic_cast< E* >( r.get() ); return p? local_shared_ptr( r, p ): local_shared_ptr(); } template local_shared_ptr reinterpret_pointer_cast( local_shared_ptr const & r ) BOOST_SP_NOEXCEPT { (void) reinterpret_cast< T* >( static_cast< U* >( 0 ) ); typedef typename local_shared_ptr::element_type E; E * p = reinterpret_cast< E* >( r.get() ); return local_shared_ptr( r, p ); } #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) template local_shared_ptr static_pointer_cast( local_shared_ptr && r ) BOOST_SP_NOEXCEPT { (void) static_cast< T* >( static_cast< U* >( 0 ) ); typedef typename local_shared_ptr::element_type E; E * p = static_cast< E* >( r.get() ); return local_shared_ptr( std::move(r), p ); } template local_shared_ptr const_pointer_cast( local_shared_ptr && r ) BOOST_SP_NOEXCEPT { (void) const_cast< T* >( static_cast< U* >( 0 ) ); typedef typename local_shared_ptr::element_type E; E * p = const_cast< E* >( r.get() ); return local_shared_ptr( std::move(r), p ); } template local_shared_ptr dynamic_pointer_cast( local_shared_ptr && r ) BOOST_SP_NOEXCEPT { (void) dynamic_cast< T* >( static_cast< U* >( 0 ) ); typedef typename local_shared_ptr::element_type E; E * p = dynamic_cast< E* >( r.get() ); return p? local_shared_ptr( std::move(r), p ): local_shared_ptr(); } template local_shared_ptr reinterpret_pointer_cast( local_shared_ptr && r ) BOOST_SP_NOEXCEPT { (void) reinterpret_cast< T* >( static_cast< U* >( 0 ) ); typedef typename local_shared_ptr::element_type E; E * p = reinterpret_cast< E* >( r.get() ); return local_shared_ptr( std::move(r), p ); } #endif // !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) // get_pointer() enables boost::mem_fn to recognize local_shared_ptr template inline typename local_shared_ptr::element_type * get_pointer( local_shared_ptr const & p ) BOOST_SP_NOEXCEPT { return p.get(); } // operator<< #if !defined(BOOST_NO_IOSTREAM) template std::basic_ostream & operator<< ( std::basic_ostream & os, local_shared_ptr const & p ) { os << p.get(); return os; } #endif // !defined(BOOST_NO_IOSTREAM) // get_deleter template D * get_deleter( local_shared_ptr const & p ) BOOST_SP_NOEXCEPT { return get_deleter( shared_ptr( p ) ); } // hash_value template< class T > struct hash; template< class T > std::size_t hash_value( local_shared_ptr const & p ) BOOST_SP_NOEXCEPT { return boost::hash< typename local_shared_ptr::element_type* >()( p.get() ); } } // namespace boost #endif // #ifndef BOOST_SMART_PTR_LOCAL_SHARED_PTR_HPP_INCLUDED