2019-01-02 13:27:25 +01:00
|
|
|
/******************************************************************************/
|
|
|
|
/* REFERENCE-COUNTING HELPERS *************************************************/
|
|
|
|
/******************************************************************************/
|
|
|
|
|
|
|
|
#ifndef _H_EBCL_REFCOUNT
|
|
|
|
#define _H_EBCL_REFCOUNT
|
|
|
|
#include <ebcl/Utilities.hh>
|
|
|
|
namespace ebcl {
|
|
|
|
|
|
|
|
// A base class and pointer type that can be used to implement classes which
|
|
|
|
// use in-instance reference counters.
|
|
|
|
|
|
|
|
|
|
|
|
/*= REFERENCE-COUNTED INSTANCES ==============================================*/
|
|
|
|
|
|
|
|
// Base class containing the reference counter. It may be an atomic, or it
|
|
|
|
// may be a simple integer.
|
|
|
|
template< bool UseAtomic = false >
|
|
|
|
class T_ReferenceCountedClass
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
// Is it atomic ?
|
|
|
|
static const bool UsingAtomic = UseAtomic;
|
|
|
|
// Reference counter type
|
|
|
|
using T_ReferenceCounter = std::conditional_t<
|
|
|
|
UseAtomic , std::atomic< uint32_t > , uint32_t
|
|
|
|
>;
|
|
|
|
|
|
|
|
// Reference-counting pointers can access the counter
|
|
|
|
template< typename > friend class T_RcPtr;
|
|
|
|
|
|
|
|
private:
|
|
|
|
T_ReferenceCounter referenceCounter_;
|
|
|
|
|
|
|
|
// Add a reference to the counter
|
|
|
|
void increaseReferences_( ) noexcept;
|
|
|
|
|
|
|
|
// Remove a reference from the counter, returning true if the instance
|
|
|
|
// is no longer referenced.
|
|
|
|
bool decreaseReferences_( ) noexcept;
|
|
|
|
|
|
|
|
protected:
|
2019-01-02 17:24:22 +01:00
|
|
|
// Initialise the counter to 0
|
2019-01-02 13:27:25 +01:00
|
|
|
T_ReferenceCountedClass( ) noexcept;
|
2019-01-02 15:50:21 +01:00
|
|
|
|
|
|
|
public:
|
2019-01-02 17:24:22 +01:00
|
|
|
// Get the reference count
|
2019-01-02 15:50:21 +01:00
|
|
|
uint32_t getReferenceCount( ) const noexcept;
|
2019-01-02 17:24:22 +01:00
|
|
|
|
|
|
|
// Deleted copy/move constructors and assignment operators
|
|
|
|
T_ReferenceCountedClass(
|
|
|
|
T_ReferenceCountedClass< UseAtomic > const& ) = delete;
|
|
|
|
T_ReferenceCountedClass< UseAtomic >& operator =(
|
|
|
|
T_ReferenceCountedClass< UseAtomic > const& ) = delete;
|
|
|
|
T_ReferenceCountedClass(
|
|
|
|
T_ReferenceCountedClass< UseAtomic >&& ) = delete;
|
|
|
|
T_ReferenceCountedClass< UseAtomic >& operator =(
|
|
|
|
T_ReferenceCountedClass< UseAtomic >&& ) = delete;
|
2019-01-02 13:27:25 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
// Shortcuts
|
|
|
|
using T_AtomicRcClass = T_ReferenceCountedClass< true >;
|
|
|
|
using T_SimpleRcClass = T_ReferenceCountedClass< false >;
|
|
|
|
|
|
|
|
|
|
|
|
/*= REFERENCE-COUNTING POINTERS ==============================================*/
|
|
|
|
|
|
|
|
// Pointers that use T_ReferenceCountedClass in order to track the reference
|
|
|
|
// counts of the instances it manages.
|
|
|
|
template< typename Type >
|
|
|
|
class T_RcPtr
|
|
|
|
{
|
|
|
|
static_assert( MetaOr< std::is_base_of< T_AtomicRcClass , Type > ,
|
|
|
|
std::is_base_of< T_SimpleRcClass , Type > >::value ,
|
|
|
|
"type does not include a reference counter" );
|
|
|
|
|
|
|
|
public:
|
|
|
|
// Target type
|
|
|
|
using T_Target = Type;
|
|
|
|
// Pointer type
|
|
|
|
using T_Self = T_RcPtr< Type >;
|
|
|
|
// Base reference counting class
|
|
|
|
using T_RcClass = std::conditional_t<
|
|
|
|
std::is_base_of< T_AtomicRcClass , Type >::value ,
|
|
|
|
T_AtomicRcClass , T_SimpleRcClass
|
|
|
|
>;
|
|
|
|
|
2019-01-02 17:14:08 +01:00
|
|
|
// All RcPtr's are friends
|
|
|
|
template< typename > friend class T_RcPtr;
|
|
|
|
|
2019-01-02 13:27:25 +01:00
|
|
|
private:
|
|
|
|
T_Target* target_;
|
2019-01-02 15:50:21 +01:00
|
|
|
void setTarget_( T_Target* t ) noexcept;
|
2019-01-02 13:27:25 +01:00
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------
|
|
|
|
|
|
|
|
T_RcPtr( ) noexcept;
|
|
|
|
~T_RcPtr( ) noexcept;
|
|
|
|
|
2019-01-02 15:50:21 +01:00
|
|
|
// Constructor function
|
|
|
|
template< typename... AT >
|
|
|
|
static T_RcPtr< Type > New( AT&& ... arguments );
|
|
|
|
|
2019-01-02 17:14:08 +01:00
|
|
|
// Initialise from raw pointer. The instance must have a reference
|
|
|
|
// count of zero, and must have been allocated using new.
|
|
|
|
static T_RcPtr< Type > FromRaw( Type* ptr ) noexcept;
|
|
|
|
|
2019-01-02 13:27:25 +01:00
|
|
|
void clear( ) noexcept;
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------
|
2019-01-02 15:50:21 +01:00
|
|
|
// Copy constructors and operators
|
2019-01-02 13:27:25 +01:00
|
|
|
|
|
|
|
T_RcPtr( T_Self const& other ) noexcept;
|
2019-01-02 15:50:21 +01:00
|
|
|
T_Self& operator= ( T_Self const& other ) noexcept;
|
|
|
|
|
2019-01-02 13:27:25 +01:00
|
|
|
template< typename Q , T_EnableForChild< Type , Q > = true >
|
|
|
|
T_RcPtr( T_RcPtr< Q > const& source ) noexcept;
|
|
|
|
template< typename Q , T_EnableForParent< Type , Q > = false >
|
|
|
|
explicit T_RcPtr( T_RcPtr< Q > const& source );
|
|
|
|
|
2019-01-02 15:50:21 +01:00
|
|
|
template< typename Q , T_EnableForChild< Type , Q > = true >
|
|
|
|
T_Self& operator= ( T_RcPtr< Q > const& other ) noexcept;
|
|
|
|
template< typename Q , T_EnableForParent< Type , Q > = false >
|
|
|
|
T_Self& operator= ( T_RcPtr< Q > const& other );
|
|
|
|
|
2019-01-02 13:27:25 +01:00
|
|
|
// ---------------------------------------------------------------------
|
2019-01-02 15:50:21 +01:00
|
|
|
// Move constructors and operators
|
2019-01-02 13:27:25 +01:00
|
|
|
|
|
|
|
template< typename Q , T_EnableForChild< Type , Q > = true >
|
|
|
|
T_RcPtr( T_RcPtr< Q >&& other ) noexcept;
|
|
|
|
template< typename Q , T_EnableForParent< Type , Q > = false >
|
|
|
|
explicit T_RcPtr( T_RcPtr< Q >&& other );
|
|
|
|
|
2019-01-02 15:50:21 +01:00
|
|
|
template< typename Q , T_EnableForChild< Type , Q > = true >
|
|
|
|
T_Self& operator= ( T_RcPtr< Q >&& other ) noexcept;
|
|
|
|
template< typename Q , T_EnableForParent< Type , Q > = false >
|
|
|
|
T_Self& operator= ( T_RcPtr< Q >&& other );
|
|
|
|
|
2019-01-02 16:51:18 +01:00
|
|
|
// ---------------------------------------------------------------------
|
|
|
|
// Swapping
|
|
|
|
|
|
|
|
T_Self swap( T_Self& other ) noexcept;
|
|
|
|
|
2019-01-02 15:50:21 +01:00
|
|
|
// ---------------------------------------------------------------------
|
|
|
|
// Boolean conversion
|
|
|
|
|
|
|
|
operator bool ( ) const noexcept;
|
|
|
|
bool operator! ( ) const noexcept;
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------
|
|
|
|
// Content access
|
|
|
|
|
|
|
|
// Access the actual pointer
|
|
|
|
Type * get( ) const noexcept;
|
|
|
|
explicit operator Type* ( ) const noexcept;
|
|
|
|
|
|
|
|
// Access the object; undefined behavior if get() == nullptr.
|
|
|
|
Type* operator -> ( ) const;
|
|
|
|
Type& operator * ( ) const;
|
|
|
|
};
|
2019-01-02 13:27:25 +01:00
|
|
|
|
2019-01-02 16:51:18 +01:00
|
|
|
template< typename T >
|
|
|
|
void swap( T_RcPtr< T >& lhs , T_RcPtr< T >& rhs ) noexcept;
|
|
|
|
|
2019-01-02 17:14:08 +01:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2019-01-02 13:27:25 +01:00
|
|
|
|
|
|
|
} // namespace
|
|
|
|
#endif // _H_EBCL_REFCOUNT
|
|
|
|
#include <ebcl/inline/RefCount.hh>
|