oculus1
diff libovr/Src/Kernel/OVR_RefCount.h @ 1:e2f9e4603129
added LibOVR and started a simple vr wrapper.
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sat, 14 Sep 2013 16:14:59 +0300 |
parents | |
children | b069a5c27388 |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/libovr/Src/Kernel/OVR_RefCount.h Sat Sep 14 16:14:59 2013 +0300 1.3 @@ -0,0 +1,1 @@ 1.4 +/************************************************************************************ 1.5 1.6 PublicHeader: Kernel 1.7 Filename : OVR_RefCount.h 1.8 Content : Reference counting implementation headers 1.9 Created : September 19, 2012 1.10 Notes : 1.11 1.12 Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 1.13 1.14 Use of this software is subject to the terms of the Oculus license 1.15 agreement provided at the time of installation or download, or which 1.16 otherwise accompanies this software in either electronic or hard copy form. 1.17 1.18 ************************************************************************************/ 1.19 1.20 #ifndef OVR_RefCount_h 1.21 #define OVR_RefCount_h 1.22 1.23 #include "OVR_Types.h" 1.24 #include "OVR_Allocator.h" 1.25 1.26 namespace OVR { 1.27 1.28 //----------------------------------------------------------------------------------- 1.29 // ***** Reference Counting 1.30 1.31 // There are three types of reference counting base classes: 1.32 // 1.33 // RefCountBase - Provides thread-safe reference counting (Default). 1.34 // RefCountBaseNTS - Non Thread Safe version of reference counting. 1.35 1.36 1.37 // ***** Declared classes 1.38 1.39 template<class C> 1.40 class RefCountBase; 1.41 template<class C> 1.42 class RefCountBaseNTS; 1.43 1.44 class RefCountImpl; 1.45 class RefCountNTSImpl; 1.46 1.47 1.48 //----------------------------------------------------------------------------------- 1.49 // ***** Implementation For Reference Counting 1.50 1.51 // RefCountImplCore holds RefCount value and defines a few utility 1.52 // functions shared by all implementations. 1.53 1.54 class RefCountImplCore 1.55 { 1.56 protected: 1.57 volatile int RefCount; 1.58 1.59 public: 1.60 // RefCountImpl constructor always initializes RefCount to 1 by default. 1.61 OVR_FORCE_INLINE RefCountImplCore() : RefCount(1) { } 1.62 1.63 // Need virtual destructor 1.64 // This: 1. Makes sure the right destructor's called. 1.65 // 2. Makes us have VTable, necessary if we are going to have format needed by InitNewMem() 1.66 virtual ~RefCountImplCore(); 1.67 1.68 // Debug method only. 1.69 int GetRefCount() const { return RefCount; } 1.70 1.71 // This logic is used to detect invalid 'delete' calls of reference counted 1.72 // objects. Direct delete calls are not allowed on them unless they come in 1.73 // internally from Release. 1.74 #ifdef OVR_BUILD_DEBUG 1.75 static void OVR_CDECL reportInvalidDelete(void *pmem); 1.76 inline static void checkInvalidDelete(RefCountImplCore *pmem) 1.77 { 1.78 if (pmem->RefCount != 0) 1.79 reportInvalidDelete(pmem); 1.80 } 1.81 #else 1.82 inline static void checkInvalidDelete(RefCountImplCore *) { } 1.83 #endif 1.84 1.85 // Base class ref-count content should not be copied. 1.86 void operator = (const RefCountImplCore &) { } 1.87 }; 1.88 1.89 class RefCountNTSImplCore 1.90 { 1.91 protected: 1.92 mutable int RefCount; 1.93 1.94 public: 1.95 // RefCountImpl constructor always initializes RefCount to 1 by default. 1.96 OVR_FORCE_INLINE RefCountNTSImplCore() : RefCount(1) { } 1.97 1.98 // Need virtual destructor 1.99 // This: 1. Makes sure the right destructor's called. 1.100 // 2. Makes us have VTable, necessary if we are going to have format needed by InitNewMem() 1.101 virtual ~RefCountNTSImplCore(); 1.102 1.103 // Debug method only. 1.104 int GetRefCount() const { return RefCount; } 1.105 1.106 // This logic is used to detect invalid 'delete' calls of reference counted 1.107 // objects. Direct delete calls are not allowed on them unless they come in 1.108 // internally from Release. 1.109 #ifdef OVR_BUILD_DEBUG 1.110 static void OVR_CDECL reportInvalidDelete(void *pmem); 1.111 OVR_FORCE_INLINE static void checkInvalidDelete(RefCountNTSImplCore *pmem) 1.112 { 1.113 if (pmem->RefCount != 0) 1.114 reportInvalidDelete(pmem); 1.115 } 1.116 #else 1.117 OVR_FORCE_INLINE static void checkInvalidDelete(RefCountNTSImplCore *) { } 1.118 #endif 1.119 1.120 // Base class ref-count content should not be copied. 1.121 void operator = (const RefCountNTSImplCore &) { } 1.122 }; 1.123 1.124 1.125 1.126 // RefCountImpl provides Thread-Safe implementation of reference counting, so 1.127 // it should be used by default in most places. 1.128 1.129 class RefCountImpl : public RefCountImplCore 1.130 { 1.131 public: 1.132 // Thread-Safe Ref-Count Implementation. 1.133 void AddRef(); 1.134 void Release(); 1.135 }; 1.136 1.137 // RefCountVImpl provides Thread-Safe implementation of reference counting, plus, 1.138 // virtual AddRef and Release. 1.139 1.140 class RefCountVImpl : public RefCountImplCore 1.141 { 1.142 public: 1.143 // Thread-Safe Ref-Count Implementation. 1.144 virtual void AddRef(); 1.145 virtual void Release(); 1.146 }; 1.147 1.148 1.149 // RefCountImplNTS provides Non-Thread-Safe implementation of reference counting, 1.150 // which is slightly more efficient since it doesn't use atomics. 1.151 1.152 class RefCountNTSImpl : public RefCountNTSImplCore 1.153 { 1.154 public: 1.155 OVR_FORCE_INLINE void AddRef() const { RefCount++; } 1.156 void Release() const; 1.157 }; 1.158 1.159 1.160 1.161 // RefCountBaseStatImpl<> is a common class that adds new/delete override with Stat tracking 1.162 // to the reference counting implementation. Base must be one of the RefCountImpl classes. 1.163 1.164 template<class Base> 1.165 class RefCountBaseStatImpl : public Base 1.166 { 1.167 public: 1.168 RefCountBaseStatImpl() { } 1.169 1.170 // *** Override New and Delete 1.171 1.172 // DOM-IGNORE-BEGIN 1.173 // Undef new temporarily if it is being redefined 1.174 #ifdef OVR_DEFINE_NEW 1.175 #undef new 1.176 #endif 1.177 1.178 #ifdef OVR_BUILD_DEBUG 1.179 // Custom check used to detect incorrect calls of 'delete' on ref-counted objects. 1.180 #define OVR_REFCOUNTALLOC_CHECK_DELETE(class_name, p) \ 1.181 do {if (p) Base::checkInvalidDelete((class_name*)p); } while(0) 1.182 #else 1.183 #define OVR_REFCOUNTALLOC_CHECK_DELETE(class_name, p) 1.184 #endif 1.185 1.186 // Redefine all new & delete operators. 1.187 OVR_MEMORY_REDEFINE_NEW_IMPL(Base, OVR_REFCOUNTALLOC_CHECK_DELETE) 1.188 1.189 #ifdef OVR_DEFINE_NEW 1.190 #define new OVR_DEFINE_NEW 1.191 #endif 1.192 // OVR_BUILD_DEFINE_NEW 1.193 // DOM-IGNORE-END 1.194 }; 1.195 1.196 1.197 1.198 //----------------------------------------------------------------------------------- 1.199 // *** End user RefCountBase<> classes 1.200 1.201 1.202 // RefCountBase is a base class for classes that require thread-safe reference 1.203 // counting; it also overrides the new and delete operators to use MemoryHeap. 1.204 // 1.205 // Reference counted objects start out with RefCount value of 1. Further lifetime 1.206 // management is done through the AddRef() and Release() methods, typically 1.207 // hidden by Ptr<>. 1.208 1.209 template<class C> 1.210 class RefCountBase : public RefCountBaseStatImpl<RefCountImpl> 1.211 { 1.212 public: 1.213 // Constructor. 1.214 OVR_FORCE_INLINE RefCountBase() : RefCountBaseStatImpl<RefCountImpl>() { } 1.215 }; 1.216 1.217 // RefCountBaseV is the same as RefCountBase but with virtual AddRef/Release 1.218 1.219 template<class C> 1.220 class RefCountBaseV : public RefCountBaseStatImpl<RefCountVImpl> 1.221 { 1.222 public: 1.223 // Constructor. 1.224 OVR_FORCE_INLINE RefCountBaseV() : RefCountBaseStatImpl<RefCountVImpl>() { } 1.225 }; 1.226 1.227 1.228 // RefCountBaseNTS is a base class for classes that require Non-Thread-Safe reference 1.229 // counting; it also overrides the new and delete operators to use MemoryHeap. 1.230 // This class should only be used if all pointers to it are known to be assigned, 1.231 // destroyed and manipulated within one thread. 1.232 // 1.233 // Reference counted objects start out with RefCount value of 1. Further lifetime 1.234 // management is done through the AddRef() and Release() methods, typically 1.235 // hidden by Ptr<>. 1.236 1.237 template<class C> 1.238 class RefCountBaseNTS : public RefCountBaseStatImpl<RefCountNTSImpl> 1.239 { 1.240 public: 1.241 // Constructor. 1.242 OVR_FORCE_INLINE RefCountBaseNTS() : RefCountBaseStatImpl<RefCountNTSImpl>() { } 1.243 }; 1.244 1.245 //----------------------------------------------------------------------------------- 1.246 // ***** Pickable template pointer 1.247 enum PickType { PickValue }; 1.248 1.249 template <typename T> 1.250 class Pickable 1.251 { 1.252 public: 1.253 Pickable() : pV(NULL) {} 1.254 explicit Pickable(T* p) : pV(p) {} 1.255 Pickable(T* p, PickType) : pV(p) 1.256 { 1.257 OVR_ASSERT(pV); 1.258 if (pV) 1.259 pV->AddRef(); 1.260 } 1.261 template <typename OT> 1.262 Pickable(const Pickable<OT>& other) : pV(other.GetPtr()) {} 1.263 1.264 public: 1.265 Pickable& operator =(const Pickable& other) 1.266 { 1.267 OVR_ASSERT(pV == NULL); 1.268 pV = other.pV; 1.269 // Extra check. 1.270 //other.pV = NULL; 1.271 return *this; 1.272 } 1.273 1.274 public: 1.275 T* GetPtr() const { return pV; } 1.276 T* operator->() const 1.277 { 1.278 return pV; 1.279 } 1.280 T& operator*() const 1.281 { 1.282 OVR_ASSERT(pV); 1.283 return *pV; 1.284 } 1.285 1.286 private: 1.287 T* pV; 1.288 }; 1.289 1.290 template <typename T> 1.291 OVR_FORCE_INLINE 1.292 Pickable<T> MakePickable(T* p) 1.293 { 1.294 return Pickable<T>(p); 1.295 } 1.296 1.297 //----------------------------------------------------------------------------------- 1.298 // ***** Ref-Counted template pointer 1.299 1.300 // Automatically AddRefs and Releases interfaces 1.301 1.302 void* ReturnArg0(void* p); 1.303 1.304 template<class C> 1.305 class Ptr 1.306 { 1.307 #ifdef OVR_CC_ARM 1.308 static C* ReturnArg(void* p) { return (C*)ReturnArg0(p); } 1.309 #endif 1.310 1.311 protected: 1.312 C *pObject; 1.313 1.314 public: 1.315 1.316 // Constructors 1.317 OVR_FORCE_INLINE Ptr() : pObject(0) 1.318 { } 1.319 #ifdef OVR_CC_ARM 1.320 OVR_FORCE_INLINE Ptr(C &robj) : pObject(ReturnArg(&robj)) 1.321 #else 1.322 OVR_FORCE_INLINE Ptr(C &robj) : pObject(&robj) 1.323 #endif 1.324 { } 1.325 OVR_FORCE_INLINE Ptr(Pickable<C> v) : pObject(v.GetPtr()) 1.326 { 1.327 // No AddRef() on purpose. 1.328 } 1.329 OVR_FORCE_INLINE Ptr(Ptr<C>& other, PickType) : pObject(other.pObject) 1.330 { 1.331 other.pObject = NULL; 1.332 // No AddRef() on purpose. 1.333 } 1.334 OVR_FORCE_INLINE Ptr(C *pobj) 1.335 { 1.336 if (pobj) pobj->AddRef(); 1.337 pObject = pobj; 1.338 } 1.339 OVR_FORCE_INLINE Ptr(const Ptr<C> &src) 1.340 { 1.341 if (src.pObject) src.pObject->AddRef(); 1.342 pObject = src.pObject; 1.343 } 1.344 1.345 template<class R> 1.346 OVR_FORCE_INLINE Ptr(Ptr<R> &src) 1.347 { 1.348 if (src) src->AddRef(); 1.349 pObject = src; 1.350 } 1.351 template<class R> 1.352 OVR_FORCE_INLINE Ptr(Pickable<R> v) : pObject(v.GetPtr()) 1.353 { 1.354 // No AddRef() on purpose. 1.355 } 1.356 1.357 // Destructor 1.358 OVR_FORCE_INLINE ~Ptr() 1.359 { 1.360 if (pObject) pObject->Release(); 1.361 } 1.362 1.363 // Compares 1.364 OVR_FORCE_INLINE bool operator == (const Ptr &other) const { return pObject == other.pObject; } 1.365 OVR_FORCE_INLINE bool operator != (const Ptr &other) const { return pObject != other.pObject; } 1.366 1.367 OVR_FORCE_INLINE bool operator == (C *pother) const { return pObject == pother; } 1.368 OVR_FORCE_INLINE bool operator != (C *pother) const { return pObject != pother; } 1.369 1.370 1.371 OVR_FORCE_INLINE bool operator < (const Ptr &other) const { return pObject < other.pObject; } 1.372 1.373 // Assignment 1.374 template<class R> 1.375 OVR_FORCE_INLINE const Ptr<C>& operator = (const Ptr<R> &src) 1.376 { 1.377 if (src) src->AddRef(); 1.378 if (pObject) pObject->Release(); 1.379 pObject = src; 1.380 return *this; 1.381 } 1.382 // Specialization 1.383 OVR_FORCE_INLINE const Ptr<C>& operator = (const Ptr<C> &src) 1.384 { 1.385 if (src) src->AddRef(); 1.386 if (pObject) pObject->Release(); 1.387 pObject = src; 1.388 return *this; 1.389 } 1.390 1.391 OVR_FORCE_INLINE const Ptr<C>& operator = (C *psrc) 1.392 { 1.393 if (psrc) psrc->AddRef(); 1.394 if (pObject) pObject->Release(); 1.395 pObject = psrc; 1.396 return *this; 1.397 } 1.398 OVR_FORCE_INLINE const Ptr<C>& operator = (C &src) 1.399 { 1.400 if (pObject) pObject->Release(); 1.401 pObject = &src; 1.402 return *this; 1.403 } 1.404 OVR_FORCE_INLINE Ptr<C>& operator = (Pickable<C> src) 1.405 { 1.406 return Pick(src); 1.407 } 1.408 template<class R> 1.409 OVR_FORCE_INLINE Ptr<C>& operator = (Pickable<R> src) 1.410 { 1.411 return Pick(src); 1.412 } 1.413 1.414 // Set Assignment 1.415 template<class R> 1.416 OVR_FORCE_INLINE Ptr<C>& SetPtr(const Ptr<R> &src) 1.417 { 1.418 if (src) src->AddRef(); 1.419 if (pObject) pObject->Release(); 1.420 pObject = src; 1.421 return *this; 1.422 } 1.423 // Specialization 1.424 OVR_FORCE_INLINE Ptr<C>& SetPtr(const Ptr<C> &src) 1.425 { 1.426 if (src) src->AddRef(); 1.427 if (pObject) pObject->Release(); 1.428 pObject = src; 1.429 return *this; 1.430 } 1.431 1.432 OVR_FORCE_INLINE Ptr<C>& SetPtr(C *psrc) 1.433 { 1.434 if (psrc) psrc->AddRef(); 1.435 if (pObject) pObject->Release(); 1.436 pObject = psrc; 1.437 return *this; 1.438 } 1.439 OVR_FORCE_INLINE Ptr<C>& SetPtr(C &src) 1.440 { 1.441 if (pObject) pObject->Release(); 1.442 pObject = &src; 1.443 return *this; 1.444 } 1.445 OVR_FORCE_INLINE Ptr<C>& SetPtr(Pickable<C> src) 1.446 { 1.447 return Pick(src); 1.448 } 1.449 1.450 // Nulls ref-counted pointer without decrement 1.451 OVR_FORCE_INLINE void NullWithoutRelease() 1.452 { 1.453 pObject = 0; 1.454 } 1.455 1.456 // Clears the pointer to the object 1.457 OVR_FORCE_INLINE void Clear() 1.458 { 1.459 if (pObject) pObject->Release(); 1.460 pObject = 0; 1.461 } 1.462 1.463 // Obtain pointer reference directly, for D3D interfaces 1.464 OVR_FORCE_INLINE C*& GetRawRef() { return pObject; } 1.465 1.466 // Access Operators 1.467 OVR_FORCE_INLINE C* GetPtr() const { return pObject; } 1.468 OVR_FORCE_INLINE C& operator * () const { return *pObject; } 1.469 OVR_FORCE_INLINE C* operator -> () const { return pObject; } 1.470 // Conversion 1.471 OVR_FORCE_INLINE operator C* () const { return pObject; } 1.472 1.473 // Pickers. 1.474 1.475 // Pick a value. 1.476 OVR_FORCE_INLINE Ptr<C>& Pick(Ptr<C>& other) 1.477 { 1.478 if (&other != this) 1.479 { 1.480 if (pObject) pObject->Release(); 1.481 pObject = other.pObject; 1.482 other.pObject = 0; 1.483 } 1.484 1.485 return *this; 1.486 } 1.487 1.488 OVR_FORCE_INLINE Ptr<C>& Pick(Pickable<C> v) 1.489 { 1.490 if (v.GetPtr() != pObject) 1.491 { 1.492 if (pObject) pObject->Release(); 1.493 pObject = v.GetPtr(); 1.494 } 1.495 1.496 return *this; 1.497 } 1.498 1.499 template<class R> 1.500 OVR_FORCE_INLINE Ptr<C>& Pick(Pickable<R> v) 1.501 { 1.502 if (v.GetPtr() != pObject) 1.503 { 1.504 if (pObject) pObject->Release(); 1.505 pObject = v.GetPtr(); 1.506 } 1.507 1.508 return *this; 1.509 } 1.510 1.511 OVR_FORCE_INLINE Ptr<C>& Pick(C* p) 1.512 { 1.513 if (p != pObject) 1.514 { 1.515 if (pObject) pObject->Release(); 1.516 pObject = p; 1.517 } 1.518 1.519 return *this; 1.520 } 1.521 }; 1.522 1.523 } // OVR 1.524 1.525 #endif 1.526 \ No newline at end of file