/******************************************************************************/ /* REFERENCE-COUNTING HELPERS - INLINE CODE ***********************************/ /******************************************************************************/ #ifndef _H_EBCL_INLINE_REFCOUNT #define _H_EBCL_INLINE_REFCOUNT #include namespace ebcl { /*= T_ReferenceCountedClass ==================================================*/ template< bool B > inline T_ReferenceCountedClass< B >::T_ReferenceCountedClass( ) noexcept : referenceCounter_{ 0 } { } template< bool B > inline void T_ReferenceCountedClass< B >::increaseReferences_( ) noexcept { referenceCounter_ ++; } template< bool B > inline bool T_ReferenceCountedClass< B >::decreaseReferences_( ) noexcept { return ( -- referenceCounter_ ) == 0; } template< bool B > inline uint32_t T_ReferenceCountedClass< B >::getReferenceCount( ) const noexcept { return uint32_t{ referenceCounter_ }; } /*= T_RcPtr ==================================================================*/ template< typename T > inline T_RcPtr< T >::T_RcPtr( ) noexcept : target_{ nullptr } { } template< typename T > inline T_RcPtr< T >::~T_RcPtr( ) noexcept { clear( ); } /*----------------------------------------------------------------------------*/ template< typename T > template< typename... AT > inline T_RcPtr< T > T_RcPtr< T >::New( AT&& ... arguments ) { T* const obj{ new T( std::forward< AT >( arguments ) ... ) }; T_RcPtr< T > ptr; ptr.setTarget_( obj ); return ptr; } template< typename T > inline T_RcPtr< T > T_RcPtr< T >::FromRaw( T* ptr ) noexcept { assert( ptr->getReferenceCount( ) == 0 ); T_RcPtr< T > rv; ptr->increaseReferences_( ); rv.target_ = ptr; return rv; } /*----------------------------------------------------------------------------*/ template< typename T > inline void T_RcPtr< T >::setTarget_( T_Target* t ) noexcept { assert( target_ == nullptr ); if ( t ) { t->increaseReferences_( ); } target_ = t; } template< typename T > inline void T_RcPtr< T >::clear( ) noexcept { if ( target_ && target_->decreaseReferences_( ) ) { delete target_; } target_ = nullptr; } /*----------------------------------------------------------------------------*/ template< typename T > inline T_RcPtr< T >::T_RcPtr( T_RcPtr< T > const& other ) noexcept : target_{ nullptr } { setTarget_( other.target_ ); } template< typename T > template< typename Q , T_EnableForChild< T , Q > > inline T_RcPtr< T >::T_RcPtr( T_RcPtr< Q > const& other ) noexcept : target_{ nullptr } { setTarget_( other.target_ ); } template< typename T > template< typename Q , T_EnableForParent< T , Q > > inline T_RcPtr< T >::T_RcPtr( T_RcPtr< Q > const& other ) : target_{ nullptr } { Q* const p{ other.target_ }; if ( p != nullptr ) { target_ = dynamic_cast< T* >( p ); if ( target_ == nullptr ) { throw std::bad_cast( ); } target_->increaseReferences_( ); } } template< typename T > inline T_RcPtr< T >& T_RcPtr< T >::operator= ( T_Self const& other ) noexcept { clear( ); setTarget_( other.target_ ); return *this; } template< typename T > template< typename Q , T_EnableForChild< T , Q > > inline T_RcPtr< T >& T_RcPtr< T >::operator= ( T_RcPtr< Q > const& other ) noexcept { clear( ); setTarget_( other.target_ ); return *this; } template< typename T > template< typename Q , T_EnableForParent< T , Q > > inline T_RcPtr< T >& T_RcPtr< T >::operator= ( T_RcPtr< Q > const& other ) { clear( ); if ( other.target_ ) { T* const nt{ dynamic_cast< T* >( other.target_ ) }; if ( nt == nullptr ) { throw std::bad_cast( ); } setTarget_( nt ); } return *this; } /*----------------------------------------------------------------------------*/ template< typename T > template< typename Q , T_EnableForChild< T , Q > > inline T_RcPtr< T >::T_RcPtr( T_RcPtr< Q >&& other ) noexcept : target_{ nullptr } { T* const ptr{ (T*) other.target_ }; other.target_ = nullptr; target_ = ptr; } template< typename T > template< typename Q , T_EnableForParent< T , Q > > inline T_RcPtr< T >::T_RcPtr( T_RcPtr< Q >&& other ) : target_{ nullptr } { Q* const p{ other.target_ }; if ( p != nullptr ) { target_ = dynamic_cast< T* >( p ); if ( target_ == nullptr ) { throw std::bad_cast( ); } other.target_ = nullptr; } } template< typename T > template< typename Q , T_EnableForChild< T , Q > > inline T_RcPtr< T >& T_RcPtr< T >::operator= ( T_RcPtr< Q >&& other ) noexcept { clear( ); target_ = other.target_; other.target_ = nullptr; return *this; } template< typename T > template< typename Q , T_EnableForParent< T , Q > > inline T_RcPtr< T >& T_RcPtr< T >::operator= ( T_RcPtr< Q >&& other ) { clear( ); if ( other.target_ ) { T* const nt{ dynamic_cast< T* >( other.target_ ) }; if ( nt == nullptr ) { throw std::bad_cast( ); } other.target_ = nullptr; target_ = nt; } return *this; } /*----------------------------------------------------------------------------*/ template< typename T > inline T_RcPtr< T > T_RcPtr< T >::swap( T_RcPtr< T >& other ) noexcept { std::swap( target_ , other.target_ ); return *this; } template< typename T > inline void swap( T_RcPtr< T >& lhs , T_RcPtr< T >& rhs ) noexcept { lhs.swap( rhs ); } /*----------------------------------------------------------------------------*/ template< typename T > inline T_RcPtr< T >::operator bool ( ) const noexcept { return target_ != nullptr; } template< typename T > inline bool T_RcPtr< T >::operator! ( ) const noexcept { return target_ == nullptr; } /*----------------------------------------------------------------------------*/ template< typename T > inline T_RcPtr< T >::operator T* ( ) const noexcept { return target_; } template< typename T > inline T* T_RcPtr< T >::get( ) const noexcept { return target_; } template< typename T > inline T* T_RcPtr< T >::operator -> ( ) const { assert( target_ != nullptr ); return target_; } template< typename T > inline T& T_RcPtr< T >::operator * ( ) const { assert( target_ != nullptr ); return *target_; } /*----------------------------------------------------------------------------*/ template< typename T > template< typename Q , T_EnableForHierarchy< T , Q > > inline bool T_RcPtr< T >::operator== ( T_RcPtr< Q > const& p ) const noexcept { return (char const*) this == (char const*) &p || (char const*) p.target_ == (char const*) target_; } template< typename T > template< typename Q , T_EnableForHierarchy< T , Q > > inline bool T_RcPtr< T >::operator!= ( T_RcPtr< Q > const& p ) const noexcept { return (char const*) this != (char const*) &p && (char const*) p.target_ != (char const*) target_; } } // namespace ebcl #endif // _H_EBCL_INLINE_REFCOUNT