// // ******************************************************************** // * DISCLAIMER * // * * // * The following disclaimer summarizes all the specific disclaimers * // * of contributors to this software. The specific disclaimers,which * // * govern, are listed with their locations in: * // * http://cern.ch/geant4/license * // * * // * 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. * // * * // * This code implementation is the intellectual property of the * // * GEANT4 collaboration. * // * By copying, distributing or modifying the Program (or any work * // * based on the Program) you indicate your acceptance of this * // * statement, and all its terms. * // ******************************************************************** // // // $Id: RCObjectHandle.hh,v 1.2 2002/06/03 12:09:33 radoone Exp $ // GEANT4 tag $Name: geant4-05-01 $ // // // -------------------------------------------------------------- // Comments // // -------------------------------------------------------------- // // Class RCObjectHandle // Class description: // A class to provide reference counting mechanism for a class which // is designed without this support. It is a templated class, a smart pointer, // wrapping the class to be counted and performs the reference counting // during the life-time of the counted object. When its count goes to zero // the counted object is destroyed by explicit call to its destructor. // This class provides overloaded operators *() and ->() to make the // maniplutation syntax the same as for the normal "dumb" pointers. // The basic rule for the use of this class is that it is passed always by // reference and is not constructed by calling new. // Before the use of this smart pointer object one can test its validity // using the operator !() or operator bool(). // if( !smartPtrObj ) { ... } // Problem! We must initialize it first! // else { ... } // OK! // The code which tries to delete this object won't compile, because it is // not a pointer it is an object. // Author: Radovan Chytracek // Version: 1.0 // Date: June 2001 // ---------------------------------------------------------------------- #ifndef RC_OBJECT_HANDLE_H #define RC_OBJECT_HANDLE_H 1 template class RCObjectHandle { public: typedef RCObjectHandle RCH; private: // with description class CountedObject { public: inline CountedObject( X* pObj = 0 ) : fCount(1), fRep( pObj ) { } // Constructor inline ~CountedObject() { delete fRep; fRep = 0; } // Destructor inline X* GetObject() const { return fRep; } inline void SetObject( const X* object ) { fRep = object; } inline unsigned int AddRef() { return( ++fCount ); } // Forward to Counter class inline unsigned int Release() { return( ( fCount > 0 ) ? --fCount : 0 ); } // Forward to Counter class inline unsigned int Count() const { return( fCount ); } // Forward to Counter class private: unsigned int fCount; // Reference counter X* fRep; // The counted object }; public: // with description RCObjectHandle( X* rep = 0 ) : fObj( 0 ) { if( rep != 0 ) { fObj = new RCH::CountedObject( rep ); } } // Constructor ~RCObjectHandle() { if( 0 == Release() ) { if( fObj != 0 ) { delete fObj; fObj = 0; } } } // Destructor RCObjectHandle( const RCObjectHandle& right ) : fObj( 0 ) { fObj = right.GetCountedObject(); AddRef(); } // Copy constructor template RCObjectHandle( const RCObjectHandle& right ) : fObj( 0 ) { fObj = right.GetCountedObject(); AddRef(); } // Copy constructor RCObjectHandle& operator =( const RCObjectHandle& right ) { if( this->fObj != right.GetCountedObject() ) { if( 0 == this->Release() ) { if( this->fObj != 0 ) { delete this->fObj; } } this->fObj = right.GetCountedObject(); this->AddRef(); } return *this; } // Assignment operator by reference template RCObjectHandle& operator=( const RCObjectHandle& right ) { if( this->fObj != right.GetCountedObject() ) { if( 0 == this->Release() ) { if( this->fObj != 0 ) { delete this->fObj; } } this->fObj = right.GetCountedObject(); this->AddRef(); } return *this; } // Assignment operator by reference RCObjectHandle& operator =( const RCObjectHandle* right ) { if( this->fObj != right->GetCountedObject() ) { if( 0 == this->Release() ) { if( this->fObj != 0 ) { delete this->fObj; } } this->fObj = right->GetCountedObject(); this->AddRef(); } return *this; } // Assignment operator by pointer, should not be ever called RCObjectHandle& operator =( X* pRefObj ) { if( this->fObj == 0 || pRefObj != this->fObj->GetObject() ) { if( 0 == Release() ) { if( fObj != 0 ) { delete fObj; } } fObj = new RCH::CountedObject( pRefObj ); } return *this; } // Assignment operator by pointer to the counted class object RCH::CountedObject* GetCountedObject() const { return fObj; } inline unsigned int AddRef() { return( ( fObj != 0 ) ? fObj->AddRef() : 0 ); } // Forward to Counter class inline unsigned int Release() { return( (fObj != 0 ) ? fObj->Release() : 0 ); } // Forward to Counter class inline unsigned int Count() const { return( ( fObj != 0 ) ? fObj->Count() : 0 ); } // Forward to Counter class X* operator ->() const { return( ( fObj != 0 ) ? fObj->GetObject() : 0 ); } // Operator -> allowing the access to counted object // The check for 0-ness is left out for performance reasons, see operator () bellow // May be called on initialized smart-pointer only! bool operator !() const { return( ( fObj == 0 || fObj->GetObject() == 0 ) ? true : false ); } // Validity test operator operator bool() const { return( ( fObj != 0 && fObj->GetObject() != 0 ) ? true : false ); } X& operator *() const { return( ( fObj != 0 ) ? *(fObj->GetObject()) : 0 ); } // Dereference operator to make the feeling of dereferencing a pointer to // the counted object // May be called on initialized smart-pointer only! X* operator ()() const { return( ( fObj != 0 ) ? fObj->GetObject() : 0 ); } // Functor operator (for covinience) private: RCH::CountedObject* fObj; // Object being the subject to reference counting }; #endif // RC_OBJECT_HANDLE_H