// // "$Id$" // // Copyright (c)1992-2011, ZheJiang Dahua Technology Stock CO.LTD. // All Rights Reserved. // // Description: // Revisions: Year-Month-Day SVN-Author Modification // #ifndef INFRA_SHARED_PTR_H__ #define INFRA_SHARED_PTR_H__ #include "Detail/smartptr_detail.h" #include "Detail/shared_count.h" #if defined(_MSC_VER) && (_MSC_VER < 1300) #define DAHUA_NO_CV_VOID_SPECIALIZATIONS #define DAHUA_NO_SFINAE #define DAHUA_NO_MEMBER_TEMPLATE_FRIENDS #endif namespace Dahua { namespace Memory { //////////////////////////////////////////////////////////////////////////////// namespace Detail { template struct shared_ptr_traits { typedef T & reference; }; template<> struct shared_ptr_traits { typedef void reference; }; #ifndef DAHUA_NO_CV_VOID_SPECIALIZATIONS template<> struct shared_ptr_traits { typedef void reference; }; template<> struct shared_ptr_traits { typedef void reference; }; template<> struct shared_ptr_traits { typedef void reference; }; #endif // rvalue auto_ptr support based on a technique by Dave Abrahams #ifndef DAHUA_NO_SFINAE template< class T, class R > struct sp_enable_if_auto_ptr { }; template< class T, class R > struct sp_enable_if_auto_ptr< std::auto_ptr< T >, R > { typedef R type; }; #endif template< class Y, class T > struct sp_convertible { typedef char (&yes) [1]; typedef char (&no) [2]; static yes f( T* ); static no f( ... ); enum _vt { value = sizeof( (f)( static_cast(0) ) ) == sizeof(yes) }; }; template< class Y, class T > inline void sp_assert_convertible() { typedef char tmp[ sp_convertible< Y, T >::value? 1: -1 ]; (void)sizeof( tmp ); } } // namespace Detail //////////////////////////////////////////////////////////////////////////////// template < class T > class TWeakPtr; template < class T > class TSharedPtr; template < class T > class TEnableSharedFromThis; template< class X, class Y, class T > inline void sp_enable_shared_from_this( TSharedPtr const * ppx, Y const * py, TEnableSharedFromThis< T > const * pe ) { if( pe != 0 ) { pe->_internal_accept_owner( ppx, const_cast< Y* >( py ) ); } } inline void sp_enable_shared_from_this( ... ) { } template< class T, class Y > inline void sp_pointer_construct( TSharedPtr< T > * ppx, Y * p, Detail::shared_count & pn ) { Detail::shared_count( p ).swap( pn ); sp_enable_shared_from_this( ppx, p, p ); } template class TSharedPtr // noncopyable { #ifdef DAHUA_NO_MEMBER_TEMPLATE_FRIENDS public: #else template friend class TSharedPtr; template friend class TWeakPtr; #endif T* px; // contained pointer Detail::shared_count pn; // reference counter public: typedef TSharedPtr this_type; typedef T element_type; typedef T value_type; typedef T * pointer; typedef typename Detail::shared_ptr_traits::reference reference; TSharedPtr(): px(0), pn() // never throws in 1.30+ { } template explicit TSharedPtr( Y * p ): px( p ), pn( ) // Y must be complete { sp_pointer_construct( this, p, pn ); } // // Requirements: D's copy constructor must not throw // // TSharedPtr will release p by calling d(p) // template TSharedPtr(Y * p, D d): px(p), pn(p, d) { } // As above, but with allocator. A's copy constructor shall not throw. template TSharedPtr( Y * p, D d, A a ): px( p ), pn( p, d, a ) { } // generated copy constructor, assignment, destructor are fine... // except that Borland C++ has a bug, and g++ with -Wsynth warns #if defined(__BORLANDC__) || defined(__GNUC__) TSharedPtr & operator=(TSharedPtr const & r) // never throws { px = r.px; pn = r.pn; // shared_count::op= doesn't throw return *this; } #endif template TSharedPtr(TSharedPtr const & r): px(r.px), pn(r.pn) // never throws { } // aliasing template< class Y > TSharedPtr( TSharedPtr const & r, T * p ): px( p ), pn( r.pn ) // never throws { } template TSharedPtr(TSharedPtr const & r, Detail::static_cast_tag): px(static_cast(r.px)), pn(r.pn) { } template TSharedPtr(TSharedPtr const & r, Detail::const_cast_tag): px(const_cast(r.px)), pn(r.pn) { } template TSharedPtr(TSharedPtr const & r, Detail::dynamic_cast_tag): px(dynamic_cast(r.px)), pn(r.pn) { if(px == 0) // need to allocate new counter -- the cast failed { pn = Detail::shared_count(); } } template TSharedPtr(TSharedPtr const & r, Detail::polymorphic_cast_tag): px(dynamic_cast(r.px)), pn(r.pn) { if(px == 0) { throw std::bad_cast(); } } template explicit TSharedPtr(std::auto_ptr & r): px(r.get()), pn() { Y * tmp = r.get(); pn = Detail::shared_count(r); } #ifndef DAHUA_NO_SFINAE template TSharedPtr( Ap r, typename Detail::sp_enable_if_auto_ptr::type = 0 ): px( r.get() ), pn() { typename Ap::element_type * tmp = r.get(); pn = Detail::shared_count( r ); } #endif template explicit TSharedPtr(TWeakPtr const & r): pn( r.m_pn ) // may throw { Detail::sp_assert_convertible< Y, T >(); px = r.m_ptr; } template explicit TSharedPtr( TWeakPtr const & r, Detail::sp_nothrow_tag ): px( 0 ), pn( r.m_pn ) // may throw { if ( !pn.empty() ) { px = r.m_ptr; } } template TSharedPtr & operator=(TSharedPtr const & r) // never throws { px = r.px; pn = r.pn; // shared_count::op= doesn't throw return *this; } template TSharedPtr & operator=( std::auto_ptr & r ) { this_type(r).swap(*this); return *this; } #ifndef DAHUA_NO_SFINAE template typename Detail::sp_enable_if_auto_ptr< Ap, TSharedPtr & >::type operator=( Ap r ) { this_type( r ).swap( *this ); return *this; } #endif void reset() // never throws in 1.30+ { this_type().swap(*this); } template void reset(Y * p) // Y must be complete { assert(p == 0 || p != px); // catch self-reset errors this_type(p).swap(*this); } template void reset( Y * p, D d ) { this_type( p, d ).swap( *this ); } template void reset( Y * p, D d, A a ) { this_type( p, d, a ).swap( *this ); } template void reset( TSharedPtr const & r, T * p ) { this_type( r, p ).swap( *this ); } reference operator* () const // never throws { assert(px != 0); return *px; } T * operator-> () const // never throws { assert(px != 0); return px; } T * get() const // never throws { return px; } // implicit conversion to "bool" typedef T * this_type::*unspecified_bool_type; operator unspecified_bool_type() const // never throws { return px == 0? 0: &this_type::px; } // operator! is redundant, but some compilers need it bool operator! () const // never throws { return px == 0; } bool unique() const // never throws { return pn.unique(); } long use_count() const // never throws { return pn.use_count(); } void swap(TSharedPtr & other) // never throws { std::swap(px, other.px); pn.swap(other.pn); } template bool _internal_less(TSharedPtr const & rhs) const { return pn < rhs.pn; } void * _internal_get_deleter(std::type_info const & ti) const { return pn.get_deleter(ti); } }; } // namespace Memory } // namespace Dahua //////////////////////////////////////////////////////////////////////////////// template inline bool operator==(Dahua::Memory::TSharedPtr const & a, Dahua::Memory::TSharedPtr const & b) { return a.get() == b.get(); } template inline bool operator!=(Dahua::Memory::TSharedPtr const & a, Dahua::Memory::TSharedPtr const & b) { return a.get() != b.get(); } #if __GNUC__ == 2 && __GNUC_MINOR__ <= 96 // Resolve the ambiguity between our op!= and the one in rel_ops template inline bool operator!=(Dahua::Memory::TSharedPtr const & a, Dahua::Memory::TSharedPtr const & b) { return a.get() != b.get(); } #endif template inline bool operator<(Dahua::Memory::TSharedPtr const & a, Dahua::Memory::TSharedPtr const & b) { return a._internal_less(b); } template inline void swap(Dahua::Memory::TSharedPtr & a, Dahua::Memory::TSharedPtr & b) { a.swap(b); } template Dahua::Memory::TSharedPtr static_pointer_cast(Dahua::Memory::TSharedPtr const & r) { return Dahua::Memory::TSharedPtr(r, Dahua::Memory::Detail::static_cast_tag()); } template Dahua::Memory::TSharedPtr const_pointer_cast(Dahua::Memory::TSharedPtr const & r) { return Dahua::Memory::TSharedPtr(r, Dahua::Memory::Detail::const_cast_tag()); } template Dahua::Memory::TSharedPtr dynamic_pointer_cast(Dahua::Memory::TSharedPtr const & r) { return Dahua::Memory::TSharedPtr(r, Dahua::Memory::Detail::dynamic_cast_tag()); } // get_pointer(p) is a generic way to say p.get() template inline T * get_pointer(Dahua::Memory::TSharedPtr const & p) { return p.get(); } // get_deleter template D * get_deleter(Dahua::Memory::TSharedPtr const & p) { return static_cast(p._internal_get_deleter(typeid(D))); } #endif // INFRA_SHARED_PTR_H__