RefPtr.h 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  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/WWOnline/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: 7/06/01 4:23p $
  63. * $Revision: 1 $
  64. *
  65. ******************************************************************************/
  66. #ifndef __REFPTR_H__
  67. #define __REFPTR_H__
  68. #include "RefCounted.h"
  69. #include <stddef.h>
  70. #include <assert.h>
  71. template<typename Type> class RefPtr;
  72. template<typename Type> class RefPtrConst;
  73. class RefPtrBase
  74. {
  75. public:
  76. inline bool operator==(const RefPtrBase& rhs) const
  77. {return (mRefObject == rhs.mRefObject);}
  78. inline bool operator!=(const RefPtrBase& rhs) const
  79. {return !operator==(rhs);}
  80. inline bool IsValid(void) const
  81. {return (mRefObject != NULL);}
  82. inline void Release(void)
  83. {
  84. if (IsValid())
  85. {
  86. mRefObject->ReleaseReference();
  87. mRefObject = NULL;
  88. }
  89. }
  90. protected:
  91. RefPtrBase() :
  92. mRefObject(NULL)
  93. {}
  94. RefPtrBase(RefCounted* object) :
  95. mRefObject(object)
  96. {
  97. assert((mRefObject == NULL) || (mRefObject->ReferenceCount() == 0));
  98. if (IsValid())
  99. {
  100. mRefObject->AddReference();
  101. }
  102. }
  103. RefPtrBase(const RefPtrBase& object) :
  104. mRefObject(object.mRefObject)
  105. {
  106. assert(!"RefPtrBase(const RefPtrBase&) - Why is this being called?");
  107. if (IsValid())
  108. {
  109. mRefObject->AddReference();
  110. }
  111. }
  112. virtual ~RefPtrBase()
  113. {Release();}
  114. const RefPtrBase& operator=(const RefPtrBase&);
  115. inline RefCounted* const GetRefObject(void)
  116. {return mRefObject;}
  117. inline const RefCounted* const GetRefObject(void) const
  118. {return mRefObject;}
  119. inline void Attach(RefCounted* object)
  120. {
  121. // If objects are different
  122. if (object != mRefObject)
  123. {
  124. // Add reference to new object
  125. if (object != NULL)
  126. {
  127. object->AddReference();
  128. }
  129. // Release reference to old object
  130. Release();
  131. // Assign new object
  132. mRefObject = object;
  133. }
  134. }
  135. private:
  136. RefCounted* mRefObject;
  137. template<typename Derived>
  138. friend RefPtr<Derived> Dynamic_Cast(RefPtrBase&);
  139. template<typename Type>
  140. friend RefPtr<Type> Reinterpret_Cast(RefPtrBase&);
  141. };
  142. template<typename Type> class RefPtr :
  143. public RefPtrBase
  144. {
  145. public:
  146. RefPtr() :
  147. RefPtrBase()
  148. {}
  149. template<typename Derived>
  150. RefPtr(const RefPtr<Derived>& derived) :
  151. RefPtrBase()
  152. {
  153. Attach(static_cast<RefCounted*>(const_cast<Derived*>(derived.ReferencedObject())));
  154. }
  155. RefPtr(const RefPtr<Type>& object) :
  156. RefPtrBase()
  157. {
  158. Attach(static_cast<RefCounted*>(const_cast<Type*>(object.ReferencedObject())));
  159. }
  160. virtual ~RefPtr()
  161. {}
  162. template<typename Derived>
  163. inline const RefPtr<Type>& operator=(const RefPtr<Derived>& derived)
  164. {
  165. Attach(static_cast<RefCounted*>(const_cast<Derived*>(derived.ReferencedObject())));
  166. return *this;
  167. }
  168. inline const RefPtr<Type>& operator=(const RefPtr<Type>& object)
  169. {
  170. Attach(static_cast<RefCounted*>(const_cast<Type*>(object.ReferencedObject())));
  171. return *this;
  172. }
  173. inline Type& operator*() const
  174. {
  175. assert(IsValid());
  176. return *const_cast<Type*>(ReferencedObject());
  177. }
  178. inline Type* const operator->() const
  179. {
  180. assert(IsValid());
  181. return const_cast<Type*>(ReferencedObject());
  182. }
  183. // Template function for implicit conversion ops
  184. template<typename NewType>
  185. inline operator RefPtr<NewType>()
  186. {return RefPtr<NewType>(GetRefObject());}
  187. // These are public mostly because I can't seem to declare rc_ptr<Other> as a friend
  188. inline Type* const ReferencedObject(void)
  189. {return reinterpret_cast<Type*>(GetRefObject());}
  190. inline const Type* const ReferencedObject(void) const
  191. {return reinterpret_cast<const Type*>(GetRefObject());}
  192. RefPtr(Type* object) :
  193. RefPtrBase()
  194. {
  195. Attach(static_cast<RefCounted*>(object));
  196. }
  197. inline const RefPtr<Type>& operator=(Type* object)
  198. {
  199. Attach(static_cast<RefCounted*>(object));
  200. return *this;
  201. }
  202. private:
  203. friend RefPtr<Type> Dynamic_Cast(RefPtrBase&);
  204. friend RefPtr<Type> Reinterpret_Cast(RefPtrBase&);
  205. friend RefPtr<Type> Const_Cast(RefPtrConst<Type>&);
  206. };
  207. template<typename Type> class RefPtrConst :
  208. public RefPtrBase
  209. {
  210. public:
  211. RefPtrConst() :
  212. RefPtrConst()
  213. {}
  214. template<typename Derived>
  215. RefPtrConst(const RefPtr<Derived>& derived) :
  216. RefPtrBase()
  217. {
  218. Attach(static_cast<RefCounted*>(derived.ReferencedObject()));
  219. }
  220. RefPtrConst(const RefPtr<Type>& object) :
  221. RefPtrBase()
  222. {
  223. Attach(static_cast<RefCounted*>(const_cast<Type* const >(object.ReferencedObject())));
  224. }
  225. template<typename Derived>
  226. RefPtrConst(const RefPtrConst<Derived>& derived) :
  227. RefPtrBase()
  228. {
  229. Attach(static_cast<RefCounted*>(derived.ReferencedObject()));
  230. }
  231. RefPtrConst(const RefPtrConst<Type>& object) :
  232. RefPtrBase()
  233. {
  234. Attach(static_cast<RefCounted*>(object.ReferencedObject()));
  235. }
  236. template<typename Derived>
  237. inline const RefPtrConst<Type>& operator=(const RefPtr<Derived>& derived)
  238. {
  239. Attach(static_cast<RefCounted*>(derived.ReferencedObject()));
  240. return *this;
  241. }
  242. inline const RefPtrConst<Type>& operator=(const RefPtr<Type>& object)
  243. {
  244. Attach(static_cast<RefCounted*>(object.ReferencedObject()));
  245. return *this;
  246. }
  247. template<typename Derived>
  248. inline const RefPtrConst<Type>& operator=(const RefPtrConst<Derived>& derived)
  249. {
  250. Attach(static_cast<RefCounted*>(derived.ReferencedObject()));
  251. return *this;
  252. }
  253. inline const RefPtrConst<Type>& operator=(const RefPtrConst<Type>& object)
  254. {
  255. Attach(static_cast<RefCounted*>(object.ReferencedObject()));
  256. return *this;
  257. }
  258. virtual ~RefPtrConst()
  259. {}
  260. inline const Type& operator*() const
  261. {
  262. assert(IsValid());
  263. return *ReferencedObject();
  264. }
  265. inline const Type* const operator->() const
  266. {
  267. assert(IsValid());
  268. return ReferencedObject();
  269. }
  270. // This is public mostly because I can't seem to declare rc_ptr<Other> as a friend
  271. inline const Type* const ReferencedObject() const
  272. {return reinterpret_cast<const Type*>(GetRefObject());}
  273. RefPtrConst(const Type* object) :
  274. RefPtrBase()
  275. {
  276. Attach(static_cast<RefCounted*>(object));
  277. }
  278. const RefPtrConst<Type>& operator=(const Type* object)
  279. {
  280. Attach(static_cast<RefCounted*>(object));
  281. }
  282. };
  283. template<typename Derived>
  284. RefPtr<Derived> Dynamic_Cast(RefPtrBase& base)
  285. {
  286. RefPtr<Derived> derived;
  287. derived.Attach(base.GetRefObject());
  288. return derived;
  289. }
  290. template<typename Type>
  291. RefPtr<Type> Reinterpret_Cast(RefPtrBase& rhs)
  292. {
  293. RefPtr<Type> object;
  294. object.Attach(rhs.GetRefObject());
  295. return object;
  296. }
  297. template<typename Type>
  298. RefPtr<Type> Const_Cast(RefPtrConst<Type>& rhs)
  299. {
  300. RefPtr<Type> object;
  301. object.Attach(static_cast<RefCounted*>(rhs.ReferencedObject()));
  302. return object;
  303. }
  304. #endif // __REFPTR_H__