/** @file
$ Id $
$ Date $
$ Author $
@ copy & copy ; Marc W & auml ; ckerlin
@ license LGPL , see file < a href = " license.html " > COPYING < / a >
*/
# ifndef __MRW__SMARTPOINTER_HPP__
# define __MRW__SMARTPOINTER_HPP__
namespace mrw {
class PointerCounter {
private :
unsigned int _cnt ;
public :
PointerCounter ( ) throw ( ) :
_cnt ( 1 ) {
}
PointerCounter * incr ( ) throw ( ) {
+ + _cnt ;
return this ;
}
int decr ( ) throw ( ) {
return - - _cnt ;
}
int get ( ) throw ( ) {
return _cnt ;
}
} ;
class SmartPointerParent {
protected :
template < class TYPE >
PointerCounter * getCounter ( TYPE & sp ) throw ( ) {
return sp . _cnt ;
}
template < class TYPE >
typename TYPE : : Pointer getPointer ( TYPE & sp ) throw ( ) {
return sp . _ptr ;
}
} ;
/** @addtogroup AutoTools */
//@{
/** @brief Smart Pointer Implementation
@ pre \ # include < mrw / smartpointer . hpp >
This is a smart pointer that can be casted withing the
inheritance of the pointer it is storing .
A smart pointer is a pointer that is automatically cleaned up
when it is no more referenced . Therefore you only allocate
memory , but you never free it , just as in Java , cleaning up is
done behind the scenes . If you assign a smart pointer to another
smart pointer , both point to the same memory . A counter counts
the number of references to the object and frees it as soon as
the last smart pointer pointing to the same memory has been
destroyed .
A smart pointer is used just as a normal pointer , except that
you can assign it only to other smart pointers , not to ordinary
pointers , and you don ' t have to delete the memory allocated . Any
memory assigned to a smart pointer is consumed and mustn ' t be
used any more . Never allocate a smart pointer with
< code > new < / code > , but only the pointer that is stored in the
smart pointer !
@ note memory assigned to a smart pointer is consumed
*/
template < class TYPE > class SmartPointer : public SmartPointerParent {
private :
typedef TYPE * Pointer ;
PointerCounter * _cnt ;
TYPE * _ptr ;
private :
void drop ( ) throw ( ) {
if ( _cnt & & ! _cnt - > decr ( ) ) {
delete _cnt ; _cnt = 0 ;
delete _ptr ; _ptr = 0 ;
}
}
private :
friend class SmartPointerParent ;
friend class SmartPointerTest ;
public :
SmartPointer ( ) throw ( ) :
_cnt ( 0 ) , _ptr ( 0 ) {
}
SmartPointer ( const SmartPointer < TYPE > & o ) throw ( ) :
_cnt ( o . _cnt ? o . _cnt - > incr ( ) : 0 ) , _ptr ( o . _ptr ) {
}
SmartPointer ( TYPE * ptr ) throw ( ) :
_cnt ( ptr ? new PointerCounter : 0 ) , _ptr ( ptr ) {
}
template < class OTHER > SmartPointer ( const SmartPointer < OTHER > & o ) throw ( ) :
_cnt ( 0 ) , _ptr ( dynamic_cast < TYPE * > ( getPointer ( o ) ) ) {
if ( _ptr ) _cnt = getCounter ( o ) - > incr ( ) ;
}
~ SmartPointer ( ) throw ( ) {
drop ( ) ;
}
SmartPointer & operator = ( const SmartPointer < TYPE > & o ) throw ( ) {
if ( o . _ptr = = _ptr ) return * this ;
drop ( ) ;
_cnt = o . _cnt ? o . _cnt - > incr ( ) : 0 ;
_ptr = o . _ptr ;
return * this ;
}
SmartPointer & operator = ( TYPE * ptr ) throw ( ) {
if ( ptr = = _ptr ) return * this ;
drop ( ) ;
_cnt = ptr ? new PointerCounter : 0 ;
_ptr = ptr ;
return * this ;
}
template < class OTHER >
SmartPointer & operator = ( const SmartPointer < OTHER > & o ) throw ( ) {
if ( getPointer ( o ) = = _ptr ) return * this ;
drop ( ) ;
_ptr = dynamic_cast < TYPE * > ( getPointer ( o ) ) ;
_cnt = _ptr ? getCounter ( o ) - > incr ( ) : 0 ;
return * this ;
}
TYPE & operator * ( ) throw ( ) {
return * _ptr ;
}
const TYPE & operator * ( ) const throw ( ) {
return * _ptr ;
}
TYPE * const operator - > ( ) throw ( ) {
return _ptr ;
}
const TYPE * const operator - > ( ) const throw ( ) {
return _ptr ;
}
operator bool ( ) throw ( ) {
return _ptr ! = 0 ;
}
} ;
//@}
}
# endif