refcount.h 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. /*
  2. ** Command & Conquer Generals Zero Hour(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /***********************************************************************************************
  19. *** 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 ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : Commando / G Library *
  23. * *
  24. * $Archive:: /Commando/Code/wwlib/refcount.h $*
  25. * *
  26. * $Author:: Greg_h $*
  27. * *
  28. * $Modtime:: 9/13/01 8:38p $*
  29. * *
  30. * $Revision:: 24 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. #if _MSC_VER >= 1000
  36. #pragma once
  37. #endif // _MSC_VER >= 1000
  38. #ifndef REFCOUNT_H
  39. #define REFCOUNT_H
  40. #ifndef ALWAYS_H
  41. #include "always.h"
  42. #endif
  43. #ifndef LISTNODE_H
  44. #include "listnode.h"
  45. #endif
  46. class RefCountClass;
  47. #ifndef NDEBUG
  48. struct ActiveRefStruct
  49. {
  50. char * File;
  51. int Line;
  52. };
  53. #define NEW_REF( C, P ) ( (C*)RefCountClass::Set_Ref_Owner( W3DNEW C P, __FILE__, __LINE__ ) )
  54. #define SET_REF_OWNER( P ) ( RefCountClass::Set_Ref_Owner( P, __FILE__, __LINE__ ) )
  55. #else
  56. #define NEW_REF( C, P ) ( W3DNEW C P )
  57. #define SET_REF_OWNER( P ) P
  58. #endif
  59. /*
  60. ** Macros for setting and releasing a pointer to a ref counted object.
  61. ** If you have a member variable which can be pointed at a ref counted object and
  62. ** you want to point it at some object. You must release whatever it currently points at,
  63. ** point it at the new object, and add-ref the new object (if its not null...)
  64. */
  65. #define REF_PTR_SET(dst,src) { if (src) (src)->Add_Ref(); if (dst) (dst)->Release_Ref(); (dst) = (src); }
  66. #define REF_PTR_RELEASE(x) { if (x) x->Release_Ref(); x = NULL; }
  67. /*
  68. ** Rules regarding the use of RefCountClass
  69. **
  70. ** If you call a function that returns a pointer to a RefCountClass,
  71. ** you MUST Release_Ref() it
  72. **
  73. ** If a functions calls you, and you return a pointer to a RefCountClass,
  74. ** you MUST Add_Ref() it
  75. **
  76. ** If you call a function and pass a pointer to a RefCountClass,
  77. ** you DO NOT Add_Ref() it
  78. **
  79. ** If a function calls you, and passes you a pointer to a RefCountClass,
  80. ** if you keep the pointer, you MUST Add_Ref() and Release_Ref() it
  81. ** otherwise, you DO NOT Add_Ref() or Release_Ref() it
  82. **
  83. */
  84. typedef DataNode<RefCountClass *> RefCountNodeClass;
  85. typedef List<RefCountNodeClass *> RefCountListClass;
  86. class RefCountClass
  87. {
  88. public:
  89. RefCountClass(void) :
  90. NumRefs(1)
  91. #ifndef NDEBUG
  92. ,ActiveRefNode(this)
  93. #endif
  94. {
  95. #ifndef NDEBUG
  96. Add_Active_Ref(this);
  97. Inc_Total_Refs(this);
  98. #endif
  99. }
  100. RefCountClass(const RefCountClass & ) :
  101. NumRefs(1)
  102. #ifndef NDEBUG
  103. ,ActiveRefNode(this)
  104. #endif
  105. {
  106. #ifndef NDEBUG
  107. Add_Active_Ref(this);
  108. Inc_Total_Refs(this);
  109. #endif
  110. }
  111. /*
  112. ** Add_Ref, call this function if you are going to keep a pointer
  113. ** to this object.
  114. */
  115. #ifdef NDEBUG
  116. WWINLINE void Add_Ref(void) const { NumRefs++; }
  117. #else
  118. void Add_Ref(void) const;
  119. #endif
  120. /*
  121. ** Release_Ref, call this function when you no longer need the pointer
  122. ** to this object.
  123. */
  124. WWINLINE void Release_Ref(void) const {
  125. #ifndef NDEBUG
  126. Dec_Total_Refs(this);
  127. #endif
  128. NumRefs--;
  129. assert(NumRefs >= 0);
  130. if (NumRefs == 0) const_cast<RefCountClass*>(this)->Delete_This();
  131. }
  132. /*
  133. ** Check the number of references to this object.
  134. */
  135. int Num_Refs(void) const { return NumRefs; }
  136. /*
  137. ** Delete_This - this function will be called when the object is being
  138. ** destroyed as a result of its last reference being released. Its
  139. ** job is to actually destroy the object.
  140. */
  141. virtual void Delete_This(void) { delete this; }
  142. /*
  143. ** Total_Refs - This static function can be used to get the total number
  144. ** of references that have been made. Once you've released all of your
  145. ** objects, it should go to zero.
  146. */
  147. static int Total_Refs(void) { return TotalRefs; }
  148. protected:
  149. /*
  150. ** Destructor, user should not have access to this...
  151. */
  152. virtual ~RefCountClass(void)
  153. {
  154. #ifndef NDEBUG
  155. Remove_Active_Ref(this);
  156. #endif
  157. assert(NumRefs == 0);
  158. }
  159. private:
  160. /*
  161. ** Current reference count of this object
  162. */
  163. mutable int NumRefs;
  164. /*
  165. ** Sum of all references to RefCountClass's. Should equal zero after
  166. ** everything has been released.
  167. */
  168. static int TotalRefs;
  169. /*
  170. ** increments the total reference count
  171. */
  172. static void Inc_Total_Refs(const RefCountClass *);
  173. /*
  174. ** decrements the total reference count
  175. */
  176. static void Dec_Total_Refs(const RefCountClass *);
  177. public:
  178. #ifndef NDEBUG // Debugging stuff
  179. /*
  180. ** Node in the Active Refs List
  181. */
  182. RefCountNodeClass ActiveRefNode;
  183. /*
  184. ** Auxiliary Active Ref Data
  185. */
  186. ActiveRefStruct ActiveRefInfo;
  187. /*
  188. ** List of the active referenced objects
  189. */
  190. static RefCountListClass ActiveRefList;
  191. /*
  192. ** Adds the ref obj pointer to the active ref list
  193. */
  194. static RefCountClass * Add_Active_Ref(RefCountClass *obj);
  195. /*
  196. ** Updates the owner file/line for the given ref obj in the active ref list
  197. */
  198. static RefCountClass * Set_Ref_Owner(RefCountClass *obj,char * file,int line);
  199. /*
  200. ** Remove the ref obj from the active ref list
  201. */
  202. static void Remove_Active_Ref(RefCountClass * obj);
  203. /*
  204. ** Confirm the active ref object using the pointer of the refbaseclass as a search key
  205. */
  206. static bool Validate_Active_Ref(RefCountClass * obj);
  207. #endif
  208. };
  209. #endif