00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifndef ArmageTron_SAFEPTR_H
00029 #define ArmageTron_SAFEPTR_H
00030
00031 #include "aa_config.h"
00032 #include <stddef.h>
00033 #if HAVE_UNISTD_H
00034
00035 #endif
00036
00037 #include "tError.h"
00038
00039 class tCheckedPTRBase{
00040 friend class tPTRList;
00041 int id;
00042 protected:
00043 void *target;
00044 public:
00045 tCheckedPTRBase(void *x);
00046 tCheckedPTRBase(const tCheckedPTRBase &x);
00047 tCheckedPTRBase();
00048 ~tCheckedPTRBase();
00049
00050 tCheckedPTRBase& operator=(void *x){target=x; return *this;}
00051
00052
00053
00054 operator bool() const{return target!=NULL;}
00055 bool operator !() const{return !target;}
00056
00057 static void CheckDestructed(void *test);
00058
00059 static void Check();
00060 };
00061
00062
00063 template<class T> class tCheckedPTR:public tCheckedPTRBase{
00064 typedef T myclass;
00065 public:
00066 tCheckedPTR(T *x):tCheckedPTRBase(x){};
00067 tCheckedPTR(const tCheckedPTR<T> &x):tCheckedPTRBase(x.target){};
00068 tCheckedPTR():tCheckedPTRBase(){};
00069 ~tCheckedPTR(){};
00070
00071 tCheckedPTR<T> &operator=(T *x){tCheckedPTRBase::operator=(x); return *this;}
00072 tCheckedPTR<T> &operator=(const tCheckedPTR<T> &x)
00073 {tCheckedPTRBase::operator=(x.target); return *this;}
00074 T * operator->() const {return reinterpret_cast<T*>(target);}
00075 T & operator*() const {return *reinterpret_cast<T*>(target);}
00076 operator T*() const {return reinterpret_cast<T*>(target);}
00077
00078
00079 bool operator==(const T* x)const{return target==x;}
00080 bool operator!=(const T* x)const{return target!=x;}
00081 bool operator==(const tCheckedPTR<T> &x)const{return target==x.target;}
00082 bool operator!=(const tCheckedPTR<T> &x)const{return target!=x.target;}
00083
00084 void Destroy(){
00085 if (target){
00086 T *dummy=reinterpret_cast<T*>(target);
00087 target=NULL;
00088 delete dummy;
00089 }
00090 }
00091 };
00092
00093 template<class T> class tCheckedPTRConst:public tCheckedPTRBase{
00094 typedef T myclass;
00095 public:
00096 tCheckedPTRConst():tCheckedPTRBase(NULL){};
00097 tCheckedPTRConst(const T *x):tCheckedPTRBase(reinterpret_cast<void *>(x)){};
00098 tCheckedPTRConst(const tCheckedPTRConst<T> &x):tCheckedPTRBase(x.target){};
00099 tCheckedPTRConst(const tCheckedPTR<T> &x):tCheckedPTRBase(x.operator->()){};
00100 ~tCheckedPTRConst(){};
00101
00102 tCheckedPTRConst<T> &operator=(const T *x)
00103 {tCheckedPTRBase::operator=(reinterpret_cast<T *>(x)); return *this;}
00104 tCheckedPTRConst<T> &operator=(const tCheckedPTRConst<T> &x)
00105 {tCheckedPTRBase::operator=(x.target); return *this;}
00106 tCheckedPTRConst<T> &operator=(const tCheckedPTR<T> &x)
00107 {tCheckedPTRBase::operator=(x.operator->()); return *this;}
00108
00109 const T * operator->() const {return target;}
00110 const T & operator*() const {return *reinterpret_cast<T*>(target);}
00111 operator const T*() const {return reinterpret_cast<const T*>(target);}
00112
00113
00114 bool operator==(const T* x)const{return target==x;}
00115 bool operator!=(const T* x)const{return target!=x;}
00116
00117 void Destroy(){
00118 if (target){
00119 T *dummy=reinterpret_cast<T *>(target);
00120 target=NULL;
00121 dummy->AddRef();
00122 dummy->Release();
00123 }
00124 }
00125 };
00126
00127
00128
00129
00130
00131
00132
00133 template<class T> void SafeDelete(T &x){
00134 x.Destroy();
00135 }
00136
00137 template<class T> void SafeDeletePtr(T * &x){
00138 if (x){
00139 T *dummy=x;
00140 x=NULL;
00141 delete dummy;
00142 }
00143 }
00144
00145 #define tDESTROY_PTR(x) SafeDeletePtr(x)
00146
00147 #ifdef DEBUG
00148 #ifdef CHECK_PTR
00149 #define tDESTROY(x) SafeDelete(x)
00150 #define tCHECKED_PTR(x) tCheckedPTR<x>
00151 #define tCHECKED_PTR_CONST(x) tCheckedPTRConst<x>
00152 #define tCHECK_DEST tCheckedPTRBase::CheckDestructed(this)
00153 #define tSAFEPTR
00154 #else
00155 #define tDESTROY(x) SafeDeletePtr(x)
00156 #define tCHECK_DEST
00157 #define tCHECKED_PTR(x) x *
00158 #define tCHECKED_PTR_CONST(x) const x *
00159 #endif
00160 #else
00161 #define tDESTROY(x) SafeDeletePtr(x)
00162 #define tCHECK_DEST
00163 #define tCHECKED_PTR(x) x *
00164 #define tCHECKED_PTR_CONST(x) const x *
00165 #endif
00166
00167 #define tCONTROLLED_PTR(x) tControlledPTR<x>
00168
00169
00170
00171 template<class T> class tControlledPTR{
00172 tCHECKED_PTR(T) target;
00173
00174 void AddRef(){
00175 if (target)
00176 target->AddRef();
00177 }
00178
00179 void Release(){
00180 if (target){
00181
00182 T *dummy=reinterpret_cast<T*>(target);
00183 target=NULL;
00184 dummy->Release();
00185
00186
00187
00188
00189 }
00190 }
00191
00192 public:
00193
00194 tControlledPTR(T *x):target(x){AddRef();}
00195 tControlledPTR(const tCheckedPTR<T> &x):target(x.operator->()){AddRef();}
00196 tControlledPTR(const tControlledPTR<T> &x):target(x.target){AddRef();}
00197 tControlledPTR():target(NULL){};
00198
00199
00200 tControlledPTR<T> &operator=(T *x){
00201 if (target!=x){
00202 Release();
00203 target=x;
00204 AddRef();
00205 }
00206 return *this;
00207 }
00208
00209 tControlledPTR<T> &operator=(const tControlledPTR<T> &x){
00210 if (target!=x.target){
00211 Release();
00212 target=x.target;
00213 AddRef();
00214 }
00215 return *this;
00216 }
00217
00218 T * operator->() const {
00219 return target;
00220 }
00221
00222 T & operator*() const {
00223 return *target;
00224 }
00225
00226 operator T*() const {
00227 return target;
00228 }
00229
00230
00231
00232
00233
00234
00235
00236 bool operator==(const T* x)const{
00237 return target==x;
00238 }
00239
00240 bool operator!=(const T* x)const{
00241 return target!=x;
00242 }
00243
00244 bool operator==(T* x)const{
00245 return target==x;
00246 }
00247
00248 bool operator!=(T* x)const{
00249 return target!=x;
00250 }
00251
00252 operator bool()const{
00253 return target!=NULL;
00254 }
00255
00256 bool operator !()const{
00257 return target==NULL;
00258 }
00259
00260 bool operator==(const tControlledPTR<T> &x)const{
00261 return target==x.target;
00262 }
00263
00264 bool operator!=(const tControlledPTR<T> &x)const{
00265 return target!=x.target;
00266 }
00267
00268 void Destroy(){
00269 if (target){
00270 #ifdef tSAFEPTR
00271 T *dummy=(T *)target;
00272 target=NULL;
00273 delete dummy;
00274 #else
00275 delete target();
00276 target=NULL;
00277 #endif
00278 }
00279 }
00280
00281
00282 ~tControlledPTR(){
00283 Release();
00284 };
00285 };
00286
00287 template<class T> class tJUST_CONTROLLED_PTR{
00288 T * target;
00289
00290 void AddRef(){
00291 if (target)
00292 target->AddRef();
00293 }
00294
00295 void Release(){
00296 if (target){
00297 T *dummy=target;
00298 target=NULL;
00299 dummy->Release();
00300 }
00301 }
00302
00303 public:
00304
00305 tJUST_CONTROLLED_PTR(T *x):target(x){AddRef();}
00306 tJUST_CONTROLLED_PTR(const tCheckedPTR<T> &x):target(x.operator->()){AddRef();}
00307 tJUST_CONTROLLED_PTR(const tJUST_CONTROLLED_PTR<T> &x):target(x.target){AddRef();}
00308 tJUST_CONTROLLED_PTR():target(NULL){};
00309
00310
00311 tJUST_CONTROLLED_PTR<T> &operator=(T *x){
00312 if (target!=x){
00313 Release();
00314 target=x;
00315 AddRef();
00316 }
00317 return *this;
00318 }
00319
00320 tJUST_CONTROLLED_PTR<T> &operator=(const tJUST_CONTROLLED_PTR<T> &x){
00321 operator=(x.target);
00322 return *this;
00323 }
00324
00325 T * operator->() const {
00326 return target;
00327 }
00328
00329 T & operator*() const {
00330 return *target;
00331 }
00332
00333 operator T*() const {
00334 return target;
00335 }
00336
00337
00338
00339
00340
00341
00342
00343 bool operator==(const T* x)const{
00344 return target==x;
00345 }
00346
00347 bool operator!=(const T* x)const{
00348 return target!=x;
00349 }
00350
00351 bool operator==(const tJUST_CONTROLLED_PTR<T> &x)const{
00352 return target==x.target;
00353 }
00354
00355 bool operator!=(const tJUST_CONTROLLED_PTR<T> &x)const{
00356 return target!=x.target;
00357 }
00358
00359 void Destroy(){
00360 if (target){
00361 #ifdef tSAFEPTR
00362 T *dummy=(T *)target;
00363 target=NULL;
00364 delete dummy;
00365 #else
00366 delete target();
00367 target=NULL;
00368 #endif
00369 }
00370 }
00371
00372
00373 ~tJUST_CONTROLLED_PTR(){
00374 Release();
00375 };
00376 };
00377
00378
00379 template<class T> bool operator==(const T *x, const tJUST_CONTROLLED_PTR<T> &y)
00380 {
00381 return (x == static_cast<const T*>(y));
00382 }
00383
00384 template<class T> bool operator==(T *x, const tJUST_CONTROLLED_PTR<T> &y)
00385 {
00386 return (x == static_cast<const T*>(y));
00387 }
00388
00389 template<class T> bool operator==(const T *x, tJUST_CONTROLLED_PTR<T> &y)
00390 {
00391 return (x == static_cast<const T*>(y));
00392 }
00393
00394 template<class T> bool operator==(T *x, tJUST_CONTROLLED_PTR<T> &y)
00395 {
00396 return (x == static_cast<const T*>(y));
00397 }
00398
00399 template< class T > class tStackObject: public T
00400 {
00401 public:
00402 tStackObject(){ this->AddRef(); }
00403 template< typename A >
00404 explicit tStackObject( A& a ): T( a ) { this->AddRef(); }
00405 template< typename A, typename B >
00406 tStackObject( A& a, B& b ): T( a, b ) { this->AddRef(); }
00407 template< typename A, typename B, typename C >
00408 tStackObject( A& a, B& b, C& c ): T( a, b, c ) { this->AddRef(); }
00409
00410 ~tStackObject()
00411 {
00412 if ( this->GetRefcount() != 1 )
00413 st_Breakpoint();
00414
00415 this->refCtr_ = -1000;
00416 }
00417 };
00418
00419 #ifdef DEBUG
00420 void st_AddRefBreakpint( void const * object );
00421 void st_ReleaseBreakpint( void const * object );
00422 #endif
00423
00424
00425 struct tNonMutex
00426 {
00427 void acquire(){};
00428 void release(){};
00429 };
00430
00431 template< class T, class MUTEX = tNonMutex > class tReferencable
00432 {
00433 friend class tStackObject< T >;
00434
00435 public:
00436 tReferencable() :refCtr_(0) {};
00437 tReferencable ( const tReferencable& ) :refCtr_(0) {};
00438 tReferencable& operator = ( const tReferencable& ){ return *this; }
00439
00440 void AddRef () const
00441 {
00442 #ifdef DEBUG
00443 st_AddRefBreakpint( this );
00444 #endif
00445 tASSERT( this && refCtr_ >= 0 );
00446 mutex_.acquire();
00447 ++refCtr_;
00448 mutex_.release();
00449 tASSERT( this && refCtr_ >= 0 );
00450 }
00451
00452 void Release () const
00453 {
00454 #ifdef DEBUG
00455 st_ReleaseBreakpint( this );
00456 #endif
00457
00458 tASSERT ( this && refCtr_ >= 0 );
00459 mutex_.acquire();
00460 --refCtr_;
00461 mutex_.release();
00462
00463 if ( refCtr_ <= 0 )
00464 {
00465 refCtr_ = -1000;
00466 delete static_cast< const T* >( this );
00467 }
00468 }
00469
00470 int GetRefcount () const
00471 {
00472 tASSERT( this );
00473 return refCtr_;
00474 }
00475 protected:
00476 ~tReferencable()
00477 {
00478 tASSERT( this && ( refCtr_ == -1000 || refCtr_ == 0 ) );
00479 refCtr_ = -1000;
00480 }
00481 private:
00482 mutable int refCtr_;
00483 mutable MUTEX mutex_;
00484 };
00485
00486
00487 #endif
00488
00489
00490