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...
1 parent 263eef1 commit 1b8f1f32c92b167e50863a73545207f80cc7c328 @daniel-kristjansson daniel-kristjansson committed Jun 17, 2012
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.