181 lines
3.8 KiB
C++
181 lines
3.8 KiB
C++
#include <iostream>
|
|
#include <map>
|
|
#include <vector>
|
|
|
|
/**
|
|
* Simple shared pointer class with NO thread safety (not even the counter is thread-safe)
|
|
*/
|
|
template <typename T>
|
|
class SharedPtr
|
|
{
|
|
//Rule 1: tracker is always NULL when ptr == NULL
|
|
//Rule 2: ID is only assigned in constructors
|
|
|
|
typedef std::map<unsigned long,SharedPtr<T>*> IDMap;
|
|
typedef std::pair<unsigned long,SharedPtr<T>*> IDPair;
|
|
|
|
T* ptr;
|
|
IDMap *tracker; //track pointers to same object
|
|
unsigned long ID;
|
|
static unsigned long __IDCounter;
|
|
|
|
public:
|
|
typedef T element_type;
|
|
SharedPtr(const SharedPtr& other);
|
|
SharedPtr<T>& operator=(const SharedPtr& other);
|
|
SharedPtr(T* new_ptr = NULL);
|
|
~SharedPtr();
|
|
unsigned long use_count() const;
|
|
operator bool();
|
|
T* const get();
|
|
T* release();
|
|
void reset(T* new_ptr = NULL);
|
|
inline bool isNull();
|
|
};
|
|
|
|
template <typename T>
|
|
unsigned long SharedPtr<T>::__IDCounter = 0;
|
|
|
|
template<typename T>
|
|
SharedPtr<T>::SharedPtr(const SharedPtr &other)
|
|
{
|
|
this->tracker = other.tracker;
|
|
this->ptr = other.ptr;
|
|
this->ID = __IDCounter++;
|
|
if(!isNull())
|
|
tracker->insert(IDPair(ID,this));
|
|
}
|
|
|
|
template<typename T>
|
|
SharedPtr<T> &SharedPtr<T>::operator=(const SharedPtr &other)
|
|
{
|
|
this->tracker = other.tracker;
|
|
this->ptr = other.ptr;
|
|
this->ID = __IDCounter++;
|
|
if(!isNull())
|
|
tracker->insert(IDPair(ID,this));
|
|
return *this;
|
|
}
|
|
|
|
template<typename T>
|
|
SharedPtr<T>::SharedPtr(T *new_ptr)
|
|
{
|
|
ptr = NULL;
|
|
tracker = NULL;
|
|
ID = __IDCounter++;
|
|
reset(new_ptr);
|
|
}
|
|
|
|
template<typename T>
|
|
SharedPtr<T>::~SharedPtr()
|
|
{
|
|
reset();
|
|
}
|
|
|
|
template<typename T>
|
|
unsigned long SharedPtr<T>::use_count() const
|
|
{
|
|
if(isNull())
|
|
return 0;
|
|
else
|
|
return tracker->size();
|
|
}
|
|
|
|
template<typename T>
|
|
SharedPtr<T>::operator bool()
|
|
{
|
|
return !isNull();
|
|
}
|
|
|
|
template<typename T>
|
|
T * const SharedPtr<T>::get()
|
|
{
|
|
return ptr;
|
|
}
|
|
|
|
template<typename T>
|
|
T *SharedPtr<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 SharedPtr<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 SharedPtr<T>::isNull()
|
|
{
|
|
return (ptr == NULL);
|
|
}
|
|
|
|
int main()
|
|
{
|
|
SharedPtr<int> s;
|
|
SharedPtr<int> x = SharedPtr<int>(new int(5));
|
|
std::vector<SharedPtr<int> > myvec;
|
|
for(long i = 0; i < 100; i++)
|
|
{
|
|
myvec.push_back(x);
|
|
}
|
|
SharedPtr<int> y(x);
|
|
s = x;
|
|
std::cout<<*x.get()<<std::endl;
|
|
std::cout<<*y.get()<<std::endl;
|
|
y.reset(NULL);
|
|
|
|
SharedPtr<int> R = SharedPtr<int>(new int(15));
|
|
std::cout<<*R.get()<<std::endl;
|
|
delete R.release();
|
|
SharedPtr<int> T = SharedPtr<int>(new int(25));
|
|
SharedPtr<int> U(T);
|
|
std::cout<<*U.get()<<std::endl;
|
|
return 0;
|
|
}
|