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

/** @file
$Id$
$Date$
$Author$
@copy © Marc Wäckerlin
@license LGPL, see file <a href="license.html">COPYING</a>
*/
20 years ago
#ifndef __MRW__SMARTPOINTER_HPP__
#define __MRW__SMARTPOINTER_HPP__
namespace mrw {
class PointerCounter {
private:
unsigned int _cnt;
public:
PointerCounter() throw():
20 years ago
_cnt(1) {
}
PointerCounter* incr() throw() {
20 years ago
++_cnt;
return this;
}
int decr() throw() {
20 years ago
return --_cnt;
}
int get() throw() {
20 years ago
return _cnt;
}
};
class SmartPointerParent {
protected:
template<class TYPE>
PointerCounter* getCounter(TYPE& sp) throw() {
20 years ago
return sp._cnt;
}
template<class TYPE>
typename TYPE::Pointer getPointer(TYPE& sp) throw() {
20 years ago
return sp._ptr;
}
};
/** @addtogroup AutoTools */
//@{
/** @brief Smart Pointer Implementation
@pre \#include <mrw/smartpointer.hpp>
20 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:
void drop() throw() {
20 years ago
if (_cnt && !_cnt->decr()) {
delete _cnt; _cnt=0;
delete _ptr; _ptr=0;
}
}
private:
friend class SmartPointerParent;
friend class SmartPointerTest;
public:
SmartPointer() throw():
20 years ago
_cnt(0), _ptr(0) {
}
SmartPointer(const SmartPointer<TYPE>& o) throw():
20 years ago
_cnt(o._cnt?o._cnt->incr():0), _ptr(o._ptr) {
}
SmartPointer(TYPE* ptr) throw():
20 years ago
_cnt(ptr ? new PointerCounter : 0), _ptr(ptr) {
}
template<class OTHER> SmartPointer(const SmartPointer<OTHER>& o) throw():
20 years ago
_cnt(0), _ptr(dynamic_cast<TYPE*>(getPointer(o))) {
if (_ptr) _cnt = getCounter(o)->incr();
}
~SmartPointer() throw() {
20 years ago
drop();
}
SmartPointer& operator=(const SmartPointer<TYPE>& o) throw() {
20 years ago
if (o._ptr==_ptr) return *this;
drop();
_cnt = o._cnt ? o._cnt->incr() : 0;
_ptr = o._ptr;
return *this;
}
SmartPointer& operator=(TYPE* ptr) throw() {
20 years ago
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() {
20 years ago
if (getPointer(o)==_ptr) return *this;
drop();
_ptr = dynamic_cast<TYPE*>(getPointer(o));
_cnt = _ptr ? getCounter(o)->incr() : 0;
return *this;
}
TYPE& operator*() throw() {
20 years ago
return *_ptr;
}
const TYPE& operator*() const throw() {
20 years ago
return *_ptr;
}
TYPE* const operator->() throw() {
20 years ago
return _ptr;
}
const TYPE* const operator->() const throw() {
20 years ago
return _ptr;
}
operator bool() throw() {
20 years ago
return _ptr!=0;
}
};
//@}
}
#endif