summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorf4exb <f4exb06@gmail.com>2020-12-12 16:31:38 +0100
committerf4exb <f4exb06@gmail.com>2020-12-12 16:31:38 +0100
commit38a06c4f6949c46b327add392920dbd4dd9a3812 (patch)
treea0ffc9baa7a8ced2ded5314d4ab29bbe93bb6531
parentba642e8fab4afa5ddc1a510ffec3d097db99f771 (diff)
Added MessagePipes garbage collector. Updated versions and changelogsv6.3.1sdrangel-v$(appveyor_build_version)
-rw-r--r--CHANGELOG9
-rw-r--r--CMakeLists.txt2
-rw-r--r--debian/changelog9
-rw-r--r--plugins/channelrx/demodatv/atvdemodplugin.cpp2
-rw-r--r--plugins/channelrx/demodfreedv/freedvplugin.cpp2
-rw-r--r--plugins/channeltx/modfreedv/freedvmodplugin.cpp2
-rw-r--r--plugins/feature/vorlocalizer/vorlocalizer.cpp15
-rw-r--r--plugins/feature/vorlocalizer/vorlocalizerplugin.cpp2
-rw-r--r--sdrbase/CMakeLists.txt4
-rw-r--r--sdrbase/maincore.h4
-rw-r--r--sdrbase/pipes/messagepipes.cpp92
-rw-r--r--sdrbase/pipes/messagepipes.h28
-rw-r--r--sdrbase/pipes/messagepipescommon.cpp29
-rw-r--r--sdrbase/pipes/messagepipescommon.h70
-rw-r--r--sdrbase/pipes/messagepipesgcworker.cpp115
-rw-r--r--sdrbase/pipes/messagepipesgcworker.h63
16 files changed, 403 insertions, 45 deletions
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 <f4exb06@gmail.com> 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 <f4exb06@gmail.com> 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<int>& 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<ChannelAPI*>(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<VORLocalizerReport::MsgReportChannels::Channel>& msgChannels = msgToGUI->getChannels();
+ // TODO: check https://github.com/microsoft/vscode-cpptools/issues/6222
QHash<ChannelAPI*, VORLocalizerSettings::AvailableChannel>::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<ChannelAPI*>(channel)); }
+ bool existsFeature(const Feature *feature) const { return m_featuresMap.contains(const_cast<Feature*>(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 <QGlobalStatic>
+#include "messagepipesgcworker.h"
#include "messagepipes.h"
-bool MessagePipes::ChannelRegistrationKey::operator<(const ChannelRegistrationKey& other) const
+MessagePipes::MessagePipes() :
+ m_typeCount(0),
+ m_c2fMutex(QMutex::Recursive)
{
- if (m_channel != other.m_channel) {
- return m_channel < other.m_channel;
- } else {
- return m_typeId < other.m_typeId;
- }
+ m_gcWorker = new MessagePipesGCWorker();
+ m_gcWorker->setC2FRegistrations(&m_c2fMutex, &m_c2fQueues, &m_c2fFEatures);
+ m_gcWorker->moveToThread(&m_gcThread);
+ startGC();
}
-MessagePipes::MessagePipes() :
- m_typeCount(0)
-{}
-
MessagePipes::~MessagePipes()
{
- QMap<ChannelRegistrationKey, QList<MessageQueue*>>::iterator mit = m_messageRegistrations.begin();
+ if (m_gcWorker->isRunning()) {
+ stopGC();
+ }
+
+ QMap<MessagePipesCommon::ChannelRegistrationKey, QList<MessageQueue*>>::iterator mit = m_c2fQueues.begin();
- for (; mit != m_messageRegistrations.end(); ++mit)
+ for (; mit != m_c2fQueues.end(); ++mit)
{
QList<MessageQueue*>::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<MessageQueue*>());
- m_featureRegistrations.insert(regKey, QList<const Feature*>());
+ 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<MessageQueue*>* 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 <QObject>
#include <QHash>
#include <QMap>
+#include <QMutex>
+#include <QThread>
#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<MessageQueue*>* getMessageQueues(const ChannelAPI *source, const QString& type);
private:
QHash<QString, int> m_typeIds;
int m_typeCount;
- QMap<ChannelRegistrationKey, QList<MessageQueue*>> m_messageRegistrations;
- QMap<ChannelRegistrationKey, QList<const Feature*>> m_featureRegistrations;
+ QMap<MessagePipesCommon::ChannelRegistrationKey, QList<MessageQueue*>> m_c2fQueues;
+ QMap<MessagePipesCommon::ChannelRegistrationKey, QList<Feature*>> 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 <http://www.gnu.org/licenses/>. //
+///////////////////////////////////////////////////////////////////////////////////
+
+#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 <http://www.gnu.org/licenses/>. //
+///////////////////////////////////////////////////////////////////////////////////
+
+#ifndef SDRBASE_PIPES_MESSAGEPIPESCOMON_H_
+#define SDRBASE_PIPES_MESSAGEPIPESCOMON_H_
+
+#include <QHash>
+#include <QMap>
+#include <QMutex>
+
+#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 <http://www.gnu.org/licenses/>. //
+///////////////////////////////////////////////////////////////////////////////////
+
+#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<MessagePipesCommon::ChannelRegistrationKey, QList<Feature*>>::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<Feature*>& 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<Feature*>& 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<MessagePipesCommon::ChannelRegistrationKey, QList<MessageQueue*>>::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 <http://www.gnu.org/licenses/>. //
+///////////////////////////////////////////////////////////////////////////////////
+
+#ifndef SDRBASE_PIPES_MESSAGEPIPESGCWORKER_H_
+#define SDRBASE_PIPES_MESSAGEPIPESGCWORKER_H_
+
+#include <QObject>
+#include <QTimer>
+
+#include "export.h"
+
+#include "messagepipescommon.h"
+
+class QMutex;
+
+class SDRBASE_API MessagePipesGCWorker : public QObject
+{
+ Q_OBJECT
+public:
+ MessagePipesGCWorker();
+ ~MessagePipesGCWorker();
+
+ void setC2FRegistrations(
+ QMutex *c2fMutex,
+ QMap<MessagePipesCommon::ChannelRegistrationKey, QList<MessageQueue*>> *c2fQueues,
+ QMap<MessagePipesCommon::ChannelRegistrationKey, QList<Feature*>> *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<MessagePipesCommon::ChannelRegistrationKey, QList<MessageQueue*>> *m_c2fQueues ;
+ QMap<MessagePipesCommon::ChannelRegistrationKey, QList<Feature*>> *m_c2fFeatures;
+ QTimer m_gcTimer;
+
+private slots:
+ void processGC(); //!< Collect garbage
+};
+
+#endif