[b3 bug] SimObject::setAutoDelete() doesn't work. [w/ fix] - RESOLVED
by Manoel Neto · in Torque 3D Professional · 03/03/2011 (6:56 am) · 6 replies
In beta2 the SimObjectPtr was re-written to be nothing more than a thin shell for WeakRefPtr. I believe this was done to allow SimObjectPtrs to be stored in movable memory, since with WeakRefPtrs the reference pointer has an extra indirection layer over it.
The problem is in that the new SimObjectPtr no longer calls registerReference/unregisterReference to the referred object and thus cannot trigger the AutoDelete behavior. This causes any code that relied in setAutoDelete() to clean up temporary/dynamic SimObjects to turn into memory leaks.
I'm looking into how to fix this, since using registerReference() would bring back old bugs about SimObjectPtr and movable memory.
The problem is in that the new SimObjectPtr no longer calls registerReference/unregisterReference to the referred object and thus cannot trigger the AutoDelete behavior. This causes any code that relied in setAutoDelete() to clean up temporary/dynamic SimObjects to turn into memory leaks.
I'm looking into how to fix this, since using registerReference() would bring back old bugs about SimObjectPtr and movable memory.
About the author
Recent Threads
#2
03/03/2011 (5:21 pm)
Compiles fine Manoel, though I don't yet have the coding mad skillz to verify the fix. ;)
#3
One is the current current reference, ok, the second, for the global group reference?
For me it´s not clear at the moment, if the SFX Resource is released, when erased from the mPlayOnceSources vector, because I haven't found any template specialisation for our smart pointers. Propably I'm wrong, so I will check it.
Included your code already and will conduct a smart test.
03/03/2011 (11:29 pm)
Hi Manoel, I remember we discussed the matter in history. I have a question to your code, you checked on line 42 for refCount == 2.One is the current current reference, ok, the second, for the global group reference?
For me it´s not clear at the moment, if the SFX Resource is released, when erased from the mPlayOnceSources vector, because I haven't found any template specialisation for our smart pointers. Propably I'm wrong, so I will check it.
Included your code already and will conduct a smart test.
#4
So a refCount == 2 right before a decRefCount() means this the last external reference is being removed.
03/04/2011 (10:58 am)
Quote:Hi Manoel, I remember we discussed the matter in history. I have a question to your code, you checked on line 42 for refCount == 2.A refCount == 1 means no external references to the object exist. Since these are weak references, the object contains an internal reference to itself. I could check for refCount == 1 after decRefCount(), but that would be unsafe since the internal reference pointer might have been deleted already.
One is the current current reference, ok, the second, for the global group reference?
So a refCount == 2 right before a decRefCount() means this the last external reference is being removed.
#6
04/18/2011 (4:12 pm)
Fixed in 1.1 Final and Preview.
Associate Manoel Neto
Default Studio Name
First we need a few extra features in engine/source/core/util/refBase.h.
Add this:
U32 getRefCount() { return mRefCount; }Right after this block:WeakRefBase * get() { return mObject; } void incRefCount() { mRefCount++; } void decRefCount() { AssertFatal( mRefCount > 0, "WeakReference - decrementing count of zero!" ); if (--mRefCount==0) delete this; }Add this:
Right above this:
Now change this block:
To this:
Now go to engine/source/console/simObject.h and replace this:
class SimObjectPtr : public WeakRefPtr< T > { public: typedef WeakRefPtr< T > Parent; SimObjectPtr() {} SimObjectPtr( T* ptr ) : Parent( ptr ) {} SimObjectPtr( const SimObjectPtr& ref ) : Parent( ref ) {} T* getObject() const { return Parent::getPointer(); } };By this:
class SimObjectPtr : public WeakRefPtr< T > { public: typedef WeakRefPtr< T > Parent; SimObjectPtr() {} /* // THIS CODE IS DISABLED SimObjectPtr( T* ptr ) : Parent( ptr ) {} SimObjectPtr( const SimObjectPtr& ref ) : Parent( ref ) {} */ T* getObject() const { return Parent::getPointer(); } //--------------------------------------------- // NEW CODE SimObjectPtr(T *ptr) { mReference = NULL; set(ptr); } SimObjectPtr( const SimObjectPtr& ref ) { mReference = NULL; set(ref.mReference); } ~SimObjectPtr() { set((WeakRefBase::WeakReference*)NULL); } SimObjectPtr<T>& operator=(const SimObjectPtr ref) { set(ref.mReference); return *this; } SimObjectPtr<T>& operator=(T *ptr) { set(ptr); return *this; } protected: void set(WeakRefBase::WeakReference * ref) { if (mReference) { // Auto-delete T* obj = getPointer(); if ( mReference->getRefCount() == 2 && obj && obj->isAutoDeleted() ) obj->deleteObject(); mReference->decRefCount(); } mReference = NULL; if (ref) { mReference = ref; mReference->incRefCount(); } } void set(T * obj) { set(obj ? obj->getWeakReference() : (WeakRefBase::WeakReference *)NULL); } // END OF NEW CODE //--------------------------------------------- };