mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-07-10 14:14:33 +00:00
ref base use smart pointers
This commit is contained in:
parent
88da6f60f6
commit
8c8c2591fe
5 changed files with 216 additions and 318 deletions
18
Engine/source/core/util/refBase.cpp
Normal file
18
Engine/source/core/util/refBase.cpp
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
#include "refBase.h"
|
||||
|
||||
WeakRefBase::~WeakRefBase()
|
||||
{
|
||||
if (mControl)
|
||||
mControl->object = NULL;
|
||||
}
|
||||
|
||||
WeakControlBlock::WeakControlBlock(WeakRefBase* obj)
|
||||
: object(obj)
|
||||
{
|
||||
}
|
||||
|
||||
WeakControlBlock::~WeakControlBlock()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -30,52 +30,52 @@
|
|||
# include "platform/typetraits.h"
|
||||
#endif
|
||||
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
|
||||
class WeakRefBase;
|
||||
|
||||
struct WeakControlBlock
|
||||
{
|
||||
explicit WeakControlBlock(WeakRefBase* obj);
|
||||
~WeakControlBlock();
|
||||
|
||||
WeakRefBase* object;
|
||||
};
|
||||
|
||||
/// Base class for objects which can be weakly referenced
|
||||
/// (i.e., reference goes away when object is destroyed).
|
||||
class WeakRefBase
|
||||
{
|
||||
public:
|
||||
|
||||
/// Weak reference to WeakRefBase.
|
||||
class WeakReference
|
||||
WeakRefBase()
|
||||
: mControl(std::make_shared<WeakControlBlock>(this))
|
||||
{
|
||||
public:
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr WeakRefBase* get() const { return mObject; }
|
||||
[[nodiscard]] constexpr U32 getRefCount() const { return mRefCount; }
|
||||
virtual ~WeakRefBase();
|
||||
|
||||
constexpr void incRefCount() { mRefCount++; }
|
||||
constexpr void decRefCount() {
|
||||
AssertFatal( mRefCount > 0, "WeakReference - decrementing count of zero!" );
|
||||
if (--mRefCount==0)
|
||||
delete this;
|
||||
}
|
||||
private:
|
||||
// Copy constructor
|
||||
WeakRefBase(const WeakRefBase&) = delete;
|
||||
WeakRefBase& operator=(const WeakRefBase&) = delete;
|
||||
WeakRefBase(WeakRefBase&&) = delete;
|
||||
WeakRefBase& operator=(WeakRefBase&&) = delete;
|
||||
|
||||
friend class WeakRefBase;
|
||||
constexpr explicit WeakReference(WeakRefBase *object) :mObject(object), mRefCount(0) {}
|
||||
std::weak_ptr<WeakControlBlock> getWeakControl()
|
||||
{
|
||||
return mControl;
|
||||
}
|
||||
|
||||
~WeakReference() { AssertFatal(mObject==NULL, "Deleting weak reference which still points at an object."); }
|
||||
|
||||
// Object we reference
|
||||
WeakRefBase *mObject;
|
||||
|
||||
// reference count for this structure (not WeakObjectRef itself)
|
||||
U32 mRefCount;
|
||||
};
|
||||
|
||||
public:
|
||||
constexpr WeakRefBase() : mReference(NULL) {}
|
||||
virtual ~WeakRefBase() { clearWeakReferences(); }
|
||||
|
||||
WeakReference* getWeakReference();
|
||||
std::shared_ptr<WeakControlBlock> getSharedControl()
|
||||
{
|
||||
return mControl;
|
||||
}
|
||||
|
||||
protected:
|
||||
void clearWeakReferences();
|
||||
|
||||
std::shared_ptr<WeakControlBlock> mControl;
|
||||
private:
|
||||
WeakReference * mReference;
|
||||
|
||||
};
|
||||
|
||||
template< typename T > class SimObjectPtr;
|
||||
|
|
@ -88,100 +88,48 @@ template< typename T > class SimObjectPtr;
|
|||
template <class T> class WeakRefPtr
|
||||
{
|
||||
public:
|
||||
constexpr WeakRefPtr() : mReference(NULL) {}
|
||||
WeakRefPtr(T *ptr) : mReference(NULL) { set(ptr); }
|
||||
WeakRefPtr(const WeakRefPtr<T> & ref) { mReference = NULL; set(ref.mReference); }
|
||||
|
||||
~WeakRefPtr() { set(static_cast<WeakRefBase::WeakReference *>(NULL)); }
|
||||
WeakRefPtr() = default;
|
||||
WeakRefPtr(T* obj) { set(obj); }
|
||||
|
||||
WeakRefPtr<T>& operator=(const WeakRefPtr<T>& ref)
|
||||
{
|
||||
if (this == &ref) { return *this; } // handle self assignment ( x = x; )
|
||||
set(ref.mReference);
|
||||
return *this;
|
||||
}
|
||||
WeakRefPtr<T>& operator=(T *ptr)
|
||||
{
|
||||
set(ptr);
|
||||
return *this;
|
||||
}
|
||||
WeakRefPtr(const WeakRefPtr&) = default;
|
||||
WeakRefPtr& operator=(const WeakRefPtr&) = default;
|
||||
|
||||
/// Returns true if the pointer is not set.
|
||||
[[nodiscard]] constexpr bool isNull() const { return mReference == NULL || mReference->get() == NULL; }
|
||||
|
||||
/// Returns true if the pointer is set.
|
||||
[[nodiscard]] constexpr bool isValid() const { return mReference && mReference->get(); }
|
||||
WeakRefPtr& operator=(T* obj)
|
||||
{
|
||||
set(obj);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool isValid() const { return getPointer() != NULL; }
|
||||
bool isNull() const { return getPointer() == NULL; }
|
||||
|
||||
[[nodiscard]] constexpr T* operator->() const { return getPointer(); }
|
||||
[[nodiscard]] constexpr T& operator*() const { return *getPointer(); }
|
||||
[[nodiscard]] constexpr operator T*() const { return getPointer(); }
|
||||
|
||||
/// Returns the pointer.
|
||||
[[nodiscard]] constexpr T* getPointer() const { return mReference ? (T*)mReference->get() : NULL; }
|
||||
[[nodiscard]] constexpr T* getPointer() const
|
||||
{
|
||||
auto ctrl = mWeak.lock();
|
||||
if (!ctrl || !ctrl->object)
|
||||
return NULL;
|
||||
return (T*)(ctrl->object);
|
||||
}
|
||||
|
||||
protected:
|
||||
void set(WeakRefBase::WeakReference* ref)
|
||||
{
|
||||
if (mReference)
|
||||
mReference->decRefCount();
|
||||
mReference = NULL;
|
||||
if (ref)
|
||||
void set(T* obj)
|
||||
{
|
||||
if (!obj)
|
||||
{
|
||||
mReference = ref;
|
||||
mReference->incRefCount();
|
||||
mWeak.reset();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void set(T* obj) { set(obj ? obj->getWeakReference() : NULL); }
|
||||
mWeak = obj->getWeakControl();
|
||||
}
|
||||
private:
|
||||
template< typename > friend class SimObjectPtr;
|
||||
WeakRefBase::WeakReference * mReference {NULL};
|
||||
};
|
||||
|
||||
/// Union of an arbitrary type with a WeakRefBase. The exposed type will
|
||||
/// remain accessible so long as the WeakRefBase is not cleared. Once
|
||||
/// it is cleared, accessing the exposed type will result in a NULL pointer.
|
||||
template<class ExposedType>
|
||||
class WeakRefUnion
|
||||
{
|
||||
typedef WeakRefUnion<ExposedType> Union;
|
||||
|
||||
public:
|
||||
constexpr WeakRefUnion() : mPtr(NULL) {}
|
||||
constexpr WeakRefUnion(const WeakRefPtr<WeakRefBase> & ref, ExposedType * ptr) : mPtr(NULL) { set(ref, ptr); }
|
||||
constexpr WeakRefUnion(const Union & lock) : mPtr(NULL) { *this = lock; }
|
||||
constexpr WeakRefUnion(WeakRefBase * ref) : mPtr(NULL) { set(ref, dynamic_cast<ExposedType*>(ref)); }
|
||||
~WeakRefUnion() { mWeakReference = NULL; }
|
||||
|
||||
Union & operator=(const Union & ptr)
|
||||
{
|
||||
if (this == *ptr) { return *this; }
|
||||
set(ptr.mWeakReference, ptr.getPointer());
|
||||
return *this;
|
||||
}
|
||||
|
||||
void set(const WeakRefPtr<WeakRefBase> & ref, ExposedType * ptr)
|
||||
{
|
||||
mWeakReference = ref;
|
||||
mPtr = ptr;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool operator == (const ExposedType * t ) const { return getPointer() == t; }
|
||||
[[nodiscard]] constexpr bool operator != (const ExposedType * t ) const { return getPointer() != t; }
|
||||
[[nodiscard]] constexpr bool operator == (const Union &t ) const { return getPointer() == t.getPointer(); }
|
||||
[[nodiscard]] constexpr bool operator != (const Union &t ) const { return getPointer() != t.getPointer(); }
|
||||
[[nodiscard]] constexpr bool isNull() const { return mWeakReference.isNull() || !mPtr; }
|
||||
|
||||
[[nodiscard]] constexpr ExposedType* getPointer() const { return !mWeakReference.isNull() ? mPtr : NULL; }
|
||||
[[nodiscard]] constexpr ExposedType* operator->() const { return getPointer(); }
|
||||
[[nodiscard]] constexpr ExposedType& operator*() const { return *getPointer(); }
|
||||
[[nodiscard]] constexpr operator ExposedType*() const { return getPointer(); }
|
||||
|
||||
[[nodiscard]] WeakRefPtr<WeakRefBase> getRef() const { return mWeakReference; }
|
||||
|
||||
private:
|
||||
WeakRefPtr<WeakRefBase> mWeakReference;
|
||||
ExposedType * mPtr;
|
||||
std::weak_ptr<WeakControlBlock> mWeak;
|
||||
};
|
||||
|
||||
/// Base class for objects which can be strongly referenced
|
||||
|
|
@ -189,34 +137,40 @@ private:
|
|||
/// when all strong references go away, object is destroyed).
|
||||
class StrongRefBase : public WeakRefBase
|
||||
{
|
||||
friend class StrongObjectRef;
|
||||
friend class StrongObjectRef;
|
||||
|
||||
public:
|
||||
StrongRefBase() { mRefCount = 0; }
|
||||
StrongRefBase()
|
||||
{
|
||||
mRefCount = 0;
|
||||
}
|
||||
|
||||
U32 getRefCount() const { return mRefCount; }
|
||||
virtual ~StrongRefBase() = default;
|
||||
|
||||
/// object destroy self call (from StrongRefPtr). Override if this class has specially allocated memory.
|
||||
virtual void destroySelf() { delete this; }
|
||||
U32 getRefCount() const { return mRefCount; }
|
||||
|
||||
/// Increments the reference count.
|
||||
void incRefCount()
|
||||
{
|
||||
mRefCount++;
|
||||
}
|
||||
/// object destroy self call (from StrongRefPtr). Override if this class has specially allocated memory.
|
||||
virtual void destroySelf() { delete this; }
|
||||
|
||||
/// Decrements the reference count.
|
||||
void decRefCount()
|
||||
{
|
||||
AssertFatal(mRefCount, "Decrementing a reference with refcount 0!");
|
||||
if(!--mRefCount)
|
||||
destroySelf();
|
||||
}
|
||||
/// Increments the reference count.
|
||||
void incRefCount()
|
||||
{
|
||||
mRefCount++;
|
||||
}
|
||||
|
||||
/// Decrements the reference count.
|
||||
void decRefCount()
|
||||
{
|
||||
AssertFatal(mRefCount, "Decrementing a reference with refcount 0!");
|
||||
if (!--mRefCount)
|
||||
destroySelf();
|
||||
}
|
||||
|
||||
protected:
|
||||
U32 mRefCount; ///< reference counter for StrongRefPtr objects
|
||||
U32 mRefCount; ///< reference counter for StrongRefPtr objects
|
||||
};
|
||||
|
||||
|
||||
/// Base class for StrongRefBase strong reference pointers.
|
||||
class StrongObjectRef
|
||||
{
|
||||
|
|
@ -289,55 +243,6 @@ public:
|
|||
T* getPointer() const { return const_cast<T*>(static_cast<T* const>(mObject)); }
|
||||
};
|
||||
|
||||
/// Union of an arbitrary type with a StrongRefBase. StrongRefBase will remain locked
|
||||
/// until the union is destructed. Handy for when the exposed class will
|
||||
/// become invalid whenever the reference becomes invalid and you want to make sure that doesn't
|
||||
/// happen.
|
||||
template<class ExposedType>
|
||||
class StrongRefUnion
|
||||
{
|
||||
typedef StrongRefUnion<ExposedType> Union;
|
||||
|
||||
public:
|
||||
StrongRefUnion() : mPtr(NULL) {}
|
||||
|
||||
StrongRefUnion(const StrongRefPtr<StrongRefBase> & ref, ExposedType * ptr) : mPtr(NULL) { set(ref, ptr); }
|
||||
StrongRefUnion(const Union & lock) : mPtr(NULL) { *this = lock; }
|
||||
StrongRefUnion(StrongRefBase * ref) : mPtr(NULL) { set(ref, dynamic_cast<ExposedType*>(ref)); }
|
||||
|
||||
~StrongRefUnion() { mReference = NULL; }
|
||||
|
||||
Union & operator=(const Union & ptr)
|
||||
{
|
||||
set(ptr.mReference, ptr.mPtr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void set(const StrongRefPtr<StrongRefBase> & ref, ExposedType * ptr)
|
||||
{
|
||||
mReference = ref;
|
||||
mPtr = ptr;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool operator == (const ExposedType * t ) const { return mPtr == t; }
|
||||
[[nodiscard]] constexpr bool operator != (const ExposedType * t ) const { return mPtr != t; }
|
||||
[[nodiscard]] constexpr bool operator == (const Union &t ) const { return mPtr == t.mPtr; }
|
||||
[[nodiscard]] constexpr bool operator != (const Union &t ) const { return mPtr != t.mPtr; }
|
||||
[[nodiscard]] constexpr bool isNull() const { return mReference.isNull() || !mPtr; }
|
||||
[[nodiscard]] constexpr bool isValid() const { return mReference.isValid() && mPtr; }
|
||||
|
||||
ExposedType* operator->() const { return mPtr; }
|
||||
ExposedType& operator*() const { return *mPtr; }
|
||||
operator ExposedType*() const { return mPtr; }
|
||||
ExposedType* getPointer() const { return mPtr; }
|
||||
|
||||
StrongRefPtr<StrongRefBase> getRef() const { return mReference; }
|
||||
|
||||
private:
|
||||
StrongRefPtr<StrongRefBase> mReference;
|
||||
ExposedType * mPtr;
|
||||
};
|
||||
|
||||
/// This oxymoron is a pointer that reference-counts the referenced
|
||||
/// object but also NULLs out if the object goes away.
|
||||
///
|
||||
|
|
@ -347,97 +252,91 @@ private:
|
|||
/// StrongWeakRefs that keep object live as long as the superior entity doesn't
|
||||
/// step in and kill them (in which case, the client code sees the reference
|
||||
/// disappear).
|
||||
template< class T >
|
||||
template<class T>
|
||||
class StrongWeakRefPtr
|
||||
{
|
||||
public:
|
||||
constexpr StrongWeakRefPtr() : mReference( NULL ) {}
|
||||
constexpr StrongWeakRefPtr( T* ptr ) : mReference( NULL ) { _set( ptr ); }
|
||||
~StrongWeakRefPtr()
|
||||
{
|
||||
if( mReference )
|
||||
{
|
||||
T* ptr = _get();
|
||||
if( ptr )
|
||||
ptr->decRefCount();
|
||||
StrongWeakRefPtr() = default;
|
||||
|
||||
mReference->decRefCount();
|
||||
}
|
||||
StrongWeakRefPtr(T* ptr) { set(ptr); }
|
||||
|
||||
StrongWeakRefPtr(const StrongWeakRefPtr& other)
|
||||
{
|
||||
set(other.getPointer());
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool isNull() const { return ( _get() == NULL ); }
|
||||
[[nodiscard]] constexpr bool operator ==( T* ptr ) const { return ( _get() == ptr ); }
|
||||
[[nodiscard]] constexpr bool operator !=( T* ptr ) const { return ( _get() != ptr ); }
|
||||
[[nodiscard]] constexpr bool operator !() const { return isNull(); }
|
||||
[[nodiscard]] constexpr T* operator ->() const { return _get(); }
|
||||
[[nodiscard]] constexpr T& operator *() const { return *( _get() ); }
|
||||
|
||||
constexpr operator T*() const { return _get(); } // consider making this explicit
|
||||
|
||||
T* getPointer() const { return _get(); }
|
||||
|
||||
StrongWeakRefPtr& operator =( T* ptr )
|
||||
StrongWeakRefPtr& operator=(const StrongWeakRefPtr& other)
|
||||
{
|
||||
_set( ptr );
|
||||
if (this != &other)
|
||||
set(other.getPointer());
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
WeakRefBase::WeakReference* mReference;
|
||||
|
||||
T* _get() const
|
||||
~StrongWeakRefPtr()
|
||||
{
|
||||
if( mReference )
|
||||
return static_cast< T* >( mReference->get() );
|
||||
else
|
||||
return NULL;
|
||||
release();
|
||||
}
|
||||
void _set( T* ptr )
|
||||
|
||||
StrongWeakRefPtr& operator=(T* ptr)
|
||||
{
|
||||
set(ptr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool isValid() const { return getPointer() != NULL; }
|
||||
bool isNull() const { return getPointer() == NULL; }
|
||||
[[nodiscard]] bool operator==(T* ptr) const { return getPointer() == ptr; }
|
||||
[[nodiscard]] bool operator!=(T* ptr) const { return getPointer() != ptr; }
|
||||
[[nodiscard]] bool operator!() const { return isNull(); }
|
||||
|
||||
[[nodiscard]] T* operator->() const { return getPointer(); }
|
||||
[[nodiscard]] T& operator*() const { return *getPointer(); }
|
||||
constexpr operator T* () const { return getPointer(); }
|
||||
|
||||
[[nodiscard]] T* getPointer() const
|
||||
{
|
||||
if( mReference )
|
||||
{
|
||||
T* old = _get();
|
||||
if( old )
|
||||
old->decRefCount();
|
||||
return mControl ? static_cast<T*>(mControl->object) : NULL;
|
||||
}
|
||||
|
||||
mReference->decRefCount();
|
||||
|
||||
private:
|
||||
std::shared_ptr<WeakControlBlock> mControl;
|
||||
T* mPtr = NULL;
|
||||
|
||||
void set(T* ptr)
|
||||
{
|
||||
release();
|
||||
if (!ptr) return;
|
||||
|
||||
// Always hold the identity
|
||||
mControl = ptr->getWeakControl().lock();
|
||||
if (!mControl) return;
|
||||
|
||||
mPtr = ptr;
|
||||
|
||||
// Conditionally retain object lifetime if T supports intrusive refcount
|
||||
// runtime check: only strong ref if T inherits StrongRefBase
|
||||
if constexpr (std::is_base_of_v<StrongRefBase, T>)
|
||||
{
|
||||
mPtr->incRefCount();
|
||||
}
|
||||
}
|
||||
|
||||
void release()
|
||||
{
|
||||
if (mPtr)
|
||||
{
|
||||
if constexpr (std::is_base_of_v<StrongRefBase, T>)
|
||||
{
|
||||
mPtr->decRefCount();
|
||||
}
|
||||
}
|
||||
|
||||
if( ptr )
|
||||
{
|
||||
ptr->incRefCount();
|
||||
mReference = ptr->getWeakReference();
|
||||
mReference->incRefCount();
|
||||
}
|
||||
else
|
||||
mReference = NULL;
|
||||
mPtr = NULL;
|
||||
mControl.reset();
|
||||
}
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------
|
||||
|
||||
inline void WeakRefBase::clearWeakReferences()
|
||||
{
|
||||
if (mReference)
|
||||
{
|
||||
mReference->mObject = NULL;
|
||||
mReference->decRefCount();
|
||||
mReference = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
inline WeakRefBase::WeakReference* WeakRefBase::getWeakReference()
|
||||
{
|
||||
if (!mReference)
|
||||
{
|
||||
mReference = new WeakReference(this);
|
||||
mReference->incRefCount();
|
||||
}
|
||||
return mReference;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
|
||||
template< typename T >
|
||||
struct TypeTraits< WeakRefPtr< T > > : public _TypeTraits< WeakRefPtr< T > >
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue