refBase.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #ifndef _REFBASE_H_
  23. #define _REFBASE_H_
  24. #ifndef _PLATFORMASSERT_H_
  25. # include "platform/platformAssert.h"
  26. #endif
  27. #ifndef _TYPETRAITS_H_
  28. # include "platform/typetraits.h"
  29. #endif
  30. /// Base class for objects which can be weakly referenced
  31. /// (i.e., reference goes away when object is destroyed).
  32. class WeakRefBase
  33. {
  34. public:
  35. /// Weak reference to WeakRefBase.
  36. class WeakReference
  37. {
  38. public:
  39. [[nodiscard]] constexpr WeakRefBase* get() const { return mObject; }
  40. [[nodiscard]] constexpr U32 getRefCount() const { return mRefCount; }
  41. constexpr void incRefCount() { mRefCount++; }
  42. constexpr void decRefCount() {
  43. AssertFatal( mRefCount > 0, "WeakReference - decrementing count of zero!" );
  44. if (--mRefCount==0)
  45. delete this;
  46. }
  47. private:
  48. friend class WeakRefBase;
  49. constexpr explicit WeakReference(WeakRefBase *object) :mObject(object), mRefCount(0) {}
  50. ~WeakReference() { AssertFatal(mObject==nullptr, "Deleting weak reference which still points at an object."); }
  51. // Object we reference
  52. WeakRefBase *mObject;
  53. // reference count for this structure (not WeakObjectRef itself)
  54. U32 mRefCount;
  55. };
  56. public:
  57. constexpr WeakRefBase() : mReference(nullptr) {}
  58. virtual ~WeakRefBase() { clearWeakReferences(); }
  59. WeakReference* getWeakReference();
  60. protected:
  61. void clearWeakReferences();
  62. private:
  63. WeakReference * mReference;
  64. };
  65. template< typename T > class SimObjectPtr;
  66. /// Weak reference pointer class.
  67. /// Instances of this template class can be used as pointers to
  68. /// instances of WeakRefBase and its subclasses.
  69. /// When the object referenced by a WeakRefPtr instance is deleted,
  70. /// the pointer to the object is set to NULL in the WeakRefPtr instance.
  71. template <class T> class WeakRefPtr
  72. {
  73. public:
  74. constexpr WeakRefPtr() : mReference(nullptr) {}
  75. WeakRefPtr(T *ptr) : mReference(nullptr) { set(ptr); }
  76. WeakRefPtr(const WeakRefPtr<T> & ref) { mReference = nullptr; set(ref.mReference); }
  77. ~WeakRefPtr() { set(static_cast<WeakRefBase::WeakReference *>(nullptr)); }
  78. WeakRefPtr<T>& operator=(const WeakRefPtr<T>& ref)
  79. {
  80. if (this == &ref) { return *this; } // handle self assignment ( x = x; )
  81. set(ref.mReference);
  82. return *this;
  83. }
  84. WeakRefPtr<T>& operator=(T *ptr)
  85. {
  86. set(ptr);
  87. return *this;
  88. }
  89. /// Returns true if the pointer is not set.
  90. [[nodiscard]] constexpr bool isNull() const { return mReference == nullptr || mReference->get() == nullptr; }
  91. /// Returns true if the pointer is set.
  92. [[nodiscard]] constexpr bool isValid() const { return mReference && mReference->get(); }
  93. [[nodiscard]] constexpr T* operator->() const { return getPointer(); }
  94. [[nodiscard]] constexpr T& operator*() const { return *getPointer(); }
  95. [[nodiscard]] constexpr operator T*() const { return getPointer(); }
  96. /// Returns the pointer.
  97. [[nodiscard]] constexpr T* getPointer() const { return mReference ? (T*)mReference->get() : nullptr; }
  98. protected:
  99. void set(WeakRefBase::WeakReference* ref)
  100. {
  101. if (mReference)
  102. mReference->decRefCount();
  103. mReference = nullptr;
  104. if (ref)
  105. {
  106. mReference = ref;
  107. mReference->incRefCount();
  108. }
  109. }
  110. void set(T* obj) { set(obj ? obj->getWeakReference() : nullptr); }
  111. private:
  112. template< typename > friend class SimObjectPtr;
  113. WeakRefBase::WeakReference * mReference {nullptr};
  114. };
  115. /// Union of an arbitrary type with a WeakRefBase. The exposed type will
  116. /// remain accessible so long as the WeakRefBase is not cleared. Once
  117. /// it is cleared, accessing the exposed type will result in a NULL pointer.
  118. template<class ExposedType>
  119. class WeakRefUnion
  120. {
  121. typedef WeakRefUnion<ExposedType> Union;
  122. public:
  123. constexpr WeakRefUnion() : mPtr(nullptr) {}
  124. constexpr WeakRefUnion(const WeakRefPtr<WeakRefBase> & ref, ExposedType * ptr) : mPtr(nullptr) { set(ref, ptr); }
  125. constexpr WeakRefUnion(const Union & lock) : mPtr(nullptr) { *this = lock; }
  126. constexpr WeakRefUnion(WeakRefBase * ref) : mPtr(nullptr) { set(ref, dynamic_cast<ExposedType*>(ref)); }
  127. ~WeakRefUnion() { mWeakReference = nullptr; }
  128. Union & operator=(const Union & ptr)
  129. {
  130. if (this == *ptr) { return *this; }
  131. set(ptr.mWeakReference, ptr.getPointer());
  132. return *this;
  133. }
  134. void set(const WeakRefPtr<WeakRefBase> & ref, ExposedType * ptr)
  135. {
  136. mWeakReference = ref;
  137. mPtr = ptr;
  138. }
  139. [[nodiscard]] constexpr bool operator == (const ExposedType * t ) const { return getPointer() == t; }
  140. [[nodiscard]] constexpr bool operator != (const ExposedType * t ) const { return getPointer() != t; }
  141. [[nodiscard]] constexpr bool operator == (const Union &t ) const { return getPointer() == t.getPointer(); }
  142. [[nodiscard]] constexpr bool operator != (const Union &t ) const { return getPointer() != t.getPointer(); }
  143. [[nodiscard]] constexpr bool isNull() const { return mWeakReference.isNull() || !mPtr; }
  144. [[nodiscard]] constexpr ExposedType* getPointer() const { return !mWeakReference.isNull() ? mPtr : nullptr; }
  145. [[nodiscard]] constexpr ExposedType* operator->() const { return getPointer(); }
  146. [[nodiscard]] constexpr ExposedType& operator*() const { return *getPointer(); }
  147. [[nodiscard]] constexpr operator ExposedType*() const { return getPointer(); }
  148. [[nodiscard]] WeakRefPtr<WeakRefBase> getRef() const { return mWeakReference; }
  149. private:
  150. WeakRefPtr<WeakRefBase> mWeakReference;
  151. ExposedType * mPtr;
  152. };
  153. /// Base class for objects which can be strongly referenced
  154. /// (i.e., as long as reference exists, object will exist,
  155. /// when all strong references go away, object is destroyed).
  156. class StrongRefBase : public WeakRefBase
  157. {
  158. friend class StrongObjectRef;
  159. public:
  160. StrongRefBase() { mRefCount = 0; }
  161. U32 getRefCount() const { return mRefCount; }
  162. /// object destroy self call (from StrongRefPtr). Override if this class has specially allocated memory.
  163. virtual void destroySelf() { delete this; }
  164. /// Increments the reference count.
  165. void incRefCount()
  166. {
  167. mRefCount++;
  168. }
  169. /// Decrements the reference count.
  170. void decRefCount()
  171. {
  172. AssertFatal(mRefCount, "Decrementing a reference with refcount 0!");
  173. if(!--mRefCount)
  174. destroySelf();
  175. }
  176. protected:
  177. U32 mRefCount; ///< reference counter for StrongRefPtr objects
  178. };
  179. /// Base class for StrongRefBase strong reference pointers.
  180. class StrongObjectRef
  181. {
  182. public:
  183. /// Constructor, assigns from the object and increments its reference count if it's not NULL
  184. StrongObjectRef(StrongRefBase *object = nullptr) : mObject( object ) { incRef(); }
  185. /// Destructor, dereferences the object, if there is one
  186. ~StrongObjectRef() { decRef(); }
  187. /// Assigns this reference object from an existing StrongRefBase instance
  188. void set(StrongRefBase *object)
  189. {
  190. if( mObject != object )
  191. {
  192. decRef();
  193. mObject = object;
  194. incRef();
  195. }
  196. }
  197. protected:
  198. StrongRefBase *mObject; ///< the object this RefObjectRef references
  199. /// increments the reference count on the referenced object
  200. constexpr void incRef() const
  201. {
  202. if(mObject)
  203. mObject->incRefCount();
  204. }
  205. /// decrements the reference count on the referenced object
  206. constexpr void decRef() const
  207. {
  208. if(mObject)
  209. mObject->decRefCount();
  210. }
  211. };
  212. /// Reference counted object template pointer class
  213. /// Instances of this template class can be used as pointers to
  214. /// instances of StrongRefBase and its subclasses. The object will not
  215. /// be deleted until all of the StrongRefPtr instances pointing to it
  216. /// have been destructed.
  217. template <class T> class StrongRefPtr : protected StrongObjectRef
  218. {
  219. public:
  220. StrongRefPtr() : StrongObjectRef() {}
  221. StrongRefPtr(T *ptr) : StrongObjectRef(ptr) {}
  222. StrongRefPtr(const StrongRefPtr<T>& ref) : StrongObjectRef(ref.mObject) {}
  223. ~StrongRefPtr() = default;
  224. StrongRefPtr<T>& operator=(const StrongRefPtr<T>& ref)
  225. {
  226. set(ref.mObject);
  227. return *this;
  228. }
  229. StrongRefPtr<T>& operator=(T *ptr)
  230. {
  231. set(ptr);
  232. return *this;
  233. }
  234. [[nodiscard]] constexpr bool isNull() const { return mObject == nullptr; }
  235. [[nodiscard]] constexpr bool isValid() const { return mObject != nullptr; }
  236. [[nodiscard]] T* operator->() const { return getPointer(); }
  237. T& operator*() const { return *getPointer(); }
  238. operator T*() const { return getPointer(); }
  239. T* getPointer() const { return const_cast<T*>(static_cast<T* const>(mObject)); }
  240. };
  241. /// Union of an arbitrary type with a StrongRefBase. StrongRefBase will remain locked
  242. /// until the union is destructed. Handy for when the exposed class will
  243. /// become invalid whenever the reference becomes invalid and you want to make sure that doesn't
  244. /// happen.
  245. template<class ExposedType>
  246. class StrongRefUnion
  247. {
  248. typedef StrongRefUnion<ExposedType> Union;
  249. public:
  250. StrongRefUnion() : mPtr(nullptr) {}
  251. StrongRefUnion(const StrongRefPtr<StrongRefBase> & ref, ExposedType * ptr) : mPtr(nullptr) { set(ref, ptr); }
  252. StrongRefUnion(const Union & lock) : mPtr(nullptr) { *this = lock; }
  253. StrongRefUnion(StrongRefBase * ref) : mPtr(nullptr) { set(ref, dynamic_cast<ExposedType*>(ref)); }
  254. ~StrongRefUnion() { mReference = nullptr; }
  255. Union & operator=(const Union & ptr)
  256. {
  257. set(ptr.mReference, ptr.mPtr);
  258. return *this;
  259. }
  260. void set(const StrongRefPtr<StrongRefBase> & ref, ExposedType * ptr)
  261. {
  262. mReference = ref;
  263. mPtr = ptr;
  264. }
  265. [[nodiscard]] constexpr bool operator == (const ExposedType * t ) const { return mPtr == t; }
  266. [[nodiscard]] constexpr bool operator != (const ExposedType * t ) const { return mPtr != t; }
  267. [[nodiscard]] constexpr bool operator == (const Union &t ) const { return mPtr == t.mPtr; }
  268. [[nodiscard]] constexpr bool operator != (const Union &t ) const { return mPtr != t.mPtr; }
  269. [[nodiscard]] constexpr bool isNull() const { return mReference.isNull() || !mPtr; }
  270. [[nodiscard]] constexpr bool isValid() const { return mReference.isValid() && mPtr; }
  271. ExposedType* operator->() const { return mPtr; }
  272. ExposedType& operator*() const { return *mPtr; }
  273. operator ExposedType*() const { return mPtr; }
  274. ExposedType* getPointer() const { return mPtr; }
  275. StrongRefPtr<StrongRefBase> getRef() const { return mReference; }
  276. private:
  277. StrongRefPtr<StrongRefBase> mReference;
  278. ExposedType * mPtr;
  279. };
  280. /// This oxymoron is a pointer that reference-counts the referenced
  281. /// object but also NULLs out if the object goes away.
  282. ///
  283. /// This is useful for situations where an object's lifetime is ultimately
  284. /// governed by a superior entity but where individual objects may also die
  285. /// independently of the superior entity. All client code should use
  286. /// StrongWeakRefs that keep object live as long as the superior entity doesn't
  287. /// step in and kill them (in which case, the client code sees the reference
  288. /// disappear).
  289. template< class T >
  290. class StrongWeakRefPtr
  291. {
  292. public:
  293. constexpr StrongWeakRefPtr() : mReference( nullptr ) {}
  294. constexpr StrongWeakRefPtr( T* ptr ) : mReference( nullptr ) { _set( ptr ); }
  295. ~StrongWeakRefPtr()
  296. {
  297. if( mReference )
  298. {
  299. T* ptr = _get();
  300. if( ptr )
  301. ptr->decRefCount();
  302. mReference->decRefCount();
  303. }
  304. }
  305. [[nodiscard]] constexpr bool isNull() const { return ( _get() == nullptr ); }
  306. [[nodiscard]] constexpr bool operator ==( T* ptr ) const { return ( _get() == ptr ); }
  307. [[nodiscard]] constexpr bool operator !=( T* ptr ) const { return ( _get() != ptr ); }
  308. [[nodiscard]] constexpr bool operator !() const { return isNull(); }
  309. [[nodiscard]] constexpr T* operator ->() const { return _get(); }
  310. [[nodiscard]] constexpr T& operator *() const { return *( _get() ); }
  311. constexpr operator T*() const { return _get(); } // consider making this explicit
  312. T* getPointer() const { return _get(); }
  313. StrongWeakRefPtr& operator =( T* ptr )
  314. {
  315. _set( ptr );
  316. return *this;
  317. }
  318. private:
  319. WeakRefBase::WeakReference* mReference;
  320. T* _get() const
  321. {
  322. if( mReference )
  323. return static_cast< T* >( mReference->get() );
  324. else
  325. return nullptr;
  326. }
  327. void _set( T* ptr )
  328. {
  329. if( mReference )
  330. {
  331. T* old = _get();
  332. if( old )
  333. old->decRefCount();
  334. mReference->decRefCount();
  335. }
  336. if( ptr )
  337. {
  338. ptr->incRefCount();
  339. mReference = ptr->getWeakReference();
  340. mReference->incRefCount();
  341. }
  342. else
  343. mReference = nullptr;
  344. }
  345. };
  346. //---------------------------------------------------------------
  347. inline void WeakRefBase::clearWeakReferences()
  348. {
  349. if (mReference)
  350. {
  351. mReference->mObject = nullptr;
  352. mReference->decRefCount();
  353. mReference = nullptr;
  354. }
  355. }
  356. inline WeakRefBase::WeakReference* WeakRefBase::getWeakReference()
  357. {
  358. if (!mReference)
  359. {
  360. mReference = new WeakReference(this);
  361. mReference->incRefCount();
  362. }
  363. return mReference;
  364. }
  365. //---------------------------------------------------------------
  366. template< typename T >
  367. struct TypeTraits< WeakRefPtr< T > > : public _TypeTraits< WeakRefPtr< T > >
  368. {
  369. typedef typename TypeTraits< T >::BaseType BaseType;
  370. };
  371. template< typename T >
  372. struct TypeTraits< StrongRefPtr< T > > : public _TypeTraits< StrongRefPtr< T > >
  373. {
  374. typedef typename TypeTraits< T >::BaseType BaseType;
  375. };
  376. template< typename T >
  377. struct TypeTraits< StrongWeakRefPtr< T > > : public _TypeTraits< StrongWeakRefPtr< T > >
  378. {
  379. typedef typename TypeTraits< T >::BaseType BaseType;
  380. };
  381. template< typename T >
  382. [[nodiscard]] constexpr T& Deref( WeakRefPtr< T >& ref )
  383. {
  384. return *ref;
  385. }
  386. template< typename T >
  387. [[nodiscard]] constexpr T& Deref( StrongRefPtr< T >& ref )
  388. {
  389. return *ref;
  390. }
  391. template< typename T >
  392. [[nodiscard]] constexpr T& Deref( StrongWeakRefPtr< T >& ref )
  393. {
  394. return *ref;
  395. }
  396. #endif