openModeller
Version 1.4.0
|
00001 #ifndef _REFCOUNT_HH 00002 #define _REFCOUNT_HH 00003 00004 #include <openmodeller/Log.hh> 00005 00006 #undef DEBUG_MEMORY 00007 00008 // 00009 // This is a very small templated TypeTraits class which really only 00010 // provides a convient way to strip const qualifiers. It is needed 00011 // by the ReferenceCountedPointer<> template below to create 00012 // ReferenceCountedPointer< const T * >. Without the PlainPointerType, 00013 // the underlying type would be const T* instead of the correct 00014 // T*. 00015 // 00016 template< typename T > 00017 class TypeTraits { 00018 private: 00019 template< class U > struct UnConst 00020 { 00021 typedef U* PointerType; 00022 typedef U* PlainPointerType; 00023 typedef U& ReferenceType; 00024 typedef U& PlainReferenceType; 00025 }; 00026 template< class U > struct UnConst<const U> { 00027 typedef U const * PointerType; 00028 typedef U* PlainPointerType; 00029 typedef const U & ReferenceType; 00030 typedef U& PlainReferenceType; 00031 }; 00032 public: 00033 typedef typename UnConst<T>::PointerType PointerType; 00034 typedef typename UnConst<T>::ReferenceType ReferenceType; 00035 typedef typename UnConst<T>::PlainPointerType PlainPointerType; 00036 }; 00037 00038 // 00039 // Declaration of ReferenceCountedObject. 00040 // 00041 // This class contains the _ref_count and is used to decorate 00042 // objects which ReferenceCountedPointer points to. 00043 // This is an intrusive reference count (you need to derive from 00044 // this class). This mechanism has been chosen because 00045 // we have the source of the library and can change the code 00046 // to derive from this class, and it's space and runtime overhead 00047 // is minimal. 00048 // 00049 class dllexp ReferenceCountedObject 00050 { 00051 00052 /* I'd like to get friendship to work here */ 00053 /* Instead each derived class from this base needs 00054 To have it's container's class declared a friend */ 00055 template< typename T > 00056 friend class ReferenceCountedPointer; 00057 00058 protected: 00059 ReferenceCountedObject() : 00060 _ref_count(0) 00061 {} 00062 00063 virtual inline ~ReferenceCountedObject() = 0; 00064 00065 private: 00066 00067 int _ref_count; 00068 00069 }; 00070 00071 template< class T > 00072 class ReferenceCountedPointer { 00073 public: 00074 00075 typedef typename TypeTraits<T>::PointerType PointerType; 00076 typedef typename TypeTraits<T>::ReferenceType ReferenceType; 00077 typedef typename TypeTraits<T>::PlainPointerType PlainPointerType; 00078 00079 template< typename S > 00080 friend class ReferenceCountedPointer; 00081 00082 // 00083 // Default constructor creates pointer to null. 00084 inline ReferenceCountedPointer( ); 00085 00086 // 00087 // implict conversion constructor from T*. 00088 // Provides for the following syntax 00089 // ReferenceCountedPointer<T> ptr = new T(); 00090 // ... ReferenceCountedPoitner<T> ( new T() ); 00091 // 00092 inline ReferenceCountedPointer( PointerType ); 00093 // 00094 // Conversion from class S derived from T 00095 template< class S > 00096 inline ReferenceCountedPointer( S* ); 00097 00098 // 00099 // copy constructor. 00100 inline ReferenceCountedPointer( const ReferenceCountedPointer & ); 00101 // 00102 // copy constructor from derived classes 00103 template< class S > 00104 inline ReferenceCountedPointer( const ReferenceCountedPointer<S> & ); 00105 00106 // 00107 // destructor 00108 inline virtual ~ReferenceCountedPointer(); 00109 00110 inline ReferenceType operator*() const; 00111 inline PointerType operator->() const; 00112 00113 // 00114 // Assignment operator. 00115 inline ReferenceCountedPointer<T>& operator=( const ReferenceCountedPointer& ); 00116 template< class S > 00117 inline ReferenceCountedPointer<T>& operator=( const ReferenceCountedPointer<S>& ); 00118 00119 // 00120 // Assignment from plain pointer classes. 00121 inline ReferenceCountedPointer<T>& operator=( PointerType& ); 00122 template< class S > 00123 inline ReferenceCountedPointer<T>& operator=( S*& ); 00124 00125 // Two ways to test for NULL-ness. 00126 inline bool operator!() const; 00127 inline operator bool() const; 00128 00129 // Need a member for swap since VC doesn't allow friend templates 00130 inline void swap( ReferenceCountedPointer<T>& rhs) { 00131 PlainPointerType tmp = this->_p; 00132 this->_p = rhs._p; 00133 rhs._p = tmp; 00134 } 00135 00136 private: 00137 inline void releasePointer(); 00138 inline void takePointer( PlainPointerType ptr ); 00139 00140 PlainPointerType _p; 00141 00142 }; 00143 00144 template< class T > 00145 void 00146 swap( ReferenceCountedPointer<T>& lhs, ReferenceCountedPointer<T>& rhs ) { 00147 lhs.swap(rhs); 00148 } 00149 00150 /* 00151 * 00152 * Implementation for ReferenceCountedPointer inlines 00153 * 00154 */ 00155 template< class T > 00156 ReferenceCountedPointer<T>::ReferenceCountedPointer() : 00157 _p( 0 ) 00158 { 00159 # if defined(DEBUG_MEMORY) 00160 Log::instance()->debug( "ReferenceCountedPointer<T>::ReferenceCountedPointer()\n"); 00161 # endif 00162 } 00163 00164 template< class T > 00165 ReferenceCountedPointer<T>::ReferenceCountedPointer( const ReferenceCountedPointer & rhs ) 00166 { 00167 # if defined(DEBUG_MEMORY) 00168 Log::instance()->debug( "ReferenceCountedPointer<T>::ReferenceCountedPointer( const ReferenceCountedPointer & rhs )\n" ); 00169 # endif 00170 takePointer( rhs._p ); 00171 } 00172 00173 template< class T > 00174 template< class S > 00175 ReferenceCountedPointer<T>::ReferenceCountedPointer( const ReferenceCountedPointer<S> & rhs ) 00176 { 00177 # if defined(DEBUG_MEMORY) 00178 Log::instance()->debug( "ReferenceCountedPointer<T>::ReferenceCountedPointer( const ReferenceCountedPointer<S> & rhs )\n" ); 00179 # endif 00180 takePointer( rhs._p ); 00181 } 00182 00183 template< class T > 00184 ReferenceCountedPointer<T>::ReferenceCountedPointer( PointerType rhs ) 00185 { 00186 # if defined(DEBUG_MEMORY) 00187 Log::instance()->debug( "ReferenceCountedPointer<T>::ReferenceCountedPointer( T* rhs )\n" ); 00188 # endif 00189 takePointer( rhs ); 00190 } 00191 00192 template< class T > 00193 template< class S > 00194 ReferenceCountedPointer<T>::ReferenceCountedPointer( S* rhs ) 00195 { 00196 # if defined(DEBUG_MEMORY) 00197 Log::instance()->debug( "ReferenceCountedPointer<T>::ReferenceCountedPointer( S* rhs )\n" ); 00198 # endif 00199 takePointer( rhs ); 00200 } 00201 00202 template< class T > 00203 ReferenceCountedPointer<T>::~ReferenceCountedPointer() 00204 { 00205 # if defined(DEBUG_MEMORY) 00206 Log::instance()->debug( "ReferenceCountedPointer<T>::~ReferenceCountedPointer()\n" ); 00207 # endif 00208 releasePointer(); 00209 } 00210 00211 template< class T > 00212 ReferenceCountedPointer<T>& 00213 ReferenceCountedPointer<T>::operator=( const ReferenceCountedPointer& rhs ) 00214 { 00215 # if defined(DEBUG_MEMORY) 00216 Log::instance()->debug( "ReferenceCountedPointer<T>::operator=( const ReferenceCountedPointer<T>& rhs )\n" ); 00217 # endif 00218 if ( this == &rhs ) 00219 return *this; 00220 00221 if ( this->_p == rhs._p ) 00222 return *this; 00223 00224 releasePointer(); 00225 takePointer( rhs._p ); 00226 return *this; 00227 } 00228 00229 template< class T > 00230 template< class S > 00231 ReferenceCountedPointer<T>& 00232 ReferenceCountedPointer<T>::operator=( const ReferenceCountedPointer<S>& rhs ) 00233 { 00234 # if defined(DEBUG_MEMORY) 00235 Log::instance()->debug( "ReferenceCountedPointer<T>::operator=( const ReferenceCountedPointer<S>& rhs )\n" ); 00236 # endif 00237 if ( this == &rhs ) 00238 return *this; 00239 00240 if ( this->_p == rhs._p ) 00241 return *this; 00242 00243 releasePointer(); 00244 takePointer( rhs._p ); 00245 return *this; 00246 } 00247 00248 template< class T > 00249 ReferenceCountedPointer<T>& 00250 ReferenceCountedPointer<T>::operator=( PointerType& rhs ) 00251 { 00252 # if defined(DEBUG_MEMORY) 00253 Log::instance()->debug( "ReferenceCountedPointer<T>::operator=( T*& rhs )\n" ); 00254 # endif 00255 if ( this->_p == rhs ) 00256 return *this; 00257 00258 releasePointer(); 00259 takePointer( rhs ); 00260 return *this; 00261 } 00262 00263 template< class T > 00264 template< class S > 00265 ReferenceCountedPointer<T>& 00266 ReferenceCountedPointer<T>::operator=( S*& rhs ) 00267 { 00268 # if defined(DEBUG_MEMORY) 00269 Log::instance()->debug( "ReferenceCountedPointer<T>::operator=( S*& rhs )\n" ); 00270 # endif 00271 if ( this->_p == rhs ) 00272 return *this; 00273 00274 releasePointer(); 00275 takePointer( rhs ); 00276 return *this; 00277 } 00278 00279 template< class T > 00280 typename TypeTraits<T>::ReferenceType 00281 ReferenceCountedPointer<T>::operator*() const 00282 { 00283 return *_p; 00284 } 00285 00286 template< class T > 00287 typename TypeTraits<T>::PointerType 00288 ReferenceCountedPointer<T>::operator->() const 00289 { 00290 return _p; 00291 } 00292 00293 template< class T > 00294 bool ReferenceCountedPointer<T>::operator!() const 00295 { 00296 return (_p == 0); 00297 } 00298 00299 template< class T > 00300 ReferenceCountedPointer<T>::operator bool() const 00301 { 00302 return (_p != 0); 00303 } 00304 00305 template< class T > 00306 void 00307 ReferenceCountedPointer<T>::releasePointer() 00308 { 00309 if ( _p ) { 00310 00311 --_p->_ref_count; 00312 00313 if ( _p->_ref_count <= 0 ) { 00314 delete _p; 00315 _p = 0; 00316 } 00317 } 00318 } 00319 00320 template< class T > 00321 void 00322 ReferenceCountedPointer<T>::takePointer( PlainPointerType ptr ) 00323 { 00324 # if defined(DEBUG_MEMORY) 00325 Log::instance()->debug( "Taking Pointer: %x\n", ptr ); 00326 # endif 00327 _p = ptr; 00328 if ( _p != 0 ) { 00329 00330 ++_p->_ref_count; 00331 00332 # if defined(DEBUG_MEMORY) 00333 Log::instance()->debug( "Recount is: %d\n",_p->_ref_count); 00334 # endif 00335 00336 } 00337 } 00338 00339 ReferenceCountedObject::~ReferenceCountedObject() 00340 {} 00341 00342 #endif