From 8181bed55c76be42a0dc65e7e789e0b67559b80f Mon Sep 17 00:00:00 2001 From: xezon <4720891+xezon@users.noreply.github.com> Date: Tue, 4 Aug 2026 20:28:21 +0200 Subject: [PATCH 1/3] refactor(refcountptr): Simplify RefCountPtr's Create_NoAddRef, Create_AddRef and add Assign_NoAddRef, Assign_AddRef --- Core/Libraries/Source/WWVegas/WWLib/ref_ptr.h | 78 ++++++++++++++----- .../GameEngine/Source/Common/StateMachine.cpp | 2 +- .../GameEngine/Source/GameLogic/AI/AI.cpp | 3 +- .../Source/GameLogic/AI/AIGroup.cpp | 6 +- .../Source/GameLogic/Object/Object.cpp | 2 +- 5 files changed, 67 insertions(+), 24 deletions(-) diff --git a/Core/Libraries/Source/WWVegas/WWLib/ref_ptr.h b/Core/Libraries/Source/WWVegas/WWLib/ref_ptr.h index f9a57c7c1ef..3cc7c1d4b82 100644 --- a/Core/Libraries/Source/WWVegas/WWLib/ref_ptr.h +++ b/Core/Libraries/Source/WWVegas/WWLib/ref_ptr.h @@ -217,6 +217,7 @@ class RefCountPtr // Creates a RefCountPtr and does not increment the reference counter of the passed object. // Is generally used for objects returned by operator new and "Get" functions. + // Prefer using Assign_NoAddRef. static RefCountPtr Create_NoAddRef(T *t) { WWASSERT(t == nullptr || t->Num_Refs() >= 1); @@ -225,13 +226,14 @@ class RefCountPtr // Creates a RefCountPtr and increments the reference counter of the passed object. // Is generally used for objects returned by "Peek" functions. + // Prefer using Assign_AddRef. static RefCountPtr Create_AddRef(T *t) { return RefCountPtr(t, RefCountPtr::PEEK); } RefCountPtr() - : Referent(0) + : Referent(nullptr) { } @@ -247,9 +249,9 @@ class RefCountPtr // This allows construction of the smart pointer from 0 (null) // Without allows unwanted conversions from T * (and related types, including void *) RefCountPtr(DummyPtrType * dummy) - : Referent(0) + : Referent(nullptr) { - WWASSERT(dummy == 0); + WWASSERT(dummy == nullptr); } #endif @@ -292,12 +294,41 @@ class RefCountPtr Referent->Release_Ref(); } - Referent = 0; + Referent = nullptr; return *this; } #endif + + // Assigns a pointer T and does not increment the reference counter of the passed object. + // Is generally used for objects returned by operator new and "Get" functions. + void Assign_NoAddRef(T *t) + { + WWASSERT(t == nullptr || t->Num_Refs() >= 1); + + if (Referent) { + Referent->Release_Ref(); + } + + Referent = t; + } + + // Assigns a pointer T and increments the reference counter of the passed object. + // Is generally used for objects returned by "Peek" functions. + void Assign_AddRef(T *t) + { + if (t != nullptr) { + t->Add_Ref(); + } + + if (Referent) { + Referent->Release_Ref(); + } + + Referent = t; + } + template const RefCountPtr & operator =(const RefCountPtr & rhs) { @@ -320,7 +351,6 @@ class RefCountPtr rhs.Referent->Add_Ref(); } - if (Referent) { Referent->Release_Ref(); } @@ -333,7 +363,7 @@ class RefCountPtr { if (Referent) { Referent->Release_Ref(); - Referent = 0; + Referent = nullptr; } } @@ -353,7 +383,7 @@ class RefCountPtr { if (Referent) { Referent->Release_Ref(); - Referent = 0; + Referent = nullptr; } } @@ -380,7 +410,7 @@ class RefCountPtr T * Release() { T * p = Referent; - Referent = 0; + Referent = nullptr; return p; } @@ -390,7 +420,7 @@ class RefCountPtr RefCountPtr(T * referent, ReferenceHandling reference_handling) : Referent(referent) { - if (reference_handling == PEEK && 0 != referent) { + if (reference_handling == PEEK && nullptr != referent) { referent->Add_Ref(); } } @@ -412,34 +442,46 @@ bool operator <(const RefCountPtr & lhs, const RefCountPtr & rhs) return lhs.Peek() < rhs.Peek(); } -// This comparison allows us to test our smart pointer against 0 using -// 0 == my_ptr +// This comparison allows us to test our smart pointer against null using +// nullptr == my_ptr template bool operator ==(DummyPtrType * dummy, const RefCountPtr & rhs) { - if (0 != dummy) { + if (nullptr != dummy) { WWASSERT(0); return false; } - return 0 == rhs.Peek(); + return nullptr == rhs.Peek(); } -// This comparison allows us to test our smart pointer against 0 using -// 0 != my_ptr +// This comparison allows us to test our smart pointer against null using +// nullptr != my_ptr template bool operator !=(DummyPtrType * dummy, const RefCountPtr & rhs) { - if (0 != dummy) { + if (nullptr != dummy) { WWASSERT(0); return true; } - return 0 != rhs.Peek(); + return nullptr != rhs.Peek(); } template RefCountPtr Static_Cast(const RefCountPtr & base) { - return RefCountPtr::Create_AddRef((Derived *)base.Peek()); + return RefCountPtr::Create_AddRef(static_cast(base.Peek())); +} + +template +RefCountPtr Create_AddRef(T *ptr) +{ + return RefCountPtr::Create_AddRef(ptr); +} + +template +RefCountPtr Create_NoAddRef(T *ptr) +{ + return RefCountPtr::Create_NoAddRef(ptr); } diff --git a/GeneralsMD/Code/GameEngine/Source/Common/StateMachine.cpp b/GeneralsMD/Code/GameEngine/Source/Common/StateMachine.cpp index 935fba19c5b..35842a82cc7 100644 --- a/GeneralsMD/Code/GameEngine/Source/Common/StateMachine.cpp +++ b/GeneralsMD/Code/GameEngine/Source/Common/StateMachine.cpp @@ -432,7 +432,7 @@ StateReturnType StateMachine::updateStateMachine() // Calling m_currentState->update() can release this state machine in certain circumstances, // for example if something kills the entity of this state machine as a result of this state update. // See https://github.com/TheSuperHackers/GeneralsGameCode/issues/212 - RefCountPtr refThis = RefCountPtr::Create_AddRef(this); + RefCountPtr refThis = Create_AddRef(this); // update() can change m_currentState, so save it for a moment... State* stateBeforeUpdate = m_currentState; diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AI.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AI.cpp index ff0d155d9f2..431fdadf167 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AI.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AI.cpp @@ -448,7 +448,8 @@ AIGroupPtr AI::createGroup() #if RETAIL_COMPATIBLE_AIGROUP AIGroup *group = newInstance(AIGroup); #else - AIGroupPtr group = AIGroupPtr::Create_NoAddRef(newInstance(AIGroup)); + AIGroupPtr group; + group.Assign_NoAddRef(newInstance(AIGroup)); #endif // add it to the list diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIGroup.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIGroup.cpp index dfc65a9c666..a47c88c9e7d 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIGroup.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIGroup.cpp @@ -211,7 +211,7 @@ Bool AIGroup::remove( Object *obj ) { #if !RETAIL_COMPATIBLE_AIGROUP // Defer deletion until the end of this function. - AIGroupPtr refThis = AIGroupPtr::Create_AddRef(this); + AIGroupPtr refThis = Create_AddRef(this); #endif // DEBUG_LOG(("***AIGROUP %x is removing Object %x (%s).", this, obj, obj->getTemplate()->getName().str())); @@ -250,7 +250,7 @@ void AIGroup::removeAll() { #if !RETAIL_COMPATIBLE_AIGROUP // Defer deletion until the end of this function. - AIGroupPtr refThis = AIGroupPtr::Create_AddRef(this); + AIGroupPtr refThis = Create_AddRef(this); #endif std::list memberList; @@ -2835,7 +2835,7 @@ void AIGroup::groupSell( CommandSourceType cmdSource ) { #if !RETAIL_COMPATIBLE_AIGROUP // Defer deletion until the end of this function. - AIGroupPtr refThis = AIGroupPtr::Create_AddRef(this); + AIGroupPtr refThis = Create_AddRef(this); #endif std::list::iterator i; diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp index 5c35b57b38d..575e8b674d9 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp @@ -6456,7 +6456,7 @@ void Object::enterGroup( AIGroup *group ) #if RETAIL_COMPATIBLE_AIGROUP m_group = group; #else - m_group = AIGroupPtr::Create_AddRef(group); + m_group.Assign_AddRef(group); #endif } From 68d4700d01811e1e4295c904f48028b5d2b669be Mon Sep 17 00:00:00 2001 From: xezon <4720891+xezon@users.noreply.github.com> Date: Wed, 5 Aug 2026 21:26:07 +0200 Subject: [PATCH 2/3] Rename functions to match WWVegas style --- Core/Libraries/Source/WWVegas/WWLib/ref_ptr.h | 32 +++++++++---------- .../GameEngine/Source/Common/StateMachine.cpp | 2 +- .../GameEngine/Source/GameLogic/AI/AI.cpp | 2 +- .../Source/GameLogic/AI/AIGroup.cpp | 6 ++-- .../Source/GameLogic/Object/Object.cpp | 2 +- 5 files changed, 22 insertions(+), 22 deletions(-) diff --git a/Core/Libraries/Source/WWVegas/WWLib/ref_ptr.h b/Core/Libraries/Source/WWVegas/WWLib/ref_ptr.h index 3cc7c1d4b82..f58f7b158ca 100644 --- a/Core/Libraries/Source/WWVegas/WWLib/ref_ptr.h +++ b/Core/Libraries/Source/WWVegas/WWLib/ref_ptr.h @@ -129,15 +129,15 @@ copying. To create a RefCountPtr from a raw pointer, use the global template functions - Create_NoAddRef should be used when wrapping a pointer that has just been created with NEW - Create_NoAddRef should be used when wrapping a pointer that has been returned from a "Get" function + Create_No_Add_Ref should be used when wrapping a pointer that has just been created with NEW + Create_No_Add_Ref should be used when wrapping a pointer that has been returned from a "Get" function (the function added a reference prior to returning the pointer) - Create_AddRef should be used when wrapping a pointer that has been returned from a "Peek" function + Create_Add_Ref should be used when wrapping a pointer that has been returned from a "Peek" function (the function did not add a reference prior to returning the pointer). - Create_NoAddRef and Create_AddRef are provided to allow old code to migrate from manual reference count + Create_No_Add_Ref and Create_Add_Ref are provided to allow old code to migrate from manual reference count management to RefCountPtr. New code written with RefCountPtr should rarely if ever use - Create_NoAddRef and Create_AddRef. + Create_No_Add_Ref and Create_Add_Ref. If it is absolutely necessary to extract the raw pointer, use Peek. Peek does not add a new reference to the object. Using a Peek'd object after its RefCountPtr has gone out of scope requires @@ -217,8 +217,8 @@ class RefCountPtr // Creates a RefCountPtr and does not increment the reference counter of the passed object. // Is generally used for objects returned by operator new and "Get" functions. - // Prefer using Assign_NoAddRef. - static RefCountPtr Create_NoAddRef(T *t) + // Prefer using Assign_No_Add_Ref. + static RefCountPtr Create_No_Add_Ref(T *t) { WWASSERT(t == nullptr || t->Num_Refs() >= 1); return RefCountPtr(t, RefCountPtr::GET); @@ -226,8 +226,8 @@ class RefCountPtr // Creates a RefCountPtr and increments the reference counter of the passed object. // Is generally used for objects returned by "Peek" functions. - // Prefer using Assign_AddRef. - static RefCountPtr Create_AddRef(T *t) + // Prefer using Assign_Add_Ref. + static RefCountPtr Create_Add_Ref(T *t) { return RefCountPtr(t, RefCountPtr::PEEK); } @@ -303,7 +303,7 @@ class RefCountPtr // Assigns a pointer T and does not increment the reference counter of the passed object. // Is generally used for objects returned by operator new and "Get" functions. - void Assign_NoAddRef(T *t) + void Assign_No_Add_Ref(T *t) { WWASSERT(t == nullptr || t->Num_Refs() >= 1); @@ -316,7 +316,7 @@ class RefCountPtr // Assigns a pointer T and increments the reference counter of the passed object. // Is generally used for objects returned by "Peek" functions. - void Assign_AddRef(T *t) + void Assign_Add_Ref(T *t) { if (t != nullptr) { t->Add_Ref(); @@ -471,17 +471,17 @@ bool operator !=(DummyPtrType * dummy, const RefCountPtr & rhs) template RefCountPtr Static_Cast(const RefCountPtr & base) { - return RefCountPtr::Create_AddRef(static_cast(base.Peek())); + return RefCountPtr::Create_Add_Ref(static_cast(base.Peek())); } template -RefCountPtr Create_AddRef(T *ptr) +RefCountPtr Create_Add_Ref(T *ptr) { - return RefCountPtr::Create_AddRef(ptr); + return RefCountPtr::Create_Add_Ref(ptr); } template -RefCountPtr Create_NoAddRef(T *ptr) +RefCountPtr Create_No_Add_Ref(T *ptr) { - return RefCountPtr::Create_NoAddRef(ptr); + return RefCountPtr::Create_No_Add_Ref(ptr); } diff --git a/GeneralsMD/Code/GameEngine/Source/Common/StateMachine.cpp b/GeneralsMD/Code/GameEngine/Source/Common/StateMachine.cpp index 35842a82cc7..1a0bc0f6315 100644 --- a/GeneralsMD/Code/GameEngine/Source/Common/StateMachine.cpp +++ b/GeneralsMD/Code/GameEngine/Source/Common/StateMachine.cpp @@ -432,7 +432,7 @@ StateReturnType StateMachine::updateStateMachine() // Calling m_currentState->update() can release this state machine in certain circumstances, // for example if something kills the entity of this state machine as a result of this state update. // See https://github.com/TheSuperHackers/GeneralsGameCode/issues/212 - RefCountPtr refThis = Create_AddRef(this); + RefCountPtr refThis = Create_Add_Ref(this); // update() can change m_currentState, so save it for a moment... State* stateBeforeUpdate = m_currentState; diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AI.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AI.cpp index 431fdadf167..975cb6f832c 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AI.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AI.cpp @@ -449,7 +449,7 @@ AIGroupPtr AI::createGroup() AIGroup *group = newInstance(AIGroup); #else AIGroupPtr group; - group.Assign_NoAddRef(newInstance(AIGroup)); + group.Assign_No_Add_Ref(newInstance(AIGroup)); #endif // add it to the list diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIGroup.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIGroup.cpp index a47c88c9e7d..607a643e560 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIGroup.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIGroup.cpp @@ -211,7 +211,7 @@ Bool AIGroup::remove( Object *obj ) { #if !RETAIL_COMPATIBLE_AIGROUP // Defer deletion until the end of this function. - AIGroupPtr refThis = Create_AddRef(this); + AIGroupPtr refThis = Create_Add_Ref(this); #endif // DEBUG_LOG(("***AIGROUP %x is removing Object %x (%s).", this, obj, obj->getTemplate()->getName().str())); @@ -250,7 +250,7 @@ void AIGroup::removeAll() { #if !RETAIL_COMPATIBLE_AIGROUP // Defer deletion until the end of this function. - AIGroupPtr refThis = Create_AddRef(this); + AIGroupPtr refThis = Create_Add_Ref(this); #endif std::list memberList; @@ -2835,7 +2835,7 @@ void AIGroup::groupSell( CommandSourceType cmdSource ) { #if !RETAIL_COMPATIBLE_AIGROUP // Defer deletion until the end of this function. - AIGroupPtr refThis = Create_AddRef(this); + AIGroupPtr refThis = Create_Add_Ref(this); #endif std::list::iterator i; diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp index 575e8b674d9..800b5c20e4a 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp @@ -6456,7 +6456,7 @@ void Object::enterGroup( AIGroup *group ) #if RETAIL_COMPATIBLE_AIGROUP m_group = group; #else - m_group.Assign_AddRef(group); + m_group.Assign_Add_Ref(group); #endif } From a1a7e1a3660c6e9d1544a3b318237de74a554216 Mon Sep 17 00:00:00 2001 From: xezon <4720891+xezon@users.noreply.github.com> Date: Wed, 5 Aug 2026 21:27:59 +0200 Subject: [PATCH 3/3] Replicate in Generals --- Generals/Code/GameEngine/Source/Common/StateMachine.cpp | 2 +- Generals/Code/GameEngine/Source/GameLogic/AI/AI.cpp | 3 ++- Generals/Code/GameEngine/Source/GameLogic/AI/AIGroup.cpp | 6 +++--- Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/Generals/Code/GameEngine/Source/Common/StateMachine.cpp b/Generals/Code/GameEngine/Source/Common/StateMachine.cpp index b1c5b20e015..7f700a83648 100644 --- a/Generals/Code/GameEngine/Source/Common/StateMachine.cpp +++ b/Generals/Code/GameEngine/Source/Common/StateMachine.cpp @@ -432,7 +432,7 @@ StateReturnType StateMachine::updateStateMachine() // Calling m_currentState->update() can release this state machine in certain circumstances, // for example if something kills the entity of this state machine as a result of this state update. // See https://github.com/TheSuperHackers/GeneralsGameCode/issues/212 - RefCountPtr refThis = RefCountPtr::Create_AddRef(this); + RefCountPtr refThis = Create_Add_Ref(this); // update() can change m_currentState, so save it for a moment... State* stateBeforeUpdate = m_currentState; diff --git a/Generals/Code/GameEngine/Source/GameLogic/AI/AI.cpp b/Generals/Code/GameEngine/Source/GameLogic/AI/AI.cpp index f3b2f362db5..ad9493ccf4f 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/AI/AI.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/AI/AI.cpp @@ -445,7 +445,8 @@ AIGroupPtr AI::createGroup() #if RETAIL_COMPATIBLE_AIGROUP AIGroup *group = newInstance(AIGroup); #else - AIGroupPtr group = AIGroupPtr::Create_NoAddRef(newInstance(AIGroup)); + AIGroupPtr group; + group.Assign_No_Add_Ref(newInstance(AIGroup)); #endif // add it to the list diff --git a/Generals/Code/GameEngine/Source/GameLogic/AI/AIGroup.cpp b/Generals/Code/GameEngine/Source/GameLogic/AI/AIGroup.cpp index c91139780ea..1799a20e537 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/AI/AIGroup.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/AI/AIGroup.cpp @@ -211,7 +211,7 @@ Bool AIGroup::remove( Object *obj ) { #if !RETAIL_COMPATIBLE_AIGROUP // Defer deletion until the end of this function. - AIGroupPtr refThis = AIGroupPtr::Create_AddRef(this); + AIGroupPtr refThis = Create_Add_Ref(this); #endif // DEBUG_LOG(("***AIGROUP %x is removing Object %x (%s).", this, obj, obj->getTemplate()->getName().str())); @@ -250,7 +250,7 @@ void AIGroup::removeAll() { #if !RETAIL_COMPATIBLE_AIGROUP // Defer deletion until the end of this function. - AIGroupPtr refThis = AIGroupPtr::Create_AddRef(this); + AIGroupPtr refThis = Create_Add_Ref(this); #endif std::list memberList; @@ -2762,7 +2762,7 @@ void AIGroup::groupSell( CommandSourceType cmdSource ) { #if !RETAIL_COMPATIBLE_AIGROUP // Defer deletion until the end of this function. - AIGroupPtr refThis = AIGroupPtr::Create_AddRef(this); + AIGroupPtr refThis = Create_Add_Ref(this); #endif std::list::iterator i; diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp index 55770f4ea0d..24c4e694bb1 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp @@ -5613,7 +5613,7 @@ void Object::enterGroup( AIGroup *group ) #if RETAIL_COMPATIBLE_AIGROUP m_group = group; #else - m_group = AIGroupPtr::Create_AddRef(group); + m_group.Assign_Add_Ref(group); #endif }