Geant4 Cross Reference |
1 // 2 // ******************************************************************** 3 // * License and Disclaimer * 4 // * * 5 // * The Geant4 software is copyright of the Copyright Holders of * 6 // * the Geant4 Collaboration. It is provided under the terms and * 7 // * conditions of the Geant4 Software License, included in the file * 8 // * LICENSE and available at http://cern.ch/geant4/license . These * 9 // * include a list of copyright holders. * 10 // * * 11 // * Neither the authors of this software system, nor their employing * 12 // * institutes,nor the agencies providing financial support for this * 13 // * work make any representation or warranty, express or implied, * 14 // * regarding this software system or assume any liability for its * 15 // * use. Please see the license in the file LICENSE and URL above * 16 // * for the full disclaimer and the limitation of liability. * 17 // * * 18 // * This code implementation is the result of the scientific and * 19 // * technical work of the GEANT4 collaboration. * 20 // * By using, copying, modifying or distributing the software (or * 21 // * any work based on the software) you agree to acknowledge its * 22 // * use in resulting scientific publications, and indicate your * 23 // * acceptance of all terms of the Geant4 Software license. * 24 // ******************************************************************** 25 // 26 // G4ReferenceCountedHandle 27 // 28 // Class description: 29 // 30 // A class to provide reference counting mechanism. 31 // It is a templated class, acting as a smart pointer, 32 // wrapping the type to be counted. It performs the reference counting 33 // during the life-time of the counted object. When its count reaches zero 34 // the counted object is destroyed by explicit call to its destructor. 35 // This class provides overloaded operators *() and ->() to allow similar 36 // syntax as for the normal "dumb" pointers. 37 // The basic rule for the use of this class is that a handle must always 38 // be exchanged by reference never dinamically allocated (i.e. never 39 // instantiated using 'new'). 40 // The validity of a smart pointer object can be verified by using the 41 // operator !() or operator bool(). I.e.: 42 // if( !smartPtrObj ) { ... } // Problem! We must initialize it first! 43 // else { ... } // OK! 44 // Trying to 'delete' a smart pointer object will generate a compilation 45 // error (since we're dealing with objects, not pointers!). 46 47 // Author: Radovan Chytracek, CERN - November 2001 48 // -------------------------------------------------------------------- 49 #ifndef G4REFERENCECOUNTEDHANDLE_HH 50 #define G4REFERENCECOUNTEDHANDLE_HH 1 51 52 #include "G4Allocator.hh" 53 #include "G4Types.hh" 54 55 template <class X> 56 class G4CountedObject; 57 58 template <class X> 59 class G4ReferenceCountedHandle 60 { 61 public: 62 inline G4ReferenceCountedHandle(X* rep = nullptr); 63 // Constructor. 64 65 inline G4ReferenceCountedHandle(const G4ReferenceCountedHandle<X>& right); 66 // Copy constructor. 67 68 inline ~G4ReferenceCountedHandle(); 69 // Destructor. 70 71 inline G4ReferenceCountedHandle<X>& operator=( 72 const G4ReferenceCountedHandle<X>& right); 73 // Assignment operator by reference. 74 75 inline G4ReferenceCountedHandle<X>& operator=(X* objPtr); 76 // Assignment operator by pointer. 77 78 inline unsigned int Count() const; 79 // Forward to Counter class. 80 81 inline X* operator->() const; 82 // Operator -> allowing the access to counted object. 83 // The check for 0-ness is left out for performance reasons, 84 // see operator () below. 85 // May be called on initialised smart-pointer only! 86 87 inline G4bool operator!() const; 88 // Validity test operator. 89 90 inline operator bool() const; 91 // Boolean operator. 92 93 inline X* operator()() const; 94 // Functor operator (for convenience). 95 96 // There is no provision that this class is subclassed. 97 // If it is subclassed & new data members are added then the 98 // following "new" & "delete" will fail and give errors. 99 // 100 inline void* operator new(std::size_t); 101 // Operator new defined for G4Allocator. 102 103 inline void operator delete(void* pObj); 104 // Operator delete defined for G4Allocator. 105 106 private: 107 G4CountedObject<X>* fObj = nullptr; 108 // The object subject to reference counting. 109 }; 110 111 extern G4GLOB_DLL G4Allocator<G4ReferenceCountedHandle<void>>*& aRCHAllocator(); 112 113 template <class X> 114 class G4CountedObject 115 { 116 friend class G4ReferenceCountedHandle<X>; 117 118 public: 119 G4CountedObject(X* pObj = nullptr); 120 // Constructor. 121 122 ~G4CountedObject(); 123 // Destructor. 124 125 inline void AddRef(); 126 // Increase the count. 127 128 inline void Release(); 129 // Decrease the count and if zero destroy itself. 130 131 // There is no provision that this class is subclassed. 132 // If it is subclassed & new data members are added then the 133 // following "new" & "delete" will fail and give errors. 134 // 135 inline void* operator new(std::size_t); 136 // Operator new defined for G4Allocator. 137 138 inline void operator delete(void* pObj); 139 // operator delete defined for G4Allocator. 140 141 private: 142 unsigned int fCount = 0; 143 // Reference counter. 144 X* fRep = nullptr; 145 // The counted object. 146 }; 147 148 extern G4GLOB_DLL G4Allocator<G4CountedObject<void>>*& 149 aCountedObjectAllocator(); 150 151 // --------- G4CountedObject<X> Inline function definitions --------- 152 153 template <class X> 154 G4CountedObject<X>::G4CountedObject(X* pObj) 155 : fRep(pObj) 156 { 157 if(pObj != nullptr) 158 fCount = 1; 159 } 160 161 template <class X> 162 G4CountedObject<X>::~G4CountedObject() 163 { 164 delete fRep; 165 } 166 167 template <class X> 168 void G4CountedObject<X>::AddRef() 169 { 170 ++fCount; 171 } 172 173 template <class X> 174 void G4CountedObject<X>::Release() 175 { 176 if(--fCount == 0) 177 delete this; 178 } 179 180 template <class X> 181 void* G4CountedObject<X>::operator new(std::size_t) 182 { 183 if(aCountedObjectAllocator() == nullptr) 184 aCountedObjectAllocator() = new G4Allocator<G4CountedObject<void>>; 185 return ((void*) aCountedObjectAllocator()->MallocSingle()); 186 } 187 188 template <class X> 189 void G4CountedObject<X>::operator delete(void* pObj) 190 { 191 aCountedObjectAllocator()->FreeSingle((G4CountedObject<void>*) pObj); 192 } 193 194 // --------- G4ReferenceCountedHandle<X> Inline function definitions --------- 195 196 template <class X> 197 G4ReferenceCountedHandle<X>::G4ReferenceCountedHandle(X* rep) 198 { 199 if(rep != nullptr) 200 fObj = new G4CountedObject<X>(rep); 201 } 202 203 template <class X> 204 G4ReferenceCountedHandle<X>::G4ReferenceCountedHandle( 205 const G4ReferenceCountedHandle<X>& right) 206 : fObj(right.fObj) 207 { 208 fObj->AddRef(); 209 } 210 211 template <class X> 212 G4ReferenceCountedHandle<X>::~G4ReferenceCountedHandle() 213 { 214 if(fObj != nullptr) 215 fObj->Release(); 216 } 217 218 template <class X> 219 G4ReferenceCountedHandle<X>& G4ReferenceCountedHandle<X>::operator=( 220 const G4ReferenceCountedHandle<X>& right) 221 { 222 if(fObj != right.fObj) 223 { 224 if(fObj != nullptr) 225 fObj->Release(); 226 this->fObj = right.fObj; 227 fObj->AddRef(); 228 } 229 return *this; 230 } 231 232 template <class X> 233 G4ReferenceCountedHandle<X>& G4ReferenceCountedHandle<X>::operator=(X* objPtr) 234 { 235 if(fObj != nullptr) 236 fObj->Release(); 237 this->fObj = new G4CountedObject<X>(objPtr); 238 return *this; 239 } 240 241 template <class X> 242 unsigned int G4ReferenceCountedHandle<X>::Count() const 243 { 244 return ((fObj != nullptr) ? fObj->fCount : 0); 245 } 246 247 template <class X> 248 X* G4ReferenceCountedHandle<X>::operator->() const 249 { 250 return ((fObj != nullptr) ? fObj->fRep : 0); 251 } 252 253 template <class X> 254 G4bool G4ReferenceCountedHandle<X>::operator!() const 255 { 256 return fObj == nullptr; 257 } 258 259 template <class X> 260 G4ReferenceCountedHandle<X>::operator bool() const 261 { 262 return fObj != nullptr; 263 } 264 265 template <class X> 266 X* G4ReferenceCountedHandle<X>::operator()() const 267 { 268 return ((fObj != nullptr) ? fObj->fRep : nullptr); 269 } 270 271 template <class X> 272 void* G4ReferenceCountedHandle<X>::operator new(std::size_t) 273 { 274 if(aRCHAllocator() == nullptr) 275 aRCHAllocator() = new G4Allocator<G4ReferenceCountedHandle<void>>; 276 return ((void*) aRCHAllocator()->MallocSingle()); 277 } 278 279 template <class X> 280 void G4ReferenceCountedHandle<X>::operator delete(void* pObj) 281 { 282 aRCHAllocator()->FreeSingle((G4ReferenceCountedHandle<void>*) pObj); 283 } 284 285 #endif 286