refBase.h

Engine/source/core/util/refBase.h

More...

Classes:

class

Base class for StrongRefBase strong reference pointers.

class

Base class for objects which can be strongly referenced (i.e., as long as reference exists, object will exist, when all strong references go away, object is destroyed).

class

Reference counted object template pointer class Instances of this template class can be used as pointers to instances of StrongRefBase and its subclasses.

class

Union of an arbitrary type with a StrongRefBase.

class

This oxymoron is a pointer that reference-counts the referenced object but also NULLs out if the object goes away.

class

Base class for objects which can be weakly referenced (i.e., reference goes away when object is destroyed).

class

Weak reference pointer class.

class

Union of an arbitrary type with a WeakRefBase.

Public Functions

T &
Deref(StrongRefPtr< T > & ref)
T &
T &
Deref(WeakRefPtr< T > & ref)

Detailed Description

Public Functions

Deref(StrongRefPtr< T > & ref)

Deref(StrongWeakRefPtr< T > & ref)

Deref(WeakRefPtr< T > & ref)

  1
  2//-----------------------------------------------------------------------------
  3// Copyright (c) 2012 GarageGames, LLC
  4//
  5// Permission is hereby granted, free of charge, to any person obtaining a copy
  6// of this software and associated documentation files (the "Software"), to
  7// deal in the Software without restriction, including without limitation the
  8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9// sell copies of the Software, and to permit persons to whom the Software is
 10// furnished to do so, subject to the following conditions:
 11//
 12// The above copyright notice and this permission notice shall be included in
 13// all copies or substantial portions of the Software.
 14//
 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 21// IN THE SOFTWARE.
 22//-----------------------------------------------------------------------------
 23
 24#ifndef _REFBASE_H_
 25#define _REFBASE_H_
 26
 27#ifndef _PLATFORMASSERT_H_
 28#  include "platform/platformAssert.h"
 29#endif
 30#ifndef _TYPETRAITS_H_
 31#  include "platform/typetraits.h"
 32#endif
 33
 34
 35/// Base class for objects which can be weakly referenced
 36/// (i.e., reference goes away when object is destroyed).
 37class WeakRefBase
 38{
 39public:
 40
 41   /// Weak reference to WeakRefBase. 
 42   class WeakReference
 43   {
 44   public:
 45
 46      WeakRefBase * get() { return mObject; }
 47      void incRefCount() { mRefCount++; }
 48      void decRefCount()
 49      {
 50         AssertFatal( mRefCount > 0, "WeakReference - decrementing count of zero!" );
 51         if (--mRefCount==0)
 52            delete this;
 53      }
 54      U32 getRefCount() { return mRefCount; }
 55
 56   private:
 57
 58      friend class WeakRefBase;
 59      WeakReference(WeakRefBase *object) { mObject = object; mRefCount = 0; }
 60      ~<a href="/coding/class/classweakrefbase_1_1weakreference/">WeakReference</a>() { AssertFatal(mObject==<a href="/coding/file/types_8lint_8h/#types_8lint_8h_1a070d2ce7b6bb7e5c05602aa8c308d0c4">NULL</a>, "Deleting weak reference which still points at an object."); }
 61
 62      // Object we reference
 63      WeakRefBase *mObject;
 64
 65      // reference count for this structure (not WeakObjectRef itself)
 66      U32 mRefCount; 
 67   };
 68
 69public:
 70   WeakRefBase() { mReference = NULL; }
 71   virtual ~WeakRefBase() { clearWeakReferences(); }
 72
 73   WeakReference * getWeakReference();
 74
 75protected:
 76   void clearWeakReferences();
 77
 78private:
 79   WeakReference * mReference;
 80};
 81
 82template< typename T > class SimObjectPtr;
 83
 84/// Weak reference pointer class.
 85/// Instances of this template class can be used as pointers to
 86/// instances of WeakRefBase and its subclasses.
 87/// When the object referenced by a WeakRefPtr instance is deleted,
 88/// the pointer to the object is set to NULL in the WeakRefPtr instance.
 89template <class T> class WeakRefPtr
 90{
 91public:
 92   WeakRefPtr()  { mReference = NULL; }
 93   WeakRefPtr(T *ptr)  { mReference = NULL; set(ptr); }
 94   WeakRefPtr(const WeakRefPtr<T> & ref) { mReference = NULL; set(ref.mReference); }
 95   
 96   ~WeakRefPtr() { set((WeakRefBase::WeakReference*)NULL); }
 97
 98   WeakRefPtr<T>& operator=(const WeakRefPtr<T>& ref)
 99   {
100      set(ref.mReference);
101      return *this;
102   }
103   WeakRefPtr<T>& operator=(T *ptr)
104   {
105      set(ptr);
106      return *this;
107   }
108
109   /// Returns true if the pointer is not set.
110   bool isNull() const { return mReference == NULL || mReference->get() == NULL; }
111   
112   /// Returns true if the pointer is set.
113   bool isValid() const { return mReference && mReference->get(); }
114   
115   T* operator->() const { return getPointer(); }
116   T& operator*() const { return *getPointer(); }
117   operator T*() const { return getPointer(); }
118   
119   /// Returns the pointer.
120   T* getPointer() const { return mReference ? ( T* ) mReference->get() : NULL; }
121
122protected:
123   void set(WeakRefBase::WeakReference * ref)
124   {
125      if (mReference)
126         mReference->decRefCount();
127      mReference = NULL;
128      if (ref)
129      {
130         mReference = ref;
131         mReference->incRefCount();
132      }
133   }
134
135   void set(T * obj) { set(obj ? obj->getWeakReference() : (WeakRefBase::WeakReference *)NULL); }
136private:
137   template< typename > friend class SimObjectPtr;
138   WeakRefBase::WeakReference * mReference;
139};
140
141/// Union of an arbitrary type with a WeakRefBase.  The exposed type will
142/// remain accessible so long as the WeakRefBase is not cleared.  Once
143/// it is cleared, accessing the exposed type will result in a NULL pointer.
144template<class ExposedType>
145class WeakRefUnion
146{
147   typedef WeakRefUnion<ExposedType> Union;
148
149public:
150   WeakRefUnion() : mPtr(NULL) {}
151   WeakRefUnion(const WeakRefPtr<WeakRefBase> & ref, ExposedType * ptr) : mPtr(NULL) { set(ref, ptr); }
152   WeakRefUnion(const Union & lock) : mPtr(NULL) { *this = lock; }
153   WeakRefUnion(WeakRefBase * ref) : mPtr(NULL) { set(ref, dynamic_cast<ExposedType*>(ref)); }
154   ~WeakRefUnion() { mWeakReference = NULL; }
155
156   Union & operator=(const Union & ptr)
157   {
158      set(ptr.mWeakReference, ptr.getPointer());
159      return *this;
160   }
161
162   void set(const WeakRefPtr<WeakRefBase> & ref, ExposedType * ptr)
163   {
164      mWeakReference = ref;
165      mPtr = ptr;
166   }
167
168   bool operator ==(const ExposedType * t ) const { return getPointer() == t; }
169   bool operator !=(const ExposedType * t ) const { return getPointer() != t; }
170   bool operator ==(const Union &t ) const { return getPointer() == t.getPointer(); }
171   bool operator !=(const Union &t ) const { return getPointer() != t.getPointer(); }
172   bool isNull()  const  { return mWeakReference.isNull() || !mPtr; }
173
174   ExposedType* getPointer() const { return !mWeakReference.isNull() ? mPtr : NULL; }
175   ExposedType* operator->() const { return getPointer(); }
176   ExposedType& operator*() const { return *getPointer(); }
177   operator ExposedType*() const { return getPointer(); }
178
179   WeakRefPtr<WeakRefBase> getRef() const { return mWeakReference; }
180
181private:
182   WeakRefPtr<WeakRefBase> mWeakReference;
183   ExposedType * mPtr;
184};
185
186/// Base class for objects which can be strongly referenced
187/// (i.e., as long as reference exists, object will exist,
188/// when all strong references go away, object is destroyed).
189class StrongRefBase : public WeakRefBase
190{
191   friend class StrongObjectRef;
192
193public:
194   StrongRefBase() { mRefCount = 0; }
195
196   U32 getRefCount() const { return mRefCount; }
197
198   /// object destroy self call (from StrongRefPtr).  Override if this class has specially allocated memory.
199   virtual void destroySelf() { delete this; }
200
201   /// Increments the reference count.
202   void incRefCount()
203   {
204      mRefCount++;
205   }
206
207   /// Decrements the reference count.
208   void decRefCount()
209   {
210      AssertFatal(mRefCount, "Decrementing a reference with refcount 0!");
211      if(!--mRefCount)
212         destroySelf();
213   }
214
215protected:
216   U32 mRefCount; ///< reference counter for StrongRefPtr objects
217};
218
219/// Base class for StrongRefBase strong reference pointers.
220class StrongObjectRef
221{
222
223public:
224   /// Constructor, assigns from the object and increments its reference count if it's not NULL
225   StrongObjectRef(StrongRefBase *object = NULL) : mObject( object )
226   {
227      mObject = object;
228      incRef();
229   }
230
231   /// Destructor, dereferences the object, if there is one
232   ~StrongObjectRef() { decRef(); }
233
234   /// Assigns this reference object from an existing StrongRefBase instance
235   void set(StrongRefBase *object)
236   {
237      if( mObject != object )
238      {
239         decRef();
240         mObject = object;
241         incRef();
242      }
243   }
244
245protected:
246   StrongRefBase *mObject; ///< the object this RefObjectRef references
247
248   /// increments the reference count on the referenced object
249   void incRef()
250   {
251      if(mObject)
252         mObject->incRefCount();
253   }
254
255   /// decrements the reference count on the referenced object
256   void decRef()
257   {
258      if(mObject)
259         mObject->decRefCount();
260   }
261};
262
263/// Reference counted object template pointer class
264/// Instances of this template class can be used as pointers to
265/// instances of StrongRefBase and its subclasses.  The object will not
266/// be deleted until all of the StrongRefPtr instances pointing to it
267/// have been destructed.
268template <class T> class StrongRefPtr : protected StrongObjectRef
269{
270public:
271   StrongRefPtr() : StrongObjectRef() {}
272   StrongRefPtr(T *ptr) : StrongObjectRef(ptr) {}
273   StrongRefPtr(const StrongRefPtr<T>& ref) : StrongObjectRef(ref.mObject) {}
274   ~StrongRefPtr() {}
275
276   StrongRefPtr<T>& operator=(const StrongRefPtr<T>& ref)
277   {
278      set(ref.mObject);
279      return *this;
280   }
281   StrongRefPtr<T>& operator=(T *ptr)
282   {
283      set(ptr);
284      return *this;
285   }
286
287   bool isNull()  const  { return mObject == 0; }
288   bool isValid() const  { return mObject != 0; }
289   T* operator->() const { return getPointer(); }
290   T& operator*() const  { return *getPointer(); }
291   operator T*() const { return getPointer(); }
292   T* getPointer() const { return const_cast<T*>(static_cast<T* const>(mObject)); }
293};
294
295/// Union of an arbitrary type with a StrongRefBase.  StrongRefBase will remain locked
296/// until the union is destructed.  Handy for when the exposed class will
297/// become invalid whenever the reference becomes invalid and you want to make sure that doesn't
298/// happen.
299template<class ExposedType>
300class StrongRefUnion
301{
302   typedef StrongRefUnion<ExposedType> Union;
303
304public:
305   StrongRefUnion() : mPtr(NULL) {}
306
307   StrongRefUnion(const StrongRefPtr<StrongRefBase> & ref, ExposedType * ptr) : mPtr(NULL) { set(ref, ptr); }
308   StrongRefUnion(const Union & lock) : mPtr(NULL) { *this = lock; }
309   StrongRefUnion(StrongRefBase * ref) : mPtr(NULL) { set(ref, dynamic_cast<ExposedType*>(ref)); }
310
311   ~StrongRefUnion() { mReference = NULL; }
312
313   Union & operator=(const Union & ptr)
314   {
315      set(ptr.mReference, ptr.mPtr);
316      return *this;
317   }
318
319   void set(const StrongRefPtr<StrongRefBase> & ref, ExposedType * ptr)
320   {
321      mReference = ref;
322      mPtr = ptr;
323   }
324
325   bool operator ==(const ExposedType * t ) const { return mPtr == t; }
326   bool operator !=(const ExposedType * t ) const { return mPtr != t; }
327   bool operator ==(const Union &t ) const { return mPtr == t.mPtr; }
328   bool operator !=(const Union &t ) const { return mPtr != t.mPtr; }
329   bool isNull()  const  { return mReference.isNull() || !mPtr; }
330   bool isValid() const  { return mReference.isValid() && mPtr; }
331
332   ExposedType* operator->() const { return mPtr; }
333   ExposedType& operator*() const { return *mPtr; }
334   operator ExposedType*() const { return mPtr; }
335   ExposedType* getPointer() const { return mPtr; }
336
337   StrongRefPtr<StrongRefBase> getRef() const { return mReference; }
338
339private:
340   StrongRefPtr<StrongRefBase> mReference;
341   ExposedType * mPtr;
342};
343
344/// This oxymoron is a pointer that reference-counts the referenced
345/// object but also NULLs out if the object goes away.
346///
347/// This is useful for situations where an object's lifetime is ultimately
348/// governed by a superior entity but where individual objects may also die
349/// independently of the superior entity.  All client code should use
350/// StrongWeakRefs that keep object live as long as the superior entity doesn't
351/// step in and kill them (in which case, the client code sees the reference
352/// disappear).
353template< class T >
354class StrongWeakRefPtr
355{
356public:
357   StrongWeakRefPtr() : mReference( NULL ) {}
358   StrongWeakRefPtr( T* ptr ) : mReference( NULL ) { _set( ptr ); }
359   ~StrongWeakRefPtr()
360   {
361      if( mReference )
362      {
363         T* ptr = _get();
364         if( ptr )
365            ptr->decRefCount();
366
367         mReference->decRefCount();
368      }
369   }
370
371   bool isNull() const { return ( _get() == NULL ); }
372   bool operator==( T* ptr ) const { return ( _get() == ptr ); }
373   bool operator!=( T* ptr ) const { return ( _get() != ptr ); }
374   bool operator!() const { return isNull(); }
375   T* operator->() const { return _get(); }
376   T& operator*() const { return *( _get() ); }
377   operator T*() const { return _get(); }
378   T* getPointer() const { return _get(); }
379
380   StrongWeakRefPtr& operator=( T* ptr )
381   {
382      _set( ptr );
383      return *this;
384   }
385
386private:
387   WeakRefBase::WeakReference* mReference;
388
389   T* _get() const
390   {
391      if( mReference )
392         return static_cast< T* >( mReference->get() );
393      else
394         return NULL;
395   }
396   void _set( T* ptr )
397   {
398      if( mReference )
399      {
400         T* old = _get();
401         if( old )
402            old->decRefCount();
403
404         mReference->decRefCount();
405      }
406
407      if( ptr )
408      {
409         ptr->incRefCount();
410         mReference = ptr->getWeakReference();
411         mReference->incRefCount();
412      }
413      else
414         mReference = NULL;
415   }
416};
417
418//---------------------------------------------------------------
419
420inline void WeakRefBase::clearWeakReferences()
421{
422   if (mReference)
423   {
424      mReference->mObject = NULL;
425      mReference->decRefCount();
426      mReference = NULL;
427   }
428}
429
430inline WeakRefBase::WeakReference * WeakRefBase::getWeakReference()
431{
432   if (!mReference)
433   {
434      mReference = new WeakReference(this);
435      mReference->incRefCount();
436   }
437   return mReference;
438}
439
440//---------------------------------------------------------------
441
442template< typename T >
443struct TypeTraits< WeakRefPtr< T > > : public _TypeTraits< WeakRefPtr< T > >
444{
445   typedef typename TypeTraits< T >::BaseType BaseType;
446};
447template< typename T >
448struct TypeTraits< StrongRefPtr< T > > : public _TypeTraits< StrongRefPtr< T > >
449{
450   typedef typename TypeTraits< T >::BaseType BaseType;
451};
452template< typename T >
453struct TypeTraits< StrongWeakRefPtr< T > > : public _TypeTraits< StrongWeakRefPtr< T > >
454{
455   typedef typename TypeTraits< T >::BaseType BaseType;
456};
457
458template< typename T >
459inline T& Deref( WeakRefPtr< T>& ref )
460{
461   return *ref;
462}
463template< typename T >
464inline T& Deref( StrongRefPtr< T>& ref )
465{
466   return *ref;
467}
468template< typename T >
469inline T& Deref( StrongWeakRefPtr< T>& ref )
470{
471   return *ref;
472}
473
474#endif
475