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.
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
149 lines
4.0 KiB
149 lines
4.0 KiB
21 years ago
|
/** @file
|
||
|
|
||
|
$Id$
|
||
|
|
||
|
$Date$
|
||
|
$Author$
|
||
|
|
||
|
@copy © Marc Wäckerlin
|
||
|
@license LGPL, see file <a href="license.html">COPYING</a>
|
||
|
|
||
|
*/
|
||
21 years ago
|
#ifndef __MRW__SMARTPOINTER_HPP__
|
||
|
#define __MRW__SMARTPOINTER_HPP__
|
||
|
|
||
|
namespace mrw {
|
||
|
|
||
|
class PointerCounter {
|
||
|
private:
|
||
|
unsigned int _cnt;
|
||
|
public:
|
||
21 years ago
|
PointerCounter() throw():
|
||
21 years ago
|
_cnt(1) {
|
||
|
}
|
||
21 years ago
|
PointerCounter* incr() throw() {
|
||
21 years ago
|
++_cnt;
|
||
|
return this;
|
||
|
}
|
||
21 years ago
|
int decr() throw() {
|
||
21 years ago
|
return --_cnt;
|
||
|
}
|
||
21 years ago
|
int get() throw() {
|
||
21 years ago
|
return _cnt;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
class SmartPointerParent {
|
||
|
protected:
|
||
|
template<class TYPE>
|
||
21 years ago
|
PointerCounter* getCounter(TYPE& sp) throw() {
|
||
21 years ago
|
return sp._cnt;
|
||
|
}
|
||
|
template<class TYPE>
|
||
21 years ago
|
typename TYPE::Pointer getPointer(TYPE& sp) throw() {
|
||
21 years ago
|
return sp._ptr;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/** @addtogroup AutoTools */
|
||
|
//@{
|
||
|
|
||
|
/** @brief Smart Pointer Implementation
|
||
14 years ago
|
@pre \#include <mrw/smartpointer.hxx>
|
||
21 years ago
|
|
||
|
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:
|
||
21 years ago
|
void drop() throw() {
|
||
21 years ago
|
if (_cnt && !_cnt->decr()) {
|
||
|
delete _cnt; _cnt=0;
|
||
|
delete _ptr; _ptr=0;
|
||
|
}
|
||
|
}
|
||
|
private:
|
||
|
friend class SmartPointerParent;
|
||
|
friend class SmartPointerTest;
|
||
|
public:
|
||
21 years ago
|
SmartPointer() throw():
|
||
21 years ago
|
_cnt(0), _ptr(0) {
|
||
|
}
|
||
21 years ago
|
SmartPointer(const SmartPointer<TYPE>& o) throw():
|
||
21 years ago
|
_cnt(o._cnt?o._cnt->incr():0), _ptr(o._ptr) {
|
||
|
}
|
||
21 years ago
|
SmartPointer(TYPE* ptr) throw():
|
||
21 years ago
|
_cnt(ptr ? new PointerCounter : 0), _ptr(ptr) {
|
||
|
}
|
||
21 years ago
|
template<class OTHER> SmartPointer(const SmartPointer<OTHER>& o) throw():
|
||
21 years ago
|
_cnt(0), _ptr(dynamic_cast<TYPE*>(getPointer(o))) {
|
||
|
if (_ptr) _cnt = getCounter(o)->incr();
|
||
|
}
|
||
21 years ago
|
~SmartPointer() throw() {
|
||
21 years ago
|
drop();
|
||
|
}
|
||
21 years ago
|
SmartPointer& operator=(const SmartPointer<TYPE>& o) throw() {
|
||
21 years ago
|
if (o._ptr==_ptr) return *this;
|
||
|
drop();
|
||
|
_cnt = o._cnt ? o._cnt->incr() : 0;
|
||
|
_ptr = o._ptr;
|
||
|
return *this;
|
||
|
}
|
||
21 years ago
|
SmartPointer& operator=(TYPE* ptr) throw() {
|
||
21 years ago
|
if (ptr==_ptr) return *this;
|
||
|
drop();
|
||
|
_cnt = ptr ? new PointerCounter : 0;
|
||
|
_ptr = ptr;
|
||
|
return *this;
|
||
|
}
|
||
|
template<class OTHER>
|
||
21 years ago
|
SmartPointer& operator=(const SmartPointer<OTHER>& o) throw() {
|
||
21 years ago
|
if (getPointer(o)==_ptr) return *this;
|
||
|
drop();
|
||
|
_ptr = dynamic_cast<TYPE*>(getPointer(o));
|
||
|
_cnt = _ptr ? getCounter(o)->incr() : 0;
|
||
|
return *this;
|
||
|
}
|
||
21 years ago
|
TYPE& operator*() throw() {
|
||
21 years ago
|
return *_ptr;
|
||
|
}
|
||
21 years ago
|
const TYPE& operator*() const throw() {
|
||
21 years ago
|
return *_ptr;
|
||
|
}
|
||
21 years ago
|
TYPE* const operator->() throw() {
|
||
21 years ago
|
return _ptr;
|
||
|
}
|
||
21 years ago
|
const TYPE* const operator->() const throw() {
|
||
21 years ago
|
return _ptr;
|
||
|
}
|
||
21 years ago
|
operator bool() throw() {
|
||
21 years ago
|
return _ptr!=0;
|
||
|
}
|
||
|
};
|
||
|
//@}
|
||
|
}
|
||
|
#endif
|