// // ******************************************************************** // * License and Disclaimer * // * * // * The Geant4 software is copyright of the Copyright Holders of * // * the Geant4 Collaboration. It is provided under the terms and * // * conditions of the Geant4 Software License, included in the file * // * LICENSE and available at http://cern.ch/geant4/license . These * // * include a list of copyright holders. * // * * // * Neither the authors of this software system, nor their employing * // * institutes,nor the agencies providing financial support for this * // * work make any representation or warranty, express or implied, * // * regarding this software system or assume any liability for its * // * use. Please see the license in the file LICENSE and URL above * // * for the full disclaimer and the limitation of liability. * // * * // * This code implementation is the result of the scientific and * // * technical work of the GEANT4 collaboration. * // * By using, copying, modifying or distributing the software (or * // * any work based on the software) you agree to acknowledge its * // * use in resulting scientific publications, and indicate your * // * acceptance of all terms of the Geant4 Software license. * // ******************************************************************** // // G4ReferenceCountedHandle // // Class description: // // A class to provide reference counting mechanism. // It is a templated class, acting as a smart pointer, // wrapping the type to be counted. It performs the reference counting // during the life-time of the counted object. When its count reaches zero // the counted object is destroyed by explicit call to its destructor. // This class provides overloaded operators *() and ->() to allow similar // syntax as for the normal "dumb" pointers. // The basic rule for the use of this class is that a handle must always // be exchanged by reference never dinamically allocated (i.e. never // instantiated using 'new'). // The validity of a smart pointer object can be verified by using the // operator !() or operator bool(). I.e.: // if( !smartPtrObj ) { ... } // Problem! We must initialize it first! // else { ... } // OK! // Trying to 'delete' a smart pointer object will generate a compilation // error (since we're dealing with objects, not pointers!). // Author: Radovan Chytracek, CERN - November 2001 // -------------------------------------------------------------------- #ifndef G4REFERENCECOUNTEDHANDLE_HH #define G4REFERENCECOUNTEDHANDLE_HH 1 #include "G4Allocator.hh" #include "G4Types.hh" template class G4CountedObject; template class G4ReferenceCountedHandle { public: inline G4ReferenceCountedHandle(X* rep = nullptr); // Constructor. inline G4ReferenceCountedHandle(const G4ReferenceCountedHandle& right); // Copy constructor. inline ~G4ReferenceCountedHandle(); // Destructor. inline G4ReferenceCountedHandle& operator=( const G4ReferenceCountedHandle& right); // Assignment operator by reference. inline G4ReferenceCountedHandle& operator=(X* objPtr); // Assignment operator by pointer. inline unsigned int Count() const; // Forward to Counter class. inline X* operator->() const; // Operator -> allowing the access to counted object. // The check for 0-ness is left out for performance reasons, // see operator () below. // May be called on initialised smart-pointer only! inline G4bool operator!() const; // Validity test operator. inline operator bool() const; // Boolean operator. inline X* operator()() const; // Functor operator (for convenience). // There is no provision that this class is subclassed. // If it is subclassed & new data members are added then the // following "new" & "delete" will fail and give errors. // inline void* operator new(std::size_t); // Operator new defined for G4Allocator. inline void operator delete(void* pObj); // Operator delete defined for G4Allocator. private: G4CountedObject* fObj = nullptr; // The object subject to reference counting. }; extern G4GLOB_DLL G4Allocator>*& aRCHAllocator(); template class G4CountedObject { friend class G4ReferenceCountedHandle; public: G4CountedObject(X* pObj = nullptr); // Constructor. ~G4CountedObject(); // Destructor. inline void AddRef(); // Increase the count. inline void Release(); // Decrease the count and if zero destroy itself. // There is no provision that this class is subclassed. // If it is subclassed & new data members are added then the // following "new" & "delete" will fail and give errors. // inline void* operator new(std::size_t); // Operator new defined for G4Allocator. inline void operator delete(void* pObj); // operator delete defined for G4Allocator. private: unsigned int fCount = 0; // Reference counter. X* fRep = nullptr; // The counted object. }; extern G4GLOB_DLL G4Allocator>*& aCountedObjectAllocator(); // --------- G4CountedObject Inline function definitions --------- template G4CountedObject::G4CountedObject(X* pObj) : fRep(pObj) { if(pObj != nullptr) fCount = 1; } template G4CountedObject::~G4CountedObject() { delete fRep; } template void G4CountedObject::AddRef() { ++fCount; } template void G4CountedObject::Release() { if(--fCount == 0) delete this; } template void* G4CountedObject::operator new(std::size_t) { if(aCountedObjectAllocator() == nullptr) aCountedObjectAllocator() = new G4Allocator>; return ((void*) aCountedObjectAllocator()->MallocSingle()); } template void G4CountedObject::operator delete(void* pObj) { aCountedObjectAllocator()->FreeSingle((G4CountedObject*) pObj); } // --------- G4ReferenceCountedHandle Inline function definitions --------- template G4ReferenceCountedHandle::G4ReferenceCountedHandle(X* rep) { if(rep != nullptr) fObj = new G4CountedObject(rep); } template G4ReferenceCountedHandle::G4ReferenceCountedHandle( const G4ReferenceCountedHandle& right) : fObj(right.fObj) { fObj->AddRef(); } template G4ReferenceCountedHandle::~G4ReferenceCountedHandle() { if(fObj != nullptr) fObj->Release(); } template G4ReferenceCountedHandle& G4ReferenceCountedHandle::operator=( const G4ReferenceCountedHandle& right) { if(fObj != right.fObj) { if(fObj != nullptr) fObj->Release(); this->fObj = right.fObj; fObj->AddRef(); } return *this; } template G4ReferenceCountedHandle& G4ReferenceCountedHandle::operator=(X* objPtr) { if(fObj != nullptr) fObj->Release(); this->fObj = new G4CountedObject(objPtr); return *this; } template unsigned int G4ReferenceCountedHandle::Count() const { return ((fObj != nullptr) ? fObj->fCount : 0); } template X* G4ReferenceCountedHandle::operator->() const { return ((fObj != nullptr) ? fObj->fRep : 0); } template G4bool G4ReferenceCountedHandle::operator!() const { return fObj == nullptr; } template G4ReferenceCountedHandle::operator bool() const { return fObj != nullptr; } template X* G4ReferenceCountedHandle::operator()() const { return ((fObj != nullptr) ? fObj->fRep : nullptr); } template void* G4ReferenceCountedHandle::operator new(std::size_t) { if(aRCHAllocator() == nullptr) aRCHAllocator() = new G4Allocator>; return ((void*) aRCHAllocator()->MallocSingle()); } template void G4ReferenceCountedHandle::operator delete(void* pObj) { aRCHAllocator()->FreeSingle((G4ReferenceCountedHandle*) pObj); } #endif