Merge pull request #1682 from marauder2k9-torque/RefBase-refactor

RefBase classes refactored to use smart pointers
This commit is contained in:
Areloch 2026-04-08 23:42:19 -05:00 committed by GitHub
commit 4fe0dd05b4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 216 additions and 318 deletions

View file

@ -189,12 +189,6 @@ SoundAsset::SoundAsset()
SoundAsset::~SoundAsset()
{
for (U32 i = 0; i < SFXPlayList::NUM_SLOTS; i++)
{
if(mSFXProfile[i].isProperlyAdded() && !mSFXProfile[i].isDeleted())
mSFXProfile[i].unregisterObject();
}
if (mPlaylist.isProperlyAdded() && !mPlaylist.isDeleted())
mPlaylist.unregisterObject();
@ -404,22 +398,17 @@ U32 SoundAsset::load()
{
Con::errorf("SoundAsset::initializeAsset: Attempted to load file %s but it was not valid!", mSoundFile[i]);
mLoadedState = BadFileReference;
mSFXProfile[i].setDescription(NULL);
mSFXProfile[i].setSoundFileName(StringTable->insert(StringTable->EmptyString()));
mSFXProfile[i].setPreload(false);
return mLoadedState;
}
else
{
SFXProfile* trackProfile = new SFXProfile();
trackProfile->setDescription(&mProfileDesc);
trackProfile->setSoundFileName(mSoundPath[i]);
trackProfile->setPreload(mPreload);
mSFXProfile[i] = new SFXProfile;
mSFXProfile[i]->setDescription(&mProfileDesc);
mSFXProfile[i]->setSoundFileName(mSoundPath[i]);
mSFXProfile[i]->setPreload(mPreload);
mSFXProfile[i]->registerObject(String::ToString("%s_profile_track%d", getAssetName()).c_str());
mSFXProfile[i] = *trackProfile;
mSFXProfile[i].registerObject(String::ToString("%s_profile_track%d", getAssetName()).c_str());
mPlaylist.mSlots.mTrack[i] = trackProfile;
mPlaylist.mSlots.mTrack[i] = mSFXProfile[i];
}
}
@ -436,18 +425,15 @@ U32 SoundAsset::load()
{
Con::errorf("SoundAsset::initializeAsset: Attempted to load file %s but it was not valid!", mSoundFile[0]);
mLoadedState = BadFileReference;
mSFXProfile[0].setDescription(NULL);
mSFXProfile[0].setSoundFileName(StringTable->insert(StringTable->EmptyString()));
mSFXProfile[0].setPreload(false);
return mLoadedState;
}
else
{
mSFXProfile[0].setDescription(&mProfileDesc);
mSFXProfile[0].setSoundFileName(mSoundPath[0]);
mSFXProfile[0].setPreload(mPreload);
mSFXProfile[0].registerObject(String::ToString("%s_profile", getAssetName()).c_str());
mSFXProfile[0] = new SFXProfile;
mSFXProfile[0]->setDescription(&mProfileDesc);
mSFXProfile[0]->setSoundFileName(mSoundPath[0]);
mSFXProfile[0]->setPreload(mPreload);
mSFXProfile[0]->registerObject(String::ToString("%s_profile", getAssetName()).c_str());
}
}

View file

@ -87,9 +87,9 @@ class SoundAsset : public AssetBase
typedef AssetPtr<SoundAsset> ConcreteAssetPtr;
protected:
StringTableEntry mSoundFile[SFXPlayList::SFXPlaylistSettings::NUM_SLOTS];
StringTableEntry mSoundPath[SFXPlayList::SFXPlaylistSettings::NUM_SLOTS];
SFXProfile mSFXProfile[SFXPlayList::SFXPlaylistSettings::NUM_SLOTS];
StringTableEntry mSoundFile[SFXPlayList::SFXPlaylistSettings::NUM_SLOTS];
StringTableEntry mSoundPath[SFXPlayList::SFXPlaylistSettings::NUM_SLOTS];
SimObjectPtr<SFXProfile> mSFXProfile[SFXPlayList::SFXPlaylistSettings::NUM_SLOTS];
SFXDescription mProfileDesc;
SFXPlayList mPlaylist;
@ -150,7 +150,7 @@ public:
void copyTo(SimObject* object) override;
//SFXResource* getSound() { return mSoundResource; }
Resource<SFXResource> getSoundResource(const U32 slotId = 0) { load(); return mSFXProfile[slotId].getResource(); }
Resource<SFXResource> getSoundResource(const U32 slotId = 0) { load(); return mSFXProfile[slotId]->getResource(); }
/// Declare Console Object.
DECLARE_CONOBJECT(SoundAsset);
@ -158,9 +158,9 @@ public:
static bool _setSoundFile(void* object, const char* index, const char* data);
U32 load() override;
inline StringTableEntry getSoundPath(const U32 slotId = 0) const { return mSoundPath[slotId]; };
SFXProfile* getSfxProfile(const U32 slotId = 0) { return &mSFXProfile[slotId]; }
SFXProfile* getSfxProfile(const U32 slotId = 0) { return mSFXProfile[slotId]; }
SFXPlayList* getSfxPlaylist() { return &mPlaylist; }
SFXTrack* getSFXTrack() { load(); return mIsPlaylist ? dynamic_cast<SFXTrack*>(&mPlaylist) : dynamic_cast<SFXTrack*>(&mSFXProfile[0]); }
SFXTrack* getSFXTrack() { load(); return mIsPlaylist ? dynamic_cast<SFXTrack*>(&mPlaylist) : dynamic_cast<SFXTrack*>(mSFXProfile[0].getPointer()); }
SFXDescription* getSfxDescription() { return &mProfileDesc; }
bool isPlaylist(){ return mIsPlaylist; }

