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