From 38a06c4f6949c46b327add392920dbd4dd9a3812 Mon Sep 17 00:00:00 2001 From: f4exb Date: Sat, 12 Dec 2020 16:31:38 +0100 Subject: [PATCH] Added MessagePipes garbage collector. Updated versions and changelogs --- CHANGELOG | 9 ++ CMakeLists.txt | 2 +- debian/changelog | 9 ++ plugins/channelrx/demodatv/atvdemodplugin.cpp | 2 +- .../channelrx/demodfreedv/freedvplugin.cpp | 2 +- .../channeltx/modfreedv/freedvmodplugin.cpp | 2 +- plugins/feature/vorlocalizer/vorlocalizer.cpp | 15 ++- .../vorlocalizer/vorlocalizerplugin.cpp | 2 +- sdrbase/CMakeLists.txt | 4 + sdrbase/maincore.h | 4 +- sdrbase/pipes/messagepipes.cpp | 94 ++++++++++---- sdrbase/pipes/messagepipes.h | 28 +++-- sdrbase/pipes/messagepipescommon.cpp | 29 +++++ sdrbase/pipes/messagepipescommon.h | 70 +++++++++++ sdrbase/pipes/messagepipesgcworker.cpp | 115 ++++++++++++++++++ sdrbase/pipes/messagepipesgcworker.h | 63 ++++++++++ 16 files changed, 404 insertions(+), 46 deletions(-) create mode 100644 sdrbase/pipes/messagepipescommon.cpp create mode 100644 sdrbase/pipes/messagepipescommon.h create mode 100644 sdrbase/pipes/messagepipesgcworker.cpp create mode 100644 sdrbase/pipes/messagepipesgcworker.h diff --git a/CHANGELOG b/CHANGELOG index 8cf23208c..1d7adb401 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,12 @@ +sdrangel (6.3.1-1) unstable; urgency=medium + + * Implemented garbage collector for message pipes. Applies to VORLocalizer. + * FreeDV: removed useless set callback functions. Use mutex appropriately. Issue #728 + * ATV demod: initialize m_tvScreenBuffer when setting m_registeredTVScreen. Issue #728 + * TVScreenAnalog: removed usage of std::shared_ptr. Issue #728 + + -- Edouard Griffiths, F4EXB Sat, 12 Dec 2020 14:45:22 +0100 + sdrangel (6.3.0-1) unstable; urgency=medium * Single channel VOR demodulator plugin. Issue #729 diff --git a/CMakeLists.txt b/CMakeLists.txt index bccaf8d83..8447a943c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,7 +16,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # configure version set(sdrangel_VERSION_MAJOR "6") set(sdrangel_VERSION_MINOR "3") -set(sdrangel_VERSION_PATCH "0") +set(sdrangel_VERSION_PATCH "1") set(sdrangel_VERSION_SUFFIX "") # SDRAngel cmake options diff --git a/debian/changelog b/debian/changelog index 33eecbd2f..e276faae1 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,12 @@ +sdrangel (6.3.1-1) unstable; urgency=medium + + * Implemented garbage collector for message pipes. Applies to VORLocalizer. + * FreeDV: removed useless set callback functions. Use mutex appropriately. Issue #728 + * ATV demod: initialize m_tvScreenBuffer when setting m_registeredTVScreen. Issue #728 + * TVScreenAnalog: removed usage of std::shared_ptr. Issue #728 + + -- Edouard Griffiths, F4EXB Sat, 12 Dec 2020 14:45:22 +0100 + sdrangel (6.3.0-1) unstable; urgency=medium * Single channel VOR demodulator plugin. Issue #729 diff --git a/plugins/channelrx/demodatv/atvdemodplugin.cpp b/plugins/channelrx/demodatv/atvdemodplugin.cpp index bfcc9e7f7..7959151b1 100644 --- a/plugins/channelrx/demodatv/atvdemodplugin.cpp +++ b/plugins/channelrx/demodatv/atvdemodplugin.cpp @@ -30,7 +30,7 @@ const PluginDescriptor ATVDemodPlugin::m_ptrPluginDescriptor = { ATVDemod::m_channelId, QString("ATV Demodulator"), - QString("4.19.0"), + QString("6.3.1"), QString("(c) F4HKW for F4EXB / SDRAngel"), QString("https://github.com/f4exb/sdrangel"), true, diff --git a/plugins/channelrx/demodfreedv/freedvplugin.cpp b/plugins/channelrx/demodfreedv/freedvplugin.cpp index 8bfe18280..6a3bfe4c7 100644 --- a/plugins/channelrx/demodfreedv/freedvplugin.cpp +++ b/plugins/channelrx/demodfreedv/freedvplugin.cpp @@ -28,7 +28,7 @@ const PluginDescriptor FreeDVPlugin::m_pluginDescriptor = { FreeDVDemod::m_channelId, QStringLiteral("FreeDV Demodulator"), - QStringLiteral("4.19.0"), + QStringLiteral("6.3.1"), QStringLiteral("(c) Edouard Griffiths, F4EXB"), QStringLiteral("https://github.com/f4exb/sdrangel"), true, diff --git a/plugins/channeltx/modfreedv/freedvmodplugin.cpp b/plugins/channeltx/modfreedv/freedvmodplugin.cpp index 91da2ba32..9a3e0cf1f 100644 --- a/plugins/channeltx/modfreedv/freedvmodplugin.cpp +++ b/plugins/channeltx/modfreedv/freedvmodplugin.cpp @@ -28,7 +28,7 @@ const PluginDescriptor FreeDVModPlugin::m_pluginDescriptor = { FreeDVMod::m_channelId, QStringLiteral("FreeDV Modulator"), - QStringLiteral("6.1.0"), + QStringLiteral("6.3.1"), QStringLiteral("(c) Edouard Griffiths, F4EXB"), QStringLiteral("https://github.com/f4exb/sdrangel"), true, diff --git a/plugins/feature/vorlocalizer/vorlocalizer.cpp b/plugins/feature/vorlocalizer/vorlocalizer.cpp index 5d0f37f5c..90ce38fcc 100644 --- a/plugins/feature/vorlocalizer/vorlocalizer.cpp +++ b/plugins/feature/vorlocalizer/vorlocalizer.cpp @@ -218,7 +218,7 @@ bool VORLocalizer::handleMessage(const Message& cmd) } else if (VORLocalizerReport::MsgReportServiceddVORs::match(cmd)) { - qDebug() << "VORLocalizer::handleMessage: MsgReportServiceddVORs:"; + qDebug() << "VORLocalizer::handleMessage: MsgReportServiceddVORs"; VORLocalizerReport::MsgReportServiceddVORs& report = (VORLocalizerReport::MsgReportServiceddVORs&) cmd; std::vector& vorNavIds = report.getNavIds(); m_vorSinglePlans = report.getSinglePlans(); @@ -239,6 +239,18 @@ bool VORLocalizer::handleMessage(const Message& cmd) return true; } + else if (MessagePipesCommon::MsgReportChannelDeleted::match(cmd)) + { + qDebug() << "VORLocalizer::handleMessage: MsgReportChannelDeleted"; + MessagePipesCommon::MsgReportChannelDeleted& report = (MessagePipesCommon::MsgReportChannelDeleted&) cmd; + const MessagePipesCommon::ChannelRegistrationKey& channelKey = report.getChannelRegistrationKey(); + const ChannelAPI *channel = channelKey.m_channel; + m_availableChannels.remove(const_cast(channel)); + updateChannels(); + MainCore::instance()->getMessagePipes().unregisterChannelToFeature(channel, this, "report"); + + return true; + } else { return false; @@ -366,6 +378,7 @@ void VORLocalizer::updateChannels() { VORLocalizerReport::MsgReportChannels *msgToGUI = VORLocalizerReport::MsgReportChannels::create(); std::vector& msgChannels = msgToGUI->getChannels(); + // TODO: check https://github.com/microsoft/vscode-cpptools/issues/6222 QHash::iterator it = m_availableChannels.begin(); for (; it != m_availableChannels.end(); ++it) diff --git a/plugins/feature/vorlocalizer/vorlocalizerplugin.cpp b/plugins/feature/vorlocalizer/vorlocalizerplugin.cpp index b1e9e1971..0761fc85c 100644 --- a/plugins/feature/vorlocalizer/vorlocalizerplugin.cpp +++ b/plugins/feature/vorlocalizer/vorlocalizerplugin.cpp @@ -29,7 +29,7 @@ const PluginDescriptor VORLocalizerPlugin::m_pluginDescriptor = { VORLocalizer::m_featureId, QStringLiteral("VOR Localizer"), - QStringLiteral("6.3.0"), + QStringLiteral("6.3.1"), QStringLiteral("(c) Jon Beniston, M7RCE"), QStringLiteral("https://github.com/f4exb/sdrangel"), true, diff --git a/sdrbase/CMakeLists.txt b/sdrbase/CMakeLists.txt index f14df3460..82465b34f 100644 --- a/sdrbase/CMakeLists.txt +++ b/sdrbase/CMakeLists.txt @@ -161,6 +161,8 @@ set(sdrbase_SOURCES limerfe/limerfeusbcalib.cpp pipes/messagepipes.cpp + pipes/messagepipescommon.cpp + pipes/messagepipesgcworker.cpp settings/featuresetpreset.cpp settings/preferences.cpp @@ -335,6 +337,8 @@ set(sdrbase_HEADERS limerfe/limerfeusbcalib.h pipes/messagepipes.h + pipes/messagepipescommon.h + pipes/messagepipesgcworker.h plugin/plugininterface.h plugin/pluginapi.h diff --git a/sdrbase/maincore.h b/sdrbase/maincore.h index dd73d498f..a121ead23 100644 --- a/sdrbase/maincore.h +++ b/sdrbase/maincore.h @@ -449,8 +449,8 @@ public: void setLoggingOptions(); ChannelAPI *getChannel(unsigned int deviceSetIndex, int channelIndex); Feature *getFeature(unsigned int featureSetIndex, int featureIndex); - bool existsChannel(ChannelAPI *channel) const { return m_channelsMap.contains(channel); } - bool existsFeature(Feature *feature) const { return m_featuresMap.contains(feature); } + bool existsChannel(const ChannelAPI *channel) const { return m_channelsMap.contains(const_cast(channel)); } + bool existsFeature(const Feature *feature) const { return m_featuresMap.contains(const_cast(feature)); } // slave mode void appendFeatureSet(); void removeFeatureSet(unsigned int index); diff --git a/sdrbase/pipes/messagepipes.cpp b/sdrbase/pipes/messagepipes.cpp index 3aaae269b..139e1e6df 100644 --- a/sdrbase/pipes/messagepipes.cpp +++ b/sdrbase/pipes/messagepipes.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2015 Edouard Griffiths, F4EXB // +// Copyright (C) 2020 Edouard Griffiths, F4EXB // // // // This program is free software; you can redistribute it and/or modify // // it under the terms of the GNU General Public License as published by // @@ -17,26 +17,28 @@ #include +#include "messagepipesgcworker.h" #include "messagepipes.h" -bool MessagePipes::ChannelRegistrationKey::operator<(const ChannelRegistrationKey& other) const -{ - if (m_channel != other.m_channel) { - return m_channel < other.m_channel; - } else { - return m_typeId < other.m_typeId; - } -} - MessagePipes::MessagePipes() : - m_typeCount(0) -{} + m_typeCount(0), + m_c2fMutex(QMutex::Recursive) +{ + m_gcWorker = new MessagePipesGCWorker(); + m_gcWorker->setC2FRegistrations(&m_c2fMutex, &m_c2fQueues, &m_c2fFEatures); + m_gcWorker->moveToThread(&m_gcThread); + startGC(); +} MessagePipes::~MessagePipes() { - QMap>::iterator mit = m_messageRegistrations.begin(); + if (m_gcWorker->isRunning()) { + stopGC(); + } - for (; mit != m_messageRegistrations.end(); ++mit) + QMap>::iterator mit = m_c2fQueues.begin(); + + for (; mit != m_c2fQueues.end(); ++mit) { QList::iterator lit = mit->begin(); @@ -46,9 +48,10 @@ MessagePipes::~MessagePipes() } } -MessageQueue *MessagePipes::registerChannelToFeature(const ChannelAPI *source, const Feature *feature, const QString& type) +MessageQueue *MessagePipes::registerChannelToFeature(const ChannelAPI *source, Feature *feature, const QString& type) { int typeId; + QMutexLocker mlock(&m_c2fMutex); if (m_typeIds.contains(type)) { @@ -60,32 +63,71 @@ MessageQueue *MessagePipes::registerChannelToFeature(const ChannelAPI *source, c m_typeIds.insert(type, typeId); } - const ChannelRegistrationKey regKey = ChannelRegistrationKey{source, typeId}; + const MessagePipesCommon::ChannelRegistrationKey regKey = MessagePipesCommon::ChannelRegistrationKey{source, typeId}; + MessageQueue *messageQueue; - if (m_messageRegistrations.contains(regKey)) + if (m_c2fFEatures[regKey].contains(feature)) { - m_messageRegistrations.insert(regKey, QList()); - m_featureRegistrations.insert(regKey, QList()); + int i = m_c2fFEatures[regKey].indexOf(feature); + messageQueue = m_c2fQueues[regKey][i]; + } + else + { + messageQueue = new MessageQueue(); + m_c2fQueues[regKey].append(messageQueue); + m_c2fFEatures[regKey].append(feature); } - MessageQueue *messageQueue = new MessageQueue(); - m_messageRegistrations[regKey].append(messageQueue); - m_featureRegistrations[regKey].append(feature); - return messageQueue; } +void MessagePipes::unregisterChannelToFeature(const ChannelAPI *source, Feature *feature, const QString& type) +{ + if (m_typeIds.contains(type)) + { + int typeId = m_typeIds.value(type); + const MessagePipesCommon::ChannelRegistrationKey regKey = MessagePipesCommon::ChannelRegistrationKey{source, typeId}; + + if (m_c2fFEatures.contains(regKey) && m_c2fFEatures[regKey].contains(feature)) + { + QMutexLocker mlock(&m_c2fMutex); + int i = m_c2fFEatures[regKey].indexOf(feature); + m_c2fFEatures[regKey].removeAt(i); + MessageQueue *messageQueue = m_c2fQueues[regKey][i]; + delete messageQueue; + m_c2fQueues[regKey].removeAt(i); + } + } +} + QList* MessagePipes::getMessageQueues(const ChannelAPI *source, const QString& type) { if (!m_typeIds.contains(type)) { return nullptr; } - const ChannelRegistrationKey regKey = ChannelRegistrationKey{source, m_typeIds.value(type)}; + QMutexLocker mlock(&m_c2fMutex); + const MessagePipesCommon::ChannelRegistrationKey regKey = MessagePipesCommon::ChannelRegistrationKey{source, m_typeIds.value(type)}; - if (m_messageRegistrations.contains(regKey)) { - return &m_messageRegistrations[regKey]; + if (m_c2fQueues.contains(regKey)) { + return &m_c2fQueues[regKey]; } else { return nullptr; } } + +void MessagePipes::startGC() +{ + qDebug("MessagePipes::startGC"); + + m_gcWorker->startWork(); + m_gcThread.start(); +} + +void MessagePipes::stopGC() +{ + qDebug("MessagePipes::stopGC"); + m_gcWorker->stopWork(); + m_gcThread.quit(); + m_gcThread.wait(); +} diff --git a/sdrbase/pipes/messagepipes.h b/sdrbase/pipes/messagepipes.h index 0f97b75fc..8145e1252 100644 --- a/sdrbase/pipes/messagepipes.h +++ b/sdrbase/pipes/messagepipes.h @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2015 Edouard Griffiths, F4EXB // +// Copyright (C) 2020 Edouard Griffiths, F4EXB // // // // This program is free software; you can redistribute it and/or modify // // it under the terms of the GNU General Public License as published by // @@ -21,38 +21,42 @@ #include #include #include +#include +#include #include "export.h" #include "util/messagequeue.h" +#include "messagepipescommon.h" + class ChannelAPI; class Feature; +class MessagePipesGCWorker; class SDRBASE_API MessagePipes : public QObject { Q_OBJECT public: - struct ChannelRegistrationKey - { - const ChannelAPI *m_channel; - int m_typeId; - - bool operator<(const ChannelRegistrationKey& other) const; - }; - MessagePipes(); MessagePipes(const MessagePipes&) = delete; MessagePipes& operator=(const MessagePipes&) = delete; ~MessagePipes(); - MessageQueue *registerChannelToFeature(const ChannelAPI *source, const Feature *feature, const QString& type); + MessageQueue *registerChannelToFeature(const ChannelAPI *source, Feature *feature, const QString& type); + void unregisterChannelToFeature(const ChannelAPI *source, Feature *feature, const QString& type); QList* getMessageQueues(const ChannelAPI *source, const QString& type); private: QHash m_typeIds; int m_typeCount; - QMap> m_messageRegistrations; - QMap> m_featureRegistrations; + QMap> m_c2fQueues; + QMap> m_c2fFEatures; + QMutex m_c2fMutex; + QThread m_gcThread; //!< Garbage collector thread + MessagePipesGCWorker *m_gcWorker; //!< Garbage collector + + void startGC(); //!< Start garbage collector + void stopGC(); //!< Stop garbage collector }; #endif // SDRBASE_PIPES_MESSAGEPIPES_H_ diff --git a/sdrbase/pipes/messagepipescommon.cpp b/sdrbase/pipes/messagepipescommon.cpp new file mode 100644 index 000000000..1244d1a10 --- /dev/null +++ b/sdrbase/pipes/messagepipescommon.cpp @@ -0,0 +1,29 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2020 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include "messagepipescommon.h" + +MESSAGE_CLASS_DEFINITION(MessagePipesCommon::MsgReportChannelDeleted, Message) + +bool MessagePipesCommon::ChannelRegistrationKey::operator<(const ChannelRegistrationKey& other) const +{ + if (m_channel != other.m_channel) { + return m_channel < other.m_channel; + } else { + return m_typeId < other.m_typeId; + } +} diff --git a/sdrbase/pipes/messagepipescommon.h b/sdrbase/pipes/messagepipescommon.h new file mode 100644 index 000000000..e4467b5c7 --- /dev/null +++ b/sdrbase/pipes/messagepipescommon.h @@ -0,0 +1,70 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2020 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef SDRBASE_PIPES_MESSAGEPIPESCOMON_H_ +#define SDRBASE_PIPES_MESSAGEPIPESCOMON_H_ + +#include +#include +#include + +#include "export.h" +#include "util/message.h" + +class ChannelAPI; +class Feature; +class MessageQueue; + +class SDRBASE_API MessagePipesCommon +{ +public: + struct ChannelRegistrationKey + { + const ChannelAPI *m_channel; + int m_typeId; + + ChannelRegistrationKey() = default; + ChannelRegistrationKey(const ChannelRegistrationKey&) = default; + ChannelRegistrationKey& operator=(const ChannelRegistrationKey&) = default; + bool operator<(const ChannelRegistrationKey& other) const; + }; + + /** Send this message to stakeholders when the garbage collector finds that a channel was deleted */ + class MsgReportChannelDeleted : public Message { + MESSAGE_CLASS_DECLARATION + + public: + const MessageQueue *getMessageQueue() const { return m_messageQueue; } + const ChannelRegistrationKey& getChannelRegistrationKey() const { return m_channelRegistrationKey; } + + static MsgReportChannelDeleted* create(const MessageQueue *messageQueue, const ChannelRegistrationKey& channelRegistrationKey) { + return new MsgReportChannelDeleted(messageQueue, channelRegistrationKey); + } + + private: + const MessageQueue *m_messageQueue; + ChannelRegistrationKey m_channelRegistrationKey; + + MsgReportChannelDeleted(const MessageQueue *messageQueue, const ChannelRegistrationKey& channelRegistrationKey) : + Message(), + m_messageQueue(messageQueue), + m_channelRegistrationKey(channelRegistrationKey) + { } + }; +}; + +#endif // SDRBASE_PIPES_MESSAGEPIPESCOMON_H_ diff --git a/sdrbase/pipes/messagepipesgcworker.cpp b/sdrbase/pipes/messagepipesgcworker.cpp new file mode 100644 index 000000000..1ca839232 --- /dev/null +++ b/sdrbase/pipes/messagepipesgcworker.cpp @@ -0,0 +1,115 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2020 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include "feature/feature.h" +#include "maincore.h" +#include "messagepipescommon.h" +#include "messagepipesgcworker.h" + +MessagePipesGCWorker::MessagePipesGCWorker() : + m_running(false), + m_c2fMutex(nullptr), + m_c2fQueues(nullptr), + m_c2fFeatures(nullptr) +{} + +MessagePipesGCWorker::~MessagePipesGCWorker() +{} + +void MessagePipesGCWorker::startWork() +{ + connect(&m_gcTimer, SIGNAL(timeout()), this, SLOT(processGC())); + m_gcTimer.start(10000); // collect garbage every 10s + m_running = true; +} + +void MessagePipesGCWorker::stopWork() +{ + m_running = false; + m_gcTimer.stop(); + disconnect(&m_gcTimer, SIGNAL(timeout()), this, SLOT(processGC())); +} + +void MessagePipesGCWorker::processGC() +{ + // qDebug("MessagePipesGCWorker::processGC"); + if (m_c2fMutex) + { + QMutexLocker mlock(m_c2fMutex); + QMap>::iterator fIt = m_c2fFeatures->begin(); + + // check deleted channels and features + for (;fIt != m_c2fFeatures->end(); ++fIt) + { + MessagePipesCommon::ChannelRegistrationKey channelKey = fIt.key(); + const ChannelAPI *channel = channelKey.m_channel; + + if (MainCore::instance()->existsChannel(channel)) // look for deleted features + { + QList& features = fIt.value(); + int i = 0; + + while (i < features.size()) + { + if (MainCore::instance()->existsFeature(features[i])) { + i++; + } + else + { + features.removeAt(i); + m_c2fQueues->operator[](channelKey).removeAt(i); + } + } + } + else // channel was destroyed + { + QList& features = fIt.value(); + + for (int i = 0; i < features.size(); i++) + { + MessagePipesCommon::MsgReportChannelDeleted *msg = MessagePipesCommon::MsgReportChannelDeleted::create( + m_c2fQueues->operator[](channelKey)[i], channelKey); + features[i]->getInputMessageQueue()->push(msg); + } + } + } + + // remove keys with empty features + fIt = m_c2fFeatures->begin(); + + while (fIt != m_c2fFeatures->end()) + { + if (fIt.value().size() == 0) { + fIt = m_c2fFeatures->erase(fIt); + } else { + ++fIt; + } + } + + // remove keys with empty message queues + QMap>::iterator qIt = m_c2fQueues->begin(); + + while (qIt != m_c2fQueues->end()) + { + if (qIt.value().size() == 0) { + qIt = m_c2fQueues->erase(qIt); + } else { + ++qIt; + } + } + } +} diff --git a/sdrbase/pipes/messagepipesgcworker.h b/sdrbase/pipes/messagepipesgcworker.h new file mode 100644 index 000000000..2f2c198cc --- /dev/null +++ b/sdrbase/pipes/messagepipesgcworker.h @@ -0,0 +1,63 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2020 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef SDRBASE_PIPES_MESSAGEPIPESGCWORKER_H_ +#define SDRBASE_PIPES_MESSAGEPIPESGCWORKER_H_ + +#include +#include + +#include "export.h" + +#include "messagepipescommon.h" + +class QMutex; + +class SDRBASE_API MessagePipesGCWorker : public QObject +{ + Q_OBJECT +public: + MessagePipesGCWorker(); + ~MessagePipesGCWorker(); + + void setC2FRegistrations( + QMutex *c2fMutex, + QMap> *c2fQueues, + QMap> *c2fFeatures + ) + { + m_c2fMutex = c2fMutex; + m_c2fQueues = c2fQueues; + m_c2fFeatures = c2fFeatures; + } + + void startWork(); + void stopWork(); + bool isRunning() const { return m_running; } + +private: + bool m_running; + QMutex *m_c2fMutex; + QMap> *m_c2fQueues ; + QMap> *m_c2fFeatures; + QTimer m_gcTimer; + +private slots: + void processGC(); //!< Collect garbage +}; + +#endif