/* ** Command & Conquer Renegade(tm) ** Copyright 2025 Electronic Arts Inc. ** ** This program is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation, either version 3 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program. If not, see . */ /*********************************************************************************************** *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S *** *********************************************************************************************** * * * Project Name : Commando / G Library * * * * $Archive:: /Commando/Code/wwlib/refcount.h $* * * * $Author:: Greg_h $* * * * $Modtime:: 9/13/01 8:38p $* * * * $Revision:: 24 $* * * *---------------------------------------------------------------------------------------------* * Functions: * * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #if _MSC_VER >= 1000 #pragma once #endif // _MSC_VER >= 1000 #ifndef REFCOUNT_H #define REFCOUNT_H #ifndef ALWAYS_H #include "always.h" #endif #ifndef LISTNODE_H #include "listnode.h" #endif class RefCountClass; #ifndef NDEBUG struct ActiveRefStruct { char * File; int Line; }; #define NEW_REF( C, P ) ( (C*)RefCountClass::Set_Ref_Owner( new C P, __FILE__, __LINE__ ) ) #define SET_REF_OWNER( P ) ( RefCountClass::Set_Ref_Owner( P, __FILE__, __LINE__ ) ) #else #define NEW_REF( C, P ) ( new C P ) #define SET_REF_OWNER( P ) P #endif /* ** Macros for setting and releasing a pointer to a ref counted object. ** If you have a member variable which can be pointed at a ref counted object and ** you want to point it at some object. You must release whatever it currently points at, ** point it at the new object, and add-ref the new object (if its not null...) */ #define REF_PTR_SET(dst,src) { if (src) (src)->Add_Ref(); if (dst) (dst)->Release_Ref(); (dst) = (src); } #define REF_PTR_RELEASE(x) { if (x) x->Release_Ref(); x = NULL; } /* ** Rules regarding the use of RefCountClass ** ** If you call a function that returns a pointer to a RefCountClass, ** you MUST Release_Ref() it ** ** If a functions calls you, and you return a pointer to a RefCountClass, ** you MUST Add_Ref() it ** ** If you call a function and pass a pointer to a RefCountClass, ** you DO NOT Add_Ref() it ** ** If a function calls you, and passes you a pointer to a RefCountClass, ** if you keep the pointer, you MUST Add_Ref() and Release_Ref() it ** otherwise, you DO NOT Add_Ref() or Release_Ref() it ** */ typedef DataNode RefCountNodeClass; typedef List RefCountListClass; class RefCountClass { public: RefCountClass(void) : NumRefs(1) #ifndef NDEBUG ,ActiveRefNode(this) #endif { #ifndef NDEBUG Add_Active_Ref(this); Inc_Total_Refs(this); #endif } RefCountClass(const RefCountClass & ) : NumRefs(1) #ifndef NDEBUG ,ActiveRefNode(this) #endif { #ifndef NDEBUG Add_Active_Ref(this); Inc_Total_Refs(this); #endif } /* ** Add_Ref, call this function if you are going to keep a pointer ** to this object. */ #ifdef NDEBUG WWINLINE void Add_Ref(void) { NumRefs++; } #else void Add_Ref(void); #endif /* ** Release_Ref, call this function when you no longer need the pointer ** to this object. */ WWINLINE void Release_Ref(void) { #ifndef NDEBUG Dec_Total_Refs(this); #endif NumRefs--; assert(NumRefs >= 0); if (NumRefs == 0) Delete_This(); } /* ** Check the number of references to this object. */ int Num_Refs(void) { return NumRefs; } /* ** Delete_This - this function will be called when the object is being ** destroyed as a result of its last reference being released. Its ** job is to actually destroy the object. */ virtual void Delete_This(void) { delete this; } /* ** Total_Refs - This static function can be used to get the total number ** of references that have been made. Once you've released all of your ** objects, it should go to zero. */ static int Total_Refs(void) { return TotalRefs; } protected: /* ** Destructor, user should not have access to this... */ virtual ~RefCountClass(void) { #ifndef NDEBUG Remove_Active_Ref(this); #endif assert(NumRefs == 0); } private: /* ** Current reference count of this object */ int NumRefs; /* ** Sum of all references to RefCountClass's. Should equal zero after ** everything has been released. */ static int TotalRefs; /* ** increments the total reference count */ static void Inc_Total_Refs(RefCountClass *); /* ** decrements the total reference count */ static void Dec_Total_Refs(RefCountClass *); public: #ifndef NDEBUG // Debugging stuff /* ** Node in the Active Refs List */ RefCountNodeClass ActiveRefNode; /* ** Auxiliary Active Ref Data */ ActiveRefStruct ActiveRefInfo; /* ** List of the active referenced objects */ static RefCountListClass ActiveRefList; /* ** Adds the ref obj pointer to the active ref list */ static RefCountClass * Add_Active_Ref(RefCountClass *obj); /* ** Updates the owner file/line for the given ref obj in the active ref list */ static RefCountClass * Set_Ref_Owner(RefCountClass *obj,char * file,int line); /* ** Remove the ref obj from the active ref list */ static void Remove_Active_Ref(RefCountClass * obj); /* ** Confirm the active ref object using the pointer of the refbaseclass as a search key */ static bool Validate_Active_Ref(RefCountClass * obj); #endif }; #endif