mirror of
https://foundry.openuru.org/gitblit/r/CWE-ou-minkata.git
synced 2025-07-18 11:19:10 +00:00
Add a RefCnt leak debug tracker
This commit is contained in:
@ -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
|
||||||
|
@ -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; }
|
||||||
|
Reference in New Issue
Block a user