RefPtr.h 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. /*
  2. ** Command & Conquer Renegade(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. *
  20. * FILE
  21. * $Archive: /Commando/Code/Launcher/Toolkit/Support/RefPtr.h $
  22. *
  23. * DESCRIPTION
  24. * RefPtr<> and RefPtrConst<> are const-friendly, polymorphic reference
  25. * counting smart pointers.
  26. *
  27. * The pointed-to class must be derived from RefCount.
  28. *
  29. * RefPtr<X> replaces X*
  30. * RefPtrConst<X> replaces const X*
  31. *
  32. * Dynamic_Cast<X> replaces dynamic_cast<X*> and dynamic_cast<X&>
  33. * Reinterpret_Cast<X> replaces reinterpret_cast<X*> and reinterpret_cast<X&>
  34. * Const_Cast<X> replaces const_cast<X*> and const_cast<X&>
  35. *
  36. * IsValid() replaces (x != NULL)
  37. *
  38. * Member function Attach() or assigning RefPtr<X>() will NULL a pointer.
  39. *
  40. * Generally, RefPtr<> and RefPtrConst<> behave like their raw pointer
  41. * counterparts, except of course they are reference counted and will delete
  42. * the pointed-to object when the last reference is lost. The major
  43. * syntatical differences are the use of RefPtrConst<> to represent a pointer
  44. * to a constant object (I found it impossible to represent this within rc_ptr)
  45. * and the use of the upper-case cast functions (it is not possible to overload
  46. * these built-in functions).
  47. *
  48. * An explicit goal of this class is to completely avoid the "new" and "delete"
  49. * operators in client code. The constructors for these pointers are private;
  50. * they are friends of the pointed-to class. This forces the use of Factory
  51. * Method functions (or similar) in the pointed-to class. Pointed-to classes
  52. * should make the constructor protected or private to disallow clients from
  53. * creating an instance with "new". If this is done, it becomes very difficult
  54. * for the client to accidentally leak objects and/or misuse the pointed-to
  55. * class or the reference counting pointers.
  56. *
  57. * PROGRAMMER
  58. * Steven Clinard
  59. * $Author: Denzil_l $
  60. *
  61. * VERSION INFO
  62. * $Modtime: 8/30/00 10:12a $
  63. * $Revision: 1 $
  64. *
  65. ******************************************************************************/
  66. #ifndef REFPTR_H
  67. #define REFPTR_H
  68. #include "VisualC.h"
  69. #include "RefCounted.h"
  70. #include <stddef.h>
  71. #include <assert.h>
  72. template<typename Type> class RefPtr;
  73. template<typename Type> class RefPtrConst;
  74. class RefPtrBase
  75. {
  76. public:
  77. inline bool operator==(const RefPtrBase& rhs) const
  78. {return (mRefObject == rhs.mRefObject);}
  79. inline bool operator!=(const RefPtrBase& rhs) const
  80. {return !operator==(rhs);}
  81. inline bool IsValid(void) const
  82. {return (mRefObject != NULL);}
  83. inline void Detach(void)
  84. {
  85. if (IsValid())
  86. {
  87. mRefObject->Release();
  88. mRefObject = NULL;
  89. }
  90. }
  91. protected:
  92. RefPtrBase()
  93. : mRefObject(NULL)
  94. {}
  95. RefPtrBase(RefCounted* object)
  96. : mRefObject(object)
  97. {
  98. assert((mRefObject == NULL) || (mRefObject->mRefCount == 0));
  99. if (IsValid())
  100. {
  101. mRefObject->AddReference();
  102. }
  103. }
  104. RefPtrBase(const RefPtrBase& object)
  105. : mRefObject(object.mRefObject)
  106. {
  107. assert(false); // why is this being called?
  108. if (IsValid())
  109. {
  110. mRefObject->AddReference();
  111. }
  112. }
  113. virtual ~RefPtrBase()
  114. {Detach();}
  115. const RefPtrBase& operator=(const RefPtrBase&);
  116. inline RefCounted* const GetRefObject(void)
  117. {return mRefObject;}
  118. inline const RefCounted* const GetRefObject(void) const
  119. {return mRefObject;}
  120. inline void Attach(RefCounted* object)
  121. {
  122. // If objects are different
  123. if (object != mRefObject)
  124. {
  125. // Add reference to new object
  126. if (object != NULL)
  127. {
  128. object->AddReference();
  129. }
  130. // Release reference to old object
  131. Detach();
  132. // Assign new object
  133. mRefObject = object;
  134. }
  135. }
  136. private:
  137. RefCounted* mRefObject;
  138. template<typename Derived>
  139. friend RefPtr<Derived> Dynamic_Cast(RefPtrBase&);
  140. template<typename Type>
  141. friend RefPtr<Type> Reinterpret_Cast(RefPtrBase&);
  142. };
  143. template<typename Type> class RefPtr
  144. : public RefPtrBase
  145. {
  146. public:
  147. RefPtr()
  148. : RefPtrBase()
  149. {}
  150. template<typename Derived>
  151. RefPtr(const RefPtr<Derived>& derived)
  152. : RefPtrBase()
  153. {
  154. Attach(const_cast<Derived*>(derived.ReferencedObject()));
  155. }
  156. RefPtr(const RefPtr<Type>& object)
  157. : RefPtrBase()
  158. {
  159. Attach(const_cast<Type*>(object.ReferencedObject()));
  160. }
  161. virtual ~RefPtr()
  162. {}
  163. template<typename Derived>
  164. inline const RefPtr<Type>& operator=(const RefPtr<Derived>& derived)
  165. {
  166. Attach(const_cast<Derived*>(derived.ReferencedObject()));
  167. return *this;
  168. }
  169. inline const RefPtr<Type>& operator=(const RefPtr<Type>& object)
  170. {
  171. Attach(const_cast<Type*>(object.ReferencedObject()));
  172. return *this;
  173. }
  174. inline Type& operator*() const
  175. {
  176. assert(IsValid());
  177. return *const_cast<Type*>(ReferencedObject());
  178. }
  179. inline Type* const operator->() const
  180. {
  181. assert(IsValid());
  182. return const_cast<Type*>(ReferencedObject());
  183. }
  184. // These are public mostly because I can't seem to declare rc_ptr<Other> as a friend
  185. inline Type* const ReferencedObject(void)
  186. {return reinterpret_cast<Type*>(GetRefObject());}
  187. inline const Type* const ReferencedObject(void) const
  188. {return reinterpret_cast<const Type*>(GetRefObject());}
  189. RefPtr(Type* object)
  190. : RefPtrBase()
  191. {
  192. Attach(object);
  193. }
  194. inline const RefPtr<Type>& operator=(Type* object)
  195. {
  196. Attach(object);
  197. return *this;
  198. }
  199. private:
  200. friend RefPtr<Type> Dynamic_Cast(RefPtrBase&);
  201. friend RefPtr<Type> Reinterpret_Cast(RefPtrBase&);
  202. friend RefPtr<Type> Const_Cast(RefPtrConst<Type>&);
  203. };
  204. template<typename Type> class RefPtrConst
  205. : public RefPtrBase
  206. {
  207. public:
  208. RefPtrConst()
  209. : RefPtrConst()
  210. {}
  211. template<typename Derived>
  212. RefPtrConst(const RefPtr<Derived>& derived)
  213. : RefPtrBase()
  214. {
  215. Attach(derived.ReferencedObject());
  216. }
  217. RefPtrConst(const RefPtr<Type>& object)
  218. : RefPtrBase()
  219. {
  220. Attach(const_cast<Type* const >(object.ReferencedObject()));
  221. }
  222. template<typename Derived>
  223. RefPtrConst(const RefPtrConst<Derived>& derived)
  224. : RefPtrBase()
  225. {
  226. Attach(derived.ReferencedObject());
  227. }
  228. RefPtrConst(const RefPtrConst<Type>& object)
  229. : RefPtrBase()
  230. {
  231. Attach(object.ReferencedObject());
  232. }
  233. template<typename Derived>
  234. inline const RefPtrConst<Type>& operator=(const RefPtr<Derived>& derived)
  235. {
  236. Attach(derived.ReferencedObject());
  237. return *this;
  238. }
  239. inline const RefPtrConst<Type>& operator=(const RefPtr<Type>& object)
  240. {
  241. Attach(object.ReferencedObject());
  242. return *this;
  243. }
  244. template<typename Derived>
  245. inline const RefPtrConst<Type>& operator=(const RefPtrConst<Derived>& derived)
  246. {
  247. Attach(derived.ReferencedObject());
  248. return *this;
  249. }
  250. inline const RefPtrConst<Type>& operator=(const RefPtrConst<Type>& object)
  251. {
  252. Attach(object.ReferencedObject());
  253. return *this;
  254. }
  255. virtual ~RefPtrConst()
  256. {}
  257. inline const Type& operator*() const
  258. {
  259. assert(IsValid());
  260. return *ReferencedObject();
  261. }
  262. inline const Type* const operator->() const
  263. {
  264. assert(IsValid());
  265. return ReferencedObject();
  266. }
  267. // This is public mostly because I can't seem to declare rc_ptr<Other> as a friend
  268. inline const Type* const ReferencedObject() const
  269. {return reinterpret_cast<const Type*>(GetRefObject());}
  270. RefPtrConst(const Type* object)
  271. : RefPtrBase()
  272. {
  273. Attach(object);
  274. }
  275. const RefPtrConst<Type>& operator=(const Type* object)
  276. {
  277. Attach(object);
  278. }
  279. };
  280. template<typename Derived>
  281. RefPtr<Derived> Dynamic_Cast(RefPtrBase& base)
  282. {
  283. RefPtr<Derived> derived;
  284. derived.Attach(base.GetRefObject());
  285. return derived;
  286. }
  287. template<typename Type>
  288. RefPtr<Type> Reinterpret_Cast(RefPtrBase& rhs)
  289. {
  290. RefPtr<Type> object;
  291. object.Attach(rhs.GetRefObject());
  292. return object;
  293. }
  294. template<typename Type>
  295. RefPtr<Type> Const_Cast(RefPtrConst<Type>& rhs)
  296. {
  297. RefPtr<Type> object;
  298. object.Attach(rhs.ReferencedObject());
  299. return object;
  300. }
  301. #endif // RC_PTR_H