Code:
#ifndef MAD_SHARED_PTR_175451_H
#define MAD_SHARED_PTR_175451_H
#include <boost/cstdint.hpp>
#include <memory>
#include <assert.h>
#if defined(THREAD_SAFE) || defined(THREAD_STORAGE)
// Requirements: Windows Vista
#undef _WIN32_WINNT
#undef WINVER
#define _WIN32_WINNT 0x600
#define WINVER 0x600
#include <Windows.h>
#endif
const int nullptr = NULL;
#pragma warning(push)
#pragma warning(disable: 4355)
template<typename T> T* mad_ptr_clone(const T* pOld) { return smad_ptr_int<T, boost::is_polymorphic<T>::value>::Clone(pOld); }
template<typename T, bool Polymorphic> struct smad_ptr_int
{
static T* Clone(const T* pOld) { return pOld->Clone(); } // IsPolymorphic = yes
};
template<typename T> struct smad_ptr_int<T, false>
{
static T* Clone(const T* pOld) { return new T(*pOld); } // IsPolymorphic = no
};
template<int N> struct ptr_bits { /*typedef current_amount_of_bits_not_supported rf_type;*/ };
template<> struct ptr_bits<32> { typedef boost::uint32_t rf_type; };
template<> struct ptr_bits<64> { typedef boost::uint64_t rf_type; };
#ifdef THREAD_SAFE
template<int Bits> class ptr_thread_safe { };
template<> class ptr_thread_safe<32>
{
public:
static void Increment(void* p) { InterlockedIncrement((LONG*)p); }
static void Decrement(void* p) { InterlockedDecrement((LONG*)p); }
};
template<> class ptr_thread_safe<64>
{
public:
static void Increment(void* p) { InterlockedIncrement64((LONGLONG*)p); }
static void Decrement(void* p) { InterlockedDecrement64((LONGLONG*)p); }
};
#endif
template<int Bits> class ptr_thread_dangerous
{
public:
template<typename T> static void Increment(T* p) { (*p)++; }
template<typename T> static void Decrement(T* p) { (*p)--; }
};
template<typename T, template<int> class thread_safety = ptr_thread_dangerous, int Bits = 32>
class mad_shared_ptr
{
protected:
typedef void (mad_shared_ptr::* bool_type)() const;
template<typename T, int Bits> struct sptr
{
template<typename T> class deleter_base { public: virtual void destroy(T* p) = 0; };
template<typename T, typename deleter_t> class deleter: public deleter_base<T>
{
public:
deleter(deleter_t delete_fnc): m_delete_fnc(delete_fnc) { }
virtual void destroy(T* p) { m_delete_fnc(p); }
private:
deleter_t m_delete_fnc;
};
sptr(): p(nullptr), RefCount(0), pDeleter(nullptr) { }
T* p;
typename ptr_bits<Bits>::rf_type RefCount;
deleter_base<T>* pDeleter;
};
typedef sptr<T, Bits> ptr_t;
public:
mad_shared_ptr(): m_ptr(nullptr) { }
template<typename Other> mad_shared_ptr(Other* p): m_ptr(nullptr) { *this = p; }
template<typename Other, typename Deleter> mad_shared_ptr(Other* p, Deleter delete_fnc): m_ptr(nullptr) { ConstructWithDeleter(p, delete_fnc); }
mad_shared_ptr(const mad_shared_ptr& rhs): m_ptr(nullptr) { *this = rhs; }
template<typename Other> mad_shared_ptr(const mad_shared_ptr<Other>& rhs): m_ptr(nullptr) { *this = rhs; }
protected:
mad_shared_ptr(ptr_t* ptr): m_ptr(ptr) { }
template<typename Other> mad_shared_ptr(Other* p, ptr_t* ptr): m_ptr(ptr) { *this = p; }
template<typename Other, typename Deleter> mad_shared_ptr(Other* p, Deleter delete_fnc, ptr_t* ptr): m_ptr(ptr) { ConstructWithDeleter(p, delete_fnc); }
template<typename Other, typename Deleter> void ConstructWithDeleter(Other* p, Deleter delete_fnc)
{
std::auto_ptr< ptr_t::deleter_base<T> > pDeleter( new ptr_t::deleter<T, Deleter>(delete_fnc) );
//*this = p;
if (m_ptr)
Assign(p, m_ptr, nullptr);
else
Assign(p, new ptr_t, m_ptr);
m_ptr->pDeleter = pDeleter.release();
}
public:
~mad_shared_ptr() { DecRefCount(m_ptr); }
bool empty() { return (m_ptr == nullptr || m_ptr->p == nullptr); }
bool unique() const { return (m_ptr->RefCount == 1); }
void make_unique()
{
if (unique())
return;
std::auto_ptr<ptr_t> pNewPtr(new ptr_t);
pNewPtr->p = mad_ptr_clone(m_ptr->p);
pNewPtr->RefCount = 1;
pNewPtr->pDeleter = m_ptr->pDeleter;
DecRefCount(m_ptr);
m_ptr = pNewPtr.release();
}
void release()
{
DecRefCount();
m_p = nullptr;
m_RefCount = nullptr;
m_deleter = nullptr;
}
template<typename Other> mad_shared_ptr& operator = (Other* rhs)
{
if (m_ptr && rhs == m_ptr->p)
return *this;
/*std::auto_ptr<ptr_t>*/ptr_t* pNewPtr( AllocPtr() );
Assign(rhs, pNewPtr, m_ptr);
//pNewPtr->p = rhs;
//pNewPtr->RefCount++;
//m_ptr = pNewPtr.release();
//DecRefCount(pOldPtr);
return *this;
}
template<typename Other>
void Assign(Other* rhs, ptr_t* NewPtr, ptr_t* OldPtr)
{
std::auto_ptr<ptr_t> pNewPtr(NewPtr);
pNewPtr->p = rhs;
pNewPtr->RefCount++;
m_ptr = pNewPtr.release();
DecRefCount(OldPtr);
}
mad_shared_ptr& operator = (const mad_shared_ptr& rhs)
{
return operator = <T>(rhs);
}
template<typename Other> mad_shared_ptr& operator = (const mad_shared_ptr<Other>& rhs)
{
if (rhs == *this)
return *this;
DecRefCount(m_ptr);
m_ptr = rhs.m_ptr;
IncRefCount(m_ptr);
return *this;
}
virtual T& operator * () const { assert(m_ptr); return *m_ptr->p; }
T* operator -> () const { assert(m_ptr); return m_ptr->p; }
template<typename rhs_t>
friend bool operator == (const mad_shared_ptr& lhs, const mad_shared_ptr<rhs_t>& rhs)
{
return (lhs.m_ptr == rhs.m_ptr);
}
template<typename rhs_t>
friend bool operator != (const mad_shared_ptr& lhs, const mad_shared_ptr<rhs_t>& rhs)
{
return !(lhs == rhs);
}
operator bool_type() const
{
return m_ptr && m_ptr->p ? &mad_shared_ptr::this_type_does_not_support_comparisons : nullptr;
}
protected:
void IncRefCount(sptr<T, Bits>* ptr)
{
thread_safety<Bits>::Increment(&ptr->RefCount);
}
void DecRefCount(sptr<T, Bits>*& ptr)
{
if (ptr == nullptr)
return;
thread_safety<Bits>::Decrement(&ptr->RefCount);
if (ptr->RefCount == 0)
{
if (ptr->pDeleter)
ptr->pDeleter->destroy(ptr->p);
else
delete ptr->p;
delete ptr;
ptr = nullptr;
}
}
void this_type_does_not_support_comparisons() const {}
ptr_t* AllocPtr() { return new ptr_t; }
ptr_t* m_ptr;
};
#ifdef THREAD_STORAGE
template<typename T, template<int> class thread_safety = ptr_thread_dangerous, int Bits = 32>
class mad_thread_storage_ptr: public mad_shared_ptr<T, thread_safety, Bits>
{
public:
mad_thread_storage_ptr(): mad_shared_ptr(new T, boost::bind(&mad_thread_storage_ptr::DeleteTlsStorage, this), AllocPtr()) { }
mad_thread_storage_ptr(T Value): mad_shared_ptr(new T(Value), boost::bind(&mad_thread_storage_ptr::DeleteTlsStorage, this), AllocPtr()) { }
virtual T& operator * () { return *GetTlsStorage()->p; }
protected:
#ifdef _DEBUG
#define MAD_ASSERT(x) assert(x)
#else
#define MAD_ASSERT(x) x
#endif
ptr_t* AllocPtr()
{
ptr_t* p = new ptr_t;
NewTlsStorage();
SetTlsStorage(p);
return p;
}
void NewTlsStorage() { m_StorageId = TlsAlloc(); MAD_ASSERT(m_StorageId != TLS_OUT_OF_INDEXES); }
void SetTlsStorage(ptr_t* p) { MAD_ASSERT( TlsSetValue(m_StorageId, p) ); }
void DeleteTlsStorage() { MAD_ASSERT( TlsFree(m_StorageId) ); }
ptr_t* GetTlsStorage()
{
ptr_t* p = static_cast<ptr_t*>(TlsGetValue(m_StorageId));
MAD_ASSERT(p != NULL && GetLastError() == ERROR_SUCCESS);
return p;
}
DWORD m_StorageId;
};
#endif
#pragma warning(pop)
//#define sptr mad_shared_ptr
#endif // MAD_SHARED_PTR_175451_H
It currently relies on boost. Is that okay?