// // ******************************************************************** // * 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. * // ******************************************************************** // // // $Id$ // // // Class 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 (Radovan.Chytracek@cern.ch) // Version: 3.0 // Date: November 2001 // ---------------------------------------------------------------------- #ifndef _G4REFERENCECOUNTEDHANDLE_H_ #define _G4REFERENCECOUNTEDHANDLE_H_ 1 #include "G4Allocator.hh" template class G4CountedObject; template class G4ReferenceCountedHandle { public: // with description inline G4ReferenceCountedHandle( X* rep = 0 ); // 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( size_t ); // Operator new defined for G4Allocator. inline void operator delete( void *pObj ); // Operator delete defined for G4Allocator. public: #ifdef G4RF_DEBUG void* operator new( size_t, void *pObj ); // This is required on some compilers (Windows/VC++, Linux/g++) when this // class is used in the context of STL container. It generates a warning // saying something about not existing correspondent delete... #endif private: G4CountedObject* fObj; // The object subject to reference counting. }; #ifdef G4GLOB_ALLOC_EXPORT extern G4DLLEXPORT G4Allocator > aRCHAllocator; #else extern G4DLLIMPORT G4Allocator > aRCHAllocator; #endif template class G4CountedObject { friend class G4ReferenceCountedHandle; public: // with description G4CountedObject( X* pObj = 0 ); // 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( size_t ); // Operator new defined for G4Allocator. inline void operator delete( void *pObj ); // operator delete defined for G4Allocator. private: unsigned int fCount; // Reference counter. X* fRep; // The counted object. }; #ifdef G4GLOB_ALLOC_EXPORT extern G4DLLEXPORT G4Allocator > aCountedObjectAllocator; #else extern G4DLLIMPORT G4Allocator > aCountedObjectAllocator; #endif // --------- G4CountedObject Inline function definitions --------- template G4CountedObject::G4CountedObject( X* pObj ) : fCount(0), fRep( pObj ) { if( pObj != 0 ) { 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( size_t ) { return( (void *)aCountedObjectAllocator.MallocSingle() ); } template void G4CountedObject::operator delete( void *pObj ) { aCountedObjectAllocator.FreeSingle( (G4CountedObject*)pObj ); } // --------- G4ReferenceCountedHandle Inline function definitions --------- template G4ReferenceCountedHandle:: G4ReferenceCountedHandle( X* rep ) : fObj( 0 ) { if( rep != 0 ) { fObj = new G4CountedObject( rep ); } } template G4ReferenceCountedHandle:: G4ReferenceCountedHandle( const G4ReferenceCountedHandle& right ) : fObj( right.fObj ) { fObj->AddRef(); } template G4ReferenceCountedHandle::~G4ReferenceCountedHandle() { if( fObj ) fObj->Release(); } template G4ReferenceCountedHandle& G4ReferenceCountedHandle:: operator =( const G4ReferenceCountedHandle& right ) { if( fObj != right.fObj ) { if( fObj ) fObj->Release(); this->fObj = right.fObj; fObj->AddRef(); } return *this; } template G4ReferenceCountedHandle& G4ReferenceCountedHandle:: operator =( X* objPtr ) { if( fObj ) fObj->Release(); this->fObj = new G4CountedObject( objPtr ); return *this; } template unsigned int G4ReferenceCountedHandle::Count() const { return( fObj ? fObj->fCount : 0 ); } template X* G4ReferenceCountedHandle::operator ->() const { return( fObj ? fObj->fRep : 0 ); } template G4bool G4ReferenceCountedHandle::operator !() const { return( ( !fObj ) ? true : false ); } template G4ReferenceCountedHandle::operator bool() const { return( ( fObj ) ? true : false ); } template X* G4ReferenceCountedHandle::operator ()() const { return( fObj ? fObj->fRep : 0 ); } template void* G4ReferenceCountedHandle::operator new( size_t ) { return( (void *)aRCHAllocator.MallocSingle() ); } template void G4ReferenceCountedHandle::operator delete( void *pObj ) { aRCHAllocator.FreeSingle( (G4ReferenceCountedHandle*)pObj ); } #ifdef G4RF_DEBUG template void* G4ReferenceCountedHandle::operator new( size_t, void *pObj ) { return pObj; } #endif #endif // _G4REFERENCECOUNTEDHANDLE_H_