1 #ifndef __RAKNET_SMART_PTR_H 2 #define __RAKNET_SMART_PTR_H 3 4 // From http://www.codeproject.com/KB/cpp/SmartPointers.aspx 5 // with bugs fixed 6 7 #include "RakMemoryOverride.h" 8 #include "Export.h" 9 10 //static int allocCount=0; 11 //static int deallocCount=0; 12 13 class RAK_DLL_EXPORT ReferenceCounter 14 { 15 private: 16 int refCount; 17 18 public: ReferenceCounter()19 ReferenceCounter() {refCount=0;} ~ReferenceCounter()20 ~ReferenceCounter() {} AddRef()21 void AddRef() {refCount++;} Release()22 int Release() {return --refCount;} GetRefCount(void)23 int GetRefCount(void) const {return refCount;} 24 }; 25 26 template < typename T > class RAK_DLL_EXPORT RakNetSmartPtr 27 { 28 private: 29 T* ptr; // pointer 30 ReferenceCounter* reference; // Reference refCount 31 32 public: RakNetSmartPtr()33 RakNetSmartPtr() : ptr(0), reference(0) 34 { 35 // Do not allocate by default, wasteful if we just have a list of preallocated and unassigend smart pointers 36 } 37 RakNetSmartPtr(T * pValue)38 RakNetSmartPtr(T* pValue) : ptr(pValue) 39 { 40 reference = RakNet::OP_NEW<ReferenceCounter>(__FILE__,__LINE__); 41 reference->AddRef(); 42 43 // allocCount+=2; 44 // printf("allocCount=%i deallocCount=%i Line=%i\n",allocCount, deallocCount, __LINE__); 45 } 46 RakNetSmartPtr(const RakNetSmartPtr<T> & sp)47 RakNetSmartPtr(const RakNetSmartPtr<T>& sp) : ptr(sp.ptr), reference(sp.reference) 48 { 49 if (reference) 50 reference->AddRef(); 51 } 52 ~RakNetSmartPtr()53 ~RakNetSmartPtr() 54 { 55 if(reference && reference->Release() == 0) 56 { 57 RakNet::OP_DELETE(ptr, __FILE__, __LINE__); 58 RakNet::OP_DELETE(reference, __FILE__, __LINE__); 59 60 // deallocCount+=2; 61 // printf("allocCount=%i deallocCount=%i Line=%i\n",allocCount, deallocCount, __LINE__); 62 } 63 } 64 IsNull(void)65 bool IsNull(void) const 66 { 67 return ptr==0; 68 } 69 SetNull(void)70 void SetNull(void) 71 { 72 if(reference && reference->Release() == 0) 73 { 74 RakNet::OP_DELETE(ptr, __FILE__, __LINE__); 75 RakNet::OP_DELETE(reference, __FILE__, __LINE__); 76 77 // deallocCount+=2; 78 // printf("allocCount=%i deallocCount=%i Line=%i\n",allocCount, deallocCount, __LINE__); 79 } 80 ptr=0; 81 reference=0; 82 } 83 IsUnique(void)84 bool IsUnique(void) const 85 { 86 return reference->GetRefCount()==1; 87 } 88 89 // Allow you to change the values of the internal contents of the pointer, without changing what is pointed to by other instances of the smart pointer Clone(bool copyContents)90 void Clone(bool copyContents) 91 { 92 if (IsUnique()==false) 93 { 94 reference->Release(); 95 96 reference = RakNet::OP_NEW<ReferenceCounter>(__FILE__,__LINE__); 97 reference->AddRef(); 98 T* oldPtr=ptr; 99 ptr=RakNet::OP_NEW<T>(__FILE__,__LINE__); 100 if (copyContents) 101 *ptr=*oldPtr; 102 } 103 } 104 GetRefCount(void)105 int GetRefCount(void) const 106 { 107 return reference->GetRefCount(); 108 } 109 110 T& operator* () 111 { 112 return *ptr; 113 } 114 115 const T& operator* () const 116 { 117 return *ptr; 118 } 119 120 T* operator-> () 121 { 122 return ptr; 123 } 124 125 const T* operator-> () const 126 { 127 return ptr; 128 } 129 130 bool operator == (const RakNetSmartPtr<T>& sp) 131 { 132 return ptr == sp.ptr; 133 } 134 bool operator<( const RakNetSmartPtr<T> &right ) {return ptr < right.ptr;} 135 bool operator>( const RakNetSmartPtr<T> &right ) {return ptr > right.ptr;} 136 137 bool operator != (const RakNetSmartPtr<T>& sp) 138 { 139 return ptr != sp.ptr; 140 } 141 142 RakNetSmartPtr<T>& operator = (const RakNetSmartPtr<T>& sp) 143 { 144 // Assignment operator 145 146 if (this != &sp) // Avoid self assignment 147 { 148 if(reference && reference->Release() == 0) 149 { 150 RakNet::OP_DELETE(ptr, __FILE__, __LINE__); 151 RakNet::OP_DELETE(reference, __FILE__, __LINE__); 152 153 // deallocCount+=2; 154 // printf("allocCount=%i deallocCount=%i Line=%i\n",allocCount, deallocCount, __LINE__); 155 } 156 157 ptr = sp.ptr; 158 reference = sp.reference; 159 if (reference) 160 reference->AddRef(); 161 } 162 return *this; 163 } 164 165 166 }; 167 168 #endif 169