ref pointers

TODO: Cleanup

WeakRefBase lifetime is now controlled by a shared_ptr and a control block
objects now act like shared and weakptrs so they free themselves without any outside involvement, last of an objects reference goes out of scope object deletes.
This commit is contained in:
marauder2k7 2026-02-22 23:37:08 +00:00
parent f1f09efbfa
commit 43e673d8ea
4 changed files with 166 additions and 164 deletions

View file

@ -1053,17 +1053,17 @@ class SimObjectPtr : public WeakRefPtr< T >
typedef WeakRefPtr< T > Parent; typedef WeakRefPtr< T > Parent;
SimObjectPtr() {} SimObjectPtr() = default;
SimObjectPtr(T *ptr) { this->mReference = NULL; set(ptr); } SimObjectPtr(T *ptr) { set(ptr); }
SimObjectPtr( const SimObjectPtr& ref ) { this->mReference = NULL; set(ref.mReference); } SimObjectPtr( const SimObjectPtr& ref ) { this->mReference = ref.mReference; }
T* getObject() const { return Parent::getPointer(); } T* getObject() const { return Parent::getPointer(); }
~SimObjectPtr() { set((WeakRefBase::WeakReference*)NULL); } ~SimObjectPtr() { mReference = NULL; }
SimObjectPtr<T>& operator=(const SimObjectPtr ref) SimObjectPtr<T>& operator=(const SimObjectPtr ref)
{ {
set(ref.mReference); mReference = ref.mReference;
return *this; return *this;
} }
SimObjectPtr<T>& operator=(T *ptr) SimObjectPtr<T>& operator=(T *ptr)
@ -1073,31 +1073,10 @@ class SimObjectPtr : public WeakRefPtr< T >
} }
protected: protected:
void set(WeakRefBase::WeakReference * ref)
{
if( ref == this->mReference )
return;
if( this->mReference )
{
// 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();
}
}
void set(T * obj) void set(T * obj)
{ {
set(obj ? obj->getWeakReference() : (WeakRefBase::WeakReference *)NULL); mReference = obj ? obj->getWeakReference() : nullptr;
} }
}; };

View file

@ -3,7 +3,7 @@
WeakRefBase::~WeakRefBase() WeakRefBase::~WeakRefBase()
{ {
if (mControl) if (mControl)
mControl->object = nullptr; mControl->object = NULL;
} }
WeakControlBlock::WeakControlBlock(WeakRefBase* obj) WeakControlBlock::WeakControlBlock(WeakRefBase* obj)
@ -15,3 +15,7 @@ WeakControlBlock::~WeakControlBlock()
{ {
} }
WeakRefBase::WeakReference::~WeakReference()
{
}

View file

