OVR_RefCount.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554
  1. /************************************************************************************
  2. PublicHeader: Kernel
  3. Filename : OVR_RefCount.h
  4. Content : Reference counting implementation headers
  5. Created : September 19, 2012
  6. Notes :
  7. Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved.
  8. Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License");
  9. you may not use the Oculus VR Rift SDK except in compliance with the License,
  10. which is provided at the time of installation or download, or which
  11. otherwise accompanies this software in either electronic or hard copy form.
  12. You may obtain a copy of the License at
  13. http://www.oculusvr.com/licenses/LICENSE-3.2
  14. Unless required by applicable law or agreed to in writing, the Oculus VR SDK
  15. distributed under the License is distributed on an "AS IS" BASIS,
  16. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17. See the License for the specific language governing permissions and
  18. limitations under the License.
  19. ************************************************************************************/
  20. #ifndef OVR_RefCount_h
  21. #define OVR_RefCount_h
  22. #include "OVR_Types.h"
  23. #include "OVR_Allocator.h"
  24. namespace OVR {
  25. //-----------------------------------------------------------------------------------
  26. // ***** Reference Counting
  27. // There are three types of reference counting base classes:
  28. //
  29. // RefCountBase - Provides thread-safe reference counting (Default).
  30. // RefCountBaseNTS - Non Thread Safe version of reference counting.
  31. // ***** Declared classes
  32. template<class C>
  33. class RefCountBase;
  34. template<class C>
  35. class RefCountBaseNTS;
  36. class RefCountImpl;
  37. class RefCountNTSImpl;
  38. //-----------------------------------------------------------------------------------
  39. // ***** Implementation For Reference Counting
  40. // RefCountImplCore holds RefCount value and defines a few utility
  41. // functions shared by all implementations.
  42. class RefCountImplCore
  43. {
  44. protected:
  45. AtomicInt<int> RefCount;
  46. public:
  47. // RefCountImpl constructor always initializes RefCount to 1 by default.
  48. OVR_FORCE_INLINE RefCountImplCore() : RefCount(1) { }
  49. // Need virtual destructor
  50. // This: 1. Makes sure the right destructor's called.
  51. // 2. Makes us have VTable, necessary if we are going to have format needed by InitNewMem()
  52. virtual ~RefCountImplCore();
  53. // Debug method only.
  54. int GetRefCount() const { return RefCount; }
  55. // This logic is used to detect invalid 'delete' calls of reference counted
  56. // objects. Direct delete calls are not allowed on them unless they come in
  57. // internally from Release.
  58. #ifdef OVR_BUILD_DEBUG
  59. static void OVR_CDECL reportInvalidDelete(void *pmem);
  60. inline static void checkInvalidDelete(RefCountImplCore *pmem)
  61. {
  62. if (pmem->RefCount != 0)
  63. reportInvalidDelete(pmem);
  64. }
  65. #else
  66. inline static void checkInvalidDelete(RefCountImplCore *) { }
  67. #endif
  68. // Base class ref-count content should not be copied.
  69. void operator = (const RefCountImplCore &) { }
  70. };
  71. class RefCountNTSImplCore
  72. {
  73. protected:
  74. mutable int RefCount;
  75. public:
  76. // RefCountImpl constructor always initializes RefCount to 1 by default.
  77. OVR_FORCE_INLINE RefCountNTSImplCore() : RefCount(1) { }
  78. // Need virtual destructor
  79. // This: 1. Makes sure the right destructor's called.
  80. // 2. Makes us have VTable, necessary if we are going to have format needed by InitNewMem()
  81. virtual ~RefCountNTSImplCore();
  82. // Debug method only.
  83. int GetRefCount() const
  84. {
  85. return RefCount;
  86. }
  87. // This logic is used to detect invalid 'delete' calls of reference counted
  88. // objects. Direct delete calls are not allowed on them unless they come in
  89. // internally from Release.
  90. #ifdef OVR_BUILD_DEBUG
  91. static void OVR_CDECL reportInvalidDelete(void *pmem);
  92. OVR_FORCE_INLINE static void checkInvalidDelete(RefCountNTSImplCore *pmem)
  93. {
  94. if (pmem->RefCount != 0)
  95. reportInvalidDelete(pmem);
  96. }
  97. #else
  98. OVR_FORCE_INLINE static void checkInvalidDelete(RefCountNTSImplCore *) { }
  99. #endif
  100. // Base class ref-count content should not be copied.
  101. void operator = (const RefCountNTSImplCore &) { }
  102. };
  103. // RefCountImpl provides Thread-Safe implementation of reference counting, so
  104. // it should be used by default in most places.
  105. class RefCountImpl : public RefCountImplCore
  106. {
  107. public:
  108. // Thread-Safe Ref-Count Implementation.
  109. void AddRef();
  110. void Release();
  111. };
  112. // RefCountVImpl provides Thread-Safe implementation of reference counting, plus,
  113. // virtual AddRef and Release.
  114. class RefCountVImpl : virtual public RefCountImplCore
  115. {
  116. public:
  117. // Thread-Safe Ref-Count Implementation.
  118. virtual void AddRef();
  119. virtual void Release();
  120. };
  121. // RefCountImplNTS provides Non-Thread-Safe implementation of reference counting,
  122. // which is slightly more efficient since it doesn't use atomics.
  123. class RefCountNTSImpl : public RefCountNTSImplCore
  124. {
  125. public:
  126. OVR_FORCE_INLINE void AddRef() const
  127. {
  128. RefCount++;
  129. }
  130. void Release() const;
  131. };
  132. // RefCountBaseStatImpl<> is a common class that adds new/delete override with Stat tracking
  133. // to the reference counting implementation. Base must be one of the RefCountImpl classes.
  134. template<class Base>
  135. class RefCountBaseStatImpl : public Base
  136. {
  137. public:
  138. RefCountBaseStatImpl() { }
  139. // *** Override New and Delete
  140. // DOM-IGNORE-BEGIN
  141. // Undef new temporarily if it is being redefined
  142. #ifdef OVR_DEFINE_NEW
  143. #undef new
  144. #endif
  145. #ifdef OVR_BUILD_DEBUG
  146. // Custom check used to detect incorrect calls of 'delete' on ref-counted objects.
  147. #define OVR_REFCOUNTALLOC_CHECK_DELETE(class_name, p) \
  148. do {if (p) Base::checkInvalidDelete((class_name*)p); } while(0)
  149. #else
  150. #define OVR_REFCOUNTALLOC_CHECK_DELETE(class_name, p)
  151. #endif
  152. // Redefine all new & delete operators.
  153. OVR_MEMORY_REDEFINE_NEW_IMPL(Base, OVR_REFCOUNTALLOC_CHECK_DELETE)
  154. #undef OVR_REFCOUNTALLOC_CHECK_DELETE
  155. #ifdef OVR_DEFINE_NEW
  156. #define new OVR_DEFINE_NEW
  157. #endif
  158. // OVR_BUILD_DEFINE_NEW
  159. // DOM-IGNORE-END
  160. };
  161. template<class Base>
  162. class RefCountBaseStatVImpl : virtual public Base
  163. {
  164. public:
  165. RefCountBaseStatVImpl() { }
  166. // *** Override New and Delete
  167. // DOM-IGNORE-BEGIN
  168. // Undef new temporarily if it is being redefined
  169. #ifdef OVR_DEFINE_NEW
  170. #undef new
  171. #endif
  172. #define OVR_REFCOUNTALLOC_CHECK_DELETE(class_name, p)
  173. // Redefine all new & delete operators.
  174. OVR_MEMORY_REDEFINE_NEW_IMPL(Base, OVR_REFCOUNTALLOC_CHECK_DELETE)
  175. #undef OVR_REFCOUNTALLOC_CHECK_DELETE
  176. #ifdef OVR_DEFINE_NEW
  177. #define new OVR_DEFINE_NEW
  178. #endif
  179. // OVR_BUILD_DEFINE_NEW
  180. // DOM-IGNORE-END
  181. };
  182. //-----------------------------------------------------------------------------------
  183. // *** End user RefCountBase<> classes
  184. // RefCountBase is a base class for classes that require thread-safe reference
  185. // counting; it also overrides the new and delete operators to use MemoryHeap.
  186. //
  187. // Reference counted objects start out with RefCount value of 1. Further lifetime
  188. // management is done through the AddRef() and Release() methods, typically
  189. // hidden by Ptr<>.
  190. template<class C>
  191. class RefCountBase : public RefCountBaseStatImpl<RefCountImpl>
  192. {
  193. public:
  194. // Constructor.
  195. OVR_FORCE_INLINE RefCountBase() : RefCountBaseStatImpl<RefCountImpl>() { }
  196. };
  197. // RefCountBaseV is the same as RefCountBase but with virtual AddRef/Release
  198. template<class C>
  199. class RefCountBaseV : virtual public RefCountBaseStatVImpl<RefCountVImpl>
  200. {
  201. public:
  202. // Constructor.
  203. OVR_FORCE_INLINE RefCountBaseV() : RefCountBaseStatVImpl<RefCountVImpl>() { }
  204. };
  205. // RefCountBaseNTS is a base class for classes that require Non-Thread-Safe reference
  206. // counting; it also overrides the new and delete operators to use MemoryHeap.
  207. // This class should only be used if all pointers to it are known to be assigned,
  208. // destroyed and manipulated within one thread.
  209. //
  210. // Reference counted objects start out with RefCount value of 1. Further lifetime
  211. // management is done through the AddRef() and Release() methods, typically
  212. // hidden by Ptr<>.
  213. template<class C>
  214. class RefCountBaseNTS : public RefCountBaseStatImpl<RefCountNTSImpl>
  215. {
  216. public:
  217. // Constructor.
  218. OVR_FORCE_INLINE RefCountBaseNTS() : RefCountBaseStatImpl<RefCountNTSImpl>() { }
  219. };
  220. //-----------------------------------------------------------------------------------
  221. // ***** Ref-Counted template pointer
  222. //
  223. // Automatically AddRefs and Releases interfaces
  224. //
  225. // Note: Some of the member functions take C& as opposed to C* arguments:
  226. // Ptr(C&)
  227. // const Ptr<C>& operator= (C&)
  228. // Ptr<C>& SetPtr(C&)
  229. // These functions do not AddRef the assigned C& value, unlike the C* assignment
  230. // functions. Thus the purpose of these functions is for the Ptr instance to
  231. // assume ownership of a C reference count. Example usage:
  232. // Ptr<Widget> w = *new Widget; // Calls the Ptr(C&) constructor. Note that the Widget constructor sets initial refcount to 1.
  233. //
  234. template<class C>
  235. class Ptr
  236. {
  237. protected:
  238. C *pObject;
  239. public:
  240. // Constructors
  241. OVR_FORCE_INLINE Ptr()
  242. : pObject(0)
  243. { }
  244. // This constructor adopts the object's existing reference count rather than increment it.
  245. OVR_FORCE_INLINE Ptr(C &robj)
  246. : pObject(&robj)
  247. { }
  248. OVR_FORCE_INLINE Ptr(C *pobj)
  249. {
  250. if (pobj)
  251. pobj->AddRef();
  252. pObject = pobj;
  253. }
  254. OVR_FORCE_INLINE Ptr(const Ptr<C> &src)
  255. {
  256. if (src.pObject)
  257. src.pObject->AddRef();
  258. pObject = src.pObject;
  259. }
  260. template<class R>
  261. OVR_FORCE_INLINE Ptr(Ptr<R> &src)
  262. {
  263. if (src)
  264. src->AddRef();
  265. pObject = src;
  266. }
  267. // Destructor
  268. OVR_FORCE_INLINE ~Ptr()
  269. {
  270. if (pObject)
  271. pObject->Release();
  272. }
  273. // Compares
  274. OVR_FORCE_INLINE bool operator == (const Ptr &other) const
  275. {
  276. return pObject == other.pObject;
  277. }
  278. OVR_FORCE_INLINE bool operator != (const Ptr &other) const
  279. {
  280. return pObject != other.pObject;
  281. }
  282. OVR_FORCE_INLINE bool operator == (C *pother) const
  283. {
  284. return pObject == pother;
  285. }
  286. OVR_FORCE_INLINE bool operator != (C *pother) const
  287. {
  288. return pObject != pother;
  289. }
  290. OVR_FORCE_INLINE bool operator < (const Ptr &other) const
  291. {
  292. return pObject < other.pObject;
  293. }
  294. // Assignment
  295. template<class R>
  296. OVR_FORCE_INLINE const Ptr<C>& operator = (const Ptr<R> &src)
  297. {
  298. // By design we don't check for src == pObject, as we don't expect that to be the case the large majority of the time.
  299. if (src)
  300. src->AddRef();
  301. if (pObject)
  302. pObject->Release();
  303. pObject = src;
  304. return *this;
  305. }
  306. // Specialization
  307. OVR_FORCE_INLINE const Ptr<C>& operator = (const Ptr<C> &src)
  308. {
  309. if (src)
  310. src->AddRef();
  311. if (pObject)
  312. pObject->Release();
  313. pObject = src;
  314. return *this;
  315. }
  316. OVR_FORCE_INLINE const Ptr<C>& operator = (C *psrc)
  317. {
  318. if (psrc)
  319. psrc->AddRef();
  320. if (pObject)
  321. pObject->Release();
  322. pObject = psrc;
  323. return *this;
  324. }
  325. // This operator adopts the object's existing reference count rather than increment it.
  326. OVR_FORCE_INLINE const Ptr<C>& operator = (C &src)
  327. {
  328. if (pObject)
  329. pObject->Release();
  330. pObject = &src;
  331. return *this;
  332. }
  333. // Set Assignment
  334. template<class R>
  335. OVR_FORCE_INLINE Ptr<C>& SetPtr(const Ptr<R> &src)
  336. {
  337. if (src)
  338. src->AddRef();
  339. if (pObject)
  340. pObject->Release();
  341. pObject = src;
  342. return *this;
  343. }
  344. // Specialization
  345. OVR_FORCE_INLINE Ptr<C>& SetPtr(const Ptr<C> &src)
  346. {
  347. if (src)
  348. src->AddRef();
  349. if (pObject)
  350. pObject->Release();
  351. pObject = src;
  352. return *this;
  353. }
  354. OVR_FORCE_INLINE Ptr<C>& SetPtr(C *psrc)
  355. {
  356. if (psrc)
  357. psrc->AddRef();
  358. if (pObject)
  359. pObject->Release();
  360. pObject = psrc;
  361. return *this;
  362. }
  363. // This function adopts the object's existing reference count rather than increment it.
  364. OVR_FORCE_INLINE Ptr<C>& SetPtr(C &src)
  365. {
  366. if (pObject)
  367. pObject->Release();
  368. pObject = &src;
  369. return *this;
  370. }
  371. // Nulls ref-counted pointer without decrement
  372. OVR_FORCE_INLINE void NullWithoutRelease()
  373. {
  374. pObject = 0;
  375. }
  376. // Clears the pointer to the object
  377. OVR_FORCE_INLINE void Clear()
  378. {
  379. if (pObject)
  380. pObject->Release();
  381. pObject = 0;
  382. }
  383. // Obtain pointer reference directly, for D3D interfaces
  384. OVR_FORCE_INLINE C*& GetRawRef()
  385. {
  386. return pObject;
  387. }
  388. // Access Operators
  389. OVR_FORCE_INLINE C* GetPtr() const
  390. {
  391. return pObject;
  392. }
  393. OVR_FORCE_INLINE C& operator * () const
  394. {
  395. return *pObject;
  396. }
  397. OVR_FORCE_INLINE C* operator -> () const
  398. {
  399. return pObject;
  400. }
  401. // Conversion
  402. OVR_FORCE_INLINE operator C* () const
  403. {
  404. return pObject;
  405. }
  406. };
  407. // LockedPtr
  408. //
  409. // Helper class to simplify thread-safety of the TrackingManager.
  410. // It wraps the Ptr<> object it contains in a Lock.
  411. template<class T>
  412. class LockedPtr
  413. {
  414. public:
  415. LockedPtr(Lock* lock = nullptr) :
  416. TheLock(lock)
  417. {
  418. }
  419. void Set(T* value)
  420. {
  421. OVR_ASSERT(TheLock);
  422. TheLock->DoLock();
  423. Ptr<T> oldPtr = ThePtr; // Keep a reference to the old ptr
  424. ThePtr = value; // Change/decrement the old ptr (cannot die here due to oldPtr)
  425. TheLock->Unlock();
  426. // Release the old Ptr reference here, outside of the lock
  427. // so that the object will not die while TheLock is held.
  428. }
  429. template<class S>
  430. void Get(Ptr<S>& outputPtr) const
  431. {
  432. OVR_ASSERT(TheLock);
  433. TheLock->DoLock();
  434. Ptr<T> retval = ThePtr;
  435. TheLock->Unlock();
  436. outputPtr = retval;
  437. }
  438. protected:
  439. mutable Lock* TheLock;
  440. Ptr<T> ThePtr;
  441. };
  442. } // OVR
  443. #endif