#pragma once #include "base/assert.hpp" #include "base/mutex.hpp" #include "std/map.hpp" #include "std/typeinfo.hpp" namespace dp { class PointerTracker { public: ~PointerTracker(); template void Ref(T * p, bool needDestroyCheck) { threads::MutexGuard g(m_mutex); if (p == NULL) return; map_t::iterator it = m_countMap.find(p); if (it == m_countMap.end()) { m_countMap.insert(make_pair((void *)p, make_pair(1, typeid(p).name()))); if (needDestroyCheck) m_alivePointers.insert(p); } else it->second.first++; } void Deref(void * p); void Destroy(void * p); private: typedef map > map_t; map_t m_countMap; typedef set alive_pointers_t; alive_pointers_t m_alivePointers; threads::Mutex m_mutex; }; #define DISABLE_DEBUG_PRT_TRACKING #if defined(DEBUG) && !defined(DISABLE_DEBUG_PRT_TRACKING) #define CHECK_POINTERS #endif #if defined(CHECK_POINTERS) extern PointerTracker g_tracker; #define REF_POINTER(p, c) g_tracker.Ref(p, c) #define DEREF_POINTER(p) g_tracker.Deref(p) #define DESTROY_POINTER(p) g_tracker.Destroy(p) #define DECLARE_CHECK bool m_checkOnDestroy #define DECLARE_CHECK_GET bool IsCheckOnDestroy() const { return m_checkOnDestroy; } #define DECLARE_CHECK_SET void SetCheckOnDestroy(bool doCheck) { m_checkOnDestroy = doCheck; } #define SET_CHECK_FLAG(x) SetCheckOnDestroy(x) #define GET_CHECK_FLAG(x) (x).IsCheckOnDestroy() #define ASSERT_CHECK_FLAG(x) ASSERT(GET_CHECK_FLAG(x), ()) #else #define REF_POINTER(p, c) #define DEREF_POINTER(p) #define DESTROY_POINTER(p) #define DECLARE_CHECK #define DECLARE_CHECK_GET #define DECLARE_CHECK_SET #define SET_CHECK_FLAG(x) #define GET_CHECK_FLAG(x) false #define ASSERT_CHECK_FLAG(x) #endif template class DrapePointer { public: DrapePointer() : m_p(NULL) { SET_CHECK_FLAG(true); } bool operator==(DrapePointer const & other) const { return m_p == other.m_p; } protected: DrapePointer(T * p, bool needDestroyedCheck = true) : m_p(p) { SET_CHECK_FLAG(needDestroyedCheck); REF_POINTER(m_p, GET_CHECK_FLAG(*this)); } DrapePointer(DrapePointer const & other) : m_p(NULL) { SET_CHECK_FLAG(GET_CHECK_FLAG(other)); Reset(other.GetNonConstRaw()); } DrapePointer & operator=(DrapePointer const & other) { SET_CHECK_FLAG(GET_CHECK_FLAG(other)); Reset(other.GetNonConstRaw()); return *this; } void Destroy() { DESTROY_POINTER(m_p); delete m_p; DEREF_POINTER(m_p); m_p = NULL; } void Reset(T * p) { ResetImpl(p); } T * GetRaw() { return m_p; } T const * GetRaw() const { return m_p; } T * GetNonConstRaw() const { return m_p; } DECLARE_CHECK_GET; DECLARE_CHECK_SET; // Need to be const for copy constructor and assigment operator of TransfromPointer void SetToNull() const { ResetImpl(NULL); } private: void ResetImpl(T * p) const { DEREF_POINTER(m_p); m_p = p; REF_POINTER(m_p, GET_CHECK_FLAG(*this)); } private: // Mutable for Move method mutable T * m_p; DECLARE_CHECK; }; template class MasterPointer; template class TransferPointer : public DrapePointer { typedef DrapePointer base_t; public: TransferPointer(TransferPointer const & other) : base_t(other) { ASSERT_CHECK_FLAG(other); other.SetToNull(); } TransferPointer & operator=(TransferPointer const & other) { ASSERT_CHECK_FLAG(other); base_t::operator =(other); other.SetToNull(); return *this; } ~TransferPointer() { ASSERT(base_t::GetRaw() == NULL, ()); Destroy(); } void Destroy() { base_t::Destroy(); } // IsNull need for test bool IsNull() { return base_t::GetRaw() == NULL; } private: friend class MasterPointer; TransferPointer() {} explicit TransferPointer(T * p) : base_t(p) {} }; template class RefPointer; template RefPointer MakeStackRefPointer(T * p); template class RefPointer : public DrapePointer { typedef DrapePointer base_t; public: RefPointer() : base_t() {} ~RefPointer() { base_t::Reset(NULL); } template RefPointer(RefPointer const & p) : base_t(p.GetNonConstRaw(), GET_CHECK_FLAG(p)) {} bool IsContentLess(RefPointer const & other) const { return *GetRaw() < *other.GetRaw(); } bool IsNull() const { return base_t::GetRaw() == NULL; } T * operator->() { return base_t::GetRaw(); } T const * operator->() const { return base_t::GetRaw(); } T * GetRaw() { return base_t::GetRaw(); } T const * GetRaw() const { return base_t::GetRaw(); } private: template friend class RefPointer; friend class MasterPointer; friend RefPointer MakeStackRefPointer(T *); explicit RefPointer(T * p, bool needDestroyedCheck = true) : base_t(p, needDestroyedCheck) {} }; template RefPointer MakeStackRefPointer(T * p) { return RefPointer(p, false); } template class MasterPointer : public DrapePointer { typedef DrapePointer base_t; public: MasterPointer() : base_t() {} explicit MasterPointer(T * p) : base_t(p) {} explicit MasterPointer(TransferPointer & transferPointer) { Reset(transferPointer.GetRaw()); transferPointer.Reset(NULL); } ~MasterPointer() { base_t::Reset(NULL); } RefPointer GetRefPointer() const { return RefPointer(base_t::GetNonConstRaw()); } TransferPointer Move() { TransferPointer result(GetRaw()); base_t::Reset(NULL); return result; } void Destroy() { Reset(NULL); } void Reset(T * p) { base_t::Destroy(); base_t::Reset(p); } bool IsNull() const { return base_t::GetRaw() == NULL; } T * operator->() { return base_t::GetRaw(); } T const * operator->() const { return base_t::GetRaw(); } T * GetRaw() { return base_t::GetRaw(); } T const * GetRaw() const { return base_t::GetRaw(); } }; template TransferPointer MovePointer(T * p) { return MasterPointer(p).Move(); } template T * NonConstGetter(dp::MasterPointer & p) { return p.GetRaw(); } struct MasterPointerDeleter { template void operator() (pair > & value) { Destroy(value.second); } template void operator() (MasterPointer & value) { Destroy(value); } private: template void Destroy(MasterPointer & value) { value.Destroy(); } }; } // namespace dp