mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-03-20 12:50:57 +00:00
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:
parent
f1f09efbfa
commit
43e673d8ea
4 changed files with 166 additions and 164 deletions
|
|
@ -1053,17 +1053,17 @@ class SimObjectPtr : public WeakRefPtr< T >
|
|||
|
||||
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& ref ) { this->mReference = ref.mReference; }
|
||||
|
||||
T* getObject() const { return Parent::getPointer(); }
|
||||
|
||||
~SimObjectPtr() { set((WeakRefBase::WeakReference*)NULL); }
|
||||
~SimObjectPtr() { mReference = NULL; }
|
||||
|
||||
SimObjectPtr<T>& operator=(const SimObjectPtr ref)
|
||||
{
|
||||
set(ref.mReference);
|
||||
mReference = ref.mReference;
|
||||
return *this;
|
||||
}
|
||||
SimObjectPtr<T>& operator=(T *ptr)
|
||||
|
|
@ -1073,31 +1073,10 @@ class SimObjectPtr : public WeakRefPtr< T >
|
|||
}
|
||||
|
||||
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)
|
||||
{
|
||||
set(obj ? obj->getWeakReference() : (WeakRefBase::WeakReference *)NULL);
|
||||
mReference = obj ? obj->getWeakReference() : nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
WeakRefBase::~WeakRefBase()
|
||||
{
|
||||
if (mControl)
|
||||
mControl->object = nullptr;
|
||||
mControl->object = NULL;
|
||||
}
|
||||
|
||||
WeakControlBlock::WeakControlBlock(WeakRefBase* obj)
|
||||
|
|
@ -15,3 +15,7 @@ WeakControlBlock::~WeakControlBlock()
|
|||
{
|
||||
|
||||
}
|
||||
|
||||
WeakRefBase::WeakReference::~WeakReference()
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,53 +50,71 @@ public:
|
|||
class WeakReference
|
||||
{
|
||||
public:
|
||||
~WeakReference();
|
||||
|
||||
WeakRefBase* get() const
|
||||
{
|
||||
auto locked = mWeak.lock();
|
||||
return locked ? locked->object : NULL;
|
||||
}
|
||||
WeakRefBase* get() const { return mStrong ? mStrong->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 decRefCount() { /* compatibility no-op */ }
|
||||
|
||||
explicit WeakReference(const std::shared_ptr<WeakControlBlock>& ctrl)
|
||||
: mStrong(ctrl) {
|
||||
}
|
||||
private:
|
||||
friend class WeakRefBase;
|
||||
|
||||
explicit WeakReference(const std::shared_ptr<WeakControlBlock>& ctrl)
|
||||
: mWeak(ctrl) {
|
||||
}
|
||||
|
||||
std::weak_ptr<WeakControlBlock> mWeak;
|
||||
std::shared_ptr<WeakControlBlock> mStrong;
|
||||
};
|
||||
|
||||
public:
|
||||
constexpr WeakRefBase() {}
|
||||
virtual ~WeakRefBase();
|
||||
|
||||
WeakReference* getWeakReference()
|
||||
WeakRefBase()
|
||||
{
|
||||
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:
|
||||
|
||||
void ensureControl()
|
||||
{
|
||||
if (!mControl)
|
||||
mControl = std::shared_ptr<WeakControlBlock>(new WeakControlBlock(this));
|
||||
if (!mControl)
|
||||
mControl = std::make_shared<WeakControlBlock>(this);
|
||||
}
|
||||
|
||||
std::shared_ptr<WeakControlBlock> mControl;
|
||||
private:
|
||||
|
||||
std::shared_ptr<WeakReference> mReference;
|
||||
|
||||
|
||||
};
|
||||
|
||||
template< typename T > class SimObjectPtr;
|
||||
|
|
@ -109,29 +127,24 @@ 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(const WeakRefPtr& other) { mReference = other.mReference; }
|
||||
|
||||
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& operator=(const WeakRefPtr& other)
|
||||
{
|
||||
mReference = other.mReference;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// 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 mReference && mReference->get(); }
|
||||
bool isNull() const { return !isValid(); }
|
||||
|
||||
[[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; }
|
||||
|
||||
protected:
|
||||
void set(WeakRefBase::WeakReference* ref)
|
||||
{
|
||||
if (mReference)
|
||||
mReference->decRefCount();
|
||||
mReference = NULL;
|
||||
if (ref)
|
||||
{
|
||||
mReference = ref;
|
||||
mReference->incRefCount();
|
||||
}
|
||||
}
|
||||
|
||||
void set(T* obj) { set(obj ? obj->getWeakReference() : NULL); }
|
||||
void set(T* obj)
|
||||
{
|
||||
mReference = obj ? obj->getWeakReference() : NULL;
|
||||
}
|
||||
private:
|
||||
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
|
||||
|
|
@ -210,40 +214,42 @@ private:
|
|||
/// when all strong references go away, object is destroyed).
|
||||
class StrongRefBase : public WeakRefBase
|
||||
{
|
||||
friend class StrongObjectRef;
|
||||
friend class StrongObjectRef;
|
||||
|
||||
public:
|
||||
StrongRefBase()
|
||||
{
|
||||
mRefCount = 0;
|
||||
ensureControl();
|
||||
mStrongControlRef = mControl;
|
||||
}
|
||||
StrongRefBase()
|
||||
{
|
||||
mRefCount = 0;
|
||||
mReference = getWeakReference();
|
||||
}
|
||||
|
||||
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
|
||||
std::shared_ptr<WeakControlBlock> mStrongControlRef;
|
||||
U32 mRefCount; ///< reference counter for StrongRefPtr objects
|
||||
std::shared_ptr<WeakRefBase::WeakReference> mReference;
|
||||
};
|
||||
|
||||
|
||||
/// Base class for StrongRefBase strong reference pointers.
|
||||
class StrongObjectRef
|
||||
{
|
||||
|
|
@ -374,71 +380,53 @@ 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();
|
||||
constexpr StrongWeakRefPtr() = default;
|
||||
StrongWeakRefPtr(T* ptr) { set(ptr); }
|
||||
StrongWeakRefPtr(const StrongWeakRefPtr& other) { mReference = other.mReference; }
|
||||
|
||||
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() ); }
|
||||
StrongWeakRefPtr& operator=(T* ptr)
|
||||
{
|
||||
set(ptr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
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 )
|
||||
{
|
||||
_set( ptr );
|
||||
return *this;
|
||||
}
|
||||
[[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:
|
||||
WeakRefBase::WeakReference* mReference;
|
||||
std::shared_ptr<typename WeakRefBase::WeakReference> mReference;
|
||||
|
||||
T* _get() const
|
||||
{
|
||||
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 )
|
||||
{
|
||||
ptr->incRefCount();
|
||||
mReference = ptr->getWeakReference();
|
||||
mReference->incRefCount();
|
||||
}
|
||||
else
|
||||
mReference = NULL;
|
||||
}
|
||||
void set(T* ptr)
|
||||
{
|
||||
if (ptr)
|
||||
{
|
||||
mReference = ptr->getWeakReference(); // shared_ptr returned
|
||||
}
|
||||
else
|
||||
{
|
||||
mReference.reset();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -216,7 +216,38 @@ public:
|
|||
//-----------------------------------------------------------------------
|
||||
// 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, DetailNormalMap, GFXNormalMapProfile, MAX_STAGES)
|
||||
DECLARE_IMAGEASSET_ARRAY(Material, OverlayMap, GFXStaticTextureProfile, MAX_STAGES)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue