diff --git a/Core/Libraries/Source/WWVegas/WWLib/refcount.h b/Core/Libraries/Source/WWVegas/WWLib/refcount.h index 41a5789a739..c7d1a702936 100644 --- a/Core/Libraries/Source/WWVegas/WWLib/refcount.h +++ b/Core/Libraries/Source/WWVegas/WWLib/refcount.h @@ -103,6 +103,10 @@ struct ActiveRefStruct typedef DataNode RefCountNodeClass; typedef List RefCountListClass; +/* +** Note that Add_Ref and Release_Ref are always const, because copying, destroying and reference +** counting const objects is meant to work. +*/ class RefCountClass { public: @@ -249,10 +253,71 @@ class RefCountClass */ static bool Validate_Active_Ref(RefCountClass * obj); -#endif +#endif // NDEBUG }; +/* +** This template class is meant to be used as a class member for compact reference counter placements. +** A 1 byte reference counter can be alright if the counter is not reaching the value limits. +* +** Note that Add_Ref and Release_Ref are always const, because copying, destroying and reference +** counting const objects is meant to work. +*/ +template +class RefCountValue +{ +public: -#endif + RefCountValue(void) + : NumRefs(1) + { + } + + ~RefCountValue(void) + { + WWASSERT(NumRefs == IntegerType(0)); + } + + /* + ** Add_Ref, call this function if you are going to keep a pointer to this object. + */ + void Add_Ref(void) const + { + WWASSERT(NumRefs != ~IntegerType(0)); + ++NumRefs; + } + + /* + ** Release_Ref, call this function when you no longer need the pointer to this object. + ** You can pass a static function of type void(*)(DeleteType*) or 'operator delete'. + ** + ** Note that this function takes a const ObjectType*, because this function is expected + ** to be called from within a const function as well. + */ + template + void Release_Ref(DeleteFunction deleteFunction, const ObjectType* objectToDelete) const + { + WWASSERT(NumRefs != IntegerType(0)); + if (--NumRefs == IntegerType(0)) + { + deleteFunction(const_cast(objectToDelete)); + } + } + + /* + ** Check the number of references to this object. + */ + IntegerType Num_Refs(void) const + { + return NumRefs; + } + +private: + + mutable IntegerType NumRefs; +}; + + +#endif // REFCOUNT_H diff --git a/Generals/Code/GameEngine/Include/Common/StateMachine.h b/Generals/Code/GameEngine/Include/Common/StateMachine.h index 3d1dd9e5521..534f9c12a92 100644 --- a/Generals/Code/GameEngine/Include/Common/StateMachine.h +++ b/Generals/Code/GameEngine/Include/Common/StateMachine.h @@ -238,7 +238,7 @@ inline State::~State() { } /** * A finite state machine. */ -class StateMachine : public MemoryPoolObject, public Snapshot, public RefCountClass +class StateMachine : public MemoryPoolObject, public Snapshot { MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( StateMachine, "StateMachinePool" ); @@ -264,6 +264,10 @@ class StateMachine : public MemoryPoolObject, public Snapshot, public RefCountCl virtual StateReturnType setState( StateID newStateID ); ///< change the current state of the machine (which may cause further state changes, due to onEnter) + void Add_Ref() const { m_refCount.Add_Ref(); } + void Release_Ref() const { m_refCount.Release_Ref(MemoryPoolObject::deleteInstanceInternal, this); } + void Num_Refs() const { m_refCount.Num_Refs(); } + StateID getCurrentStateID() const { return m_currentState ? m_currentState->getID() : INVALID_STATE_ID; } ///< return the id of the current state of the machine Bool isInIdleState() const { return m_currentState ? m_currentState->isIdle() : true; } // stateless things are considered 'idle' Bool isInAttackState() const { return m_currentState ? m_currentState->isAttack() : true; } // stateless things are considered 'idle' @@ -342,12 +346,6 @@ class StateMachine : public MemoryPoolObject, public Snapshot, public RefCountCl virtual void xfer( Xfer *xfer ); virtual void loadPostProcess(); - // RefCountClass interface - virtual void Delete_This() - { - MemoryPoolObject::deleteInstanceInternal(this); - } - protected: /** @@ -384,6 +382,8 @@ class StateMachine : public MemoryPoolObject, public Snapshot, public RefCountCl Bool m_locked; ///< whether this machine is locked or not Bool m_defaultStateInited; ///< if initDefaultState has been called + RefCountValue m_refCount; + #ifdef STATE_MACHINE_DEBUG Bool m_debugOutput; AsciiString m_name; ///< Human readable name of this state - for debugging. jba. diff --git a/GeneralsMD/Code/GameEngine/Include/Common/StateMachine.h b/GeneralsMD/Code/GameEngine/Include/Common/StateMachine.h index 7478a97dd62..d99abfdfa5b 100644 --- a/GeneralsMD/Code/GameEngine/Include/Common/StateMachine.h +++ b/GeneralsMD/Code/GameEngine/Include/Common/StateMachine.h @@ -239,7 +239,7 @@ inline State::~State() { } /** * A finite state machine. */ -class StateMachine : public MemoryPoolObject, public Snapshot, public RefCountClass +class StateMachine : public MemoryPoolObject, public Snapshot { MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( StateMachine, "StateMachinePool" ); @@ -265,6 +265,10 @@ class StateMachine : public MemoryPoolObject, public Snapshot, public RefCountCl virtual StateReturnType setState( StateID newStateID ); ///< change the current state of the machine (which may cause further state changes, due to onEnter) + void Add_Ref() const { m_refCount.Add_Ref(); } + void Release_Ref() const { m_refCount.Release_Ref(MemoryPoolObject::deleteInstanceInternal, this); } + void Num_Refs() const { m_refCount.Num_Refs(); } + StateID getCurrentStateID() const { return m_currentState ? m_currentState->getID() : INVALID_STATE_ID; } ///< return the id of the current state of the machine Bool isInIdleState() const { return m_currentState ? m_currentState->isIdle() : true; } // stateless things are considered 'idle' Bool isInAttackState() const { return m_currentState ? m_currentState->isAttack() : true; } // stateless things are considered 'idle' @@ -344,12 +348,6 @@ class StateMachine : public MemoryPoolObject, public Snapshot, public RefCountCl virtual void xfer( Xfer *xfer ); virtual void loadPostProcess(); - // RefCountClass interface - virtual void Delete_This() - { - MemoryPoolObject::deleteInstanceInternal(this); - } - protected: /** @@ -386,6 +384,8 @@ class StateMachine : public MemoryPoolObject, public Snapshot, public RefCountCl Bool m_locked; ///< whether this machine is locked or not Bool m_defaultStateInited; ///< if initDefaultState has been called + RefCountValue m_refCount; + #ifdef STATE_MACHINE_DEBUG Bool m_debugOutput; AsciiString m_name; ///< Human readable name of this state - for debugging. jba.