refs #467 Refactored CLogPatternHandler garbage collection by hooking into QObject::disconnectNotify.

This commit is contained in:
Mathew Sutcliffe
2015-09-17 21:57:58 +01:00
parent eb6a638099
commit 6d5e3b5897
2 changed files with 53 additions and 16 deletions

View File

@@ -118,8 +118,6 @@ namespace BlackMisc
void CLogHandler::logMessage(const CStatusMessage &statusMessage) void CLogHandler::logMessage(const CStatusMessage &statusMessage)
{ {
collectGarbage();
auto handlers = handlersForMessage(statusMessage); auto handlers = handlersForMessage(statusMessage);
if (isFallThroughEnabled(handlers)) if (isFallThroughEnabled(handlers))
@@ -138,14 +136,38 @@ namespace BlackMisc
} }
} }
void CLogHandler::collectGarbage() void CLogHandler::removePatternHandler(CLogPatternHandler *handler)
{ {
auto newEnd = std::stable_partition(m_patternHandlers.begin(), m_patternHandlers.end(), [](const PatternPair &pair) auto it = std::find_if(m_patternHandlers.begin(), m_patternHandlers.end(), [handler](const PatternPair &pair)
{ {
return ! pair.second->canBeDeleted(); return pair.second == handler;
}); });
std::for_each(newEnd, m_patternHandlers.end(), [](const PatternPair &pair) { pair.second->deleteLater(); }); if (it != m_patternHandlers.end())
m_patternHandlers.erase(newEnd, m_patternHandlers.end()); {
it->second->deleteLater();
m_patternHandlers.erase(it);
}
}
CLogPatternHandler::CLogPatternHandler(CLogHandler *parent) :
QObject(parent), m_parent(parent)
{
connect(&m_subscriptionUpdateTimer, &QTimer::timeout, this, &CLogPatternHandler::updateSubscription);
m_subscriptionUpdateTimer.start(1);
}
void CLogPatternHandler::updateSubscription()
{
if (m_subscriptionNeedsUpdate)
{
m_subscriptionNeedsUpdate = false;
bool isSubscribed = isSignalConnected(QMetaMethod::fromSignal(&CLogPatternHandler::messageLogged));
if (m_inheritFallThrough && ! isSubscribed)
{
m_parent->removePatternHandler(this);
}
}
} }
void CLogSubscriber::changeSubscription(const CLogPattern &pattern) void CLogSubscriber::changeSubscription(const CLogPattern &pattern)

View File

@@ -20,6 +20,8 @@
#include <QPointer> #include <QPointer>
#include <QThread> #include <QThread>
#include <QMetaMethod> #include <QMetaMethod>
#include <QTimer>
#include <atomic>
namespace BlackMisc namespace BlackMisc
{ {
@@ -79,14 +81,15 @@ namespace BlackMisc
void enableConsoleOutput(bool enable); void enableConsoleOutput(bool enable);
private: private:
friend class CLogPatternHandler;
void logMessage(const BlackMisc::CStatusMessage &message); void logMessage(const BlackMisc::CStatusMessage &message);
void collectGarbage();
QtMessageHandler m_oldHandler = nullptr; QtMessageHandler m_oldHandler = nullptr;
bool m_enableFallThrough = true; bool m_enableFallThrough = true;
bool isFallThroughEnabled(const QList<CLogPatternHandler *> &handlers) const; bool isFallThroughEnabled(const QList<CLogPatternHandler *> &handlers) const;
using PatternPair = std::pair<CLogPattern, CLogPatternHandler *>; using PatternPair = std::pair<CLogPattern, CLogPatternHandler *>;
QList<PatternPair> m_patternHandlers; QList<PatternPair> m_patternHandlers;
QList<CLogPatternHandler *> handlersForMessage(const CStatusMessage &message) const; QList<CLogPatternHandler *> handlersForMessage(const CStatusMessage &message) const;
void removePatternHandler(CLogPatternHandler *);
}; };
/*! /*!
@@ -110,6 +113,7 @@ namespace BlackMisc
Q_ASSERT(thread() == QThread::currentThread()); Q_ASSERT(thread() == QThread::currentThread());
m_inheritFallThrough = false; m_inheritFallThrough = false;
m_enableFallThrough = enable; m_enableFallThrough = enable;
m_subscriptionNeedsUpdate = true;
} }
/*! /*!
@@ -123,6 +127,7 @@ namespace BlackMisc
{ {
Q_ASSERT(thread() == QThread::currentThread()); Q_ASSERT(thread() == QThread::currentThread());
m_inheritFallThrough = true; m_inheritFallThrough = true;
m_subscriptionNeedsUpdate = true;
} }
signals: signals:
@@ -158,18 +163,28 @@ namespace BlackMisc
return connect(this, &CLogPatternHandler::messageLogged, slot); return connect(this, &CLogPatternHandler::messageLogged, slot);
} }
protected:
//! \copydoc QObject::connectNotify
virtual void connectNotify(const QMetaMethod &signal) override
{
if (signal == QMetaMethod::fromSignal(&CLogPatternHandler::messageLogged)) { m_subscriptionNeedsUpdate = true; }
}
//! \copydoc QObject::disconnectNotify
virtual void disconnectNotify(const QMetaMethod &signal) override
{
if (signal == QMetaMethod::fromSignal(&CLogPatternHandler::messageLogged)) { m_subscriptionNeedsUpdate = true; }
}
private: private:
friend class CLogHandler; friend class CLogHandler;
CLogPatternHandler(QObject *parent) : QObject(parent) {} CLogPatternHandler(CLogHandler *parent);
CLogHandler *m_parent = nullptr;
bool m_inheritFallThrough = true; bool m_inheritFallThrough = true;
bool m_enableFallThrough = true; bool m_enableFallThrough = true;
std::atomic<bool> m_subscriptionNeedsUpdate = false;
bool canBeDeleted() QTimer m_subscriptionUpdateTimer;
{ void updateSubscription();
if (! m_inheritFallThrough) { return false; }
static const auto signal = QMetaMethod::fromSignal(&CLogPatternHandler::messageLogged);
return ! isSignalConnected(signal);
}
}; };
/*! /*!