/******************************************************************************/ /* POINTERS - INLINE CODE *****************************************************/ /******************************************************************************/ #ifndef _H_EBCL_INLINE_POINTERS #define _H_EBCL_INLINE_POINTERS #include namespace ebcl { /*= T_OwnPtr =================================================================*/ template< typename T > inline T_OwnPtr< T >::T_OwnPtr( T* p ) noexcept : p_( p ) { } template< typename T > inline T_OwnPtr< T >::T_OwnPtr( ) : T_OwnPtr( nullptr ) { } /*----------------------------------------------------------------------------*/ template< typename T > template< typename Q , T_EnableForChild< T , Q > > inline T_OwnPtr< T >::T_OwnPtr( T_OwnPtr< Q >&& source ) noexcept : p_( nullptr ) { T* temp( source.p_ ); source.p_ = nullptr; p_ = temp; } template< typename T > template< typename Q , T_EnableForParent< T , Q > > inline T_OwnPtr< T >::T_OwnPtr( T_OwnPtr< Q >&& source ) : p_( nullptr ) { T* temp( dynamic_cast< T* >( source.p_ ) ); if ( source.p_ && !temp ) { throw std::bad_cast( ); } source.p_ = nullptr; p_ = temp; } template< typename T > template< typename Q , T_EnableForChild< T , Q > > inline T_OwnPtr< T >& T_OwnPtr< T >::operator= ( T_OwnPtr< Q >&& source ) noexcept { T* temp( source.p_ ); clear( ); source.p_ = nullptr; p_ = temp; return *this; } template< typename T > template< typename Q , T_EnableForParent< T , Q > > inline T_OwnPtr< T >& T_OwnPtr< T >::operator= ( T_OwnPtr< Q >&& source ) { T* temp( dynamic_cast< T* >( source.p_ ) ); if ( source.p_ && !temp ) { throw std::bad_cast( ); } clear( ); source.p_ = nullptr; p_ = temp; return *this; } /*----------------------------------------------------------------------------*/ template< typename T > inline T_OwnPtr< T >::~T_OwnPtr( ) { clear( ); } /*----------------------------------------------------------------------------*/ template< typename T > inline void swap( T_OwnPtr< T >& lhs , T_OwnPtr< T >& rhs ) noexcept { std::swap( lhs.p_ , rhs.p_ ); } /*----------------------------------------------------------------------------*/ template< typename T > inline void T_OwnPtr< T >::clear( ) { T* ptr( nullptr ); std::swap( p_ , ptr ); delete ptr; } /*----------------------------------------------------------------------------*/ template< typename T > inline bool T_OwnPtr< T >::operator== ( const T* p ) const { return p == p_; } template< typename T > inline bool T_OwnPtr< T >::operator!= ( const T* p ) const { return p != p_; } template< typename T > inline T_OwnPtr< T >::operator bool ( ) const { return p_ != nullptr; } template< typename T > inline bool T_OwnPtr< T >::operator! ( ) const { return p_ == nullptr; } /*----------------------------------------------------------------------------*/ template< typename T > inline T* T_OwnPtr< T >::get( ) const { return p_; } template< typename T > inline T* T_OwnPtr< T >::operator-> ( ) const { assert( p_ != nullptr ); return p_; } template< typename T > inline T& T_OwnPtr< T >::operator* ( ) const { assert( p_ != nullptr ); return *p_; } /*----------------------------------------------------------------------------*/ template< typename T > inline T_SharedPtr< T > T_OwnPtr< T >::makeShared( ) { T* temp( nullptr ); std::swap( p_ , temp ); return T_SharedPtr< T >( temp ); } /*= NewOwned / OwnRawPointer =================================================*/ template< typename Type , typename... ArgTypes > inline T_OwnPtr< Type > NewOwned( ArgTypes&& ... arguments ) { return T_OwnPtr< Type >( new Type( std::forward< ArgTypes >( arguments ) ... ) ); } template< typename Type > inline T_OwnPtr< Type > OwnRawPointer( Type*& pointer ) noexcept { assert( pointer != nullptr ); T_OwnPtr< Type > p( pointer ); pointer = nullptr; return p; } template< typename Type , typename Other , T_EnableForChild< Type , Other > > inline T_OwnPtr< Type > OwnRawPointer( Other*& pointer ) noexcept { assert( pointer != nullptr ); T_OwnPtr< Type > p( pointer ); pointer = nullptr; return p; } template< typename Type , typename Other , T_EnableForParent< Type , Other > > inline T_OwnPtr< Type > OwnRawPointer( Other*& pointer ) { assert( pointer != nullptr ); Type* temp( dynamic_cast< Type* >( pointer ) ); if ( temp == nullptr ) { throw std::bad_cast( ); } T_OwnPtr< Type > p( temp ); pointer = nullptr; return p; } /*= T_Reference_ =============================================================*/ // Reference counter for shared pointers class T_Reference_ { private: typedef std::function< void ( void* ) > F_Destr_; friend struct T_WeakChain_; void* pointer_; F_Destr_ destr_; uint32_t count_; T_WeakChain_* weaks_; public: /* References are pooled */ void* operator new( size_t count ) noexcept; void operator delete( void* object ) noexcept; T_Reference_( ) = delete; T_Reference_( T_Reference_ const& ) = delete; T_Reference_( T_Reference_&& ) = delete; T_Reference_( void* ptr , F_Destr_ destructor ); ~T_Reference_( ); void* pointer( ) const; T_Reference_ * increase( ); void decrease( ); void* extract( ); }; /*----------------------------------------------------------------------------*/ inline void* T_Reference_::pointer( ) const { return pointer_; } inline T_Reference_* T_Reference_::increase( ) { assert( count_ > 0 ); count_ ++; return this; } inline void T_Reference_::decrease( ) { assert( count_ > 0 ); count_ --; if ( count_ == 0 ) { delete this; } } /*= T_BasePtr_ ===============================================================*/ template< typename T > inline T_BasePtr_< T >::T_BasePtr_( T_Reference_* ref ) noexcept : ref_( ref ) { } template< typename T > inline T_BasePtr_< T >::operator bool ( ) const { return ref_ != nullptr; } template< typename T > inline bool T_BasePtr_< T >::operator! ( ) const { return ref_ == nullptr; } template< typename T > inline T* T_BasePtr_< T >::operator-> ( ) const { assert( ref_ != nullptr ); return reinterpret_cast< T* >( ref_->pointer( ) ); } template< typename T > inline T_BasePtr_< T >::operator T* ( ) const { return ref_ == nullptr ? nullptr : reinterpret_cast< T* >( ref_->pointer( ) ); } template< typename T > inline T& T_BasePtr_< T >::operator* ( ) const { assert( ref_ != nullptr ); return *reinterpret_cast< T* >( ref_->pointer( ) ); } /*= X_TooManyReferences ======================================================*/ inline X_TooManyReferences::X_TooManyReferences( ) : std::runtime_error( "too many references" ) { } /*= T_SharedPtr ==============================================================*/ template< typename T > inline T_Reference_* T_SharedPtr< T >::setRef( T_Reference_* from ) { if ( from == nullptr ) { return nullptr; } return from->increase( ); } template< typename T > inline void T_SharedPtr< T >::clearRef( ) { if ( ref_ != nullptr ) { ref_->decrease( ); } } /*----------------------------------------------------------------------------*/ template< typename T > inline T_SharedPtr< T >::T_SharedPtr( T* ptr ) : T_Base_( new T_Reference_( ptr , []( void* p ) { delete reinterpret_cast< T* >( p ); } ) ) { } template< typename T > inline T_SharedPtr< T >::T_SharedPtr( ) noexcept : T_Base_( nullptr ) { } template< typename T > inline T_SharedPtr< T >::~T_SharedPtr( ) { clearRef( ); } /*----------------------------------------------------------------------------*/ template< typename T > inline T_SharedPtr< T >::T_SharedPtr( T_Self_ const& source ) : T_Base_( setRef( source.ref_ ) ) { } template< typename T > template< typename Q , T_EnableForChild< T , Q > > inline T_SharedPtr< T >::T_SharedPtr( T_SharedPtr< Q > const& other ) : T_Base_( setRef( other.ref_ ) ) { } template< typename T > template< typename Q , T_EnableForParent< T , Q > > inline T_SharedPtr< T >::T_SharedPtr( T_SharedPtr< Q > const& other ) : T_Base_( nullptr ) { Q* const p( other ); if ( p != nullptr && dynamic_cast< T* >( p ) == nullptr ) { throw std::bad_cast( ); } ref_ = setRef( other.ref_ ); } /*----------------------------------------------------------------------------*/ template< typename T > template< typename Q , T_EnableForChild< T , Q > > inline T_SharedPtr< T >::T_SharedPtr( T_SharedPtr< Q >&& other ) noexcept : T_Base_( other.ref_ ) { other.ref_ = nullptr; } template< typename T > template< typename Q , T_EnableForParent< T , Q > > inline T_SharedPtr< T >::T_SharedPtr( T_SharedPtr< Q >&& other ) : T_Base_( nullptr ) { Q* const p( other ); if ( p != nullptr && dynamic_cast< T* >( p ) == nullptr ) { throw std::bad_cast( ); } using std::swap; swap( ref_ , other.ref_ ); } /*----------------------------------------------------------------------------*/ template< typename T > inline T_SharedPtr< T >& T_SharedPtr< T >::operator= ( T_SharedPtr< T > const& other ) { if ( &other != this && other.ref_ != ref_ ) { clearRef( ); ref_ = setRef( other.ref_ ); } return *this; } template< typename T > template< typename Q , T_EnableForChild< T , Q > > inline T_SharedPtr< T >& T_SharedPtr< T >::operator= ( T_SharedPtr< Q > const& other ) { if ( other.ref_ != ref_ ) { clearRef( ); ref_ = setRef( other.ref_ ); } return *this; } template< typename T > template< typename Q , T_EnableForParent< T , Q > > inline T_SharedPtr< T >& T_SharedPtr< T >::operator= ( T_SharedPtr< Q > const& other ) { if ( other.ref_ != ref_ ) { Q* const p( other ); if ( p != nullptr && dynamic_cast< T* >( p ) == nullptr ) { throw std::bad_cast( ); } clearRef( ); ref_ = setRef( other.ref_ ); } return *this; } /*----------------------------------------------------------------------------*/ template< typename T > template< typename Q , T_EnableForChild< T , Q > > inline T_SharedPtr< T >& T_SharedPtr< T >::operator= ( T_SharedPtr< Q >&& other ) noexcept { if ( other.ref_ != ref_ ) { clearRef( ); ref_ = nullptr; std::swap( ref_ , other.ref_ ); } return *this; } template< typename T > template< typename Q , T_EnableForParent< T , Q > > inline T_SharedPtr< T >& T_SharedPtr< T >::operator= ( T_SharedPtr< Q >&& other ) { if ( other.ref_ != ref_ ) { Q* const p( other ); if ( p != nullptr && dynamic_cast< T* >( p ) == nullptr ) { throw std::bad_cast( ); } clearRef( ); ref_ = nullptr; std::swap( ref_ , other.ref_ ); } return *this; } /*----------------------------------------------------------------------------*/ template< typename T > inline void swap( T_SharedPtr< T >& lhs , T_SharedPtr< T >& rhs ) noexcept { std::swap( lhs.ref_ , rhs.ref_ ); } /*----------------------------------------------------------------------------*/ template< typename T > inline bool T_SharedPtr< T >::operator== ( T_SharedPtr< T > const& other ) const { return other.ref_ == ref_; } template< typename T > inline bool T_SharedPtr< T >::operator!= ( T_SharedPtr< T > const& other ) const { return other.ref_ != ref_; } template< typename T > inline bool T_SharedPtr< T >::operator== ( T_WeakPtr< T > const& other ) const { return other.ref_ == ref_; } template< typename T > inline bool T_SharedPtr< T >::operator!= ( T_WeakPtr< T > const& other ) const { return other.ref_ != ref_; } template< typename T > inline void T_SharedPtr< T >::clear( ) { clearRef( ); ref_ = nullptr; } template< typename T > T_OwnPtr< T > T_SharedPtr< T >::makeOwned( ) { if ( ref_ == nullptr ) { return T_OwnPtr< T >( ); } void* const p( ref_->extract( ) ); ref_ = nullptr; return T_OwnPtr< T >( reinterpret_cast< T* >( p ) ); } /*= T_WeakPtr ================================================================*/ template< typename T > inline T_WeakPtr< T >::T_WeakPtr( T_Reference_* ref ) : T_BasePtr_< T >( ref ) , chain_( ref_ ) { chain_.init( ); } template< typename T > inline T_WeakPtr< T >::T_WeakPtr( ) : T_WeakPtr( nullptr ) { } template< typename T > inline T_WeakPtr< T >::~T_WeakPtr( ) { chain_.unchain( ); } /*----------------------------------------------------------------------------*/ template< typename T > inline T_WeakPtr< T >::T_WeakPtr( T_WeakPtr< T > const& other ) : T_WeakPtr( other.ref_ ) { } template< typename T > template< typename Q , T_EnableForChild< T , Q > > inline T_WeakPtr< T >::T_WeakPtr( T_WeakPtr< Q > const& other ) : T_WeakPtr( other.ref_ ) { } template< typename T > template< typename Q , T_EnableForParent< T , Q > > inline T_WeakPtr< T >::T_WeakPtr( T_WeakPtr< Q > const& other ) : T_WeakPtr( ) { Q* const p( other ); if ( p != nullptr && dynamic_cast< T* >( p ) == nullptr ) { throw std::bad_cast( ); } ref_ = other.ref_; chain_.init( ); } /*----------------------------------------------------------------------------*/ template< typename T > template< typename Q , T_EnableForChild< T , Q > > inline T_WeakPtr< T >::T_WeakPtr( T_WeakPtr< Q >&& other ) noexcept : T_WeakPtr( nullptr ) { other.chain_.unchain( ); ref_ = other.ref_; other.ref_ = nullptr; chain_.init( ); } template< typename T > template< typename Q , T_EnableForParent< T , Q > > inline T_WeakPtr< T >::T_WeakPtr( T_WeakPtr< Q >&& other ) : T_WeakPtr( nullptr ) { Q* const p( other ); if ( p != nullptr && dynamic_cast< T* >( p ) == nullptr ) { throw std::bad_cast( ); } other.chain_.unchain( ); ref_ = other.ref_; other.ref_ = nullptr; chain_.init( ); } /*----------------------------------------------------------------------------*/ template< typename T > inline T_WeakPtr< T >::T_WeakPtr( T_SharedPtr< T > const& shared ) : T_WeakPtr( shared.ref_ ) { } template< typename T > template< typename Q , T_EnableForChild< T , Q > > inline T_WeakPtr< T >::T_WeakPtr( T_SharedPtr< Q > const& shared ) : T_WeakPtr( shared.ref_ ) { } template< typename T > template< typename Q , T_EnableForParent< T , Q > > inline T_WeakPtr< T >::T_WeakPtr( T_SharedPtr< Q > const& shared ) : T_WeakPtr( nullptr ) { Q* const p( shared ); if ( p != nullptr && dynamic_cast< T* >( p ) == nullptr ) { throw std::bad_cast( ); } ref_ = shared.ref_; chain_.init( ); } /*----------------------------------------------------------------------------*/ template< typename T > inline void swap( T_WeakPtr< T >& lhs , T_WeakPtr< T >& rhs ) { if ( lhs.ref_ != rhs.ref_ ) { lhs.chain_.unchain( ); rhs.chain_.unchain( ); std::swap( lhs.ref_ , rhs.ref_ ); lhs.chain_.init( ); rhs.chain_.init( ); } } /*----------------------------------------------------------------------------*/ template< typename T > inline T_WeakPtr< T >& T_WeakPtr< T >::operator= ( T_WeakPtr< T > const& other ) { chain_.unchain( ); ref_ = other.ref_; chain_.init( ); return *this; } template< typename T > template< typename Q , T_EnableForChild< T , Q > > inline T_WeakPtr< T >& T_WeakPtr< T >::operator= ( T_WeakPtr< Q > const& other ) { chain_.unchain( ); ref_ = other.ref_; chain_.init( ); return *this; } template< typename T > template< typename Q , T_EnableForParent< T , Q > > inline T_WeakPtr< T >& T_WeakPtr< T >::operator= ( T_WeakPtr< Q > const& other ) { Q* const p( other ); if ( p != nullptr && dynamic_cast< T* >( p ) == nullptr ) { throw std::bad_cast( ); } chain_.unchain( ); ref_ = other.ref_; chain_.init( ); return *this; } /*----------------------------------------------------------------------------*/ template< typename T > template< typename Q , T_EnableForChild< T , Q > > inline T_WeakPtr< T >& T_WeakPtr< T >::operator= ( T_WeakPtr< Q >&& other ) { ref_ = nullptr; chain_.unchain( ); if ( other.ref_ ) { other.chain_.unchain( ); ref_ = other.ref_; other.ref_ = nullptr; chain_.init( ); other.chain_.init( ); } return *this; } template< typename T > template< typename Q , T_EnableForParent< T , Q > > inline T_WeakPtr< T >& T_WeakPtr< T >::operator= ( T_WeakPtr< Q >&& other ) { Q* const p( other ); if ( p != nullptr && dynamic_cast< T* >( p ) == nullptr ) { throw std::bad_cast( ); } ref_ = nullptr; chain_.unchain( ); if ( other.ref_ ) { other.chain_.unchain( ); ref_ = other.ref_; other.ref_ = nullptr; chain_.init( ); other.chain_.init( ); } return *this; } /*----------------------------------------------------------------------------*/ template< typename T > inline T_WeakPtr< T >& T_WeakPtr< T >::operator= ( T_SharedPtr< T > const& shared ) { chain_.unchain( ); ref_ = shared.ref_; chain_.init( ); return *this; } template< typename T > template< typename Q , T_EnableForChild< T , Q > > inline T_WeakPtr< T >& T_WeakPtr< T >::operator= ( T_SharedPtr< Q > const& shared ) { chain_.unchain( ); ref_ = shared.ref_; chain_.init( ); return *this; } template< typename T > template< typename Q , T_EnableForParent< T , Q > > inline T_WeakPtr< T >& T_WeakPtr< T >::operator= ( T_SharedPtr< Q > const& shared ) { Q* const p( shared ); if ( p != nullptr && dynamic_cast< T* >( p ) == nullptr ) { throw std::bad_cast( ); } chain_.unchain( ); ref_ = shared.ref_; chain_.init( ); return *this; } /*----------------------------------------------------------------------------*/ template< typename T > inline bool T_WeakPtr< T >::operator== ( T_WeakPtr< T > const& other ) const { return other.ref_ == ref_; } template< typename T > inline bool T_WeakPtr< T >::operator!= ( T_WeakPtr< T > const& other ) const { return other.ref_ != ref_; } template< typename T > inline bool T_WeakPtr< T >::operator== ( T_SharedPtr< T > const& other ) const { return other.ref_ == ref_; } template< typename T > inline bool T_WeakPtr< T >::operator!= ( T_SharedPtr< T > const& other ) const { return other.ref_ != ref_; } /*----------------------------------------------------------------------------*/ template< typename T > inline void T_WeakPtr< T >::clear( ) { chain_.unchain( ); ref_ = nullptr; } /*= NewShared ================================================================*/ template< typename Type , typename... ArgTypes > inline T_SharedPtr< Type > NewShared( ArgTypes&& ... arguments ) { return T_SharedPtr< Type >( new Type( std::forward< ArgTypes >( arguments ) ... ) ); } template< typename Type > T_SharedPtr< Type > ShareRawPointer( Type*& pointer ) noexcept { assert( pointer != nullptr ); T_SharedPtr< Type > p( pointer ); pointer = nullptr; return p; } template< typename Type , typename Other , T_EnableForChild< Type , Other > > inline T_SharedPtr< Type > ShareRawPointer( Other*& pointer ) noexcept { assert( pointer != nullptr ); T_SharedPtr< Type > p( pointer ); pointer = nullptr; return p; } template< typename Type , typename Other , T_EnableForParent< Type , Other > > inline T_SharedPtr< Type > ShareRawPointer( Other*& pointer ) { assert( pointer != nullptr ); Type* temp( dynamic_cast< Type* >( pointer ) ); if ( temp == nullptr ) { throw std::bad_cast( ); } T_SharedPtr< Type > p( temp ); pointer = nullptr; return p; } } // namespace #endif // _H_EBCL_INLINE_POINTERS