mirror of
https://foundry.openuru.org/gitblit/r/CWE-ou-minkata.git
synced 2025-07-18 11:19:10 +00:00
Unify leak checkers
This commit is contained in:
@ -56,12 +56,18 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
|||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include "plFormat.h"
|
#include "plFormat.h"
|
||||||
#include "hsWindows.h"
|
|
||||||
|
|
||||||
template <class _RefType>
|
// hsDebugMessage can get overridden to dump to a file :(
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
# include "hsWindows.h"
|
||||||
|
# define _LeakDebug(message) OutputDebugString(message)
|
||||||
|
#else
|
||||||
|
# define _LeakDebug(message) fputs(message, stderr)
|
||||||
|
#endif
|
||||||
|
|
||||||
struct _RefCountLeakCheck
|
struct _RefCountLeakCheck
|
||||||
{
|
{
|
||||||
std::unordered_set<_RefType *> m_refs;
|
std::unordered_set<_hsRefCnt_Base *> m_refs;
|
||||||
unsigned m_added, m_removed;
|
unsigned m_added, m_removed;
|
||||||
std::mutex m_mutex;
|
std::mutex m_mutex;
|
||||||
|
|
||||||
@ -69,47 +75,53 @@ struct _RefCountLeakCheck
|
|||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(m_mutex);
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||||||
|
|
||||||
OutputDebugString(plFormat("Refs tracked: {} created, {} destroyed\n",
|
_LeakDebug(plFormat("Refs tracked: {} created, {} destroyed\n",
|
||||||
m_added, m_removed).c_str());
|
m_added, m_removed).c_str());
|
||||||
if (m_refs.empty())
|
if (m_refs.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
OutputDebugString(plFormat(" {} objects leaked...\n", m_refs.size()).c_str());
|
_LeakDebug(plFormat(" {} objects leaked...\n", m_refs.size()).c_str());
|
||||||
for (_RefType *ref : m_refs) {
|
for (_hsRefCnt_Base *ref : m_refs) {
|
||||||
OutputDebugString(plFormat(" 0x{_08x} {}: {} refs remain\n",
|
_LeakDebug(plFormat(" 0x{_08x} {}: {} refs remain\n",
|
||||||
(uintptr_t)ref, typeid(*ref).name(), ref->RefCnt()).c_str());
|
(uintptr_t)ref, typeid(*ref).name(), ref->RefCnt()).c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static _RefCountLeakCheck<_RefType> *_instance()
|
static _RefCountLeakCheck *_instance()
|
||||||
{
|
{
|
||||||
static _RefCountLeakCheck<_RefType> s_instance;
|
static _RefCountLeakCheck s_instance;
|
||||||
return &s_instance;
|
return &s_instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void add(_RefType *node)
|
static void add(_hsRefCnt_Base *ref)
|
||||||
{
|
{
|
||||||
_RefCountLeakCheck<_RefType> *p = _instance();
|
_RefCountLeakCheck *this_p = _instance();
|
||||||
std::lock_guard<std::mutex> lock(p->m_mutex);
|
std::lock_guard<std::mutex> lock(this_p->m_mutex);
|
||||||
++p->m_added;
|
++this_p->m_added;
|
||||||
p->m_refs.insert(node);
|
this_p->m_refs.insert(ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void del(_RefType *node)
|
static void del(_hsRefCnt_Base *ref)
|
||||||
{
|
{
|
||||||
_RefCountLeakCheck<_RefType> *p = _instance();
|
_RefCountLeakCheck *this_p = _instance();
|
||||||
std::lock_guard<std::mutex> lock(p->m_mutex);
|
std::lock_guard<std::mutex> lock(this_p->m_mutex);
|
||||||
++p->m_removed;
|
++this_p->m_removed;
|
||||||
p->m_refs.erase(node);
|
this_p->m_refs.erase(ref);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
hsRefCnt::hsRefCnt(int initRefs)
|
_hsRefCnt_Base::_hsRefCnt_Base(int)
|
||||||
: fRefCnt(initRefs)
|
|
||||||
{
|
{
|
||||||
#if (REFCOUNT_DEBUGGING == REFCOUNT_DBG_LEAKS) || (REFCOUNT_DEBUGGING == REFCOUNT_DBG_ALL)
|
#if (REFCOUNT_DEBUGGING == REFCOUNT_DBG_LEAKS) || (REFCOUNT_DEBUGGING == REFCOUNT_DBG_ALL)
|
||||||
_RefCountLeakCheck<hsRefCnt>::add(this);
|
_RefCountLeakCheck::add(this);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
_hsRefCnt_Base::~_hsRefCnt_Base()
|
||||||
|
{
|
||||||
|
#if (REFCOUNT_DEBUGGING == REFCOUNT_DBG_LEAKS) || (REFCOUNT_DEBUGGING == REFCOUNT_DBG_ALL)
|
||||||
|
_RefCountLeakCheck::del(this);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,10 +130,6 @@ 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()
|
||||||
@ -136,23 +144,11 @@ 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)
|
||||||
|
@ -44,12 +44,22 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
|||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
|
||||||
class hsRefCnt {
|
// For easier debugging
|
||||||
|
class _hsRefCnt_Base
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
_hsRefCnt_Base(int initRefs = 1);
|
||||||
|
virtual ~_hsRefCnt_Base();
|
||||||
|
|
||||||
|
virtual int RefCnt() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class hsRefCnt : public _hsRefCnt_Base {
|
||||||
private:
|
private:
|
||||||
int fRefCnt;
|
int fRefCnt;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
hsRefCnt(int initRefs = 1);
|
hsRefCnt(int initRefs = 1) : fRefCnt(initRefs) { }
|
||||||
virtual ~hsRefCnt();
|
virtual ~hsRefCnt();
|
||||||
|
|
||||||
inline int RefCnt() const { return fRefCnt; }
|
inline int RefCnt() const { return fRefCnt; }
|
||||||
@ -70,13 +80,13 @@ public:
|
|||||||
|
|
||||||
// Thread-safe version. TODO: Evaluate whether this is fast enough to
|
// Thread-safe version. TODO: Evaluate whether this is fast enough to
|
||||||
// merge with hsRefCnt above.
|
// merge with hsRefCnt above.
|
||||||
class hsAtomicRefCnt
|
class hsAtomicRefCnt : public _hsRefCnt_Base
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
std::atomic<int> fRefCnt;
|
std::atomic<int> fRefCnt;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
hsAtomicRefCnt(int initRefs = 1);
|
hsAtomicRefCnt(int initRefs = 1) : fRefCnt(initRefs) { }
|
||||||
virtual ~hsAtomicRefCnt();
|
virtual ~hsAtomicRefCnt();
|
||||||
|
|
||||||
inline int RefCnt() const { return fRefCnt; }
|
inline int RefCnt() const { return fRefCnt; }
|
||||||
|
Reference in New Issue
Block a user