@ -50,53 +50,71 @@ public:
class WeakReference class WeakReference
{ {
public: public:
~WeakReference();
WeakRefBase* get() const WeakRefBase* get() const { return mStrong ? mStrong->object : NULL; }
{
auto locked = mWeak.lock();
return locked ? locked->object : NULL;
}
uint32_t getRefCount() const U32 getRefCount() const
{ {
return (uint32_t)mWeak.use_count(); return (U32)mStrong.use_count();
} }
void incRefCount() { /* compatibility no-op */ } void incRefCount() { /* compatibility no-op */ }
void decRefCount() { /* compatibility no-op */ } void decRefCount() { /* compatibility no-op */ }
explicit WeakReference(const std::shared_ptr<WeakControlBlock>& ctrl)
: mStrong(ctrl) {
}
private: private:
friend class WeakRefBase; friend class WeakRefBase;
std::shared_ptr<WeakControlBlock> mStrong;
explicit WeakReference(const std::shared_ptr<WeakControlBlock>& ctrl)
: mWeak(ctrl) {
}
std::weak_ptr<WeakControlBlock> mWeak;
}; };
public: public:
constexpr WeakRefBase() {} WeakRefBase()
virtual ~WeakRefBase();
WeakReference* getWeakReference()
{ {
ensureControl(); ensureControl();
return new WeakReference(mControl); }
virtual ~WeakRefBase();
// Copy constructor
WeakRefBase(const WeakRefBase& other)
{
mControl = other.mControl;
mReference = std::make_unique<WeakReference>(mControl);
}
// Copy assignment
WeakRefBase& operator=(const WeakRefBase& other)
{
if (this != &other)
{
mControl = other.mControl;
mReference = std::make_unique<WeakReference>(mControl);
}
return *this;
}
std::shared_ptr<WeakReference> getWeakReference()
{
if (!mReference)
mReference = std::make_shared<WeakReference>(mControl);
return mReference;
} }
protected: protected:
void ensureControl() void ensureControl()
{ {
if (!mControl) if (!mControl)
mControl = std::shared_ptr<WeakControlBlock>(new WeakControlBlock(this)); mControl = std::make_shared<WeakControlBlock>(this);
} }
std::shared_ptr<WeakControlBlock> mControl; std::shared_ptr<WeakControlBlock> mControl;
private: private:
std::shared_ptr<WeakReference> mReference;
}; };
template< typename T > class SimObjectPtr; template< typename T > class SimObjectPtr;
@ -109,29 +127,24 @@ template< typename T > class SimObjectPtr;
template <class T> class WeakRefPtr template <class T> class WeakRefPtr
{ {
public: public:
constexpr WeakRefPtr() : mReference(NULL) {} WeakRefPtr() = default;
WeakRefPtr(T *ptr) : mReference(NULL) { set(ptr); } WeakRefPtr(T* obj) { set(obj); }
WeakRefPtr(const WeakRefPtr<T> & ref) { mReference = NULL; set(ref.mReference); } WeakRefPtr(const WeakRefPtr& other) { mReference = other.mReference; }
~WeakRefPtr() { set(static_cast<WeakRefBase::WeakReference *>(NULL)); }
WeakRefPtr<T>& operator=(const WeakRefPtr<T>& ref) WeakRefPtr& operator=(const WeakRefPtr& other)
{ {
if (this == &ref) { return *this; } // handle self assignment ( x = x; ) mReference = other.mReference;
set(ref.mReference); return *this;
return *this; }
}
WeakRefPtr<T>& operator=(T *ptr)
{
set(ptr);
return *this;
}
/// Returns true if the pointer is not set. WeakRefPtr& operator=(T* obj)
[[nodiscard]] constexpr bool isNull() const { return mReference == NULL || mReference->get() == NULL; } {
set(obj);
/// Returns true if the pointer is set. return *this;
[[nodiscard]] constexpr bool isValid() const { return mReference && mReference->get(); } }
bool isValid() const { return mReference && mReference->get(); }
bool isNull() const { return !isValid(); }
[[nodiscard]] constexpr T* operator->() const { return getPointer(); } [[nodiscard]] constexpr T* operator->() const { return getPointer(); }
[[nodiscard]] constexpr T& operator*() const { return *getPointer(); } [[nodiscard]] constexpr T& operator*() const { return *getPointer(); }
@ -141,22 +154,13 @@ public:
[[nodiscard]] constexpr T* getPointer() const { return mReference ? (T*)mReference->get() : NULL; } [[nodiscard]] constexpr T* getPointer() const { return mReference ? (T*)mReference->get() : NULL; }
protected: protected:
void set(WeakRefBase::WeakReference* ref) void set(T* obj)
{ {
if (mReference) mReference = obj ? obj->getWeakReference() : NULL;
mReference->decRefCount(); }
mReference = NULL;
if (ref)
{
mReference = ref;
mReference->incRefCount();
}
}
void set(T* obj) { set(obj ? obj->getWeakReference() : NULL); }
private: private:
template< typename > friend class SimObjectPtr; template< typename > friend class SimObjectPtr;
WeakRefBase::WeakReference * mReference {NULL}; std::shared_ptr<WeakRefBase::WeakReference> mReference;
}; };
/// Union of an arbitrary type with a WeakRefBase. The exposed type will /// Union of an arbitrary type with a WeakRefBase. The exposed type will
@ -210,40 +214,42 @@ private:
/// when all strong references go away, object is destroyed). /// when all strong references go away, object is destroyed).
class StrongRefBase : public WeakRefBase class StrongRefBase : public WeakRefBase
{ {
friend class StrongObjectRef; friend class StrongObjectRef;
public: public:
StrongRefBase() StrongRefBase()
{ {
mRefCount = 0; mRefCount = 0;
ensureControl(); mReference = getWeakReference();
mStrongControlRef = mControl; }
}
U32 getRefCount() const { return mRefCount; } virtual ~StrongRefBase() = default;
/// object destroy self call (from StrongRefPtr). Override if this class has specially allocated memory. U32 getRefCount() const { return mRefCount; }
virtual void destroySelf() { delete this; }
/// Increments the reference count. /// object destroy self call (from StrongRefPtr). Override if this class has specially allocated memory.
void incRefCount() virtual void destroySelf() { delete this; }
{
mRefCount++;
}
/// Decrements the reference count. /// Increments the reference count.
void decRefCount() void incRefCount()
{ {
AssertFatal(mRefCount, "Decrementing a reference with refcount 0!"); mRefCount++;
if (!--mRefCount) }
destroySelf();
} /// Decrements the reference count.
void decRefCount()
{
AssertFatal(mRefCount, "Decrementing a reference with refcount 0!");
if (!--mRefCount)
destroySelf();
}
protected: protected:
U32 mRefCount; ///< reference counter for StrongRefPtr objects U32 mRefCount; ///< reference counter for StrongRefPtr objects
std::shared_ptr<WeakControlBlock> mStrongControlRef; std::shared_ptr<WeakRefBase::WeakReference> mReference;
}; };
/// Base class for StrongRefBase strong reference pointers. /// Base class for StrongRefBase strong reference pointers.
class StrongObjectRef class StrongObjectRef
{ {
@ -374,71 +380,53 @@ private:
/// StrongWeakRefs that keep object live as long as the superior entity doesn't /// 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 /// step in and kill them (in which case, the client code sees the reference
/// disappear). /// disappear).
template< class T > template<class T>
class StrongWeakRefPtr class StrongWeakRefPtr
{ {
public: public:
constexpr StrongWeakRefPtr() : mReference( NULL ) {} constexpr StrongWeakRefPtr() = default;
constexpr StrongWeakRefPtr( T* ptr ) : mReference( NULL ) { _set( ptr ); } StrongWeakRefPtr(T* ptr) { set(ptr); }
~StrongWeakRefPtr() StrongWeakRefPtr(const StrongWeakRefPtr& other) { mReference = other.mReference; }
{
if( mReference )
{
T* ptr = _get();
if( ptr )
ptr->decRefCount();
mReference->decRefCount(); ~StrongWeakRefPtr() = default; // no manual decRefCount needed
}
}
[[nodiscard]] constexpr bool isNull() const { return ( _get() == NULL ); } StrongWeakRefPtr& operator=(T* ptr)
[[nodiscard]] constexpr bool operator ==( T* ptr ) const { return ( _get() == ptr ); } {
[[nodiscard]] constexpr bool operator !=( T* ptr ) const { return ( _get() != ptr ); } set(ptr);
[[nodiscard]] constexpr bool operator !() const { return isNull(); } return *this;
[[nodiscard]] constexpr T* operator ->() const { return _get(); } }
[[nodiscard]] constexpr T& operator *() const { return *( _get() ); }
constexpr operator T*() const { return _get(); } // consider making this explicit StrongWeakRefPtr& operator=(const StrongWeakRefPtr& other)
{
mReference = other.mReference;
return *this;
}
T* getPointer() const { return _get(); } [[nodiscard]] bool isNull() const { return !mReference || !mReference->get(); }
[[nodiscard]] bool operator==(T* ptr) const { return getPointer() == ptr; }
[[nodiscard]] bool operator!=(T* ptr) const { return getPointer() != ptr; }
[[nodiscard]] bool operator!() const { return isNull(); }
StrongWeakRefPtr& operator =( T* ptr ) [[nodiscard]] T* operator->() const { return getPointer(); }
{ [[nodiscard]] T& operator*() const { return *getPointer(); }
_set( ptr ); constexpr operator T* () const { return getPointer(); }
return *this;
} T* getPointer() const { return mReference ? static_cast<T*>(mReference->get()) : NULL; }
private: private:
WeakRefBase::WeakReference* mReference; std::shared_ptr<typename WeakRefBase::WeakReference> mReference;
T* _get() const void set(T* ptr)
{ {
if( mReference ) if (ptr)
return static_cast< T* >( mReference->get() ); {
else mReference = ptr->getWeakReference(); // shared_ptr returned
return NULL; }
} else
void _set( T* ptr ) {
{ mReference.reset();
if( mReference ) }
{ }
T* old = _get();
if( old )
old->decRefCount();
mReference->decRefCount();
}
if( ptr )
{
ptr->incRefCount();
mReference = ptr->getWeakReference();
mReference->incRefCount();
}
else
mReference = NULL;
}
}; };
//--------------------------------------------------------------- //---------------------------------------------------------------

View file

@ -216,7 +216,38 @@ public:
//----------------------------------------------------------------------- //-----------------------------------------------------------------------
// Data // Data
//----------------------------------------------------------------------- //-----------------------------------------------------------------------
DECLARE_IMAGEASSET_ARRAY(Material, DiffuseMap, GFXStaticTextureSRGBProfile, MAX_STAGES) private: AssetPtr<ImageAsset> mDiffuseMapAsset[MAX_STAGES]; StringTableEntry mDiffuseMapFile[MAX_STAGES] = { _getStringTable()->EmptyString() }; public: void _setDiffuseMap(StringTableEntry _in, const U32& index) {
if (mDiffuseMapAsset[index].getAssetId() == _in) return; if (getDiffuseMapFile(index) == _in) return; if (_in == 0 || !String::compare(_in, _getStringTable()->EmptyString())) {
mDiffuseMapAsset[index] = 0; mDiffuseMapFile[index] = ""; return;
} if (!AssetDatabase.isDeclaredAsset(_in)) {
StringTableEntry imageAssetId = _getStringTable()->EmptyString(); AssetQuery query; S32 foundAssetcount = AssetDatabase.findAssetLooseFile(&query, _in); if (foundAssetcount != 0) {
imageAssetId = query.mAssetList[0];
}
else if (Torque::FS::IsFile(_in) || (_in[0] == '$' || _in[0] == '#')) {
imageAssetId = ImageAsset::getAssetIdByFilename(_in); if (imageAssetId == ImageAsset::smNoImageAssetFallback) {
ImageAsset* privateImage = new ImageAsset(); privateImage->setImageFile(_in); imageAssetId = AssetDatabase.addPrivateAsset(privateImage);
}
}
else {
Con::warnf("%s::%s: Could not find asset for: %s using fallback", "Material", "DiffuseMap", _in); imageAssetId = ImageAsset::smNoImageAssetFallback;
} mDiffuseMapAsset[index] = imageAssetId; mDiffuseMapFile[index] = _in;
}
else {
mDiffuseMapAsset[index] = _in; mDiffuseMapFile[index] = getDiffuseMapFile(index);
}
}; inline StringTableEntry _getDiffuseMap(const U32& index) const {
return mDiffuseMapAsset[index].getAssetId();
} GFXTexHandle getDiffuseMap(const U32& index) {
return getDiffuseMap(&GFXStaticTextureSRGBProfile, index);
} GFXTexHandle getDiffuseMap(GFXTextureProfile* requestedProfile, const U32& index) {
return mDiffuseMapAsset[index].notNull() ? mDiffuseMapAsset[index]->getTexture(requestedProfile) : 0;
} AssetPtr<ImageAsset> getDiffuseMapAsset(const U32& index) {
return mDiffuseMapAsset[index];
} static bool _setDiffuseMapData(void* obj, const char* index, const char* data) {
static_cast<Material*>(obj)->_setDiffuseMap(_getStringTable()->insert(data), dAtoi(index)); return false;
} StringTableEntry getDiffuseMapFile(const U32& idx) {
return mDiffuseMapAsset[idx].notNull() ? mDiffuseMapAsset[idx]->getImageFile() : "";
}
DECLARE_IMAGEASSET_ARRAY(Material, NormalMap, GFXNormalMapProfile, MAX_STAGES) DECLARE_IMAGEASSET_ARRAY(Material, NormalMap, GFXNormalMapProfile, MAX_STAGES)
DECLARE_IMAGEASSET_ARRAY(Material, DetailNormalMap, GFXNormalMapProfile, MAX_STAGES) DECLARE_IMAGEASSET_ARRAY(Material, DetailNormalMap, GFXNormalMapProfile, MAX_STAGES)
DECLARE_IMAGEASSET_ARRAY(Material, OverlayMap, GFXStaticTextureProfile, MAX_STAGES) DECLARE_IMAGEASSET_ARRAY(Material, OverlayMap, GFXStaticTextureProfile, MAX_STAGES)