1 #ifndef CAL_REF_COUNTED_H 2 #define CAL_REF_COUNTED_H 3 4 5 #include "cal3d/platform.h" 6 7 8 namespace cal3d 9 { 10 11 template<typename T> class RefPtr; 12 13 /** 14 * Derive from RefCounted to make your class have reference-counted 15 * lifetime semantics. Use RefPtr to manage references. (Don't 16 * call incRef() or decRef() directly.) When deriving from 17 * RefCounted, make your destructor protected so manual deletion 18 * won't happen on accident. 19 * 20 * Note: The reference count is initialized to 0. This makes sense, 21 * because, at object construction, no RefPtrs have referenced the 22 * object. However, this can cause trouble if you (indirectly) make 23 * a RefPtr to 'this' within your constructor. When the refptr goes 24 * out of scope, the count goes back to 0, and the object is deleted 25 * before it even exits the constructor. Current recommended solution: 26 * Don't make refptrs to 'this'. Pass 'this' by raw pointer and such. 27 */ 28 class CAL3D_API RefCounted 29 { 30 template<typename T> friend T* explicitIncRef(T* p); 31 friend void explicitDecRef(RefCounted* p); 32 33 protected: RefCounted()34 RefCounted() 35 : m_refCount(0) 36 { 37 } 38 39 /** 40 * Protected so users of refcounted classes don't use std::auto_ptr 41 * or the delete operator. 42 * 43 * Interfaces that derive from RefCounted should define an inline, 44 * empty, protected destructor as well. 45 */ ~RefCounted()46 virtual ~RefCounted() 47 { 48 assert(m_refCount == 0 && "_refCount nonzero in destructor"); 49 } 50 51 // Must use RefPtr instead of manually calling incRef() and decRef(). 52 private: incRef()53 void incRef() 54 { 55 assert(m_refCount >= 0 && "_refCount is less than zero in incRef()!"); 56 ++m_refCount; 57 } 58 59 /** 60 * Remove a reference from the internal reference count. When this 61 * reaches 0, the object is destroyed. 62 */ decRef()63 void decRef() 64 { 65 assert(m_refCount > 0 && 66 "_refCount is less than or equal to zero in decRef()!"); 67 if (--m_refCount == 0) 68 { 69 delete this; 70 } 71 } 72 73 public: getRefCount()74 int getRefCount() const 75 { 76 return m_refCount; 77 } 78 79 private: 80 // Copying a RefCounted object must be done manually by the 81 // subclass. Otherwise the refCount gets copied too, and 82 // that's Bad. 83 RefCounted(const RefCounted& rhs); 84 RefCounted& operator=(const RefCounted& rhs); 85 86 private: 87 int m_refCount; 88 }; 89 90 template<typename T> explicitIncRef(T * p)91 T* explicitIncRef(T* p) 92 { 93 p->incRef(); 94 return p; 95 } 96 explicitDecRef(RefCounted * p)97 inline void explicitDecRef(RefCounted* p) 98 { 99 p->decRef(); 100 } 101 102 } 103 104 105 #endif 106