corelib/include/ebcl/inline/RefCount.hh
Emmanuel BENOîT a4a2a9eda4 Reference-counting helpers - Equality operators
* Added == and != operators; they can only be used if the referenced types are
from the same hierarchy
 * Tests for the above
2019-01-02 17:52:56 +01:00

324 lines
6.6 KiB
C++

/******************************************************************************/
/* REFERENCE-COUNTING HELPERS - INLINE CODE ***********************************/
/******************************************************************************/
#ifndef _H_EBCL_INLINE_REFCOUNT
#define _H_EBCL_INLINE_REFCOUNT
#include <ebcl/RefCount.hh>
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