Add SmartPtr.h
This commit is contained in:
parent
9999f998d2
commit
147337c53f
205
SmartPtr.h
Normal file
205
SmartPtr.h
Normal file
@ -0,0 +1,205 @@
|
||||
#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
|
Loading…
Reference in New Issue
Block a user