00001 // +-------------------------------------------------------------------------+ 00002 // | I__n__t__e__L__i__b 0.6.10 development | 00003 // | Copyright (c) Andrey Vikt. Stolyarov <crocodil_AT_croco.net> 2000-2007. | 00004 // | | 00005 // | This is free software. The library part is available under | 00006 // | GNU LESSER GENERAL PUBLIC LICENSE v.2.1. | 00007 // | GNU LGPL v2.1 is found in docs/gnu_gpl2.txt, or at http://www.gnu.org | 00008 // | Please see also docs/readme.txt and visit http://www.intelib.org | 00009 // | | 00010 // | !!! THERE IS NO WARRANTY OF ANY KIND, NEITHER EXPRESSED NOR IMPLIED !!! | 00011 // +-------------------------------------------------------------------------+ 00012 00013 00014 00015 00026 #ifndef INTELIB_REFCOUNT_HPP_SENTRY 00027 #define INTELIB_REFCOUNT_HPP_SENTRY 00028 00030 00035 class GarbageSafe { 00036 friend class GarbageSafePointer; 00037 friend class GarbageSafeConstPointer; 00039 00042 mutable int RefCount; 00044 void AddRef() const { RefCount++; } 00046 void Unlink() const { if((--RefCount)<=0) delete this; } 00047 protected: 00049 00053 bool CanDie() { return RefCount <= 1; } 00054 public: 00056 00064 GarbageSafe() { RefCount = 0; } 00065 protected: 00070 virtual ~GarbageSafe() {} 00071 private: 00075 void operator =(const GarbageSafe &other) {} 00076 }; 00077 00079 00088 class GarbageSafePointer { 00089 GarbageSafe *p; 00090 public: 00092 GarbageSafePointer() { p = 0; } 00093 00095 GarbageSafePointer(const GarbageSafe *pp) 00096 { if((p = (GarbageSafe*) pp)) p->AddRef(); } 00097 00099 GarbageSafePointer(const GarbageSafePointer &other) 00100 { if((p = other.p)) p->AddRef(); } 00101 00103 ~GarbageSafePointer() { if(p) { p->Unlink(); p = 0; } } 00104 00105 00107 00108 GarbageSafePointer& operator =(const GarbageSafePointer &other) 00109 { 00110 GarbageSafe *tmp = p; // this is a workaround for the case 00111 if((p = other.p)) p->AddRef(); // when unlinking p we destroy 00112 if(tmp) tmp->Unlink(); // the structure our operand belongs to 00113 return *this; 00114 } 00115 00117 GarbageSafePointer& operator =(GarbageSafe *pp) 00118 { 00119 GarbageSafe *tmp = p; 00120 if((p = pp)) p->AddRef(); 00121 if(tmp) tmp->Unlink(); 00122 return *this; 00123 } 00124 00126 GarbageSafe* GetPtr() const { return p; } 00127 }; 00128 00129 00131 inline bool 00132 operator==(const GarbageSafePointer& op1, const GarbageSafePointer& op2) 00133 { return op1.GetPtr() == op2.GetPtr(); } 00134 00136 inline bool 00137 operator!=(const GarbageSafePointer& op1, const GarbageSafePointer& op2) 00138 { return op1.GetPtr() != op2.GetPtr(); } 00139 00141 00145 template <class Tp> 00146 class GenericReference : public GarbageSafePointer { 00147 public: 00149 GenericReference() {} 00151 GenericReference(const Tp *tp) : GarbageSafePointer(tp) {} 00153 GenericReference(const GenericReference &other) 00154 : GarbageSafePointer(other) {} 00156 ~GenericReference() {} 00157 00159 GenericReference& operator=(Tp *tp) 00160 { 00161 GarbageSafePointer::operator=(tp); 00162 return *this; 00163 } 00165 GenericReference& operator=(const GenericReference &other) 00166 { 00167 GarbageSafePointer::operator=(other); 00168 return *this; 00169 } 00171 Tp* GetPtr() const 00172 { return static_cast<Tp*>(GarbageSafePointer::GetPtr()); } 00173 00175 Tp* operator ->() const 00176 { return GetPtr(); } 00177 00179 Tp& operator *() const 00180 { return *(GetPtr()); } 00181 00182 }; 00183 00184 #endif //sentry