Bike-X  0.8
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
OVR_RefCount.h
Go to the documentation of this file.
1 /************************************************************************************
2 
3 PublicHeader: Kernel
4 Filename : OVR_RefCount.h
5 Content : Reference counting implementation headers
6 Created : September 19, 2012
7 Notes :
8 
9 Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved.
10 
11 Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License");
12 you may not use the Oculus VR Rift SDK except in compliance with the License,
13 which is provided at the time of installation or download, or which
14 otherwise accompanies this software in either electronic or hard copy form.
15 
16 You may obtain a copy of the License at
17 
18 http://www.oculusvr.com/licenses/LICENSE-3.1
19 
20 Unless required by applicable law or agreed to in writing, the Oculus VR SDK
21 distributed under the License is distributed on an "AS IS" BASIS,
22 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23 See the License for the specific language governing permissions and
24 limitations under the License.
25 
26 ************************************************************************************/
27 
28 #ifndef OVR_RefCount_h
29 #define OVR_RefCount_h
30 
31 #include "OVR_Types.h"
32 #include "OVR_Allocator.h"
33 
34 namespace OVR {
35 
36 //-----------------------------------------------------------------------------------
37 // ***** Reference Counting
38 
39 // There are three types of reference counting base classes:
40 //
41 // RefCountBase - Provides thread-safe reference counting (Default).
42 // RefCountBaseNTS - Non Thread Safe version of reference counting.
43 
44 
45 // ***** Declared classes
46 
47 template<class C>
49 template<class C>
51 
52 class RefCountImpl;
53 class RefCountNTSImpl;
54 
55 
56 //-----------------------------------------------------------------------------------
57 // ***** Implementation For Reference Counting
58 
59 // RefCountImplCore holds RefCount value and defines a few utility
60 // functions shared by all implementations.
61 
63 {
64 protected:
65  volatile int RefCount;
66 
67 public:
68  // RefCountImpl constructor always initializes RefCount to 1 by default.
70 
71  // Need virtual destructor
72  // This: 1. Makes sure the right destructor's called.
73  // 2. Makes us have VTable, necessary if we are going to have format needed by InitNewMem()
74  virtual ~RefCountImplCore();
75 
76  // Debug method only.
77  int GetRefCount() const { return RefCount; }
78 
79  // This logic is used to detect invalid 'delete' calls of reference counted
80  // objects. Direct delete calls are not allowed on them unless they come in
81  // internally from Release.
82 #ifdef OVR_BUILD_DEBUG
83  static void OVR_CDECL reportInvalidDelete(void *pmem);
84  inline static void checkInvalidDelete(RefCountImplCore *pmem)
85  {
86  if (pmem->RefCount != 0)
87  reportInvalidDelete(pmem);
88  }
89 #else
90  inline static void checkInvalidDelete(RefCountImplCore *) { }
91 #endif
92 
93  // Base class ref-count content should not be copied.
94  void operator = (const RefCountImplCore &) { }
95 };
96 
98 {
99 protected:
100  mutable int RefCount;
101 
102 public:
103  // RefCountImpl constructor always initializes RefCount to 1 by default.
105 
106  // Need virtual destructor
107  // This: 1. Makes sure the right destructor's called.
108  // 2. Makes us have VTable, necessary if we are going to have format needed by InitNewMem()
109  virtual ~RefCountNTSImplCore();
110 
111  // Debug method only.
112  int GetRefCount() const { return RefCount; }
113 
114  // This logic is used to detect invalid 'delete' calls of reference counted
115  // objects. Direct delete calls are not allowed on them unless they come in
116  // internally from Release.
117 #ifdef OVR_BUILD_DEBUG
118  static void OVR_CDECL reportInvalidDelete(void *pmem);
120  {
121  if (pmem->RefCount != 0)
122  reportInvalidDelete(pmem);
123  }
124 #else
126 #endif
127 
128  // Base class ref-count content should not be copied.
129  void operator = (const RefCountNTSImplCore &) { }
130 };
131 
132 
133 
134 // RefCountImpl provides Thread-Safe implementation of reference counting, so
135 // it should be used by default in most places.
136 
138 {
139 public:
140  // Thread-Safe Ref-Count Implementation.
141  void AddRef();
142  void Release();
143 };
144 
145 // RefCountVImpl provides Thread-Safe implementation of reference counting, plus,
146 // virtual AddRef and Release.
147 
148 class RefCountVImpl : virtual public RefCountImplCore
149 {
150 public:
151  // Thread-Safe Ref-Count Implementation.
152  virtual void AddRef();
153  virtual void Release();
154 };
155 
156 
157 // RefCountImplNTS provides Non-Thread-Safe implementation of reference counting,
158 // which is slightly more efficient since it doesn't use atomics.
159 
161 {
162 public:
163  OVR_FORCE_INLINE void AddRef() const { RefCount++; }
164  void Release() const;
165 };
166 
167 
168 
169 // RefCountBaseStatImpl<> is a common class that adds new/delete override with Stat tracking
170 // to the reference counting implementation. Base must be one of the RefCountImpl classes.
171 
172 template<class Base>
173 class RefCountBaseStatImpl : public Base
174 {
175 public:
177 
178  // *** Override New and Delete
179 
180  // DOM-IGNORE-BEGIN
181  // Undef new temporarily if it is being redefined
182 #ifdef OVR_DEFINE_NEW
183 #undef new
184 #endif
185 
186 #ifdef OVR_BUILD_DEBUG
187  // Custom check used to detect incorrect calls of 'delete' on ref-counted objects.
188  #define OVR_REFCOUNTALLOC_CHECK_DELETE(class_name, p) \
189  do {if (p) Base::checkInvalidDelete((class_name*)p); } while(0)
190 #else
191  #define OVR_REFCOUNTALLOC_CHECK_DELETE(class_name, p)
192 #endif
193 
194  // Redefine all new & delete operators.
196 
197 #undef OVR_REFCOUNTALLOC_CHECK_DELETE
198 
199 #ifdef OVR_DEFINE_NEW
200 #define new OVR_DEFINE_NEW
201 #endif
202  // OVR_BUILD_DEFINE_NEW
203  // DOM-IGNORE-END
204 };
205 
206 
207 template<class Base>
208 class RefCountBaseStatVImpl : virtual public Base
209 {
210 public:
212 
213  // *** Override New and Delete
214 
215  // DOM-IGNORE-BEGIN
216  // Undef new temporarily if it is being redefined
217 #ifdef OVR_DEFINE_NEW
218 #undef new
219 #endif
220 
221 #define OVR_REFCOUNTALLOC_CHECK_DELETE(class_name, p)
222 
223  // Redefine all new & delete operators.
225 
226 #undef OVR_REFCOUNTALLOC_CHECK_DELETE
227 
228 #ifdef OVR_DEFINE_NEW
229 #define new OVR_DEFINE_NEW
230 #endif
231  // OVR_BUILD_DEFINE_NEW
232  // DOM-IGNORE-END
233 };
234 
235 
236 
237 //-----------------------------------------------------------------------------------
238 // *** End user RefCountBase<> classes
239 
240 
241 // RefCountBase is a base class for classes that require thread-safe reference
242 // counting; it also overrides the new and delete operators to use MemoryHeap.
243 //
244 // Reference counted objects start out with RefCount value of 1. Further lifetime
245 // management is done through the AddRef() and Release() methods, typically
246 // hidden by Ptr<>.
247 
248 template<class C>
249 class RefCountBase : public RefCountBaseStatImpl<RefCountImpl>
250 {
251 public:
252  // Constructor.
254 };
255 
256 // RefCountBaseV is the same as RefCountBase but with virtual AddRef/Release
257 
258 template<class C>
259 class RefCountBaseV : virtual public RefCountBaseStatVImpl<RefCountVImpl>
260 {
261 public:
262  // Constructor.
264 };
265 
266 
267 // RefCountBaseNTS is a base class for classes that require Non-Thread-Safe reference
268 // counting; it also overrides the new and delete operators to use MemoryHeap.
269 // This class should only be used if all pointers to it are known to be assigned,
270 // destroyed and manipulated within one thread.
271 //
272 // Reference counted objects start out with RefCount value of 1. Further lifetime
273 // management is done through the AddRef() and Release() methods, typically
274 // hidden by Ptr<>.
275 
276 template<class C>
277 class RefCountBaseNTS : public RefCountBaseStatImpl<RefCountNTSImpl>
278 {
279 public:
280  // Constructor.
282 };
283 
284 //-----------------------------------------------------------------------------------
285 // ***** Pickable template pointer
287 
288 template <typename T>
289 class Pickable
290 {
291 public:
292  Pickable() : pV(NULL) {}
293  explicit Pickable(T* p) : pV(p) {}
294  Pickable(T* p, PickType) : pV(p)
295  {
296  OVR_ASSERT(pV);
297  if (pV)
298  pV->AddRef();
299  }
300  template <typename OT>
301  Pickable(const Pickable<OT>& other) : pV(other.GetPtr()) {}
302 
303 public:
304  Pickable& operator =(const Pickable& other)
305  {
306  OVR_ASSERT(pV == NULL);
307  pV = other.pV;
308  // Extra check.
309  //other.pV = NULL;
310  return *this;
311  }
312 
313 public:
314  T* GetPtr() const { return pV; }
315  T* operator->() const
316  {
317  return pV;
318  }
319  T& operator*() const
320  {
321  OVR_ASSERT(pV);
322  return *pV;
323  }
324 
325 private:
326  T* pV;
327 };
328 
329 template <typename T>
332 {
333  return Pickable<T>(p);
334 }
335 
336 //-----------------------------------------------------------------------------------
337 // ***** Ref-Counted template pointer
338 
339 // Automatically AddRefs and Releases interfaces
340 
341 void* ReturnArg0(void* p);
342 
343 template<class C>
344 class Ptr
345 {
346 #ifdef OVR_CC_ARM
347  static C* ReturnArg(void* p) { return (C*)ReturnArg0(p); }
348 #endif
349 
350 protected:
352 
353 public:
354 
355  // Constructors
357  { }
358 #ifdef OVR_CC_ARM
359  OVR_FORCE_INLINE Ptr(C &robj) : pObject(ReturnArg(&robj))
360 #else
361  OVR_FORCE_INLINE Ptr(C &robj) : pObject(&robj)
362 #endif
363  { }
365  {
366  // No AddRef() on purpose.
367  }
369  {
370  other.pObject = NULL;
371  // No AddRef() on purpose.
372  }
374  {
375  if (pobj) pobj->AddRef();
376  pObject = pobj;
377  }
379  {
380  if (src.pObject) src.pObject->AddRef();
381  pObject = src.pObject;
382  }
383 
384  template<class R>
386  {
387  if (src) src->AddRef();
388  pObject = src;
389  }
390  template<class R>
392  {
393  // No AddRef() on purpose.
394  }
395 
396  // Destructor
398  {
399  if (pObject) pObject->Release();
400  }
401 
402  // Compares
403  OVR_FORCE_INLINE bool operator == (const Ptr &other) const { return pObject == other.pObject; }
404  OVR_FORCE_INLINE bool operator != (const Ptr &other) const { return pObject != other.pObject; }
405 
406  OVR_FORCE_INLINE bool operator == (C *pother) const { return pObject == pother; }
407  OVR_FORCE_INLINE bool operator != (C *pother) const { return pObject != pother; }
408 
409 
410  OVR_FORCE_INLINE bool operator < (const Ptr &other) const { return pObject < other.pObject; }
411 
412  // Assignment
413  template<class R>
415  {
416  if (src) src->AddRef();
417  if (pObject) pObject->Release();
418  pObject = src;
419  return *this;
420  }
421  // Specialization
423  {
424  if (src) src->AddRef();
425  if (pObject) pObject->Release();
426  pObject = src;
427  return *this;
428  }
429 
431  {
432  if (psrc) psrc->AddRef();
433  if (pObject) pObject->Release();
434  pObject = psrc;
435  return *this;
436  }
438  {
439  if (pObject) pObject->Release();
440  pObject = &src;
441  return *this;
442  }
444  {
445  return Pick(src);
446  }
447  template<class R>
449  {
450  return Pick(src);
451  }
452 
453  // Set Assignment
454  template<class R>
456  {
457  if (src) src->AddRef();
458  if (pObject) pObject->Release();
459  pObject = src;
460  return *this;
461  }
462  // Specialization
464  {
465  if (src) src->AddRef();
466  if (pObject) pObject->Release();
467  pObject = src;
468  return *this;
469  }
470 
472  {
473  if (psrc) psrc->AddRef();
474  if (pObject) pObject->Release();
475  pObject = psrc;
476  return *this;
477  }
479  {
480  if (pObject) pObject->Release();
481  pObject = &src;
482  return *this;
483  }
485  {
486  return Pick(src);
487  }
488 
489  // Nulls ref-counted pointer without decrement
491  {
492  pObject = 0;
493  }
494 
495  // Clears the pointer to the object
497  {
498  if (pObject) pObject->Release();
499  pObject = 0;
500  }
501 
502  // Obtain pointer reference directly, for D3D interfaces
504 
505  // Access Operators
506  OVR_FORCE_INLINE C* GetPtr() const { return pObject; }
507  OVR_FORCE_INLINE C& operator * () const { return *pObject; }
508  OVR_FORCE_INLINE C* operator -> () const { return pObject; }
509  // Conversion
510  OVR_FORCE_INLINE operator C* () const { return pObject; }
511 
512  // Pickers.
513 
514  // Pick a value.
516  {
517  if (&other != this)
518  {
519  if (pObject) pObject->Release();
520  pObject = other.pObject;
521  other.pObject = 0;
522  }
523 
524  return *this;
525  }
526 
528  {
529  if (v.GetPtr() != pObject)
530  {
531  if (pObject) pObject->Release();
532  pObject = v.GetPtr();
533  }
534 
535  return *this;
536  }
537 
538  template<class R>
540  {
541  if (v.GetPtr() != pObject)
542  {
543  if (pObject) pObject->Release();
544  pObject = v.GetPtr();
545  }
546 
547  return *this;
548  }
549 
551  {
552  if (p != pObject)
553  {
554  if (pObject) pObject->Release();
555  pObject = p;
556  }
557 
558  return *this;
559  }
560 };
561 
562 } // OVR
563 
564 #endif
void Release() const
#define OVR_FORCE_INLINE
OVR_FORCE_INLINE RefCountImplCore()
Definition: OVR_RefCount.h:69
OVR_FORCE_INLINE Ptr< C > & SetPtr(const Ptr< R > &src)
Definition: OVR_RefCount.h:455
OVR_FORCE_INLINE bool operator==(const Ptr &other) const
Definition: OVR_RefCount.h:403
OVR_FORCE_INLINE void Clear()
Definition: OVR_RefCount.h:496
OVR_FORCE_INLINE Ptr< C > & SetPtr(Pickable< C > src)
Definition: OVR_RefCount.h:484
#define OVR_CDECL
OVR_FORCE_INLINE bool operator<(const Ptr &other) const
Definition: OVR_RefCount.h:410
void operator=(const RefCountNTSImplCore &)
Definition: OVR_RefCount.h:129
int GetRefCount() const
Definition: OVR_RefCount.h:77
#define NULL
OVR_FORCE_INLINE ~Ptr()
Definition: OVR_RefCount.h:397
volatile int RefCount
Definition: OVR_RefCount.h:65
#define OVR_MEMORY_REDEFINE_NEW_IMPL(class_name, check_delete)
Definition: OVR_Allocator.h:73
OVR_FORCE_INLINE C * operator->() const
Definition: OVR_RefCount.h:508
OVR_FORCE_INLINE RefCountBaseV()
Definition: OVR_RefCount.h:263
OVR_FORCE_INLINE RefCountNTSImplCore()
Definition: OVR_RefCount.h:104
OVR_FORCE_INLINE C * GetPtr() const
Definition: OVR_RefCount.h:506
T * operator->() const
Definition: OVR_RefCount.h:315
Pickable(const Pickable< OT > &other)
Definition: OVR_RefCount.h:301
OVR_FORCE_INLINE const Ptr< C > & operator=(const Ptr< R > &src)
Definition: OVR_RefCount.h:414
OVR_FORCE_INLINE Ptr(const Ptr< C > &src)
Definition: OVR_RefCount.h:378
OVR_FORCE_INLINE Ptr< C > & Pick(Pickable< R > v)
Definition: OVR_RefCount.h:539
OVR_FORCE_INLINE Ptr< C > & Pick(C *p)
Definition: OVR_RefCount.h:550
OVR_FORCE_INLINE void AddRef() const
Definition: OVR_RefCount.h:163
static OVR_FORCE_INLINE void checkInvalidDelete(RefCountNTSImplCore *)
Definition: OVR_RefCount.h:125
OVR_FORCE_INLINE Ptr< C > & SetPtr(C *psrc)
Definition: OVR_RefCount.h:471
OVR_FORCE_INLINE Ptr< C > & Pick(Pickable< C > v)
Definition: OVR_RefCount.h:527
OVR_FORCE_INLINE C & operator*() const
Definition: OVR_RefCount.h:507
virtual void Release()
OVR_FORCE_INLINE bool operator!=(const Ptr &other) const
Definition: OVR_RefCount.h:404
void * ReturnArg0(void *p)
OVR_FORCE_INLINE Ptr< C > & SetPtr(const Ptr< C > &src)
Definition: OVR_RefCount.h:463
OVR_FORCE_INLINE Ptr< C > & Pick(Ptr< C > &other)
Definition: OVR_RefCount.h:515
OVR_FORCE_INLINE Ptr()
Definition: OVR_RefCount.h:356
T * GetPtr() const
Definition: OVR_RefCount.h:314
Pickable(T *p, PickType)
Definition: OVR_RefCount.h:294
#define OVR_ASSERT(p)
OVR_FORCE_INLINE C *& GetRawRef()
Definition: OVR_RefCount.h:503
void operator=(const RefCountImplCore &)
Definition: OVR_RefCount.h:94
OVR_FORCE_INLINE Ptr(Pickable< C > v)
Definition: OVR_RefCount.h:364
OVR_FORCE_INLINE Ptr(Ptr< C > &other, PickType)
Definition: OVR_RefCount.h:368
OVR_FORCE_INLINE Ptr(Pickable< R > v)
Definition: OVR_RefCount.h:391
T & operator*() const
Definition: OVR_RefCount.h:319
#define OVR_REFCOUNTALLOC_CHECK_DELETE(class_name, p)
Definition: OVR_RefCount.h:221
static void checkInvalidDelete(RefCountImplCore *)
Definition: OVR_RefCount.h:90
OVR_FORCE_INLINE RefCountBaseNTS()
Definition: OVR_RefCount.h:281
OVR_FORCE_INLINE RefCountBase()
Definition: OVR_RefCount.h:253
OVR_FORCE_INLINE Pickable< T > MakePickable(T *p)
Definition: OVR_RefCount.h:331
OVR_FORCE_INLINE Ptr(Ptr< R > &src)
Definition: OVR_RefCount.h:385
OVR_FORCE_INLINE Ptr(C *pobj)
Definition: OVR_RefCount.h:373
OVR_FORCE_INLINE Ptr< C > & SetPtr(C &src)
Definition: OVR_RefCount.h:478
OVR_FORCE_INLINE void NullWithoutRelease()
Definition: OVR_RefCount.h:490
virtual void AddRef()
Pickable & operator=(const Pickable &other)
Definition: OVR_RefCount.h:304