00001 // 00002 // ******************************************************************** 00003 // * License and Disclaimer * 00004 // * * 00005 // * The Geant4 software is copyright of the Copyright Holders of * 00006 // * the Geant4 Collaboration. It is provided under the terms and * 00007 // * conditions of the Geant4 Software License, included in the file * 00008 // * LICENSE and available at http://cern.ch/geant4/license . These * 00009 // * include a list of copyright holders. * 00010 // * * 00011 // * Neither the authors of this software system, nor their employing * 00012 // * institutes,nor the agencies providing financial support for this * 00013 // * work make any representation or warranty, express or implied, * 00014 // * regarding this software system or assume any liability for its * 00015 // * use. Please see the license in the file LICENSE and URL above * 00016 // * for the full disclaimer and the limitation of liability. * 00017 // * * 00018 // * This code implementation is the result of the scientific and * 00019 // * technical work of the GEANT4 collaboration. * 00020 // * By using, copying, modifying or distributing the software (or * 00021 // * any work based on the software) you agree to acknowledge its * 00022 // * use in resulting scientific publications, and indicate your * 00023 // * acceptance of all terms of the Geant4 Software license. * 00024 // ******************************************************************** 00025 // 00026 // 00027 // $Id$ 00028 // 00029 // 00030 // Class G4ReferenceCountedHandle 00031 // 00032 // Class description: 00033 // 00034 // A class to provide reference counting mechanism. 00035 // It is a templated class, acting as a smart pointer, 00036 // wrapping the type to be counted. It performs the reference counting 00037 // during the life-time of the counted object. When its count reaches zero 00038 // the counted object is destroyed by explicit call to its destructor. 00039 // This class provides overloaded operators *() and ->() to allow similar 00040 // syntax as for the normal "dumb" pointers. 00041 // The basic rule for the use of this class is that a handle must always 00042 // be exchanged by reference never dinamically allocated (i.e. never 00043 // instantiated using 'new'). 00044 // The validity of a smart pointer object can be verified by using the 00045 // operator !() or operator bool(). I.e.: 00046 // if( !smartPtrObj ) { ... } // Problem! We must initialize it first! 00047 // else { ... } // OK! 00048 // Trying to 'delete' a smart pointer object will generate a compilation 00049 // error (since we're dealing with objects, not pointers!). 00050 00051 // Author: Radovan Chytracek, CERN (Radovan.Chytracek@cern.ch) 00052 // Version: 3.0 00053 // Date: November 2001 00054 // ---------------------------------------------------------------------- 00055 #ifndef _G4REFERENCECOUNTEDHANDLE_H_ 00056 #define _G4REFERENCECOUNTEDHANDLE_H_ 1 00057 00058 #include "G4Allocator.hh" 00059 00060 template <class X> class G4CountedObject; 00061 00062 template <class X> 00063 class G4ReferenceCountedHandle 00064 { 00065 00066 public: // with description 00067 00068 inline G4ReferenceCountedHandle( X* rep = 0 ); 00069 // Constructor. 00070 00071 inline G4ReferenceCountedHandle( const G4ReferenceCountedHandle<X>& right ); 00072 // Copy constructor. 00073 00074 inline ~G4ReferenceCountedHandle(); 00075 // Destructor. 00076 00077 inline G4ReferenceCountedHandle<X>& 00078 operator =( const G4ReferenceCountedHandle<X>& right ); 00079 // Assignment operator by reference. 00080 00081 inline G4ReferenceCountedHandle<X>& operator =( X* objPtr ); 00082 // Assignment operator by pointer. 00083 00084 inline unsigned int Count() const; 00085 // Forward to Counter class. 00086 00087 inline X* operator ->() const; 00088 // Operator -> allowing the access to counted object. 00089 // The check for 0-ness is left out for performance reasons, 00090 // see operator () below. 00091 // May be called on initialised smart-pointer only! 00092 00093 inline G4bool operator !() const; 00094 // Validity test operator. 00095 00096 inline operator bool() const; 00097 // Boolean operator. 00098 00099 inline X* operator ()() const; 00100 // Functor operator (for convenience). 00101 00102 // There is no provision that this class is subclassed. 00103 // If it is subclassed & new data members are added then the 00104 // following "new" & "delete" will fail and give errors. 00105 // 00106 inline void* operator new( size_t ); 00107 // Operator new defined for G4Allocator. 00108 00109 inline void operator delete( void *pObj ); 00110 // Operator delete defined for G4Allocator. 00111 00112 public: 00113 00114 #ifdef G4RF_DEBUG 00115 void* operator new( size_t, void *pObj ); 00116 // This is required on some compilers (Windows/VC++, Linux/g++) when this 00117 // class is used in the context of STL container. It generates a warning 00118 // saying something about not existing correspondent delete... 00119 #endif 00120 00121 private: 00122 00123 G4CountedObject<X>* fObj; 00124 // The object subject to reference counting. 00125 }; 00126 00127 #ifdef G4GLOB_ALLOC_EXPORT 00128 extern G4DLLEXPORT G4Allocator<G4ReferenceCountedHandle<void> > aRCHAllocator; 00129 #else 00130 extern G4DLLIMPORT G4Allocator<G4ReferenceCountedHandle<void> > aRCHAllocator; 00131 #endif 00132 00133 template <class X> 00134 class G4CountedObject 00135 { 00136 00137 friend class G4ReferenceCountedHandle<X>; 00138 00139 public: // with description 00140 00141 G4CountedObject( X* pObj = 0 ); 00142 // Constructor. 00143 00144 ~G4CountedObject(); 00145 // Destructor. 00146 00147 inline void AddRef(); 00148 // Increase the count. 00149 00150 inline void Release(); 00151 // Decrease the count and if zero destroy itself. 00152 00153 // There is no provision that this class is subclassed. 00154 // If it is subclassed & new data members are added then the 00155 // following "new" & "delete" will fail and give errors. 00156 // 00157 inline void* operator new( size_t ); 00158 // Operator new defined for G4Allocator. 00159 00160 inline void operator delete( void *pObj ); 00161 // operator delete defined for G4Allocator. 00162 00163 private: 00164 00165 unsigned int fCount; 00166 // Reference counter. 00167 X* fRep; 00168 // The counted object. 00169 }; 00170 00171 #ifdef G4GLOB_ALLOC_EXPORT 00172 extern G4DLLEXPORT G4Allocator<G4CountedObject<void> > aCountedObjectAllocator; 00173 #else 00174 extern G4DLLIMPORT G4Allocator<G4CountedObject<void> > aCountedObjectAllocator; 00175 #endif 00176 00177 // --------- G4CountedObject<X> Inline function definitions --------- 00178 00179 template <class X> 00180 G4CountedObject<X>::G4CountedObject( X* pObj ) 00181 : fCount(0), fRep( pObj ) 00182 { 00183 if( pObj != 0 ) { 00184 fCount = 1; 00185 } 00186 } 00187 00188 template <class X> 00189 G4CountedObject<X>::~G4CountedObject() 00190 { 00191 delete fRep; 00192 } 00193 00194 template <class X> 00195 void G4CountedObject<X>::AddRef() 00196 { 00197 ++fCount; 00198 } 00199 00200 template <class X> 00201 void G4CountedObject<X>::Release() 00202 { 00203 if( --fCount == 0 ) delete this; 00204 } 00205 00206 template <class X> 00207 void* G4CountedObject<X>::operator new( size_t ) 00208 { 00209 return( (void *)aCountedObjectAllocator.MallocSingle() ); 00210 } 00211 00212 template <class X> 00213 void G4CountedObject<X>::operator delete( void *pObj ) 00214 { 00215 aCountedObjectAllocator.FreeSingle( (G4CountedObject<void>*)pObj ); 00216 } 00217 00218 // --------- G4ReferenceCountedHandle<X> Inline function definitions --------- 00219 00220 template <class X> 00221 G4ReferenceCountedHandle<X>:: 00222 G4ReferenceCountedHandle( X* rep ) 00223 : fObj( 0 ) 00224 { 00225 if( rep != 0 ) { 00226 fObj = new G4CountedObject<X>( rep ); 00227 } 00228 } 00229 00230 template <class X> 00231 G4ReferenceCountedHandle<X>:: 00232 G4ReferenceCountedHandle( const G4ReferenceCountedHandle<X>& right ) 00233 : fObj( right.fObj ) 00234 { 00235 fObj->AddRef(); 00236 } 00237 00238 template <class X> 00239 G4ReferenceCountedHandle<X>::~G4ReferenceCountedHandle() 00240 { 00241 if( fObj ) fObj->Release(); 00242 } 00243 00244 template <class X> 00245 G4ReferenceCountedHandle<X>& G4ReferenceCountedHandle<X>:: 00246 operator =( const G4ReferenceCountedHandle<X>& right ) 00247 { 00248 if( fObj != right.fObj ) { 00249 if( fObj ) 00250 fObj->Release(); 00251 this->fObj = right.fObj; 00252 fObj->AddRef(); 00253 } 00254 return *this; 00255 } 00256 00257 template <class X> 00258 G4ReferenceCountedHandle<X>& G4ReferenceCountedHandle<X>:: 00259 operator =( X* objPtr ) 00260 { 00261 if( fObj ) 00262 fObj->Release(); 00263 this->fObj = new G4CountedObject<X>( objPtr ); 00264 return *this; 00265 } 00266 00267 template <class X> 00268 unsigned int G4ReferenceCountedHandle<X>::Count() const 00269 { 00270 return( fObj ? fObj->fCount : 0 ); 00271 } 00272 00273 template <class X> 00274 X* G4ReferenceCountedHandle<X>::operator ->() const 00275 { 00276 return( fObj ? fObj->fRep : 0 ); 00277 } 00278 00279 template <class X> 00280 G4bool G4ReferenceCountedHandle<X>::operator !() const 00281 { 00282 return( ( !fObj ) ? true : false ); 00283 } 00284 00285 template <class X> 00286 G4ReferenceCountedHandle<X>::operator bool() const 00287 { 00288 return( ( fObj ) ? true : false ); 00289 } 00290 00291 template <class X> 00292 X* G4ReferenceCountedHandle<X>::operator ()() const 00293 { 00294 return( fObj ? fObj->fRep : 0 ); 00295 } 00296 00297 template <class X> 00298 void* G4ReferenceCountedHandle<X>::operator new( size_t ) 00299 { 00300 return( (void *)aRCHAllocator.MallocSingle() ); 00301 } 00302 00303 template <class X> 00304 void G4ReferenceCountedHandle<X>::operator delete( void *pObj ) 00305 { 00306 aRCHAllocator.FreeSingle( (G4ReferenceCountedHandle<void>*)pObj ); 00307 } 00308 00309 #ifdef G4RF_DEBUG 00310 template <class X> 00311 void* G4ReferenceCountedHandle<X>::operator new( size_t, void *pObj ) 00312 { 00313 return pObj; 00314 } 00315 #endif 00316 00317 #endif // _G4REFERENCECOUNTEDHANDLE_H_ 00318