Skip to content

Commit 2b74bda

Browse files
authored
[GEN][ZH] Change reference counter implementation for StateMachine to avoid mismatch with Retail (#1078)
1 parent 1165fff commit 2b74bda

File tree

3 files changed

+81
-16
lines changed

3 files changed

+81
-16
lines changed

Core/Libraries/Source/WWVegas/WWLib/refcount.h

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,10 @@ struct ActiveRefStruct
103103
typedef DataNode<RefCountClass *> RefCountNodeClass;
104104
typedef List<RefCountNodeClass *> RefCountListClass;
105105

106+
/*
107+
** Note that Add_Ref and Release_Ref are always const, because copying, destroying and reference
108+
** counting const objects is meant to work.
109+
*/
106110
class RefCountClass
107111
{
108112
public:
@@ -249,10 +253,71 @@ class RefCountClass
249253
*/
250254
static bool Validate_Active_Ref(RefCountClass * obj);
251255

252-
#endif
256+
#endif // NDEBUG
253257

254258
};
255259

256260

261+
/*
262+
** This template class is meant to be used as a class member for compact reference counter placements.
263+
** A 1 byte reference counter can be alright if the counter is not reaching the value limits.
264+
*
265+
** Note that Add_Ref and Release_Ref are always const, because copying, destroying and reference
266+
** counting const objects is meant to work.
267+
*/
268+
template <typename IntegerType>
269+
class RefCountValue
270+
{
271+
public:
257272

258-
#endif
273+
RefCountValue(void)
274+
: NumRefs(1)
275+
{
276+
}
277+
278+
~RefCountValue(void)
279+
{
280+
WWASSERT(NumRefs == IntegerType(0));
281+
}
282+
283+
/*
284+
** Add_Ref, call this function if you are going to keep a pointer to this object.
285+
*/
286+
void Add_Ref(void) const
287+
{
288+
WWASSERT(NumRefs != ~IntegerType(0));
289+
++NumRefs;
290+
}
291+
292+
/*
293+
** Release_Ref, call this function when you no longer need the pointer to this object.
294+
** You can pass a static function of type void(*)(DeleteType*) or 'operator delete'.
295+
**
296+
** Note that this function takes a const ObjectType*, because this function is expected
297+
** to be called from within a const function as well.
298+
*/
299+
template <typename DeleteFunction, typename ObjectType>
300+
void Release_Ref(DeleteFunction deleteFunction, const ObjectType* objectToDelete) const
301+
{
302+
WWASSERT(NumRefs != IntegerType(0));
303+
if (--NumRefs == IntegerType(0))
304+
{
305+
deleteFunction(const_cast<ObjectType*>(objectToDelete));
306+
}
307+
}
308+
309+
/*
310+
** Check the number of references to this object.
311+
*/
312+
IntegerType Num_Refs(void) const
313+
{
314+
return NumRefs;
315+
}
316+
317+
private:
318+
319+
mutable IntegerType NumRefs;
320+
};
321+
322+
323+
#endif // REFCOUNT_H

Generals/Code/GameEngine/Include/Common/StateMachine.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ inline State::~State() { }
238238
/**
239239
* A finite state machine.
240240
*/
241-
class StateMachine : public MemoryPoolObject, public Snapshot, public RefCountClass
241+
class StateMachine : public MemoryPoolObject, public Snapshot
242242
{
243243
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( StateMachine, "StateMachinePool" );
244244

@@ -264,6 +264,10 @@ class StateMachine : public MemoryPoolObject, public Snapshot, public RefCountCl
264264

265265
virtual StateReturnType setState( StateID newStateID ); ///< change the current state of the machine (which may cause further state changes, due to onEnter)
266266

267+
void Add_Ref() const { m_refCount.Add_Ref(); }
268+
void Release_Ref() const { m_refCount.Release_Ref(MemoryPoolObject::deleteInstanceInternal, this); }
269+
void Num_Refs() const { m_refCount.Num_Refs(); }
270+
267271
StateID getCurrentStateID() const { return m_currentState ? m_currentState->getID() : INVALID_STATE_ID; } ///< return the id of the current state of the machine
268272
Bool isInIdleState() const { return m_currentState ? m_currentState->isIdle() : true; } // stateless things are considered 'idle'
269273
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
342346
virtual void xfer( Xfer *xfer );
343347
virtual void loadPostProcess();
344348

345-
// RefCountClass interface
346-
virtual void Delete_This()
347-
{
348-
MemoryPoolObject::deleteInstanceInternal(this);
349-
}
350-
351349
protected:
352350

353351
/**
@@ -384,6 +382,8 @@ class StateMachine : public MemoryPoolObject, public Snapshot, public RefCountCl
384382
Bool m_locked; ///< whether this machine is locked or not
385383
Bool m_defaultStateInited; ///< if initDefaultState has been called
386384

385+
RefCountValue<UnsignedByte> m_refCount;
386+
387387
#ifdef STATE_MACHINE_DEBUG
388388
Bool m_debugOutput;
389389
AsciiString m_name; ///< Human readable name of this state - for debugging. jba.

GeneralsMD/Code/GameEngine/Include/Common/StateMachine.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ inline State::~State() { }
239239
/**
240240
* A finite state machine.
241241
*/
242-
class StateMachine : public MemoryPoolObject, public Snapshot, public RefCountClass
242+
class StateMachine : public MemoryPoolObject, public Snapshot
243243
{
244244
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( StateMachine, "StateMachinePool" );
245245

@@ -265,6 +265,10 @@ class StateMachine : public MemoryPoolObject, public Snapshot, public RefCountCl
265265

266266
virtual StateReturnType setState( StateID newStateID ); ///< change the current state of the machine (which may cause further state changes, due to onEnter)
267267

268+
void Add_Ref() const { m_refCount.Add_Ref(); }
269+
void Release_Ref() const { m_refCount.Release_Ref(MemoryPoolObject::deleteInstanceInternal, this); }
270+
void Num_Refs() const { m_refCount.Num_Refs(); }
271+
268272
StateID getCurrentStateID() const { return m_currentState ? m_currentState->getID() : INVALID_STATE_ID; } ///< return the id of the current state of the machine
269273
Bool isInIdleState() const { return m_currentState ? m_currentState->isIdle() : true; } // stateless things are considered 'idle'
270274
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
344348
virtual void xfer( Xfer *xfer );
345349
virtual void loadPostProcess();
346350

347-
// RefCountClass interface
348-
virtual void Delete_This()
349-
{
350-
MemoryPoolObject::deleteInstanceInternal(this);
351-
}
352-
353351
protected:
354352

355353
/**
@@ -386,6 +384,8 @@ class StateMachine : public MemoryPoolObject, public Snapshot, public RefCountCl
386384
Bool m_locked; ///< whether this machine is locked or not
387385
Bool m_defaultStateInited; ///< if initDefaultState has been called
388386

387+
RefCountValue<UnsignedByte> m_refCount;
388+
389389
#ifdef STATE_MACHINE_DEBUG
390390
Bool m_debugOutput;
391391
AsciiString m_name; ///< Human readable name of this state - for debugging. jba.

0 commit comments

Comments
 (0)