Browse Source

Add a RefCnt leak debug tracker

Michael Hansen 11 years ago
parent
commit
7f4701cc1a
  1. 91
      Sources/Plasma/CoreLib/hsRefCnt.cpp
  2. 4
      Sources/Plasma/CoreLib/hsRefCnt.h

91
Sources/Plasma/CoreLib/hsRefCnt.cpp

@ -46,11 +46,76 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "hsExceptions.h" #include "hsExceptions.h"
#include "hsRefCnt.h" #include "hsRefCnt.h"
#define REFCOUNT_DBG_NONE 0
#define REFCOUNT_DBG_REFS 1
#define REFCOUNT_DBG_LEAKS 2
#define REFCOUNT_DBG_ALL 3
#define REFCOUNT_DEBUGGING REFCOUNT_DBG_NONE
#if (REFCOUNT_DEBUGGING == REFCOUNT_DBG_LEAKS) || (REFCOUNT_DEBUGGING == REFCOUNT_DBG_ALL)
#include <unordered_set>
#include "plFormat.h"
#include "hsWindows.h"
template <class _RefType>
struct _RefCountLeakCheck
{
std::unordered_set<_RefType *> m_refs;
unsigned s_added, s_removed;
~_RefCountLeakCheck()
{
OutputDebugString(plFormat("Refs tracked: {} created, {} destroyed\n",
s_added, s_removed).c_str());
if (m_refs.empty())
return;
OutputDebugString(plFormat(" {} objects leaked...\n", m_refs.size()).c_str());
for (_RefType *ref : m_refs) {
OutputDebugString(plFormat(" 0x{_08x} {}: {} refs remain\n",
(uintptr_t)ref, typeid(*ref).name(), ref->RefCnt()).c_str());
}
}
static _RefCountLeakCheck<_RefType> *_instance()
{
static _RefCountLeakCheck<_RefType> s_instance;
return &s_instance;
}
static void add(_RefType *node)
{
_RefCountLeakCheck<_RefType> *p = _instance();
++p->s_added;
p->m_refs.insert(node);
}
static void del(_RefType *node)
{
_RefCountLeakCheck<_RefType> *p = _instance();
++p->s_removed;
p->m_refs.erase(node);
}
};
#endif
hsRefCnt::hsRefCnt(int initRefs)
: fRefCnt(initRefs)
{
#if (REFCOUNT_DEBUGGING == REFCOUNT_DBG_LEAKS) || (REFCOUNT_DEBUGGING == REFCOUNT_DBG_ALL)
_RefCountLeakCheck<hsRefCnt>::add(this);
#endif
}
hsRefCnt::~hsRefCnt() hsRefCnt::~hsRefCnt()
{ {
#ifdef HS_DEBUGGING #ifdef HS_DEBUGGING
hsThrowIfFalse(fRefCnt == 1); hsThrowIfFalse(fRefCnt == 1);
#endif #endif
#if (REFCOUNT_DEBUGGING == REFCOUNT_DBG_LEAKS) || (REFCOUNT_DEBUGGING == REFCOUNT_DBG_ALL)
_RefCountLeakCheck<hsRefCnt>::del(this);
#endif
} }
void hsRefCnt::UnRef() void hsRefCnt::UnRef()
@ -65,11 +130,23 @@ void hsRefCnt::UnRef()
--fRefCnt; --fRefCnt;
} }
hsAtomicRefCnt::hsAtomicRefCnt(int initRefs)
: fRefCnt(initRefs)
{
#if (REFCOUNT_DEBUGGING == REFCOUNT_DBG_LEAKS) || (REFCOUNT_DEBUGGING == REFCOUNT_DBG_ALL)
_RefCountLeakCheck<hsAtomicRefCnt>::add(this);
#endif
}
hsAtomicRefCnt::~hsAtomicRefCnt() hsAtomicRefCnt::~hsAtomicRefCnt()
{ {
#ifdef HS_DEBUGGING #ifdef HS_DEBUGGING
hsThrowIfFalse(fRefCnt == 1); hsThrowIfFalse(fRefCnt == 1);
#endif #endif
#if (REFCOUNT_DEBUGGING == REFCOUNT_DBG_LEAKS) || (REFCOUNT_DEBUGGING == REFCOUNT_DBG_ALL)
_RefCountLeakCheck<hsAtomicRefCnt>::del(this);
#endif
} }
void hsAtomicRefCnt::UnRef(const char* tag) void hsAtomicRefCnt::UnRef(const char* tag)
@ -78,11 +155,11 @@ void hsAtomicRefCnt::UnRef(const char* tag)
hsThrowIfFalse(fRefCnt >= 1); hsThrowIfFalse(fRefCnt >= 1);
#endif #endif
#ifdef REFCOUNT_DEBUGGING #if (REFCOUNT_DEBUGGING == REFCOUNT_DBG_REFS) || (REFCOUNT_DEBUGGING == REFCOUNT_DBG_ALL)
if (tag) if (tag)
DEBUG_MSG("Dec %p %s: %u", this, tag, prev - 1); DEBUG_MSG("Dec %p %s: %u", this, tag, fRefCnt - 1);
else else
DEBUG_MSG("Dec %p: %u", this, prev - 1); DEBUG_MSG("Dec %p: %u", this, fRefCnt - 1);
#endif #endif
if (fRefCnt == 1) // don't decrement if we call delete if (fRefCnt == 1) // don't decrement if we call delete
@ -93,11 +170,11 @@ void hsAtomicRefCnt::UnRef(const char* tag)
void hsAtomicRefCnt::Ref(const char* tag) void hsAtomicRefCnt::Ref(const char* tag)
{ {
#ifdef REFCOUNT_DEBUGGING #if (REFCOUNT_DEBUGGING == REFCOUNT_DBG_REFS) || (REFCOUNT_DEBUGGING == REFCOUNT_DBG_ALL)
if (tag) if (tag)
DEBUG_MSG("Inc %p %s: %u", this, tag, prev + 1); DEBUG_MSG("Inc %p %s: %u", this, tag, fRefCnt + 1);
else else
DEBUG_MSG("Inc %p: %u", this, prev + 1); DEBUG_MSG("Inc %p: %u", this, fRefCnt + 1);
#endif #endif
++fRefCnt; ++fRefCnt;
@ -105,7 +182,7 @@ void hsAtomicRefCnt::Ref(const char* tag)
void hsAtomicRefCnt::TransferRef(const char* oldTag, const char* newTag) void hsAtomicRefCnt::TransferRef(const char* oldTag, const char* newTag)
{ {
#ifdef REFCOUNT_DEBUGGING #if (REFCOUNT_DEBUGGING == REFCOUNT_DBG_REFS) || (REFCOUNT_DEBUGGING == REFCOUNT_DBG_ALL)
DEBUG_MSG("Inc %p %s: (xfer)", this, newTag); DEBUG_MSG("Inc %p %s: (xfer)", this, newTag);
DEBUG_MSG("Dec %p %s: (xfer)", this, oldTag); DEBUG_MSG("Dec %p %s: (xfer)", this, oldTag);
#endif #endif

4
Sources/Plasma/CoreLib/hsRefCnt.h

@ -49,7 +49,7 @@ private:
int fRefCnt; int fRefCnt;
public: public:
hsRefCnt(int initRefs = 1) : fRefCnt(initRefs) {} hsRefCnt(int initRefs = 1);
virtual ~hsRefCnt(); virtual ~hsRefCnt();
inline int RefCnt() const { return fRefCnt; } inline int RefCnt() const { return fRefCnt; }
@ -76,7 +76,7 @@ private:
std::atomic<int> fRefCnt; std::atomic<int> fRefCnt;
public: public:
hsAtomicRefCnt(int initRefs = 1) : fRefCnt(initRefs) { } hsAtomicRefCnt(int initRefs = 1);
virtual ~hsAtomicRefCnt(); virtual ~hsAtomicRefCnt();
inline int RefCnt() const { return fRefCnt; } inline int RefCnt() const { return fRefCnt; }

Loading…
Cancel
Save