CppUnit project page CppUnit home page

sharedptr.h

Go to the documentation of this file.
00001 #ifndef CPPTL_SHAREDPTR_H_INCLUDED
00002 # define CPPTL_SHAREDPTR_H_INCLUDED
00003 
00004 # include <cpptl/forwards.h>
00005 
00006 // We use inheritance instead of the typedef in a struct to
00007 // simulate the template typedef because the typedef in a struct
00008 // trick does not support type deduction in template functions.
00009 
00010 
00011 // If CPPTL_USE_BOOST_SHARED_PTR is defined, then we use boost::shared_ptr
00012 // as our smart_pointer, otherwise we use a simple (partial) implementation
00013 // of our own.
00014 # ifndef CPPTL_USE_BOOST_SHARED_PTR
00015 
00016 #  include <cpptl/atomiccounter.h>
00017 
00018 namespace CppTL
00019 {
00020 
00022    namespace Impl {
00023 
00024       struct StaticPointerCastTag {};
00025 
00027       class SharedPtrBase
00028       {
00029       public:
00030          long use_count() const
00031          {
00032             if ( count_ )
00033                return count_->count();
00034             return 0;
00035          }
00036 
00037          bool unique() const
00038          {
00039             return use_count() == 1;
00040          }
00041 
00042          operator bool() const
00043          {
00044             return p_ != 0;
00045          }
00046 
00047          bool operator !() const
00048          {
00049             return p_ == 0;
00050          }
00051       protected:
00052          SharedPtrBase()
00053             : p_( 0 )
00054             , count_( 0 )
00055          {
00056          }
00057          explicit SharedPtrBase( void *p )
00058             : p_( p )
00059             , count_( p ? new AtomicCounter( 1 ) : 0 )
00060          {
00061          }
00062 
00063          SharedPtrBase( void *p, 
00064                        AtomicCounter *count, 
00065                        StaticPointerCastTag )
00066             : p_( p )
00067             , count_( count )
00068          {
00069             count_->increment();
00070          }
00071 
00072          SharedPtrBase( const SharedPtrBase &other )
00073             : p_( other.p_ )
00074             , count_( other.count_ )
00075          {
00076             if ( p_ )
00077                count_->increment();
00078          }
00079 
00080          ~SharedPtrBase()
00081          {
00082             // subclass destructor should call releaseCount();
00083          }
00084 
00085          bool releaseCount()
00086          {
00087             if ( count_  &&  count_->decrement() == 0 )
00088             {
00089                delete count_;
00090                return true;
00091             }
00092             return false;
00093          }
00094 
00095          void swap( SharedPtrBase &other )
00096          {
00097             void *tmpP = p_;
00098             AtomicCounter *tmpCount = count_;
00099             p_ = other.p_;
00100             count_ = other.count_;
00101             other.p_ = tmpP;
00102             other.count_ = tmpCount;
00103          }
00104 
00105          void *get() const
00106          {
00107             return p_;
00108          }
00109 
00110          void *deref() const
00111          {
00112             // assert( p_ != 0 )
00113             return p_;
00114          }
00115 
00116       //private:     // Friend template function is not well supported
00117                      // Private access required by function staticPointerCast<>
00118       public:
00119          void *p_;
00120          AtomicCounter *count_;
00121       };
00122 
00123    } // namespace Impl
00125       
00126    template<class PointeeType>
00127    class SharedPtr : public Impl::SharedPtrBase
00128    {
00129    public:
00130       typedef SharedPtr<PointeeType> ThisType; 
00131       typedef Impl::SharedPtrBase SuperClass;
00132 
00133       SharedPtr()
00134       {
00135       }
00136 
00137       explicit SharedPtr( PointeeType *p )
00138          : Impl::SharedPtrBase( p )
00139       {
00140       }
00141 
00142       SharedPtr( PointeeType *p, 
00143                  AtomicCounter *count, 
00144                 Impl::StaticPointerCastTag )
00145          : Impl::SharedPtrBase( p, count, Impl::StaticPointerCastTag() )
00146       {
00147       }
00148 
00149       SharedPtr( const ThisType &other )
00150          : Impl::SharedPtrBase( other )
00151       {
00152       }
00153 
00154       ~SharedPtr()
00155       {
00156          if ( releaseCount() )
00157             checkedDelete( static_cast<PointeeType *>( p_ ) );
00158       }
00159 
00160       void reset()
00161       {
00162          SharedPtr tmp;
00163          tmp.swap( *this );
00164       }
00165 
00166       void reset( PointeeType *p )
00167       {
00168          SharedPtr tmp( p );
00169          tmp.swap( *this );
00170       }
00171 
00172       PointeeType *get() const
00173       {
00174          return static_cast<PointeeType *>( SharedPtrBase::get() );
00175       }
00176 
00177       void swap( SharedPtr &other )
00178       {
00179          SuperClass::swap( other );
00180       }
00181 
00182       ThisType &operator =( const SharedPtr &other )
00183       {
00184          ThisType tmp( other );
00185          swap( tmp );
00186          return *this;
00187       }
00188 
00189       PointeeType &operator *() const
00190       {
00191          // assert( p_ != 0 )
00192          return *( static_cast<PointeeType *>( p_ ) );
00193       }
00194 
00195       PointeeType *operator ->() const
00196       {
00197          return static_cast<PointeeType *>( SuperClass::deref() );
00198       }
00199    };
00200 
00201 
00202    template<class TargetType, class SourceType>
00203    SharedPtr<TargetType>
00204    staticPointerCast( const SharedPtr<SourceType> &p )
00205    {
00206       TargetType *target = static_cast<TargetType *>( p.p_ );
00207       return SharedPtr<TargetType>( target, p.count_, 
00208                                    Impl::StaticPointerCastTag() );
00209    }
00210 
00211 } // namespace CppTL
00212 
00213 # else // ifndef CPPTL_USE_BOOST_SHARED_PTR
00214 
00215 #  include <boost/shared_ptr.hpp>
00216 
00217 namespace CppTL
00218 {
00219 
00220    template<class PointeeType>
00221    class SharedPtr : public ::boost::shared_ptr<PointeeType>
00222    {
00223    public:
00224       typedef SharedPtr<PointeeType> ThisType; 
00225 
00226       SharedPtr()
00227       {
00228       }
00229 
00230       explicit SharedPtr( PointeeType *p )
00231          : ::boost::shared_ptr( p )
00232       {
00233       }
00234 
00235       SharedPtr( const ::boost::shared_ptr<PointeeType> &other )
00236          : ::boost::shared_ptr( other )
00237       {
00238       }
00239 
00240       ThisType &operator =( const ::boost::shared_ptr<PointeeType> &other )
00241       {
00242          return ::boost::shared_ptr<PointeeType>::operator =( other );
00243       }
00244    };
00245 
00246 
00247    template<class T, class U> 
00248    SharedPtr<T>
00249    staticPointerCast( const ::boost::shared_ptr<U> & r)
00250    {
00251       return SharedPtr<T>( ::boost::static_pointer_cast<T>( r ) );
00252    }
00253 
00254 } // namespace CppTL
00255 
00256 # endif // ifndef CPPTL_USE_BOOST_SHARED_PTR
00257 
00258 
00259 
00260 #endif // CPPTL_SHAREDPTR_H_INCLUDED
00261 

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