206 lines
4.5 KiB
C
206 lines
4.5 KiB
C
|
#ifndef SMARTPTR_H
|
||
|
#define SMARTPTR_H
|
||
|
|
||
|
#include <map>
|
||
|
#include <string>
|
||
|
#include <stdexcept>
|
||
|
|
||
|
/**
|
||
|
* Simple shared pointer class with NO thread safety (not even the counter is thread-safe)
|
||
|
*/
|
||
|
template <typename T>
|
||
|
class SmartPtr
|
||
|
{
|
||
|
//Rule 1: tracker is always NULL when ptr == NULL
|
||
|
//Rule 2: ID is only assigned in constructors
|
||
|
|
||
|
typedef std::map<unsigned long,SmartPtr<T>*> IDMap;
|
||
|
typedef std::pair<unsigned long,SmartPtr<T>*> IDPair;
|
||
|
|
||
|
T* ptr;
|
||
|
IDMap *tracker; //track pointers to same object
|
||
|
unsigned long ID;
|
||
|
static unsigned long __IDCounter;
|
||
|
|
||
|
public:
|
||
|
typedef T element_type;
|
||
|
SmartPtr(const SmartPtr& other);
|
||
|
SmartPtr<T>& operator=(const SmartPtr& other);
|
||
|
SmartPtr(T* new_ptr = NULL);
|
||
|
T& operator*();
|
||
|
const T& operator*() const;
|
||
|
~SmartPtr();
|
||
|
unsigned long use_count() const;
|
||
|
operator bool();
|
||
|
T* get();
|
||
|
const T* const get() const;
|
||
|
T* release();
|
||
|
void reset(T* new_ptr = NULL);
|
||
|
inline bool isNull();
|
||
|
template <template <typename _T, typename = std::allocator<_T> > class Container>
|
||
|
static Container<T*> GetRawPtrContainer(const Container<SmartPtr<T> >& input_container);
|
||
|
};
|
||
|
|
||
|
template <typename T>
|
||
|
unsigned long SmartPtr<T>::__IDCounter = 0;
|
||
|
|
||
|
|
||
|
template<typename T>
|
||
|
template <template <typename _T, typename = std::allocator<_T> > class Container>
|
||
|
Container<T*> SmartPtr<T>::GetRawPtrContainer(const Container<SmartPtr<T> >& input_container)
|
||
|
{
|
||
|
Container<T*> container;
|
||
|
for(typename Container<SmartPtr<T> >::const_iterator it = input_container.begin();
|
||
|
it != input_container.end();
|
||
|
it++)
|
||
|
{
|
||
|
container.push_back(it->ptr);
|
||
|
}
|
||
|
return container;
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
SmartPtr<T>::SmartPtr(const SmartPtr &other)
|
||
|
{
|
||
|
this->tracker = other.tracker;
|
||
|
this->ptr = other.ptr;
|
||
|
this->ID = __IDCounter++;
|
||
|
if(!isNull())
|
||
|
tracker->insert(IDPair(ID,this));
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
SmartPtr<T> &SmartPtr<T>::operator=(const SmartPtr &other)
|
||
|
{
|
||
|
this->tracker = other.tracker;
|
||
|
this->ptr = other.ptr;
|
||
|
this->ID = __IDCounter++;
|
||
|
if(!isNull())
|
||
|
tracker->insert(IDPair(ID,this));
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
SmartPtr<T>::SmartPtr(T *new_ptr)
|
||
|
{
|
||
|
ptr = NULL;
|
||
|
tracker = NULL;
|
||
|
ID = __IDCounter++;
|
||
|
reset(new_ptr);
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
T& SmartPtr<T>::operator*()
|
||
|
{
|
||
|
if(this->get() != NULL)
|
||
|
return *this->get();
|
||
|
else
|
||
|
throw std::runtime_error("Null pointer exception. Tried to dereference a NULL in SmartPtr");
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
const T& SmartPtr<T>::operator*() const
|
||
|
{
|
||
|
if(this->get() != NULL)
|
||
|
return *this->get();
|
||
|
else
|
||
|
throw std::runtime_error("Null pointer exception. Tried to dereference a NULL in SmartPtr");
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
SmartPtr<T>::~SmartPtr()
|
||
|
{
|
||
|
reset();
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
unsigned long SmartPtr<T>::use_count() const
|
||
|
{
|
||
|
if(isNull())
|
||
|
return 0;
|
||
|
else
|
||
|
return tracker->size();
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
SmartPtr<T>::operator bool()
|
||
|
{
|
||
|
return !isNull();
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
T *SmartPtr<T>::get()
|
||
|
{
|
||
|
return ptr;
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
const T * const SmartPtr<T>::get() const
|
||
|
{
|
||
|
return ptr;
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
T *SmartPtr<T>::release()
|
||
|
{
|
||
|
T* ret_ptr = ptr;
|
||
|
if(!isNull()) {
|
||
|
IDMap* trackerHolder = tracker;
|
||
|
for(typename IDMap::iterator it = trackerHolder->begin(); it != trackerHolder->end(); it++)
|
||
|
{
|
||
|
it->second->ptr = NULL;
|
||
|
it->second->tracker = NULL;
|
||
|
}
|
||
|
delete trackerHolder;
|
||
|
}
|
||
|
return ret_ptr;
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
void SmartPtr<T>::reset(T *new_ptr) {
|
||
|
if(!isNull())
|
||
|
{
|
||
|
//ptr and tracker are not NULL, guaranteed
|
||
|
if(tracker->size() == 1) //this is the last reference
|
||
|
{
|
||
|
delete ptr;
|
||
|
ptr = NULL;
|
||
|
delete tracker;
|
||
|
tracker = NULL;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
tracker->erase(ID);
|
||
|
if(new_ptr != NULL)
|
||
|
{
|
||
|
tracker = new IDMap;
|
||
|
tracker->insert(IDPair(ID,this));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
tracker = NULL;
|
||
|
ptr = NULL;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else //if this is NULL
|
||
|
{
|
||
|
if(new_ptr != NULL)
|
||
|
{
|
||
|
if(tracker == NULL) {
|
||
|
tracker = new IDMap;
|
||
|
tracker->insert(IDPair(ID,this));
|
||
|
ptr = new_ptr;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
bool SmartPtr<T>::isNull()
|
||
|
{
|
||
|
return (ptr == NULL);
|
||
|
}
|
||
|
|
||
|
#endif // SMARTPTR_H
|