oculus1

view libovr/Src/Kernel/OVR_RefCount.h @ 3:b069a5c27388

added a couple more stuff, fixed all the LibOVR line endings
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 15 Sep 2013 04:10:05 +0300
parents e2f9e4603129
children
line source
1 /************************************************************************************
3 PublicHeader: Kernel
4 Filename : OVR_RefCount.h
5 Content : Reference counting implementation headers
6 Created : September 19, 2012
7 Notes :
9 Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
11 Use of this software is subject to the terms of the Oculus license
12 agreement provided at the time of installation or download, or which
13 otherwise accompanies this software in either electronic or hard copy form.
15 ************************************************************************************/
17 #ifndef OVR_RefCount_h
18 #define OVR_RefCount_h
20 #include "OVR_Types.h"
21 #include "OVR_Allocator.h"
23 namespace OVR {
25 //-----------------------------------------------------------------------------------
26 // ***** Reference Counting
28 // There are three types of reference counting base classes:
29 //
30 // RefCountBase - Provides thread-safe reference counting (Default).
31 // RefCountBaseNTS - Non Thread Safe version of reference counting.
34 // ***** Declared classes
36 template<class C>
37 class RefCountBase;
38 template<class C>
39 class RefCountBaseNTS;
41 class RefCountImpl;
42 class RefCountNTSImpl;
45 //-----------------------------------------------------------------------------------
46 // ***** Implementation For Reference Counting
48 // RefCountImplCore holds RefCount value and defines a few utility
49 // functions shared by all implementations.
51 class RefCountImplCore
52 {
53 protected:
54 volatile int RefCount;
56 public:
57 // RefCountImpl constructor always initializes RefCount to 1 by default.
58 OVR_FORCE_INLINE RefCountImplCore() : RefCount(1) { }
60 // Need virtual destructor
61 // This: 1. Makes sure the right destructor's called.
62 // 2. Makes us have VTable, necessary if we are going to have format needed by InitNewMem()
63 virtual ~RefCountImplCore();
65 // Debug method only.
66 int GetRefCount() const { return RefCount; }
68 // This logic is used to detect invalid 'delete' calls of reference counted
69 // objects. Direct delete calls are not allowed on them unless they come in
70 // internally from Release.
71 #ifdef OVR_BUILD_DEBUG
72 static void OVR_CDECL reportInvalidDelete(void *pmem);
73 inline static void checkInvalidDelete(RefCountImplCore *pmem)
74 {
75 if (pmem->RefCount != 0)
76 reportInvalidDelete(pmem);
77 }
78 #else
79 inline static void checkInvalidDelete(RefCountImplCore *) { }
80 #endif
82 // Base class ref-count content should not be copied.
83 void operator = (const RefCountImplCore &) { }
84 };
86 class RefCountNTSImplCore
87 {
88 protected:
89 mutable int RefCount;
91 public:
92 // RefCountImpl constructor always initializes RefCount to 1 by default.
93 OVR_FORCE_INLINE RefCountNTSImplCore() : RefCount(1) { }
95 // Need virtual destructor
96 // This: 1. Makes sure the right destructor's called.
97 // 2. Makes us have VTable, necessary if we are going to have format needed by InitNewMem()
98 virtual ~RefCountNTSImplCore();
100 // Debug method only.
101 int GetRefCount() const { return RefCount; }
103 // This logic is used to detect invalid 'delete' calls of reference counted
104 // objects. Direct delete calls are not allowed on them unless they come in
105 // internally from Release.
106 #ifdef OVR_BUILD_DEBUG
107 static void OVR_CDECL reportInvalidDelete(void *pmem);
108 OVR_FORCE_INLINE static void checkInvalidDelete(RefCountNTSImplCore *pmem)
109 {
110 if (pmem->RefCount != 0)
111 reportInvalidDelete(pmem);
112 }
113 #else
114 OVR_FORCE_INLINE static void checkInvalidDelete(RefCountNTSImplCore *) { }
115 #endif
117 // Base class ref-count content should not be copied.
118 void operator = (const RefCountNTSImplCore &) { }
119 };
123 // RefCountImpl provides Thread-Safe implementation of reference counting, so
124 // it should be used by default in most places.
126 class RefCountImpl : public RefCountImplCore
127 {
128 public:
129 // Thread-Safe Ref-Count Implementation.
130 void AddRef();
131 void Release();
132 };
134 // RefCountVImpl provides Thread-Safe implementation of reference counting, plus,
135 // virtual AddRef and Release.
137 class RefCountVImpl : public RefCountImplCore
138 {
139 public:
140 // Thread-Safe Ref-Count Implementation.
141 virtual void AddRef();
142 virtual void Release();
143 };
146 // RefCountImplNTS provides Non-Thread-Safe implementation of reference counting,
147 // which is slightly more efficient since it doesn't use atomics.
149 class RefCountNTSImpl : public RefCountNTSImplCore
150 {
151 public:
152 OVR_FORCE_INLINE void AddRef() const { RefCount++; }
153 void Release() const;
154 };
158 // RefCountBaseStatImpl<> is a common class that adds new/delete override with Stat tracking
159 // to the reference counting implementation. Base must be one of the RefCountImpl classes.
161 template<class Base>
162 class RefCountBaseStatImpl : public Base
163 {
164 public:
165 RefCountBaseStatImpl() { }
167 // *** Override New and Delete
169 // DOM-IGNORE-BEGIN
170 // Undef new temporarily if it is being redefined
171 #ifdef OVR_DEFINE_NEW
172 #undef new
173 #endif
175 #ifdef OVR_BUILD_DEBUG
176 // Custom check used to detect incorrect calls of 'delete' on ref-counted objects.
177 #define OVR_REFCOUNTALLOC_CHECK_DELETE(class_name, p) \
178 do {if (p) Base::checkInvalidDelete((class_name*)p); } while(0)
179 #else
180 #define OVR_REFCOUNTALLOC_CHECK_DELETE(class_name, p)
181 #endif
183 // Redefine all new & delete operators.
184 OVR_MEMORY_REDEFINE_NEW_IMPL(Base, OVR_REFCOUNTALLOC_CHECK_DELETE)
186 #ifdef OVR_DEFINE_NEW
187 #define new OVR_DEFINE_NEW
188 #endif
189 // OVR_BUILD_DEFINE_NEW
190 // DOM-IGNORE-END
191 };
195 //-----------------------------------------------------------------------------------
196 // *** End user RefCountBase<> classes
199 // RefCountBase is a base class for classes that require thread-safe reference
200 // counting; it also overrides the new and delete operators to use MemoryHeap.
201 //
202 // Reference counted objects start out with RefCount value of 1. Further lifetime
203 // management is done through the AddRef() and Release() methods, typically
204 // hidden by Ptr<>.
206 template<class C>
207 class RefCountBase : public RefCountBaseStatImpl<RefCountImpl>
208 {
209 public:
210 // Constructor.
211 OVR_FORCE_INLINE RefCountBase() : RefCountBaseStatImpl<RefCountImpl>() { }
212 };
214 // RefCountBaseV is the same as RefCountBase but with virtual AddRef/Release
216 template<class C>
217 class RefCountBaseV : public RefCountBaseStatImpl<RefCountVImpl>
218 {
219 public:
220 // Constructor.
221 OVR_FORCE_INLINE RefCountBaseV() : RefCountBaseStatImpl<RefCountVImpl>() { }
222 };
225 // RefCountBaseNTS is a base class for classes that require Non-Thread-Safe reference
226 // counting; it also overrides the new and delete operators to use MemoryHeap.
227 // This class should only be used if all pointers to it are known to be assigned,
228 // destroyed and manipulated within one thread.
229 //
230 // Reference counted objects start out with RefCount value of 1. Further lifetime
231 // management is done through the AddRef() and Release() methods, typically
232 // hidden by Ptr<>.
234 template<class C>
235 class RefCountBaseNTS : public RefCountBaseStatImpl<RefCountNTSImpl>
236 {
237 public:
238 // Constructor.
239 OVR_FORCE_INLINE RefCountBaseNTS() : RefCountBaseStatImpl<RefCountNTSImpl>() { }
240 };
242 //-----------------------------------------------------------------------------------
243 // ***** Pickable template pointer
244 enum PickType { PickValue };
246 template <typename T>
247 class Pickable
248 {
249 public:
250 Pickable() : pV(NULL) {}
251 explicit Pickable(T* p) : pV(p) {}
252 Pickable(T* p, PickType) : pV(p)
253 {
254 OVR_ASSERT(pV);
255 if (pV)
256 pV->AddRef();
257 }
258 template <typename OT>
259 Pickable(const Pickable<OT>& other) : pV(other.GetPtr()) {}
261 public:
262 Pickable& operator =(const Pickable& other)
263 {
264 OVR_ASSERT(pV == NULL);
265 pV = other.pV;
266 // Extra check.
267 //other.pV = NULL;
268 return *this;
269 }
271 public:
272 T* GetPtr() const { return pV; }
273 T* operator->() const
274 {
275 return pV;
276 }
277 T& operator*() const
278 {
279 OVR_ASSERT(pV);
280 return *pV;
281 }
283 private:
284 T* pV;
285 };
287 template <typename T>
288 OVR_FORCE_INLINE
289 Pickable<T> MakePickable(T* p)
290 {
291 return Pickable<T>(p);
292 }
294 //-----------------------------------------------------------------------------------
295 // ***** Ref-Counted template pointer
297 // Automatically AddRefs and Releases interfaces
299 void* ReturnArg0(void* p);
301 template<class C>
302 class Ptr
303 {
304 #ifdef OVR_CC_ARM
305 static C* ReturnArg(void* p) { return (C*)ReturnArg0(p); }
306 #endif
308 protected:
309 C *pObject;
311 public:
313 // Constructors
314 OVR_FORCE_INLINE Ptr() : pObject(0)
315 { }
316 #ifdef OVR_CC_ARM
317 OVR_FORCE_INLINE Ptr(C &robj) : pObject(ReturnArg(&robj))
318 #else
319 OVR_FORCE_INLINE Ptr(C &robj) : pObject(&robj)
320 #endif
321 { }
322 OVR_FORCE_INLINE Ptr(Pickable<C> v) : pObject(v.GetPtr())
323 {
324 // No AddRef() on purpose.
325 }
326 OVR_FORCE_INLINE Ptr(Ptr<C>& other, PickType) : pObject(other.pObject)
327 {
328 other.pObject = NULL;
329 // No AddRef() on purpose.
330 }
331 OVR_FORCE_INLINE Ptr(C *pobj)
332 {
333 if (pobj) pobj->AddRef();
334 pObject = pobj;
335 }
336 OVR_FORCE_INLINE Ptr(const Ptr<C> &src)
337 {
338 if (src.pObject) src.pObject->AddRef();
339 pObject = src.pObject;
340 }
342 template<class R>
343 OVR_FORCE_INLINE Ptr(Ptr<R> &src)
344 {
345 if (src) src->AddRef();
346 pObject = src;
347 }
348 template<class R>
349 OVR_FORCE_INLINE Ptr(Pickable<R> v) : pObject(v.GetPtr())
350 {
351 // No AddRef() on purpose.
352 }
354 // Destructor
355 OVR_FORCE_INLINE ~Ptr()
356 {
357 if (pObject) pObject->Release();
358 }
360 // Compares
361 OVR_FORCE_INLINE bool operator == (const Ptr &other) const { return pObject == other.pObject; }
362 OVR_FORCE_INLINE bool operator != (const Ptr &other) const { return pObject != other.pObject; }
364 OVR_FORCE_INLINE bool operator == (C *pother) const { return pObject == pother; }
365 OVR_FORCE_INLINE bool operator != (C *pother) const { return pObject != pother; }
368 OVR_FORCE_INLINE bool operator < (const Ptr &other) const { return pObject < other.pObject; }
370 // Assignment
371 template<class R>
372 OVR_FORCE_INLINE const Ptr<C>& operator = (const Ptr<R> &src)
373 {
374 if (src) src->AddRef();
375 if (pObject) pObject->Release();
376 pObject = src;
377 return *this;
378 }
379 // Specialization
380 OVR_FORCE_INLINE const Ptr<C>& operator = (const Ptr<C> &src)
381 {
382 if (src) src->AddRef();
383 if (pObject) pObject->Release();
384 pObject = src;
385 return *this;
386 }
388 OVR_FORCE_INLINE const Ptr<C>& operator = (C *psrc)
389 {
390 if (psrc) psrc->AddRef();
391 if (pObject) pObject->Release();
392 pObject = psrc;
393 return *this;
394 }
395 OVR_FORCE_INLINE const Ptr<C>& operator = (C &src)
396 {
397 if (pObject) pObject->Release();
398 pObject = &src;
399 return *this;
400 }
401 OVR_FORCE_INLINE Ptr<C>& operator = (Pickable<C> src)
402 {
403 return Pick(src);
404 }
405 template<class R>
406 OVR_FORCE_INLINE Ptr<C>& operator = (Pickable<R> src)
407 {
408 return Pick(src);
409 }
411 // Set Assignment
412 template<class R>
413 OVR_FORCE_INLINE Ptr<C>& SetPtr(const Ptr<R> &src)
414 {
415 if (src) src->AddRef();
416 if (pObject) pObject->Release();
417 pObject = src;
418 return *this;
419 }
420 // Specialization
421 OVR_FORCE_INLINE Ptr<C>& SetPtr(const Ptr<C> &src)
422 {
423 if (src) src->AddRef();
424 if (pObject) pObject->Release();
425 pObject = src;
426 return *this;
427 }
429 OVR_FORCE_INLINE Ptr<C>& SetPtr(C *psrc)
430 {
431 if (psrc) psrc->AddRef();
432 if (pObject) pObject->Release();
433 pObject = psrc;
434 return *this;
435 }
436 OVR_FORCE_INLINE Ptr<C>& SetPtr(C &src)
437 {
438 if (pObject) pObject->Release();
439 pObject = &src;
440 return *this;
441 }
442 OVR_FORCE_INLINE Ptr<C>& SetPtr(Pickable<C> src)
443 {
444 return Pick(src);
445 }
447 // Nulls ref-counted pointer without decrement
448 OVR_FORCE_INLINE void NullWithoutRelease()
449 {
450 pObject = 0;
451 }
453 // Clears the pointer to the object
454 OVR_FORCE_INLINE void Clear()
455 {
456 if (pObject) pObject->Release();
457 pObject = 0;
458 }
460 // Obtain pointer reference directly, for D3D interfaces
461 OVR_FORCE_INLINE C*& GetRawRef() { return pObject; }
463 // Access Operators
464 OVR_FORCE_INLINE C* GetPtr() const { return pObject; }
465 OVR_FORCE_INLINE C& operator * () const { return *pObject; }
466 OVR_FORCE_INLINE C* operator -> () const { return pObject; }
467 // Conversion
468 OVR_FORCE_INLINE operator C* () const { return pObject; }
470 // Pickers.
472 // Pick a value.
473 OVR_FORCE_INLINE Ptr<C>& Pick(Ptr<C>& other)
474 {
475 if (&other != this)
476 {
477 if (pObject) pObject->Release();
478 pObject = other.pObject;
479 other.pObject = 0;
480 }
482 return *this;
483 }
485 OVR_FORCE_INLINE Ptr<C>& Pick(Pickable<C> v)
486 {
487 if (v.GetPtr() != pObject)
488 {
489 if (pObject) pObject->Release();
490 pObject = v.GetPtr();
491 }
493 return *this;
494 }
496 template<class R>
497 OVR_FORCE_INLINE Ptr<C>& Pick(Pickable<R> v)
498 {
499 if (v.GetPtr() != pObject)
500 {
501 if (pObject) pObject->Release();
502 pObject = v.GetPtr();
503 }
505 return *this;
506 }
508 OVR_FORCE_INLINE Ptr<C>& Pick(C* p)
509 {
510 if (p != pObject)
511 {
512 if (pObject) pObject->Release();
513 pObject = p;
514 }
516 return *this;
517 }
518 };
520 } // OVR
522 #endif