Skip to content
Permalink
Browse files

Refs #10311. Use R/W lock for the leak detection.

Also exclude CommandLineArg from the leak report, these go away after the ReferenceCounter::PrintDebug() is called.
Also add extra debugging for MythImage classes, but only on linux since it can adds a cross lib dependency with OSX doesn't like.
Also use static cast for MythImage to avoid linking problems.
  • Loading branch information
daniel-kristjansson committed Jun 17, 2012
1 parent 263eef1 commit 1b8f1f32c92b167e50863a73545207f80cc7c328
Showing with 43 additions and 25 deletions.
  1. +43 −25 mythtv/libs/libmythbase/referencecounter.cpp
@@ -7,38 +7,63 @@

#ifdef EXTRA_DEBUG
// Uncomment this to see missing DecrRefs()
//#define LEAK_DEBUG
#define LEAK_DEBUG
// Uncoment this to see extra DecrRefs(), no memory will ever be freed..
//#define NO_DELETE_DEBUG
#endif

#ifdef LEAK_DEBUG
#include <QMutex>
#include <QReadWriteLock>
#include <QMap>
#include <cassert>
#undef NDEBUG
static QMutex leakLock;
#include "../libmythui/mythimage.h"
static QReadWriteLock leakLock;
struct LeakInfo
{
LeakInfo() : refCount(0) {}
LeakInfo(const QString &n) : name(n), refCount(1) {}
QString name;
uint refCount;
QAtomicInt refCount;
};
static QMap<ReferenceCounter*,LeakInfo> leakMap;
void ReferenceCounter::PrintDebug(void)
{
QMutexLocker locker(&leakLock);
LOG(VB_REFCOUNT, LOG_INFO, QString("Leaked %1 reference counted objects")
.arg(leakMap.size()));
QReadLocker locker(&leakLock);

uint cnt = 0;
QMap<ReferenceCounter*,LeakInfo>::iterator it = leakMap.begin();
for (; it != leakMap.end(); ++it)
cnt += (*it).name.startsWith("CommandLineArg") ? 0 : 1;

LOG((cnt) ? VB_GENERAL : VB_REFCOUNT, LOG_INFO,
QString("Leaked %1 reference counted objects").arg(cnt));

for (it = leakMap.begin(); it != leakMap.end(); ++it)
{
if ((*it).name.startsWith("CommandLineArg"))
continue;
LOG(VB_REFCOUNT, LOG_INFO,
QString(" Leaked %1(0x%2) reference count %3")
.arg((*it).name)
.arg(reinterpret_cast<intptr_t>(it.key()),0,16)
.arg((*it).refCount));
/// This part will not work on some non-Linux machines..
#if defined(__linux__) || defined(__LINUX__)
MythImage *img = NULL;
if ((*it).name.startsWith("MythImage") ||
(*it).name.startsWith("MythQtImage"))
{
img = reinterpret_cast<MythImage*>(it.key());
}
if (img)
{
LOG(VB_REFCOUNT, LOG_INFO,
QString(" Image id %1 cache size %2 file '%3'")
.arg(img->GetID())
.arg(img->GetCacheSize())
.arg(img->GetFileName()));
}
#endif
///
}
}
#else
@@ -53,7 +78,7 @@ ReferenceCounter::ReferenceCounter(const QString &debugName) :
{
(void) debugName;
#ifdef LEAK_DEBUG
QMutexLocker locker(&leakLock);
QWriteLocker locker(&leakLock);
leakMap[this] = LeakInfo(debugName);
#endif
}
@@ -66,19 +91,13 @@ ReferenceCounter::~ReferenceCounter(void)
"Object deleted with non-zero reference count!");
}
#ifdef LEAK_DEBUG
QMutexLocker locker(&leakLock);
QMap<ReferenceCounter*,LeakInfo>::iterator it = leakMap.find(this);
assert(it != leakMap.end());
leakMap.erase(it);
QWriteLocker locker(&leakLock);
leakMap.erase(leakMap.find(this));
#endif
}

int ReferenceCounter::IncrRef(void)
{
#ifdef LEAK_DEBUG
QMutexLocker locker(&leakLock);
#endif

int val = m_referenceCount.fetchAndAddRelease(1) + 1;

#ifdef EXTRA_DEBUG
@@ -90,23 +109,22 @@ int ReferenceCounter::IncrRef(void)
#endif

#ifdef LEAK_DEBUG
leakMap[this].refCount = val;
QReadLocker locker(&leakLock);
leakMap[this].refCount.fetchAndAddOrdered(1);
#endif

return val;
}

int ReferenceCounter::DecrRef(void)
{
#ifdef LEAK_DEBUG
QMutexLocker locker(&leakLock);
#endif

int val = m_referenceCount.fetchAndAddRelaxed(-1) - 1;

#ifdef LEAK_DEBUG
leakMap[this].refCount = val;
locker.unlock();
{
QReadLocker locker(&leakLock);
leakMap[this].refCount.fetchAndAddOrdered(-1);
}
#endif

#ifdef EXTRA_DEBUG

0 comments on commit 1b8f1f3

Please sign in to comment.
You can’t perform that action at this time.