mirror of
				https://github.com/f4exb/sdrangel.git
				synced 2025-10-31 13:00:26 -04:00 
			
		
		
		
	Added MessagePipes garbage collector. Updated versions and changelogs
This commit is contained in:
		
							parent
							
								
									ba642e8fab
								
							
						
					
					
						commit
						38a06c4f69
					
				| @ -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 | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
							
								
								
									
										9
									
								
								debian/changelog
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										9
									
								
								debian/changelog
									
									
									
									
										vendored
									
									
								
							| @ -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 | ||||
|  | ||||
| @ -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, | ||||
|  | ||||
| @ -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, | ||||
|  | ||||
| @ -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, | ||||
|  | ||||
| @ -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) | ||||
|  | ||||
| @ -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, | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
| @ -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); | ||||
|  | ||||
| @ -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 | ||||
| { | ||||
| 	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<ChannelRegistrationKey, QList<MessageQueue*>>::iterator mit = m_messageRegistrations.begin(); | ||||
| 	if (m_gcWorker->isRunning()) { | ||||
| 		stopGC(); | ||||
| 	} | ||||
| 
 | ||||
| 	for (; mit != m_messageRegistrations.end(); ++mit) | ||||
| 	QMap<MessagePipesCommon::ChannelRegistrationKey, QList<MessageQueue*>>::iterator mit = m_c2fQueues.begin(); | ||||
| 
 | ||||
| 	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(); | ||||
| } | ||||
|  | ||||
| @ -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_
 | ||||
|  | ||||
							
								
								
									
										29
									
								
								sdrbase/pipes/messagepipescommon.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								sdrbase/pipes/messagepipescommon.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -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; | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										70
									
								
								sdrbase/pipes/messagepipescommon.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								sdrbase/pipes/messagepipescommon.h
									
									
									
									
									
										Normal file
									
								
							| @ -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_
 | ||||
							
								
								
									
										115
									
								
								sdrbase/pipes/messagepipesgcworker.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								sdrbase/pipes/messagepipesgcworker.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -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; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										63
									
								
								sdrbase/pipes/messagepipesgcworker.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								sdrbase/pipes/messagepipesgcworker.h
									
									
									
									
									
										Normal file
									
								
							| @ -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 | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user