View file

@ -40,7 +40,10 @@
#ifndef _TAML_CALLBACKS_H_
#include "persistence/taml/tamlCallbacks.h"
#endif
#ifndef _OBJECTTYPES_H_
#include "T3D/objectTypes.h"
#endif
class Stream;
class LightManager;
@ -606,6 +609,7 @@ class SimObject: public ConsoleObject, public TamlCallbacks
/// @name Events
/// @{
//virtual void onPrepare();
/// Called when the object is added to the sim.
virtual bool onAdd();
@ -1045,56 +1049,47 @@ DefineBitfieldType(GameTypeMasksType);
template< typename T >
class SimObjectPtr : public WeakRefPtr< T >
{
public:
public:
typedef WeakRefPtr< T > Parent;
typedef WeakRefPtr< T > Parent;
SimObjectPtr() {}
SimObjectPtr(T *ptr) { this->mReference = NULL; set(ptr); }
SimObjectPtr( const SimObjectPtr& ref ) { this->mReference = NULL; set(ref.mReference); }
SimObjectPtr() = default;
SimObjectPtr(T* ptr) { set(ptr); }
SimObjectPtr(const SimObjectPtr&) = default;
SimObjectPtr& operator=(const SimObjectPtr&) = default;
SimObjectPtr& operator=(T* ptr)
{
set(ptr);
return *this;
}
T* getObject() const { return Parent::getPointer(); }
T* getObject() const { return Parent::getPointer(); }
~SimObjectPtr() { set((WeakRefBase::WeakReference*)NULL); }
protected:
void set(T* obj)
{
// Nothing to do if same object
if (obj && this->mWeak.lock() == obj->getWeakControl().lock())
return;
SimObjectPtr<T>& operator=(const SimObjectPtr ref)
// Before overwriting, check old object for auto-delete
if (auto old_ctrl = this->mWeak.lock())
{
set(ref.mReference);
return *this;
}
SimObjectPtr<T>& operator=(T *ptr)
{
set(ptr);
return *this;
}
protected:
void set(WeakRefBase::WeakReference * ref)
{
if( ref == this->mReference )
return;
if( this->mReference )
T* old_obj = getObject();
if (this->mWeak.use_count() == 1 && old_obj && old_obj->isAutoDeleted())
{
// Auto-delete
T* obj = this->getPointer();
if ( this->mReference->getRefCount() == 2 && obj && obj->isAutoDeleted() )
obj->deleteObject();
this->mReference->decRefCount();
}
this->mReference = NULL;
if( ref )
{
this->mReference = ref;
this->mReference->incRefCount();
old_obj->destroySelf();
}
}
void set(T * obj)
// Assign new weak reference
this->mWeak.reset();
if (obj)
{
set(obj ? obj->getWeakReference() : (WeakRefBase::WeakReference *)NULL);
auto obj_ctrl = obj->getWeakControl().lock();
this->mWeak = obj_ctrl;
}
}
};
#endif // _SIMOBJECT_H_

View file

@ -0,0 +1,18 @@
#include "refBase.h"
WeakRefBase::~WeakRefBase()
{
if (mControl)
mControl->object = NULL;
}
WeakControlBlock::WeakControlBlock(WeakRefBase* obj)
: object(obj)
{
}
WeakControlBlock::~WeakControlBlock()
{
}

View file

@ -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 > >
{