diff --git a/Engine/source/T3D/assets/SoundAsset.cpp b/Engine/source/T3D/assets/SoundAsset.cpp index f4882c50f6..e8b6d3cdbd 100644 --- a/Engine/source/T3D/assets/SoundAsset.cpp +++ b/Engine/source/T3D/assets/SoundAsset.cpp @@ -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()); } } diff --git a/Engine/source/T3D/assets/SoundAsset.h b/Engine/source/T3D/assets/SoundAsset.h index 1def010662..d005ec0c1c 100644 --- a/Engine/source/T3D/assets/SoundAsset.h +++ b/Engine/source/T3D/assets/SoundAsset.h @@ -87,9 +87,9 @@ class SoundAsset : public AssetBase typedef AssetPtr 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 mSFXProfile[SFXPlayList::SFXPlaylistSettings::NUM_SLOTS]; SFXDescription mProfileDesc; SFXPlayList mPlaylist; @@ -150,7 +150,7 @@ class SoundAsset : public AssetBase void copyTo(SimObject* object) override; //SFXResource* getSound() { return mSoundResource; } - Resource getSoundResource(const U32 slotId = 0) { load(); return mSFXProfile[slotId].getResource(); } + Resource getSoundResource(const U32 slotId = 0) { load(); return mSFXProfile[slotId]->getResource(); } /// Declare Console Object. DECLARE_CONOBJECT(SoundAsset); @@ -158,9 +158,9 @@ class SoundAsset : public AssetBase 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(&mPlaylist) : dynamic_cast(&mSFXProfile[0]); } + SFXTrack* getSFXTrack() { load(); return mIsPlaylist ? dynamic_cast(&mPlaylist) : dynamic_cast(mSFXProfile[0].getPointer()); } SFXDescription* getSfxDescription() { return &mProfileDesc; } bool isPlaylist(){ return mIsPlaylist; } diff --git a/Engine/source/console/simObject.h b/Engine/source/console/simObject.h index 4868a45853..1ea3a2b5dd 100644 --- a/Engine/source/console/simObject.h +++ b/Engine/source/console/simObject.h @@ -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); } - - T* getObject() const { return Parent::getPointer(); } + 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(); } - ~SimObjectPtr() { set((WeakRefBase::WeakReference*)NULL); } - - SimObjectPtr& operator=(const SimObjectPtr ref) - { - set(ref.mReference); - return *this; - } - SimObjectPtr& operator=(T *ptr) - { - set(ptr); - return *this; - } - - protected: - void set(WeakRefBase::WeakReference * ref) +protected: + void set(T* obj) + { + // Nothing to do if same object + if (obj && this->mWeak.lock() == obj->getWeakControl().lock()) + return; + + // Before overwriting, check old object for auto-delete + if (auto old_ctrl = this->mWeak.lock()) { - 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 ) + T* old_obj = getObject(); + if (this->mWeak.use_count() == 1 && old_obj && old_obj->isAutoDeleted()) { - 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_ diff --git a/Engine/source/core/util/refBase.cpp b/Engine/source/core/util/refBase.cpp new file mode 100644 index 0000000000..2f4314742f --- /dev/null +++ b/Engine/source/core/util/refBase.cpp @@ -0,0 +1,18 @@ +#include "refBase.h" + +WeakRefBase::~WeakRefBase() +{ + if (mControl) + mControl->object = NULL; +} + +WeakControlBlock::WeakControlBlock(WeakRefBase* obj) + : object(obj) +{ +} + +WeakControlBlock::~WeakControlBlock() +{ + +} + diff --git a/Engine/source/core/util/refBase.h b/Engine/source/core/util/refBase.h index 42ce6705d2..4323586044 100644 --- a/Engine/source/core/util/refBase.h +++ b/Engine/source/core/util/refBase.h @@ -30,52 +30,52 @@ # include "platform/typetraits.h" #endif +#include +#include + +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(this)) { - public: - - [[nodiscard]] constexpr WeakRefBase* get() const { return mObject; } - [[nodiscard]] constexpr U32 getRefCount() const { return mRefCount; } - - constexpr void incRefCount() { mRefCount++; } - constexpr void decRefCount() { - AssertFatal( mRefCount > 0, "WeakReference - decrementing count of zero!" ); - if (--mRefCount==0) - delete this; - } - private: - - friend class WeakRefBase; - constexpr explicit WeakReference(WeakRefBase *object) :mObject(object), mRefCount(0) {} - - ~WeakReference() { AssertFatal(mObject==NULL, "Deleting weak reference which still points at an object."); } + } - // Object we reference - WeakRefBase *mObject; + virtual ~WeakRefBase(); - // reference count for this structure (not WeakObjectRef itself) - U32 mRefCount; - }; + // Copy constructor + WeakRefBase(const WeakRefBase&) = delete; + WeakRefBase& operator=(const WeakRefBase&) = delete; + WeakRefBase(WeakRefBase&&) = delete; + WeakRefBase& operator=(WeakRefBase&&) = delete; -public: - constexpr WeakRefBase() : mReference(NULL) {} - virtual ~WeakRefBase() { clearWeakReferences(); } + std::weak_ptr getWeakControl() + { + return mControl; + } - WeakReference* getWeakReference(); + std::shared_ptr getSharedControl() + { + return mControl; + } protected: - void clearWeakReferences(); + std::shared_ptr mControl; private: - WeakReference * mReference; + }; template< typename T > class SimObjectPtr; @@ -88,100 +88,48 @@ template< typename T > class SimObjectPtr; template class WeakRefPtr { public: - constexpr WeakRefPtr() : mReference(NULL) {} - WeakRefPtr(T *ptr) : mReference(NULL) { set(ptr); } - WeakRefPtr(const WeakRefPtr & ref) { mReference = NULL; set(ref.mReference); } - - ~WeakRefPtr() { set(static_cast(NULL)); } + WeakRefPtr() = default; + WeakRefPtr(T* obj) { set(obj); } - WeakRefPtr& operator=(const WeakRefPtr& ref) - { - if (this == &ref) { return *this; } // handle self assignment ( x = x; ) - set(ref.mReference); - return *this; - } - WeakRefPtr& 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 WeakRefUnion -{ - typedef WeakRefUnion Union; - -public: - constexpr WeakRefUnion() : mPtr(NULL) {} - constexpr WeakRefUnion(const WeakRefPtr & 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(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 & 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 getRef() const { return mWeakReference; } - -private: - WeakRefPtr mWeakReference; - ExposedType * mPtr; + std::weak_ptr mWeak; }; /// Base class for objects which can be strongly referenced @@ -189,34 +137,40 @@ class WeakRefUnion /// 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 @@ template class StrongRefPtr : protected StrongObjectRef T* getPointer() const { return const_cast(static_cast(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 StrongRefUnion -{ - typedef StrongRefUnion Union; - -public: - StrongRefUnion() : mPtr(NULL) {} - - StrongRefUnion(const StrongRefPtr & 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(ref)); } - - ~StrongRefUnion() { mReference = NULL; } - - Union & operator=(const Union & ptr) - { - set(ptr.mReference, ptr.mPtr); - return *this; - } - - void set(const StrongRefPtr & 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 getRef() const { return mReference; } - -private: - StrongRefPtr mReference; - ExposedType * mPtr; -}; - /// This oxymoron is a pointer that reference-counts the referenced /// object but also NULLs out if the object goes away. /// @@ -347,96 +252,90 @@ class StrongRefUnion /// 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 StrongWeakRefPtr { public: - constexpr StrongWeakRefPtr() : mReference( NULL ) {} - constexpr StrongWeakRefPtr( T* ptr ) : mReference( NULL ) { _set( ptr ); } - ~StrongWeakRefPtr() + StrongWeakRefPtr() = default; + + StrongWeakRefPtr(T* ptr) { set(ptr); } + + StrongWeakRefPtr(const StrongWeakRefPtr& other) { - if( mReference ) - { - T* ptr = _get(); - if( ptr ) - ptr->decRefCount(); + set(other.getPointer()); + } - mReference->decRefCount(); - } + StrongWeakRefPtr& operator=(const StrongWeakRefPtr& other) + { + if (this != &other) + set(other.getPointer()); + return *this; } - [[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() + { + release(); + } + + StrongWeakRefPtr& operator=(T* ptr) + { + set(ptr); + return *this; + } - constexpr operator T*() const { return _get(); } // consider making this explicit + 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(); } - T* getPointer() const { return _get(); } + [[nodiscard]] T* operator->() const { return getPointer(); } + [[nodiscard]] T& operator*() const { return *getPointer(); } + constexpr operator T* () const { return getPointer(); } - StrongWeakRefPtr& operator =( T* ptr ) + [[nodiscard]] T* getPointer() const { - _set( ptr ); - return *this; + return mControl ? static_cast(mControl->object) : NULL; } + private: - WeakRefBase::WeakReference* mReference; + std::shared_ptr mControl; + T* mPtr = NULL; - T* _get() const - { - if( mReference ) - return static_cast< T* >( mReference->get() ); - else - return NULL; - } - void _set( T* ptr ) + void set(T* ptr) { - if( mReference ) - { - T* old = _get(); - if( old ) - old->decRefCount(); + release(); + if (!ptr) return; - mReference->decRefCount(); - } + // Always hold the identity + mControl = ptr->getWeakControl().lock(); + if (!mControl) return; - if( ptr ) + 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) { - ptr->incRefCount(); - mReference = ptr->getWeakReference(); - mReference->incRefCount(); + mPtr->incRefCount(); } - else - mReference = NULL; } -}; -//--------------------------------------------------------------- - -inline void WeakRefBase::clearWeakReferences() -{ - if (mReference) + void release() { - mReference->mObject = NULL; - mReference->decRefCount(); - mReference = NULL; - } -} + if (mPtr) + { + if constexpr (std::is_base_of_v) + { + mPtr->decRefCount(); + } + } -inline WeakRefBase::WeakReference* WeakRefBase::getWeakReference() -{ - if (!mReference) - { - mReference = new WeakReference(this); - mReference->incRefCount(); + mPtr = NULL; + mControl.reset(); } - return mReference; -} - -//--------------------------------------------------------------- +}; template< typename T > struct TypeTraits< WeakRefPtr< T > > : public _TypeTraits< WeakRefPtr< T > >