middle of porting; unstable, don't checkout; refs #1
This commit is contained in:
148
src/mrw/smartpointer.hpp
Normal file
148
src/mrw/smartpointer.hpp
Normal file
@@ -0,0 +1,148 @@
|
||||
/** @file
|
||||
|
||||
$Id$
|
||||
|
||||
$Date$
|
||||
$Author$
|
||||
|
||||
@copy © Marc Wä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
|
Reference in New Issue
Block a user