corelib/include/ebcl/inline/Pointers.hh

854 lines
19 KiB
C++

/******************************************************************************/
/* POINTERS - INLINE CODE *****************************************************/
/******************************************************************************/
#ifndef _H_LW_LIB_INLINE_POINTERS
#define _H_LW_LIB_INLINE_POINTERS
#include <lw/lib/Pointers.hh>
namespace lw {
/*= 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_LW_LIB_INLINE_POINTERS