CppUnit project page CppUnit home page

intrusiveptr.h

Go to the documentation of this file.
00001 #ifndef CPPTL_INTRUSIVEPTR_H_INCLUDED
00002 # define CPPTL_INTRUSIVEPTR_H_INCLUDED
00003 
00004 # include <cpptl/forwards.h>
00005 # include <cpptl/atomiccounter.h>
00006 
00007 // We use inheritance instead of the typedef in a struct to
00008 // simulate the template typedef because the typedef in a struct
00009 // trick does not support type deduction in template functions.
00010 
00011 
00012 // If CPPTL_USE_BOOST_INTRUSIVE_PTR is defined, then we use boost::intrusive_ptr
00013 // as our smart_pointer, otherwise we use a simple implementation
00014 // of our own.
00015 
00016 namespace CppTL
00017 {
00019    class IntrusiveCount
00020    {
00021    public:
00022       virtual ~IntrusiveCount()
00023       {
00024       }
00025 
00026       void incrementReferenceCount()
00027       {
00028          count_.increment();
00029       }
00030 
00031       void releaseReferenceCount()
00032       {
00033          if ( !count_.decrement() )
00034             delete this;
00035       }
00036 
00037    private:
00038       mutable AtomicCounter count_;
00039    };
00040 
00041 }
00042 
00043 # ifndef CPPTL_USE_BOOST_SHARED_PTR
00044 namespace CppTL
00045 {
00046    inline void instrusivePtrAddRef( IntrusiveCount *p )
00047    {
00048       p->incrementReferenceCount();
00049    }
00050 
00051    inline void intrusivePtrRelease( IntrusiveCount *p )
00052    {
00053       p->releaseReferenceCount();
00054    }
00055 
00056    template<class PointeeType>
00057    class IntrusivePtr
00058    {
00059    public:
00060       typedef IntrusivePtr<PointeeType> ThisType; 
00061 
00062       IntrusivePtr()
00063          : p_( 0 )
00064       {
00065       }
00066 
00067       IntrusivePtr( PointeeType *p )
00068          : p_( p )
00069       {
00070          if ( p )
00071             instrusivePtrAddRef( p );
00072       }
00073 
00074       IntrusivePtr( const ThisType &other )
00075          : p_( other.p_ )
00076       {
00077          if ( p_ )
00078             instrusivePtrAddRef( p_ );
00079       }
00080 
00081       ~IntrusivePtr()
00082       {
00083          if ( p_ )
00084             intrusivePtrRelease( p_ );
00085       }
00086 
00087       void reset()
00088       {
00089          IntrusivePtr tmp;
00090          tmp.swap( *this );
00091       }
00092 
00093       void reset( PointeeType *p )
00094       {
00095          IntrusivePtr tmp( p );
00096          tmp.swap( *this );
00097       }
00098 
00099       PointeeType *get() const
00100       {
00101          return p_;
00102       }
00103 
00104       void swap( ThisType &other )
00105       {
00106          CppTL::swap( p_, other.p_ );
00107       }
00108 
00109       ThisType &operator =( const ThisType &other )
00110       {
00111          ThisType tmp( other );
00112          swap( tmp );
00113          return *this;
00114       }
00115 
00116       PointeeType &operator *() const
00117       {
00118          CPPTL_ASSERT_MESSAGE( p_ != 0, "Attempting to dereference a null pointer with operator *." );
00119          return *p_;
00120       }
00121 
00122       PointeeType *operator ->() const
00123       {
00124          CPPTL_ASSERT_MESSAGE( p_ != 0, "Attempting to use a null pointer with operator ->." );
00125          return p_;
00126       }
00127 
00128       operator bool() const
00129       {
00130          return p_ != 0;
00131       }
00132 
00133       bool operator !() const
00134       {
00135          return p_ == 0;
00136       }
00137 
00138       bool operator ==( const ThisType &other ) const
00139       {
00140          return p_ == other.p_;
00141       }
00142 
00143       bool operator !=( const ThisType &other ) const
00144       {
00145          return !(*this == other );
00146       }
00147 
00148       bool operator <( const ThisType &other ) const
00149       {
00150          return p_ < other.p_;
00151       }
00152 
00153       bool operator <=( const ThisType &other ) const
00154       {
00155          return p_ <= other.p_;
00156       }
00157 
00158       bool operator >=( const ThisType &other ) const
00159       {
00160          return p_ >= other.p_;
00161       }
00162 
00163       bool operator >( const ThisType &other ) const
00164       {
00165          return p_ > other.p_;
00166       }
00167 
00168    private:
00169       PointeeType *p_;
00170    };
00171 
00172 
00173    template<class T, class U> 
00174    IntrusivePtr<T>
00175    staticPointerCast( const IntrusivePtr<U> & r)
00176    {
00177       return IntrusivePtr<T>( static_cast<T*>( r.get() ) );
00178    }
00179 
00180 } // namespace CppTL
00181 
00182 # else // ifndef CPPTL_USE_BOOST_SHARED_PTR
00183 
00184 #  include <boost/shared_ptr.hpp>
00185 
00186 namespace CppTL
00187 {
00188 
00189    template<class PointeeType>
00190    class IntrusivePtr : public ::boost::intrusive_ptr<PointeeType>
00191    {
00192    public:
00193       typedef IntrusivePtr<PointeeType> ThisType; 
00194 
00195       IntrusivePtr()
00196       {
00197       }
00198 
00199       IntrusivePtr( PointeeType *p )
00200          : ::boost::intrusive_ptr( p )
00201       {
00202       }
00203 
00204       IntrusivePtr( const ::boost::intrusive_ptr<PointeeType> &other )
00205          : ::boost::intrusive_ptr( other )
00206       {
00207       }
00208 
00209       ThisType &operator =( const ::boost::intrusive_ptr<PointeeType> &other )
00210       {
00211          return ::boost::intrusive_ptr<PointeeType>::operator =( other );
00212       }
00213    };
00214 
00215 
00216    template<class T, class U> 
00217    IntrusivePtr<T>
00218    staticPointerCast( const ::boost::intrusive_ptr<U> & r)
00219    {
00220       return IntrusivePtr<T>( ::boost::static_pointer_cast<T>( r ) );
00221    }
00222 
00223 } // namespace CppTL
00224 
00225 namespace boost {
00226    inline void intrusive_ptr_add_ref( CppTL::IntrusiveCount *p )
00227    {
00228       p->incrementReferenceCount();
00229    }
00230 
00231    inline void intrusive_ptr_release( CppTL::IntrusiveCount *p )
00232    {
00233       p->releaseReferenceCount();
00234    }
00235 } // namespace boost
00236 
00237 # endif // ifndef CPPTL_USE_BOOST_SHARED_PTR
00238 
00239 
00240 namespace CppTL {
00241 
00242 template<class DataType>
00243 class SharedDataPtr
00244 {
00245 public:
00246    typedef SharedDataPtr<DataType> ThisType;
00247    typedef DataType Data;
00248    
00249    SharedDataPtr()
00250    {
00251    }
00252    
00253    SharedDataPtr( const Data &data )
00254       : shared_( new CountedData( data ) )
00255    {
00256    }
00257 
00258    SharedDataPtr( const ThisType &other )
00259       : shared_( other.shared_ )
00260    {
00261    }
00262 
00263    ~SharedDataPtr()
00264    {
00265    }
00266 
00267    Data *get() const
00268    {
00269       CountedData *data = shared_.get();
00270       return data ? &(data->data_) : 0;
00271    }
00272 
00273    void swap( ThisType &other )
00274    {
00275       shared_.swap( other.shared_ );
00276    }
00277 
00278    ThisType &operator =( const ThisType &other )
00279    {
00280       ThisType tmp( other );
00281       swap( tmp );
00282       return *this;
00283    }
00284 
00285    DataType &operator *() const
00286    {
00287       // assert( p_ != 0 )
00288       return shared_->data_;
00289    }
00290 
00291    DataType *operator ->() const
00292    {
00293       return &(shared_->data_);
00294    }
00295 
00296    operator bool() const
00297    {
00298       return shared_;
00299    }
00300 
00301    bool operator !() const
00302    {
00303       return !shared_;
00304    }
00305 
00306 private:
00307    class CountedData : public IntrusiveCount
00308    {
00309    public:
00310       CountedData( const Data &data )
00311          : data_( data )
00312       {
00313       }
00314 
00315       Data data_;
00316    };
00317 
00318    IntrusivePtr<CountedData> shared_;
00319 };
00320 
00321 
00322 } // namespace CppTL
00323 
00324 
00325 #endif // CPPTL_INTRUSIVEPTR_H_INCLUDED
00326 

SourceForge Logo hosts this site. Send comments to:
CppUnit Developers