|
yast2-core
|
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
1.7.3