00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifndef REFERENCECOUNTED_H
00019 #define REFERENCECOUNTED_H
00020
00021
00022 #include <map>
00023 #include <iostream>
00024 #include <string>
00025
00026 #include "glassert.h"
00027
00028
00033 class ReferenceCounted
00034 {
00035 int count;
00036
00037
00038 public:
00039
00040 ReferenceCounted():count(0){}
00041 ReferenceCounted( const ReferenceCounted& ):count(0){}
00042
00043 virtual ~ReferenceCounted(){}
00044
00045 inline void ref() { ++count; }
00046 inline ReferenceCounted* unref()
00047 {
00048 --count;
00049 if(count < 1)
00050 { delete this; return NULL; }
00051 return this;
00052 }
00053
00054 inline int getCount() { return count; }
00055 };
00056
00060 template <class T>
00061 class IRCPointer
00062 {
00063 public:
00064 ReferenceCounted* rc;
00065
00066 IRCPointer()
00067 :rc(NULL) {}
00068
00069 IRCPointer(const IRCPointer& irc)
00070 :rc(irc.rc) { ref(); }
00071
00072 template<class T2>
00073 IRCPointer(const IRCPointer<T2>& irc)
00074 :rc(irc.rc) { ref(); }
00075
00076 IRCPointer( T* p )
00077 :rc(NULL)
00078 {
00079 rc = p;
00080 ref();
00081 }
00082
00083 ~IRCPointer()
00084 { unref(); }
00085
00086 IRCPointer& operator = (const IRCPointer& irc)
00087 { irc.ref(); unref(); rc = irc.rc; return *this; }
00088
00089 template<class T2>
00090 IRCPointer& operator = (const IRCPointer<T2>& irc)
00091 { irc.ref(); unref(); rc = irc.rc; return *this; }
00092
00093 IRCPointer& operator = (T* p)
00094 { if(p) p->ref(); unref(); rc = p; return *this; }
00095
00096 inline bool operator == (T* p)
00097 { return ((static_cast<ReferenceCounted*>(p) == rc) ? true : false ); }
00098
00099 inline bool operator != (T* p)
00100 { return ((static_cast<ReferenceCounted*>(p) != rc) ? true : false ); }
00101
00102 inline operator T* (void)
00103 { return static_cast<T*>(rc); }
00104
00105 inline T* operator ->(void)
00106 { return static_cast<T*>(rc); }
00107
00108 T& operator *(void)
00109 { return *(static_cast<T*>(rc)); }
00110
00111 inline void ref(void) const
00112 {
00113 if( rc )
00114 rc->ref();
00115 }
00116
00117 inline void unref(void)
00118 {
00119 if( rc )
00120 rc = rc->unref();
00121 }
00122 };
00123
00124
00126 template <class T, bool HasArray = false, class R = T>
00127 class RCPointer
00128 {
00129 protected:
00130 typedef std::pair<int, void*> pairType;
00131 pairType* countedPointer;
00132
00133 public:
00134
00135 RCPointer();
00136 RCPointer(T*);
00137 RCPointer(const RCPointer&);
00138 template <class T2>
00139 RCPointer(const RCPointer<T2, HasArray, T2>&);
00140
00141 ~RCPointer();
00142
00143 RCPointer& operator = (const RCPointer&);
00144
00145 template <class T2>
00146 RCPointer& operator = (const RCPointer<T2, HasArray, T2>&);
00147
00148 RCPointer& operator = (T* p)
00149 {
00150 PRINT(typeid(this).name()<<"::operator = ("<<p<<") used")
00151 if(countedPointer)
00152 {
00153 if(p != countedPointer->second)
00154 unref();
00155 else
00156 return *this;
00157 }
00158
00159 countedPointer = new pairType(1,p);
00160 return *this;
00161 }
00162
00163 inline bool operator == (T*);
00164 inline bool operator != (T*);
00165
00166
00167 inline operator T* (void);
00168 inline T* operator ->(void);
00169 T& operator *(void);
00170 R& operator [](const int);
00171
00172 inline void ref(void) const;
00173 inline void unref(void);
00174
00175 inline pairType* getCountedPointer() const { return countedPointer; }
00176 };
00177
00179 template <class T, bool HasArray, class R>
00180 RCPointer<T,HasArray,R>::RCPointer()
00181 :countedPointer(NULL)
00182 {
00183 PRINT(typeid(this).name()<<" created with no countedPointer ");
00184 }
00185
00186 template <class T, bool HasArray, class R>
00187 RCPointer<T,HasArray,R>::RCPointer(T* p)
00188 :countedPointer(NULL)
00189 {
00190 if(p)
00191 {
00192 countedPointer = new pairType(1,p);
00193 PRINT(typeid(this).name()<<" created with count: "<<countedPointer->first);
00194 }
00195 }
00196
00197 template <class T, bool HasArray, class R>
00198 RCPointer<T,HasArray,R>::RCPointer(const RCPointer& rc)
00199 :countedPointer(NULL)
00200 {
00201
00202 PRINT(typeid(this).name()<<" copied ");
00203 if( &rc )
00204 {
00205 countedPointer = rc.countedPointer;
00206
00207 ref();
00208 }
00209 }
00210
00211 template <class T, bool HasArray, class R>
00212 template <class T2>
00213 RCPointer<T,HasArray,R>::RCPointer(const RCPointer<T2, HasArray, T2>& rc)
00214 :countedPointer(NULL)
00215 {
00216
00217 PRINT(typeid(this).name()<<" copied from "<<typeid(&rc).name())
00218
00219 if( &rc )
00220 {
00221 if( rc.getCountedPointer() )
00222 {
00223 countedPointer = rc.getCountedPointer();
00224 ref();
00225 }
00226 }
00227 }
00228
00229 template <class T, bool HasArray, class R>
00230 RCPointer<T,HasArray,R>::~RCPointer()
00231 {
00232 if(countedPointer)
00233 {
00234 PRINT(typeid(this).name()<<" attempted deletion at count: "<<countedPointer->first -1);
00235 unref();
00236 }
00237 }
00238
00239 template <class T, bool HasArray, class R>
00240 RCPointer<T,HasArray,R>& RCPointer<T,HasArray,R>::operator = (const RCPointer<T,HasArray,R>& rc)
00241 {
00242 PRINT(typeid(this).name()<<"::operator = ("<<typeid(this).name()<<") used")
00243
00244 rc.ref();
00245
00246 unref();
00247
00248 countedPointer = rc.countedPointer;
00249
00250 return *this;
00251 }
00252
00253 template <class T, bool HasArray, class R>
00254 template <class T2>
00255 RCPointer<T,HasArray,R>& RCPointer<T,HasArray,R>::operator = (const RCPointer<T2, HasArray, T2>& rc)
00256 {
00257 PRINT(typeid(this).name()<<"::operator = ("<<typeid(&rc).name()<<") used")
00258
00259 rc.ref();
00260
00261 unref();
00262
00263 countedPointer = rc.getCountedPointer();
00264
00265 if( dynamic_cast<T*>( static_cast<T2*>(countedPointer->second) ) )
00266 {
00267
00268 }
00269 else
00270 {
00271 unref();
00272 }
00273
00274 return *this;
00275 }
00276
00277 template <class T, bool HasArray, class R>
00278 bool RCPointer<T,HasArray,R>::operator == (T* p)
00279 {
00280 PRINT(typeid(this).name()<<"::operator == ("<<p<<") used")
00281
00282 if(countedPointer)
00283 {
00284 if(countedPointer->second == p)
00285 return true;
00286 else
00287 return false;
00288 }
00289 else
00290 {
00291 if(p == NULL)
00292 return true;
00293 else
00294 return false;
00295 }
00296 }
00297
00298 template <class T, bool HasArray, class R>
00299 bool RCPointer<T,HasArray,R>::operator != (T* p)
00300 {
00301 PRINT(typeid(this).name()<<"::operator != ("<<p<<") used")
00302
00303 if(countedPointer)
00304 {
00305 if(p != countedPointer->second)
00306 return true;
00307 else
00308 return false;
00309 }
00310 else
00311 {
00312 if(p == NULL)
00313 return false;
00314 else
00315 return true;
00316 }
00317 }
00318
00319 template <class T, bool HasArray, class R>
00320 RCPointer<T,HasArray,R>::operator T* (void)
00321 {
00322 PRINT(typeid(this).name()<<"::operator (T*) () used")
00323 if(countedPointer)
00324 return static_cast<T*>(countedPointer->second);
00325 else
00326 return NULL;
00327 }
00328
00329 template <class T, bool HasArray, class R>
00330 inline T* RCPointer<T,HasArray,R>::operator ->(void)
00331 {
00332 PRINT(typeid(this).name()<<"::operator -> () used")
00333 if(countedPointer)
00334 return static_cast<T*>(countedPointer->second);
00335 else
00336 return NULL;
00337 }
00338
00339 template <class T, bool HasArray, class R>
00340 T& RCPointer<T,HasArray,R>::operator *(void)
00341 {
00342 PRINT(typeid(this).name()<<"::operator * () used")
00343
00344 customAssert(countedPointer, "no valid pointer in T& op * from RCP");
00345
00346 return *(static_cast<T*>(countedPointer->second));
00347 }
00348
00349 template <class T, bool HasArray, class R>
00350 R& RCPointer<T,HasArray,R>::operator [](const int index)
00351 {
00352 PRINT(typeid(this).name()<<"::operator [] ("<<index<<") used")
00353
00354 customAssert(countedPointer, "no valid pointer in R& op [] from RCP");
00355
00356 return (static_cast<T*>(countedPointer->second)) [index];
00357 }
00358
00359 template <class T, bool HasArray, class R>
00360 void RCPointer<T,HasArray,R>::ref (void) const
00361 {
00362 PRINT(typeid(this).name()<<" ref used")
00363
00364 if(countedPointer)
00365 ++(countedPointer->first);
00366 }
00367
00368 template <class T, bool HasArray, class R>
00369 void RCPointer<T,HasArray,R>::unref (void)
00370 {
00371 PRINT(typeid(this).name()<<" unref used")
00372
00373 if(countedPointer)
00374 {
00375 --(countedPointer->first);
00376
00377 if(countedPointer->first < 1)
00378 {
00379 PRINT(typeid(this).name()<<" has gone out of reference, is deleted by default.")
00380 if(countedPointer->second)
00381 {
00382 if(HasArray)
00383 delete [] (static_cast<T*>(countedPointer->second));
00384 else
00385 delete (static_cast<T*>(countedPointer->second));
00386 }
00387
00388 delete countedPointer;
00389 }
00390
00391 countedPointer = NULL;
00392
00393
00394
00395 }
00396 }
00397
00398
00399 #endif