SharedPtr.hh

00001 #ifndef __FASTJET_SHARED_PTR_HH__
00002 #define __FASTJET_SHARED_PTR_HH__
00003 
00004 //STARTHEADER
00005 // $Id: SharedPtr.hh 1761 2010-09-16 10:43:18Z soyez $
00006 //
00007 // Copyright (c) 2005-2010, Matteo Cacciari, Gavin Salam and Gregory Soyez
00008 //
00009 //----------------------------------------------------------------------
00010 // This file is part of FastJet.
00011 //
00012 //  FastJet is free software; you can redistribute it and/or modify
00013 //  it under the terms of the GNU General Public License as published by
00014 //  the Free Software Foundation; either version 2 of the License, or
00015 //  (at your option) any later version.
00016 //
00017 //  The algorithms that underlie FastJet have required considerable
00018 //  development and are described in hep-ph/0512210. If you use
00019 //  FastJet as part of work towards a scientific publication, please
00020 //  include a citation to the FastJet paper.
00021 //
00022 //  FastJet is distributed in the hope that it will be useful,
00023 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00024 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00025 //  GNU General Public License for more details.
00026 //
00027 //  You should have received a copy of the GNU General Public License
00028 //  along with FastJet; if not, write to the Free Software
00029 //  Foundation, Inc.:
00030 //      59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00031 //----------------------------------------------------------------------
00032 //ENDHEADER
00033 
00034 #include "fastjet/internal/base.hh"
00035 #include <cstdlib>  // for NULL!!!
00036 
00037 // for testing purposes, the following define makes it possible
00038 // for our SharedPtr simply to be derived from the STL TR1 one.
00039 // #define USETR1SHAREDPTR
00040 
00041 #ifdef USETR1SHAREDPTR
00042 #include <tr1/memory>
00043 #endif // USETR1SHAREDPTR
00044 
00045 FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
00046 
00047 #ifdef USETR1SHAREDPTR
00048 
00060 template<class T>
00061 class SharedPtr : public std::tr1::shared_ptr<T> {
00062 public:
00063   SharedPtr() : std::tr1::shared_ptr<T>() {}
00064   SharedPtr(T * t) : std::tr1::shared_ptr<T>(t) {}
00065   SharedPtr(const SharedPtr<T> & t) : std::tr1::shared_ptr<T>(t) {}
00066   // for some reason operator() doesn't get inherited
00067   inline operator bool() const {return (this->get()!=NULL);}
00069   T* operator ()() const{
00070     return this->get(); // automatically returns NULL when out-of-scope
00071   }
00072 };
00073 
00074 
00075 #else // USETR1SHAREDPTR
00076 
00106 template<class T>
00107 class SharedPtr{
00108 public:
00110   class __SharedCountingPtr;
00111 
00113   SharedPtr() : _ptr(NULL){}
00114   
00117   template<class Y> explicit SharedPtr(Y* ptr){
00118     _ptr = new __SharedCountingPtr(ptr);
00119   }
00120   
00123   SharedPtr(SharedPtr const & share) : _ptr(NULL){
00124     reset(share);
00125   }
00126     
00129   template<class Y> SharedPtr(SharedPtr<Y> const & share) : _ptr(NULL){
00130     reset(share);
00131   }
00132 
00134   ~SharedPtr(){
00135     // make sure the object has been allocated
00136     if (_ptr==NULL) return;
00137 
00138     _decrease_count();
00139   }
00140 
00142   void reset(){
00143     // // if we already are pointing to sth, be sure to decrease its count
00144     // if (_ptr!=NULL) _decrease_count();
00145     // _ptr = NULL;
00146     SharedPtr().swap(*this);
00147   }
00148   
00150   template<class Y> void reset(Y * ptr){
00151     // // if we already are pointing to sth, be sure to decrease its count
00152     // if (_ptr!=NULL) _decrease_count();
00153     // 
00154     // _ptr = new __SharedCountingPtr(ptr);
00155     SharedPtr(ptr).swap(*this);
00156   }
00157 
00158   // not part of the standard
00162   template<class Y> void reset(SharedPtr<Y> const & share){
00163     // if we already are pointing to sth, be sure to decrease its count
00164     if (_ptr!=NULL){
00165       // in the specific case where we're having the same
00166       // share,reset() has actually no effect. However if *this is the
00167       // only instance still alive (implying share==*this) bringing
00168       // the count down to 0 and deleting the object will not have the
00169       // expected effect. So we just avoid that situation explicitly
00170       if (_ptr == share._get_container()) return;
00171     
00172       _decrease_count();
00173     }
00174     
00175     // Watch out: if share is empty, construct an empty shared_ptr
00176     
00177     // copy the container
00178     _ptr = share._get_container();  // Note: automatically set it to NULL if share is empty
00179     
00180     if (_ptr!=NULL)
00181       (*_ptr)++;
00182   }
00183   
00186   SharedPtr& operator=(SharedPtr const & share){
00187     reset(share);
00188     return *this;
00189   }
00190   
00193   template<class Y> SharedPtr& operator=(SharedPtr<Y> const & share){
00194     reset(share);
00195     return *this;
00196   }
00197   
00199   T* operator ()() const{
00200     if (_ptr==NULL) return NULL;
00201     return _ptr->get(); // automatically returns NULL when out-of-scope
00202   }
00203   
00209   inline T& operator*() const{
00210     return *(_ptr->get());
00211   }
00212 
00218   inline T* operator->() const{
00219     if (_ptr==NULL) return NULL;
00220     return _ptr->get();
00221   }  
00222 
00224   inline T* get() const{
00225     if (_ptr==NULL) return NULL;
00226     return _ptr->get();
00227   }
00228 
00230   inline bool unique() const{
00231     return (use_count()==1);
00232   }
00233 
00235   inline long use_count() const{
00236     if (_ptr==NULL) return 0;
00237     return _ptr->use_count(); // automatically returns NULL when out-of-scope
00238   }
00239 
00242   inline operator bool() const{
00243     return (get()!=NULL);
00244   }
00245 
00247   inline void swap(SharedPtr & share){
00248     __SharedCountingPtr* share_container = share._ptr;
00249     share._ptr = _ptr;
00250     _ptr = share_container;
00251   }
00252 
00263   class __SharedCountingPtr{
00264   public:
00266     __SharedCountingPtr() : _ptr(NULL), _count(0){}
00267     
00269     template<class Y> explicit __SharedCountingPtr(Y* ptr) : _ptr(ptr), _count(1){}
00270     
00272     ~__SharedCountingPtr(){ 
00273       // force the deletion of the object we keep track of
00274       if (_ptr!=NULL){ delete _ptr;}
00275     }
00276 
00278     inline T* get() const {return _ptr;}
00279 
00281     inline long use_count() const {return _count;}
00282 
00284     inline long operator++(int unused){return _count++;}
00285 
00287     inline long operator--(int unused){return _count--;}
00288 
00290     inline long operator++(){return ++_count;}
00291 
00293     inline long operator--(){return --_count;}
00294 
00295   private:
00296     T *_ptr;              
00297     long _count;  
00298   };
00299 
00300 private:
00302   inline __SharedCountingPtr* _get_container() const{
00303     return _ptr;
00304   }
00305 
00308   void _decrease_count(){
00309     // decrease the count
00310     (*_ptr)--;
00311     
00312     // if no one else is using it, free the allocated memory
00313     if (_ptr->use_count()==0)
00314       delete _ptr; // that automatically deletes the object itself
00315   }
00316 
00317   // the real info
00318   __SharedCountingPtr *_ptr;
00319 };
00320 
00321 
00323 template<class T,class U>
00324 inline bool operator==(SharedPtr<T> const & t, SharedPtr<U> const & u){
00325   return t.get() == u.get();
00326 }
00327 
00329 template<class T,class U>
00330 inline bool operator!=(SharedPtr<T> const & t, SharedPtr<U> const & u){
00331   return t.get() != u.get();
00332 }
00333 
00335 template<class T,class U>
00336 inline bool operator<(SharedPtr<T> const & t, SharedPtr<U> const & u){
00337   return t.get() < u.get();
00338 }
00339 
00341 template<class T>
00342 inline void swap(SharedPtr<T> & a, SharedPtr<T> & b){
00343   return a.swap(b);
00344 }
00345 
00347 template<class T>
00348 inline T* get_pointer(SharedPtr<T> const & t){
00349   return t.get();
00350 }
00351 
00352 #endif // USETR1SHAREDPTR
00353 
00354 FASTJET_END_NAMESPACE      // defined in fastjet/internal/base.hh
00355 
00356 #endif   // __FASTJET_SHARED_PTR_HH__