diff --git a/src/blackmisc/loghandler.cpp b/src/blackmisc/loghandler.cpp index c6191ef15..23888c4ce 100644 --- a/src/blackmisc/loghandler.cpp +++ b/src/blackmisc/loghandler.cpp @@ -118,8 +118,6 @@ namespace BlackMisc void CLogHandler::logMessage(const CStatusMessage &statusMessage) { - collectGarbage(); - auto handlers = handlersForMessage(statusMessage); 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(); }); - m_patternHandlers.erase(newEnd, m_patternHandlers.end()); + if (it != 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) diff --git a/src/blackmisc/loghandler.h b/src/blackmisc/loghandler.h index c7531620c..eb9cbdbf7 100644 --- a/src/blackmisc/loghandler.h +++ b/src/blackmisc/loghandler.h @@ -20,6 +20,8 @@ #include #include #include +#include +#include namespace BlackMisc { @@ -79,14 +81,15 @@ namespace BlackMisc void enableConsoleOutput(bool enable); private: + friend class CLogPatternHandler; void logMessage(const BlackMisc::CStatusMessage &message); - void collectGarbage(); QtMessageHandler m_oldHandler = nullptr; bool m_enableFallThrough = true; bool isFallThroughEnabled(const QList &handlers) const; using PatternPair = std::pair; QList m_patternHandlers; QList handlersForMessage(const CStatusMessage &message) const; + void removePatternHandler(CLogPatternHandler *); }; /*! @@ -110,6 +113,7 @@ namespace BlackMisc Q_ASSERT(thread() == QThread::currentThread()); m_inheritFallThrough = false; m_enableFallThrough = enable; + m_subscriptionNeedsUpdate = true; } /*! @@ -123,6 +127,7 @@ namespace BlackMisc { Q_ASSERT(thread() == QThread::currentThread()); m_inheritFallThrough = true; + m_subscriptionNeedsUpdate = true; } signals: @@ -158,18 +163,28 @@ namespace BlackMisc 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: friend class CLogHandler; - CLogPatternHandler(QObject *parent) : QObject(parent) {} + CLogPatternHandler(CLogHandler *parent); + CLogHandler *m_parent = nullptr; bool m_inheritFallThrough = true; bool m_enableFallThrough = true; - - bool canBeDeleted() - { - if (! m_inheritFallThrough) { return false; } - static const auto signal = QMetaMethod::fromSignal(&CLogPatternHandler::messageLogged); - return ! isSignalConnected(signal); - } + std::atomic m_subscriptionNeedsUpdate = false; + QTimer m_subscriptionUpdateTimer; + void updateSubscription(); }; /*!