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 | sdrangel (6.3.0-1) unstable; urgency=medium | ||||||
| 
 | 
 | ||||||
|    * Single channel VOR demodulator plugin. Issue #729 |    * Single channel VOR demodulator plugin. Issue #729 | ||||||
|  | |||||||
| @ -16,7 +16,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON) | |||||||
| # configure version | # configure version | ||||||
| set(sdrangel_VERSION_MAJOR "6") | set(sdrangel_VERSION_MAJOR "6") | ||||||
| set(sdrangel_VERSION_MINOR "3") | set(sdrangel_VERSION_MINOR "3") | ||||||
| set(sdrangel_VERSION_PATCH "0") | set(sdrangel_VERSION_PATCH "1") | ||||||
| set(sdrangel_VERSION_SUFFIX "") | set(sdrangel_VERSION_SUFFIX "") | ||||||
| 
 | 
 | ||||||
| # SDRAngel cmake options | # 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 | sdrangel (6.3.0-1) unstable; urgency=medium | ||||||
| 
 | 
 | ||||||
|    * Single channel VOR demodulator plugin. Issue #729 |    * Single channel VOR demodulator plugin. Issue #729 | ||||||
|  | |||||||
| @ -30,7 +30,7 @@ const PluginDescriptor ATVDemodPlugin::m_ptrPluginDescriptor = | |||||||
| { | { | ||||||
|     ATVDemod::m_channelId, |     ATVDemod::m_channelId, | ||||||
| 	QString("ATV Demodulator"), | 	QString("ATV Demodulator"), | ||||||
| 	QString("4.19.0"), | 	QString("6.3.1"), | ||||||
|     QString("(c) F4HKW for F4EXB / SDRAngel"), |     QString("(c) F4HKW for F4EXB / SDRAngel"), | ||||||
| 	QString("https://github.com/f4exb/sdrangel"), | 	QString("https://github.com/f4exb/sdrangel"), | ||||||
| 	true, | 	true, | ||||||
|  | |||||||
| @ -28,7 +28,7 @@ | |||||||
| const PluginDescriptor FreeDVPlugin::m_pluginDescriptor = { | const PluginDescriptor FreeDVPlugin::m_pluginDescriptor = { | ||||||
|     FreeDVDemod::m_channelId, |     FreeDVDemod::m_channelId, | ||||||
| 	QStringLiteral("FreeDV Demodulator"), | 	QStringLiteral("FreeDV Demodulator"), | ||||||
| 	QStringLiteral("4.19.0"), | 	QStringLiteral("6.3.1"), | ||||||
| 	QStringLiteral("(c) Edouard Griffiths, F4EXB"), | 	QStringLiteral("(c) Edouard Griffiths, F4EXB"), | ||||||
| 	QStringLiteral("https://github.com/f4exb/sdrangel"), | 	QStringLiteral("https://github.com/f4exb/sdrangel"), | ||||||
| 	true, | 	true, | ||||||
|  | |||||||
| @ -28,7 +28,7 @@ | |||||||
| const PluginDescriptor FreeDVModPlugin::m_pluginDescriptor = { | const PluginDescriptor FreeDVModPlugin::m_pluginDescriptor = { | ||||||
|     FreeDVMod::m_channelId, |     FreeDVMod::m_channelId, | ||||||
|     QStringLiteral("FreeDV Modulator"), |     QStringLiteral("FreeDV Modulator"), | ||||||
|     QStringLiteral("6.1.0"), |     QStringLiteral("6.3.1"), | ||||||
|     QStringLiteral("(c) Edouard Griffiths, F4EXB"), |     QStringLiteral("(c) Edouard Griffiths, F4EXB"), | ||||||
|     QStringLiteral("https://github.com/f4exb/sdrangel"), |     QStringLiteral("https://github.com/f4exb/sdrangel"), | ||||||
|     true, |     true, | ||||||
|  | |||||||
| @ -218,7 +218,7 @@ bool VORLocalizer::handleMessage(const Message& cmd) | |||||||
|     } |     } | ||||||
|     else if (VORLocalizerReport::MsgReportServiceddVORs::match(cmd)) |     else if (VORLocalizerReport::MsgReportServiceddVORs::match(cmd)) | ||||||
|     { |     { | ||||||
|         qDebug() << "VORLocalizer::handleMessage: MsgReportServiceddVORs:"; |         qDebug() << "VORLocalizer::handleMessage: MsgReportServiceddVORs"; | ||||||
|         VORLocalizerReport::MsgReportServiceddVORs& report = (VORLocalizerReport::MsgReportServiceddVORs&) cmd; |         VORLocalizerReport::MsgReportServiceddVORs& report = (VORLocalizerReport::MsgReportServiceddVORs&) cmd; | ||||||
|         std::vector<int>& vorNavIds = report.getNavIds(); |         std::vector<int>& vorNavIds = report.getNavIds(); | ||||||
|         m_vorSinglePlans = report.getSinglePlans(); |         m_vorSinglePlans = report.getSinglePlans(); | ||||||
| @ -239,6 +239,18 @@ bool VORLocalizer::handleMessage(const Message& cmd) | |||||||
| 
 | 
 | ||||||
|         return true; |         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 |     else | ||||||
| 	{ | 	{ | ||||||
| 		return false; | 		return false; | ||||||
| @ -366,6 +378,7 @@ void VORLocalizer::updateChannels() | |||||||
|     { |     { | ||||||
|         VORLocalizerReport::MsgReportChannels *msgToGUI = VORLocalizerReport::MsgReportChannels::create(); |         VORLocalizerReport::MsgReportChannels *msgToGUI = VORLocalizerReport::MsgReportChannels::create(); | ||||||
|         std::vector<VORLocalizerReport::MsgReportChannels::Channel>& msgChannels = msgToGUI->getChannels(); |         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(); |         QHash<ChannelAPI*, VORLocalizerSettings::AvailableChannel>::iterator it = m_availableChannels.begin(); | ||||||
| 
 | 
 | ||||||
|         for (; it != m_availableChannels.end(); ++it) |         for (; it != m_availableChannels.end(); ++it) | ||||||
|  | |||||||
| @ -29,7 +29,7 @@ | |||||||
| const PluginDescriptor VORLocalizerPlugin::m_pluginDescriptor = { | const PluginDescriptor VORLocalizerPlugin::m_pluginDescriptor = { | ||||||
|     VORLocalizer::m_featureId, |     VORLocalizer::m_featureId, | ||||||
| 	QStringLiteral("VOR Localizer"), | 	QStringLiteral("VOR Localizer"), | ||||||
| 	QStringLiteral("6.3.0"), | 	QStringLiteral("6.3.1"), | ||||||
| 	QStringLiteral("(c) Jon Beniston, M7RCE"), | 	QStringLiteral("(c) Jon Beniston, M7RCE"), | ||||||
| 	QStringLiteral("https://github.com/f4exb/sdrangel"), | 	QStringLiteral("https://github.com/f4exb/sdrangel"), | ||||||
| 	true, | 	true, | ||||||
|  | |||||||
| @ -161,6 +161,8 @@ set(sdrbase_SOURCES | |||||||
|     limerfe/limerfeusbcalib.cpp |     limerfe/limerfeusbcalib.cpp | ||||||
| 
 | 
 | ||||||
|     pipes/messagepipes.cpp |     pipes/messagepipes.cpp | ||||||
|  |     pipes/messagepipescommon.cpp | ||||||
|  |     pipes/messagepipesgcworker.cpp | ||||||
| 
 | 
 | ||||||
|     settings/featuresetpreset.cpp |     settings/featuresetpreset.cpp | ||||||
|     settings/preferences.cpp |     settings/preferences.cpp | ||||||
| @ -335,6 +337,8 @@ set(sdrbase_HEADERS | |||||||
|     limerfe/limerfeusbcalib.h |     limerfe/limerfeusbcalib.h | ||||||
| 
 | 
 | ||||||
|     pipes/messagepipes.h |     pipes/messagepipes.h | ||||||
|  |     pipes/messagepipescommon.h | ||||||
|  |     pipes/messagepipesgcworker.h | ||||||
| 
 | 
 | ||||||
|     plugin/plugininterface.h |     plugin/plugininterface.h | ||||||
|     plugin/pluginapi.h |     plugin/pluginapi.h | ||||||
|  | |||||||
| @ -449,8 +449,8 @@ public: | |||||||
|     void setLoggingOptions(); |     void setLoggingOptions(); | ||||||
|     ChannelAPI *getChannel(unsigned int deviceSetIndex, int channelIndex); |     ChannelAPI *getChannel(unsigned int deviceSetIndex, int channelIndex); | ||||||
|     Feature *getFeature(unsigned int featureSetIndex, int featureIndex); |     Feature *getFeature(unsigned int featureSetIndex, int featureIndex); | ||||||
|     bool existsChannel(ChannelAPI *channel) const { return m_channelsMap.contains(channel); } |     bool existsChannel(const ChannelAPI *channel) const { return m_channelsMap.contains(const_cast<ChannelAPI*>(channel)); } | ||||||
|     bool existsFeature(Feature *feature) const { return m_featuresMap.contains(feature); } |     bool existsFeature(const Feature *feature) const { return m_featuresMap.contains(const_cast<Feature*>(feature)); } | ||||||
|     // slave mode
 |     // slave mode
 | ||||||
|     void appendFeatureSet(); |     void appendFeatureSet(); | ||||||
|     void removeFeatureSet(unsigned int index); |     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          //
 | // 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          //
 | // it under the terms of the GNU General Public License as published by          //
 | ||||||
| @ -17,26 +17,28 @@ | |||||||
| 
 | 
 | ||||||
| #include <QGlobalStatic> | #include <QGlobalStatic> | ||||||
| 
 | 
 | ||||||
|  | #include "messagepipesgcworker.h" | ||||||
| #include "messagepipes.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() : | 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() | 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(); | 		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; | 	int typeId; | ||||||
|  | 	QMutexLocker mlock(&m_c2fMutex); | ||||||
| 
 | 
 | ||||||
| 	if (m_typeIds.contains(type)) | 	if (m_typeIds.contains(type)) | ||||||
| 	{ | 	{ | ||||||
| @ -60,32 +63,71 @@ MessageQueue *MessagePipes::registerChannelToFeature(const ChannelAPI *source, c | |||||||
| 		m_typeIds.insert(type, typeId); | 		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*>()); | 		int i = m_c2fFEatures[regKey].indexOf(feature); | ||||||
| 		m_featureRegistrations.insert(regKey, QList<const 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; | 	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) | QList<MessageQueue*>* MessagePipes::getMessageQueues(const ChannelAPI *source, const QString& type) | ||||||
| { | { | ||||||
| 	if (!m_typeIds.contains(type)) { | 	if (!m_typeIds.contains(type)) { | ||||||
| 		return nullptr; | 		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)) { | 	if (m_c2fQueues.contains(regKey)) { | ||||||
| 		return &m_messageRegistrations[regKey]; | 		return &m_c2fQueues[regKey]; | ||||||
| 	} else { | 	} else { | ||||||
| 		return nullptr; | 		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          //
 | // 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          //
 | // it under the terms of the GNU General Public License as published by          //
 | ||||||
| @ -21,38 +21,42 @@ | |||||||
| #include <QObject> | #include <QObject> | ||||||
| #include <QHash> | #include <QHash> | ||||||
| #include <QMap> | #include <QMap> | ||||||
|  | #include <QMutex> | ||||||
|  | #include <QThread> | ||||||
| 
 | 
 | ||||||
| #include "export.h" | #include "export.h" | ||||||
| #include "util/messagequeue.h" | #include "util/messagequeue.h" | ||||||
| 
 | 
 | ||||||
|  | #include "messagepipescommon.h" | ||||||
|  | 
 | ||||||
| class ChannelAPI; | class ChannelAPI; | ||||||
| class Feature; | class Feature; | ||||||
|  | class MessagePipesGCWorker; | ||||||
| 
 | 
 | ||||||
| class SDRBASE_API MessagePipes : public QObject | class SDRBASE_API MessagePipes : public QObject | ||||||
| { | { | ||||||
|     Q_OBJECT |     Q_OBJECT | ||||||
| public: | public: | ||||||
|     struct ChannelRegistrationKey |  | ||||||
|     { |  | ||||||
|         const ChannelAPI *m_channel; |  | ||||||
|         int m_typeId; |  | ||||||
| 
 |  | ||||||
|         bool operator<(const ChannelRegistrationKey& other) const; |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     MessagePipes(); |     MessagePipes(); | ||||||
|     MessagePipes(const MessagePipes&) = delete; |     MessagePipes(const MessagePipes&) = delete; | ||||||
|     MessagePipes& operator=(const MessagePipes&) = delete; |     MessagePipes& operator=(const MessagePipes&) = delete; | ||||||
|     ~MessagePipes(); |     ~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); |     QList<MessageQueue*>* getMessageQueues(const ChannelAPI *source, const QString& type); | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     QHash<QString, int> m_typeIds; |     QHash<QString, int> m_typeIds; | ||||||
|     int m_typeCount; |     int m_typeCount; | ||||||
|     QMap<ChannelRegistrationKey, QList<MessageQueue*>> m_messageRegistrations; |     QMap<MessagePipesCommon::ChannelRegistrationKey, QList<MessageQueue*>> m_c2fQueues; | ||||||
|     QMap<ChannelRegistrationKey, QList<const Feature*>> m_featureRegistrations; |     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_
 | #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