C++ Library containing a lot of needful things: Stack Trace, Command Line Parser, Resource Handling, Configuration Files, Unix Command Execution, Directories, Regular Expressions, Tokenizer, Function Trace, Standard Extensions.
148 lines
4.0 KiB
148 lines
4.0 KiB
/** @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
|
|
|