/* ************************************************************************* ArmageTron -- Just another Tron Lightcycle Game in 3D. Copyright (C) 2000 Manuel Moos (manuel@moosnet.de) ************************************************************************** This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *************************************************************************** */ #ifndef ArmageTron_SAFEPTR_H #define ArmageTron_SAFEPTR_H #include #ifndef WIN32 #include #endif #include "tError.h" class tCheckedPTRBase{ friend class tPTRList; int id; protected: void *target; public: tCheckedPTRBase(void *x); tCheckedPTRBase(const tCheckedPTRBase &x); tCheckedPTRBase(); ~tCheckedPTRBase(); tCheckedPTRBase& operator=(void *x){target=x; return *this;} // void * operator->() const {return target;} // void & operator*() const {return *target;} //operator void *() const {return target;} operator bool() const{return target!=NULL;} bool operator !() const{return !target;} static void CheckDestructed(void *test); static void Check(); }; template class tCheckedPTR:public tCheckedPTRBase{ typedef T myclass; public: tCheckedPTR(T *x):tCheckedPTRBase(x){}; tCheckedPTR(const tCheckedPTR &x):tCheckedPTRBase(x.target){}; tCheckedPTR():tCheckedPTRBase(){}; ~tCheckedPTR(){}; tCheckedPTR &operator=(T *x){tCheckedPTRBase::operator=(x); return *this;} tCheckedPTR &operator=(const tCheckedPTR &x) {tCheckedPTRBase::operator=(x.target); return *this;} T * operator->() const {return reinterpret_cast(target);} T & operator*() const {return *reinterpret_cast(target);} operator T*() const {return reinterpret_cast(target);} // T** operator&() {return reinterpret_cast(&target);} bool operator==(const T* x)const{return target==x;} bool operator!=(const T* x)const{return target!=x;} bool operator==(const tCheckedPTR &x)const{return target==x.target;} bool operator!=(const tCheckedPTR &x)const{return target!=x.target;} void Destroy(){ if (target){ T *dummy=reinterpret_cast(target); target=NULL; delete dummy; } } }; template class tCheckedPTRConst:public tCheckedPTRBase{ typedef T myclass; public: tCheckedPTRConst():tCheckedPTRBase(NULL){}; tCheckedPTRConst(const T *x):tCheckedPTRBase(reinterpret_cast(x)){}; tCheckedPTRConst(const tCheckedPTRConst &x):tCheckedPTRBase(x.target){}; tCheckedPTRConst(const tCheckedPTR &x):tCheckedPTRBase(x.operator->()){}; ~tCheckedPTRConst(){}; tCheckedPTRConst &operator=(const T *x) {tCheckedPTRBase::operator=(reinterpret_cast(x)); return *this;} tCheckedPTRConst &operator=(const tCheckedPTRConst &x) {tCheckedPTRBase::operator=(x.target); return *this;} tCheckedPTRConst &operator=(const tCheckedPTR &x) {tCheckedPTRBase::operator=(x.operator->()); return *this;} const T * operator->() const {return target;} const T & operator*() const {return *reinterpret_cast(target);} operator const T*() const {return reinterpret_cast(target);} // const T** operator&() {return reinterpret_cast(&target);} bool operator==(const T* x)const{return target==x;} bool operator!=(const T* x)const{return target!=x;} void Destroy(){ if (target){ T *dummy=reinterpret_cast(target); target=NULL; dummy->AddRef(); dummy->Release(); } } }; //#define CHECK_PTR 1 template void SafeDelete(T &x){ x.Destroy(); } template void SafeDeletePtr(T * &x){ if (x){ T *dummy=x; x=NULL; delete dummy; } } #define tDESTROY_PTR(x) SafeDeletePtr(x) #ifdef DEBUG #ifdef CHECK_PTR #define tDESTROY(x) SafeDelete(x) #define tCHECKED_PTR(x) tCheckedPTR #define tCHECKED_PTR_CONST(x) tCheckedPTRConst #define tCHECK_DEST tCheckedPTRBase::CheckDestructed(this) #define tSAFEPTR #else #define tDESTROY(x) SafeDeletePtr(x) #define tCHECK_DEST #define tCHECKED_PTR(x) x * #define tCHECKED_PTR_CONST(x) const x * #endif #else #define tDESTROY(x) SafeDeletePtr(x) #define tCHECK_DEST #define tCHECKED_PTR(x) x * #define tCHECKED_PTR_CONST(x) const x * #endif #define tCONTROLLED_PTR(x) tControlledPTR template class tControlledPTR{ tCHECKED_PTR(T) target; void AddRef(){ if (target) target->AddRef(); } void Release(){ if (target){ //#ifdef tSAFEPTR T *dummy=reinterpret_cast(target); target=NULL; dummy->Release(); //#else // target->Release(); // target=NULL; //#endif } } public: tControlledPTR(T *x):target(x){AddRef();} tControlledPTR(const tCheckedPTR &x):target(x.operator->()){AddRef();} tControlledPTR(const tControlledPTR &x):target(x.target){AddRef();} tControlledPTR():target(NULL){}; tControlledPTR &operator=(T *x){ if (target!=x){ Release(); target=x; AddRef(); } return *this; } tControlledPTR &operator=(const tControlledPTR &x){ if (target!=x.target){ Release(); target=x.target; AddRef(); } return *this; } T * operator->() const { return target; } T & operator*() const { return *target; } operator T*() const { return target; } /* T** operator&() { return ⌖ } */ bool operator==(const T* x)const{ return target==x; } bool operator!=(const T* x)const{ return target!=x; } bool operator==(T* x)const{ return target==x; } bool operator!=(T* x)const{ return target!=x; } operator bool()const{ return target!=NULL; } bool operator !()const{ return target==NULL; } bool operator==(const tControlledPTR &x)const{ return target==x.target; } bool operator!=(const tControlledPTR &x)const{ return target!=x.target; } void Destroy(){ if (target){ #ifdef tSAFEPTR T *dummy=(T *)target; target=NULL; delete dummy; #else delete target(); target=NULL; #endif } } ~tControlledPTR(){ Release(); }; }; template class tJUST_CONTROLLED_PTR{ T * target; void AddRef(){ if (target) target->AddRef(); } void Release(){ if (target){ T *dummy=target; target=NULL; dummy->Release(); } } public: tJUST_CONTROLLED_PTR(T *x):target(x){AddRef();} tJUST_CONTROLLED_PTR(const tCheckedPTR &x):target(x.operator->()){AddRef();} tJUST_CONTROLLED_PTR(const tJUST_CONTROLLED_PTR &x):target(x.target){AddRef();} tJUST_CONTROLLED_PTR():target(NULL){}; tJUST_CONTROLLED_PTR &operator=(T *x){ if (target!=x){ Release(); target=x; AddRef(); } return *this; } tJUST_CONTROLLED_PTR &operator=(const tJUST_CONTROLLED_PTR &x){ operator=(x.target); return *this; } T * operator->() const { return target; } T & operator*() const { return *target; } operator T*() const { return target; } /* T** operator&() { return ⌖ } */ bool operator==(const T* x)const{ return target==x; } bool operator!=(const T* x)const{ return target!=x; } bool operator==(const tJUST_CONTROLLED_PTR &x)const{ return target==x.target; } bool operator!=(const tJUST_CONTROLLED_PTR &x)const{ return target!=x.target; } void Destroy(){ if (target){ #ifdef tSAFEPTR T *dummy=(T *)target; target=NULL; delete dummy; #else delete target(); target=NULL; #endif } } ~tJUST_CONTROLLED_PTR(){ Release(); }; }; template bool operator==(const T *x, const tJUST_CONTROLLED_PTR &y) { return (x == static_cast(y)); } template bool operator==(T *x, const tJUST_CONTROLLED_PTR &y) { return (x == static_cast(y)); } template bool operator==(const T *x, tJUST_CONTROLLED_PTR &y) { return (x == static_cast(y)); } template bool operator==(T *x, tJUST_CONTROLLED_PTR &y) { return (x == static_cast(y)); } template< class T > class tStackObject: public T { public: tStackObject(){ this->AddRef(); } template< typename A > explicit tStackObject( A& a ): T( a ) { this->AddRef(); } template< typename A, typename B > tStackObject( A& a, B& b ): T( a, b ) { this->AddRef(); } template< typename A, typename B, typename C > tStackObject( A& a, B& b, C& c ): T( a, b, c ) { this->AddRef(); } ~tStackObject() { if ( this->GetRefcount() != 1 ) st_Breakpoint(); this->refCtr_ = -1000; } }; template< class T> class tReferencable { friend class tStackObject< T >; public: tReferencable() :refCtr_(0) {}; tReferencable ( const tReferencable& ) :refCtr_(0) {}; tReferencable& operator = ( const tReferencable& ){ return *this; } void AddRef () const { tASSERT( this && refCtr_ >= 0 ); ++refCtr_; tASSERT( this && refCtr_ >= 0 ); } void Release () const { tASSERT ( this && refCtr_ >= 0 ); if ( --refCtr_ <= 0 ) { refCtr_ = -1000; delete static_cast< const T* >( this ); } } int GetRefcount () const { tASSERT( this ); return refCtr_; } protected: ~tReferencable() { tASSERT( this && refCtr_ == -1000 ); refCtr_ = -1000; } private: mutable int refCtr_; }; #endif