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,39 +50,57 @@ 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:
@ -90,12 +108,12 @@ 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;
}; };
@ -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& operator=(const WeakRefPtr& other)
WeakRefPtr<T>& operator=(const WeakRefPtr<T>& ref)
{ {
if (this == &ref) { return *this; } // handle self assignment ( x = x; ) mReference = other.mReference;
set(ref.mReference);
return *this;
}
WeakRefPtr<T>& operator=(T *ptr)
{
set(ptr);
return *this; 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);
return *this;
}
/// Returns true if the pointer is set. bool isValid() const { return mReference && mReference->get(); }
[[nodiscard]] constexpr 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
@ -216,10 +220,11 @@ public:
StrongRefBase() StrongRefBase()
{ {
mRefCount = 0; mRefCount = 0;
ensureControl(); mReference = getWeakReference();
mStrongControlRef = mControl;
} }
virtual ~StrongRefBase() = default;
U32 getRefCount() const { return mRefCount; } U32 getRefCount() const { return mRefCount; }
/// object destroy self call (from StrongRefPtr). Override if this class has specially allocated memory. /// object destroy self call (from StrongRefPtr). Override if this class has specially allocated memory.
@ -241,9 +246,10 @@ public:
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
{ {
@ -378,66 +384,48 @@ 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 ); }
[[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=(T* ptr)
{ {
_set( ptr ); set(ptr);
return *this; return *this;
} }
StrongWeakRefPtr& operator=(const StrongWeakRefPtr& other)
{
mReference = other.mReference;
return *this;
}
[[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(); }
[[nodiscard]] T* operator->() const { return getPointer(); }
[[nodiscard]] T& operator*() const { return *getPointer(); }
constexpr operator T* () const { return getPointer(); }
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 )
return static_cast< T* >( mReference->get() );
else
return NULL;
}
void _set( T* ptr )
{
if( mReference )
{
T* old = _get();
if( old )
old->decRefCount();
mReference->decRefCount();
}
if (ptr) if (ptr)
{ {
ptr->incRefCount(); mReference = ptr->getWeakReference(); // shared_ptr returned
mReference = ptr->getWeakReference();
mReference->incRefCount();
} }
else else
mReference = NULL; {
mReference.reset();
}
} }
}; };

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)