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