Rep.h

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------\
00002 |                                                                      |
00003 |                      __   __    ____ _____ ____                      |
00004 |                      \ \ / /_ _/ ___|_   _|___ \                     |
00005 |                       \ V / _` \___ \ | |   __) |                    |
00006 |                        | | (_| |___) || |  / __/                     |
00007 |                        |_|\__,_|____/ |_| |_____|                    |
00008 |                                                                      |
00009 |                               core system                            |
00010 |                                                        (C) SuSE GmbH |
00011 \----------------------------------------------------------------------/
00012 
00013    File:       Rep.h
00014 
00015    Author:     Michael Andres <ma@suse.de>
00016    Maintainer: Michael Andres <ma@suse.de>
00017 
00018    Purpose: Base class for reference counted objects and counted pointer templates.
00019 
00020 /-*/
00021 #ifndef Rep_h
00022 #define Rep_h
00023 
00024 #include <iosfwd>
00025 
00027 //
00028 //      CLASS NAME : Rep
00046 class Rep {
00047   private:
00048 
00052     mutable unsigned _counter;
00053 
00054   protected:
00055 
00059     virtual void ref_to( unsigned /* rep_cnt_r */ ) const {}
00065     virtual void unref_to( unsigned /* rep_cnt_r */ ) const {}
00066 
00067   public:
00068 
00072     Rep() : _counter( 0 ) {}
00076     Rep( const Rep & rhs ) : _counter( 0 ) {}
00080     Rep & operator=( const Rep & rhs ) { return *this; }
00084     virtual ~Rep() { if ( _counter ) throw( this ); }
00085 
00086   public:
00087 
00091     void ref() const {
00092       ref_to( ++_counter ); // trigger derived classes
00093     }
00099     void unref() const {
00100       if ( ! _counter )
00101         throw( this );
00102       if ( --_counter )
00103         unref_to( _counter ); // trigger derived classes
00104       else
00105         delete this;
00106     }
00107 
00112     static void ref( const Rep * obj_r ) {
00113       if ( obj_r )
00114         obj_r->ref();
00115     }
00120     static void unref( const Rep * obj_r ) {
00121       if ( obj_r )
00122         obj_r->unref();
00123     }
00124 
00125   public:
00126 
00130     unsigned refCount() const { return _counter; }
00131 
00132   public:
00133 
00137     virtual const char * repName() const { return "Rep"; }
00143     virtual std::ostream & dumpOn( std::ostream & str ) const;
00144 };
00145 
00149 std::ostream & operator<<( std::ostream & str, const Rep & obj );
00153 std::ostream & operator<<( std::ostream & str, const Rep * obj );
00154 
00156 
00158 //
00159 //      CLASS NAME : CountedRep
00167 class CountedRep : public Rep {
00168 
00169   private:
00170 
00174     static unsigned _objectCount;
00178     static unsigned _objectIds;
00179 
00183     const unsigned _objectId;
00184 
00185   public:
00186 
00190     CountedRep() : _objectId( ++_objectIds ) { ++_objectCount; }
00194     CountedRep( const CountedRep & rhs ) : Rep( rhs ), _objectId( ++_objectIds ) { ++_objectCount; }
00198     CountedRep & operator=( const CountedRep & rhs ) {
00199       Rep::operator=( rhs );
00200       return *this;
00201     }
00205     virtual ~CountedRep() { --_objectCount; }
00206 
00207   public:
00208 
00212     unsigned objectId() const { return _objectId; }
00213 
00217     static unsigned objectCount() { return _objectCount; }
00218 
00219   public:
00220 
00224     virtual std::ostream & dumpOn( std::ostream & str ) const;
00225 };
00226 
00228 
00230 //
00231 // Counted pointer
00232 //
00234 
00236 //
00237 //      CLASS NAME : RepPtrStore<typename _Tp, typename _Bt>
00269 template<typename _Tp, typename _Bt = _Tp>
00270 class RepPtrStore {
00271 
00272   private:
00273 
00277     _Tp * _obj;
00278 
00279   private:
00280 
00285     void _assign( _Tp * new_r );
00286 
00287   public:
00288 
00292     RepPtrStore() : _obj( 0 ) {}
00296     RepPtrStore( _Tp * ptr ) : _obj( 0 ) { _assign( ptr ); }
00300     RepPtrStore( const RepPtrStore & rhs ) : _obj( 0 ) { _assign( rhs._obj ); }
00301 
00305     RepPtrStore & operator=( _Tp * ptr ) { _assign( ptr ); return *this; }
00309     RepPtrStore & operator=( const RepPtrStore & rhs ) { _assign( rhs._obj ); return *this; }
00310 
00314     ~RepPtrStore() { _assign( 0 ); }
00315 
00319     operator _Tp *() const { return _obj; }
00320 
00321   public:
00322 
00326     void tryAssign( _Bt * ptr );
00327 
00328   public:
00329 
00333     _Bt * base() const;
00337     const Rep * refbase() const;
00338 };
00339 
00340 template<typename _Tp,typename _Bt>
00341 void RepPtrStore<_Tp,_Bt>::_assign( _Tp * new_r ) {
00342   if ( new_r != _obj ) {
00343     Rep::unref( _obj );
00344     _obj = new_r;
00345     Rep::ref( _obj );
00346   }
00347 }
00348 
00349 template<typename _Tp,typename _Bt>
00350 void RepPtrStore<_Tp,_Bt>::tryAssign( _Bt * ptr ) {
00351   _assign( dynamic_cast<_Tp*>(ptr) );
00352   if ( !_obj && ptr && ! ptr->refCount() ) {
00353     Rep::ref( ptr );
00354     Rep::unref( ptr );
00355   }
00356 }
00357 
00358 template<typename _Tp,typename _Bt>
00359 _Bt * RepPtrStore<_Tp,_Bt>::base() const { return _obj; }
00360 
00361 template<typename _Tp,typename _Bt>
00362 const Rep * RepPtrStore<_Tp,_Bt>::refbase() const { return _obj; }
00363 
00365 
00367 //
00368 //      CLASS NAME : RepPtrBase
00377 class RepPtrBase {
00381   friend std::ostream & operator<<( std::ostream & str, const RepPtrBase & obj );
00382 
00383   protected:
00384 
00388     virtual ~RepPtrBase() {}
00392     virtual const Rep * refbase() const = 0;
00393 
00394   public:
00395 
00400     operator const void *() const  { return refbase(); }
00401 };
00402 
00404 
00405 template<typename _Bt> class constPtrBase;
00406 
00408 //
00409 //      CLASS NAME : PtrBase<typename _Bt>
00415 template<typename _Bt>
00416 class PtrBase : public RepPtrBase {
00417 
00418   protected:
00419 
00420     friend class constPtrBase<_Bt>;
00421 
00425     virtual _Bt * base() const = 0;
00426 
00430     _Bt * getBase( const PtrBase & rhs ) const {
00431       return rhs.base();
00432     }
00433 };
00434 
00436 
00438 //
00439 //      CLASS NAME : constPtrBase<typename _Bt>
00445 template<typename _Bt>
00446 class constPtrBase : public RepPtrBase {
00447 
00448   protected:
00449 
00453     virtual const _Bt * base() const = 0;
00454 
00458     const _Bt * getBase( const constPtrBase & rhs ) const {
00459       return rhs.base();
00460     }
00461 
00466     const _Bt * getBase( const PtrBase<_Bt> & rhs ) const {
00467       return rhs.base();
00468     }
00469 };
00470 
00472 
00473 template<typename _Tp,typename _Bt> class constPtr;
00474 
00476 //
00477 //      CLASS NAME : Ptr<typename _Tp, typename _Bt>
00481 template<typename _Tp, typename _Bt = _Tp>
00482 class Ptr : public PtrBase<_Bt> {
00483 
00484   private:
00485 
00489     RepPtrStore<_Tp,_Bt> _ptr;
00490 
00491   protected:
00492 
00496     virtual const Rep * refbase() const { return _ptr.refbase(); }
00500     virtual _Bt * base() const { return _ptr.base(); }
00501 
00502   public:
00503 
00507     Ptr( _Tp * ptr = 0 ) : _ptr( ptr ) {}
00511     Ptr( const Ptr & rhs ) : PtrBase<_Bt>( rhs ), _ptr( rhs._ptr ) {}
00515     Ptr( const PtrBase<_Bt> & rhs ) { _ptr.tryAssign( getBase( rhs ) ); }
00516 
00517   public:
00518 
00522     Ptr & operator=( _Tp * ptr ) { _ptr = ptr; return *this; }
00526     Ptr & operator=( const Ptr & rhs ) { _ptr = rhs._ptr; return *this; }
00530     Ptr & operator=( const PtrBase<_Bt> & rhs ) { _ptr.tryAssign( getBase( rhs ) ); return *this; }
00531 
00532   public:
00533 
00537     _Tp * operator->() const { return _ptr; }
00538 
00542     _Tp & operator*() const { return *_ptr; }
00543 
00544   public:
00545 
00549     static Ptr cast_away_const( constPtr<_Tp,_Bt> rhs ) {
00550       return const_cast<_Tp*>(rhs.operator->());
00551     }
00552 };
00553 
00555 
00557 //
00558 //      CLASS NAME : constPtr<typename _Tp, typename _Bt>
00562 template<typename _Tp, typename _Bt = _Tp>
00563 class constPtr : public constPtrBase<_Bt> {
00564 
00565   private:
00566 
00570     RepPtrStore<const _Tp,const _Bt> _ptr;
00571 
00572   protected:
00573 
00577     virtual const Rep * refbase() const { return _ptr.refbase(); }
00581     virtual const _Bt * base() const { return _ptr.base(); }
00582 
00583   public:
00584 
00588     constPtr( const _Tp * ptr = 0 ) : _ptr( ptr ) {}
00592     constPtr( const constPtr & rhs ) : constPtrBase<_Bt>( rhs ), _ptr( rhs._ptr ) {}
00596     constPtr( const constPtrBase<_Bt> & rhs ) { _ptr.tryAssign( getBase( rhs ) ); }
00597 
00598   public:
00599 
00603     constPtr & operator=( const _Tp * ptr ) { _ptr = ptr; return *this; }
00607     constPtr & operator=( const constPtr & rhs ) { _ptr = rhs._ptr; return *this; }
00611     constPtr & operator=( const constPtrBase<_Bt> & rhs ) { _ptr.tryAssign( getBase( rhs ) ); return *this; }
00612 
00613   public:
00614 
00618     constPtr( const Ptr<_Tp,_Bt> & rhs ) : _ptr( rhs.operator->() ) {}
00622     constPtr( const PtrBase<_Bt> & rhs ) { _ptr.tryAssign( getBase( rhs ) ); }
00623 
00624   public:
00625 
00629     constPtr & operator=( const Ptr<_Tp,_Bt> & rhs ) { _ptr = rhs.operator->(); return *this; }
00633     constPtr & operator=( const PtrBase<_Bt> & rhs ) { _ptr.tryAssign( getBase( rhs ) ); return *this; }
00634 
00635   public:
00636 
00640     const _Tp * operator->() const { return _ptr; }
00644     const _Tp & operator*() const { return *_ptr; }
00645 };
00646 
00648 
00650 //
00651 //      CLASS NAME : VarPtr
00652 //
00654 
00656 //
00657 //      CLASS NAME : BasicRepPtr
00668 class BasicRepPtr
00669 {
00673   friend std::ostream &
00674   operator<<( std::ostream & str, const BasicRepPtr & obj )
00675   { return str << obj._ptr; }
00676 
00677   public:
00681     operator const void *() const
00682     { return _ptr; }
00683 
00684   protected:
00688     BasicRepPtr()
00689     : _ptr( NULL )
00690     {}
00691 
00692     explicit
00693     BasicRepPtr( Rep * ptr )
00694     : _ptr( NULL )
00695     { _assign( ptr ); }
00696 
00697     BasicRepPtr( const BasicRepPtr & rhs )
00698     : _ptr( NULL )
00699     { _assign( rhs._ptr ); }
00700 
00701     BasicRepPtr &
00702     operator=( const BasicRepPtr & rhs )
00703     { _assign( rhs._ptr ); return *this; }
00704 
00705     ~BasicRepPtr()
00706     { _assign( NULL ); }
00707 
00711     Rep *
00712     repPtr() const
00713     { return _ptr; }
00714 
00715   private:
00719     Rep * _ptr;
00720 
00725     void
00726     _assign( Rep * new_r )
00727     {
00728       // Don't miss this test
00729       if ( new_r != _ptr )
00730         {
00731           Rep::unref( _ptr );
00732           _ptr = new_r;
00733           Rep::ref( _ptr );
00734         }
00735     }
00736 };
00738 
00739 
00741 
00743 //
00744 //      CLASS NAME : VarPtr
00768 template<typename _Rep>
00769   class VarPtr : public BasicRepPtr
00770   {
00771   public:
00772 
00776     VarPtr()
00777     : BasicRepPtr()
00778     {}
00779 
00783     explicit
00784     VarPtr( _Rep * ptr_r )
00785     : BasicRepPtr( ptr_r )
00786     {}
00787 
00788   public:
00789 
00790     _Rep *
00791     operator->()
00792     { return ptr(); }
00793 
00794     const _Rep *
00795     operator->() const
00796     { return ptr(); }
00797 
00798     _Rep &
00799     operator*()
00800     { return *ptr(); }
00801 
00802     const _Rep &
00803     operator*() const
00804     { return *ptr(); }
00805 
00806   private:
00807 
00808     _Rep *
00809     ptr() const
00810     { return static_cast<_Rep *>( BasicRepPtr::repPtr() ); }
00811   };
00813 
00815 
00819 template<typename _Rep>
00820   inline VarPtr<_Rep>
00821   makeVarPtr( _Rep * ptr )
00822   { return VarPtr<_Rep>( ptr ); }
00823 
00825 
00826 #endif // Rep_h

Generated on Fri Jun 16 15:51:35 2006 for liby2util by  doxygen 1.4.6