SharedPtr-cpp03/main.cpp
2017-03-31 14:56:22 +02:00

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;
}