2004-08-28 16:21:25 +00:00
|
|
|
/** @file
|
|
|
|
|
|
|
|
$Id$
|
|
|
|
|
|
|
|
$Date$
|
|
|
|
$Author$
|
|
|
|
|
|
|
|
@copy © Marc Wäckerlin
|
|
|
|
@license LGPL, see file <a href="license.html">COPYING</a>
|
|
|
|
|
|
|
|
$Log$
|
|
|
|
Revision 1.2 2004/08/28 16:21:25 marc
|
|
|
|
mrw-c++-0.92 (mrw)
|
|
|
|
- new file: version.cpp
|
|
|
|
- new file header for all sources
|
|
|
|
- work around warning in mrw::auto<T>
|
|
|
|
- possibility to compile without log4cxx
|
|
|
|
- work around bugs in demangle.h and libiberty.h
|
|
|
|
- corrections in documentation
|
|
|
|
- added simple tracing mechanism
|
|
|
|
- more warnings
|
|
|
|
- small corrections in Auto<>::Free and a new test for it
|
|
|
|
- possibility to compile without stack trace
|
|
|
|
|
|
|
|
*/
|
2004-04-27 20:26:50 +00:00
|
|
|
#ifndef __MRW__SMARTPOINTER_HPP__
|
|
|
|
#define __MRW__SMARTPOINTER_HPP__
|
|
|
|
|
|
|
|
namespace mrw {
|
|
|
|
|
|
|
|
class PointerCounter {
|
|
|
|
private:
|
|
|
|
unsigned int _cnt;
|
|
|
|
public:
|
2004-08-28 16:21:25 +00:00
|
|
|
PointerCounter() throw():
|
2004-04-27 20:26:50 +00:00
|
|
|
_cnt(1) {
|
|
|
|
}
|
2004-08-28 16:21:25 +00:00
|
|
|
PointerCounter* incr() throw() {
|
2004-04-27 20:26:50 +00:00
|
|
|
++_cnt;
|
|
|
|
return this;
|
|
|
|
}
|
2004-08-28 16:21:25 +00:00
|
|
|
int decr() throw() {
|
2004-04-27 20:26:50 +00:00
|
|
|
return --_cnt;
|
|
|
|
}
|
2004-08-28 16:21:25 +00:00
|
|
|
int get() throw() {
|
2004-04-27 20:26:50 +00:00
|
|
|
return _cnt;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class SmartPointerParent {
|
|
|
|
protected:
|
|
|
|
template<class TYPE>
|
2004-08-28 16:21:25 +00:00
|
|
|
PointerCounter* getCounter(TYPE& sp) throw() {
|
2004-04-27 20:26:50 +00:00
|
|
|
return sp._cnt;
|
|
|
|
}
|
|
|
|
template<class TYPE>
|
2004-08-28 16:21:25 +00:00
|
|
|
typename TYPE::Pointer getPointer(TYPE& sp) throw() {
|
2004-04-27 20:26:50 +00:00
|
|
|
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:
|
2004-08-28 16:21:25 +00:00
|
|
|
void drop() throw() {
|
2004-04-27 20:26:50 +00:00
|
|
|
if (_cnt && !_cnt->decr()) {
|
|
|
|
delete _cnt; _cnt=0;
|
|
|
|
delete _ptr; _ptr=0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
private:
|
|
|
|
friend class SmartPointerParent;
|
|
|
|
friend class SmartPointerTest;
|
|
|
|
public:
|
2004-08-28 16:21:25 +00:00
|
|
|
SmartPointer() throw():
|
2004-04-27 20:26:50 +00:00
|
|
|
_cnt(0), _ptr(0) {
|
|
|
|
}
|
2004-08-28 16:21:25 +00:00
|
|
|
SmartPointer(const SmartPointer<TYPE>& o) throw():
|
2004-04-27 20:26:50 +00:00
|
|
|
_cnt(o._cnt?o._cnt->incr():0), _ptr(o._ptr) {
|
|
|
|
}
|
2004-08-28 16:21:25 +00:00
|
|
|
SmartPointer(TYPE* ptr) throw():
|
2004-04-27 20:26:50 +00:00
|
|
|
_cnt(ptr ? new PointerCounter : 0), _ptr(ptr) {
|
|
|
|
}
|
2004-08-28 16:21:25 +00:00
|
|
|
template<class OTHER> SmartPointer(const SmartPointer<OTHER>& o) throw():
|
2004-04-27 20:26:50 +00:00
|
|
|
_cnt(0), _ptr(dynamic_cast<TYPE*>(getPointer(o))) {
|
|
|
|
if (_ptr) _cnt = getCounter(o)->incr();
|
|
|
|
}
|
2004-08-28 16:21:25 +00:00
|
|
|
~SmartPointer() throw() {
|
2004-04-27 20:26:50 +00:00
|
|
|
drop();
|
|
|
|
}
|
2004-08-28 16:21:25 +00:00
|
|
|
SmartPointer& operator=(const SmartPointer<TYPE>& o) throw() {
|
2004-04-27 20:26:50 +00:00
|
|
|
if (o._ptr==_ptr) return *this;
|
|
|
|
drop();
|
|
|
|
_cnt = o._cnt ? o._cnt->incr() : 0;
|
|
|
|
_ptr = o._ptr;
|
|
|
|
return *this;
|
|
|
|
}
|
2004-08-28 16:21:25 +00:00
|
|
|
SmartPointer& operator=(TYPE* ptr) throw() {
|
2004-04-27 20:26:50 +00:00
|
|
|
if (ptr==_ptr) return *this;
|
|
|
|
drop();
|
|
|
|
_cnt = ptr ? new PointerCounter : 0;
|
|
|
|
_ptr = ptr;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
template<class OTHER>
|
2004-08-28 16:21:25 +00:00
|
|
|
SmartPointer& operator=(const SmartPointer<OTHER>& o) throw() {
|
2004-04-27 20:26:50 +00:00
|
|
|
if (getPointer(o)==_ptr) return *this;
|
|
|
|
drop();
|
|
|
|
_ptr = dynamic_cast<TYPE*>(getPointer(o));
|
|
|
|
_cnt = _ptr ? getCounter(o)->incr() : 0;
|
|
|
|
return *this;
|
|
|
|
}
|
2004-08-28 16:21:25 +00:00
|
|
|
TYPE& operator*() throw() {
|
2004-04-27 20:26:50 +00:00
|
|
|
return *_ptr;
|
|
|
|
}
|
2004-08-28 16:21:25 +00:00
|
|
|
const TYPE& operator*() const throw() {
|
2004-04-27 20:26:50 +00:00
|
|
|
return *_ptr;
|
|
|
|
}
|
2004-08-28 16:21:25 +00:00
|
|
|
TYPE* const operator->() throw() {
|
2004-04-27 20:26:50 +00:00
|
|
|
return _ptr;
|
|
|
|
}
|
2004-08-28 16:21:25 +00:00
|
|
|
const TYPE* const operator->() const throw() {
|
2004-04-27 20:26:50 +00:00
|
|
|
return _ptr;
|
|
|
|
}
|
2004-08-28 16:21:25 +00:00
|
|
|
operator bool() throw() {
|
2004-04-27 20:26:50 +00:00
|
|
|
return _ptr!=0;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
//@}
|
|
|
|
}
|
|
|
|
#endif
|