Data pipes redesign

This commit is contained in:
f4exb 2022-02-20 22:08:49 +01:00
parent 22604244a3
commit 4c2ca8fa20
30 changed files with 979 additions and 103 deletions

View File

@ -383,14 +383,20 @@ void AISDemodSink::processOneSample(Complex &ci)
if (m_demodBufferFill >= m_demodBuffer.size())
{
QList<DataFifo*> *dataFifos = MainCore::instance()->getDataPipes().getFifos(m_channel, "demod");
QList<ObjectPipe*> dataPipes;
MainCore::instance()->getDataPipes().getDataPipes(m_channel, "demod", dataPipes);
if (dataFifos)
if (dataPipes.size() > 0)
{
QList<DataFifo*>::iterator it = dataFifos->begin();
QList<ObjectPipe*>::iterator it = dataPipes.begin();
for (; it != dataFifos->end(); ++it) {
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
for (; it != dataPipes.end(); ++it)
{
DataFifo *fifo = qobject_cast<DataFifo*>((*it)->m_element);
if (fifo) {
fifo->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
}
}
}

View File

@ -219,14 +219,20 @@ void AMDemodSink::processOneSample(Complex &ci)
if (m_demodBufferFill >= m_demodBuffer.size())
{
QList<DataFifo*> *dataFifos = MainCore::instance()->getDataPipes().getFifos(m_channel, "demod");
QList<ObjectPipe*> dataPipes;
MainCore::instance()->getDataPipes().getDataPipes(m_channel, "demod", dataPipes);
if (dataFifos)
if (dataPipes.size() > 0)
{
QList<DataFifo*>::iterator it = dataFifos->begin();
QList<ObjectPipe*>::iterator it = dataPipes.begin();
for (; it != dataFifos->end(); ++it) {
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
for (; it != dataPipes.end(); ++it)
{
DataFifo *fifo = qobject_cast<DataFifo*>((*it)->m_element);
if (fifo) {
fifo->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
}
}
}

View File

@ -447,14 +447,20 @@ void DABDemodSink::processOneAudioSample(Complex &ci)
if (m_demodBufferFill >= m_demodBuffer.size())
{
QList<DataFifo*> *dataFifos = MainCore::instance()->getDataPipes().getFifos(m_channel, "demod");
QList<ObjectPipe*> dataPipes;
MainCore::instance()->getDataPipes().getDataPipes(m_channel, "demod", dataPipes);
if (dataFifos)
if (dataPipes.size() > 0)
{
QList<DataFifo*>::iterator it = dataFifos->begin();
QList<ObjectPipe*>::iterator it = dataPipes.begin();
for (; it != dataFifos->end(); ++it) {
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeCI16);
for (; it != dataPipes.end(); ++it)
{
DataFifo *fifo = qobject_cast<DataFifo*>((*it)->m_element);
if (fifo) {
fifo->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeCI16);
}
}
}

View File

@ -180,14 +180,20 @@ void DSDDemodSink::feed(const SampleVector::const_iterator& begin, const SampleV
if (m_demodBufferFill >= m_demodBuffer.size())
{
QList<DataFifo*> *dataFifos = MainCore::instance()->getDataPipes().getFifos(m_channel, "demod");
QList<ObjectPipe*> dataPipes;
MainCore::instance()->getDataPipes().getDataPipes(m_channel, "demod", dataPipes);
if (dataFifos)
if (dataPipes.size() > 0)
{
QList<DataFifo*>::iterator it = dataFifos->begin();
QList<ObjectPipe*>::iterator it = dataPipes.begin();
for (; it != dataFifos->end(); ++it) {
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
for (; it != dataPipes.end(); ++it)
{
DataFifo *fifo = qobject_cast<DataFifo*>((*it)->m_element);
if (fifo) {
fifo->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
}
}
}

View File

@ -256,14 +256,20 @@ void NFMDemodSink::processOneSample(Complex &ci)
if (m_demodBufferFill >= m_demodBuffer.size())
{
QList<DataFifo*> *dataFifos = MainCore::instance()->getDataPipes().getFifos(m_channel, "demod");
QList<ObjectPipe*> dataPipes;
MainCore::instance()->getDataPipes().getDataPipes(m_channel, "demod", dataPipes);
if (dataFifos)
if (dataPipes.size() > 0)
{
QList<DataFifo*>::iterator it = dataFifos->begin();
QList<ObjectPipe*>::iterator it = dataPipes.begin();
for (; it != dataFifos->end(); ++it) {
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
for (; it != dataPipes.end(); ++it)
{
DataFifo *fifo = qobject_cast<DataFifo*>((*it)->m_element);
if (fifo) {
fifo->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
}
}
}

View File

@ -249,14 +249,20 @@ void PacketDemodSink::processOneSample(Complex &ci)
if (m_demodBufferFill >= m_demodBuffer.size())
{
QList<DataFifo*> *dataFifos = MainCore::instance()->getDataPipes().getFifos(m_channel, "demod");
QList<ObjectPipe*> dataPipes;
MainCore::instance()->getDataPipes().getDataPipes(m_channel, "demod", dataPipes);
if (dataFifos)
if (dataPipes.size() > 0)
{
QList<DataFifo*>::iterator it = dataFifos->begin();
QList<ObjectPipe*>::iterator it = dataPipes.begin();
for (; it != dataFifos->end(); ++it) {
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
for (; it != dataPipes.end(); ++it)
{
DataFifo *fifo = qobject_cast<DataFifo*>((*it)->m_element);
if (fifo) {
fifo->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
}
}
}

View File

@ -594,14 +594,20 @@ void PagerDemodSink::processOneSample(Complex &ci)
if (m_demodBufferFill >= m_demodBuffer.size())
{
QList<DataFifo*> *dataFifos = MainCore::instance()->getDataPipes().getFifos(m_channel, "demod");
QList<ObjectPipe*> dataPipes;
MainCore::instance()->getDataPipes().getDataPipes(m_channel, "demod", dataPipes);
if (dataFifos)
if (dataPipes.size() > 0)
{
QList<DataFifo*>::iterator it = dataFifos->begin();
QList<ObjectPipe*>::iterator it = dataPipes.begin();
for (; it != dataFifos->end(); ++it) {
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
for (; it != dataPipes.end(); ++it)
{
DataFifo *fifo = qobject_cast<DataFifo*>((*it)->m_element);
if (fifo) {
fifo->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
}
}
}

View File

@ -207,19 +207,25 @@ void SSBDemodSink::processOneSample(Complex &ci)
if (m_demodBufferFill >= m_demodBuffer.size())
{
QList<DataFifo*> *dataFifos = MainCore::instance()->getDataPipes().getFifos(m_channel, "demod");
QList<ObjectPipe*> dataPipes;
MainCore::instance()->getDataPipes().getDataPipes(m_channel, "demod", dataPipes);
if (dataFifos)
if (dataPipes.size() > 0)
{
QList<DataFifo*>::iterator it = dataFifos->begin();
QList<ObjectPipe*>::iterator it = dataPipes.begin();
for (; it != dataFifos->end(); ++it)
for (; it != dataPipes.end(); ++it)
{
(*it)->write(
(quint8*) &m_demodBuffer[0],
m_demodBuffer.size() * sizeof(qint16),
m_audioBinaual ? DataFifo::DataTypeCI16 : DataFifo::DataTypeI16
);
DataFifo *fifo = qobject_cast<DataFifo*>((*it)->m_element);
if (fifo)
{
fifo->write(
(quint8*) &m_demodBuffer[0],
m_demodBuffer.size() * sizeof(qint16),
m_audioBinaual ? DataFifo::DataTypeCI16 : DataFifo::DataTypeI16
);
}
}
}

View File

@ -141,14 +141,20 @@ void WFMDemodSink::feed(const SampleVector::const_iterator& begin, const SampleV
if (m_demodBufferFill >= m_demodBuffer.size())
{
QList<DataFifo*> *dataFifos = MainCore::instance()->getDataPipes().getFifos(m_channel, "demod");
QList<ObjectPipe*> dataPipes;
MainCore::instance()->getDataPipes().getDataPipes(m_channel, "demod", dataPipes);
if (dataFifos)
if (dataPipes.size() > 0)
{
QList<DataFifo*>::iterator it = dataFifos->begin();
QList<ObjectPipe*>::iterator it = dataPipes.begin();
for (; it != dataFifos->end(); ++it) {
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
for (; it != dataPipes.end(); ++it)
{
DataFifo *fifo = qobject_cast<DataFifo*>((*it)->m_element);
if (fifo) {
fifo->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
}
}
}

View File

@ -272,14 +272,20 @@ void AISModSource::modulateSample()
if (m_demodBufferFill >= m_demodBuffer.size())
{
QList<DataFifo*> *dataFifos = MainCore::instance()->getDataPipes().getFifos(m_channel, "demod");
QList<ObjectPipe*> dataPipes;
MainCore::instance()->getDataPipes().getDataPipes(m_channel, "demod", dataPipes);
if (dataFifos)
if (dataPipes.size() > 0)
{
QList<DataFifo*>::iterator it = dataFifos->begin();
QList<ObjectPipe*>::iterator it = dataPipes.begin();
for (; it != dataFifos->end(); ++it) {
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
for (; it != dataPipes.end(); ++it)
{
DataFifo *fifo = qobject_cast<DataFifo*>((*it)->m_element);
if (fifo) {
fifo->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
}
}
}

View File

@ -112,14 +112,20 @@ void AMModSource::pullOne(Sample& sample)
if (m_demodBufferFill >= m_demodBuffer.size())
{
QList<DataFifo*> *dataFifos = MainCore::instance()->getDataPipes().getFifos(m_channel, "demod");
QList<ObjectPipe*> dataPipes;
MainCore::instance()->getDataPipes().getDataPipes(m_channel, "demod", dataPipes);
if (dataFifos)
if (dataPipes.size() > 0)
{
QList<DataFifo*>::iterator it = dataFifos->begin();
QList<ObjectPipe*>::iterator it = dataPipes.begin();
for (; it != dataFifos->end(); ++it) {
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
for (; it != dataPipes.end(); ++it)
{
DataFifo *fifo = qobject_cast<DataFifo*>((*it)->m_element);
if (fifo) {
fifo->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
}
}
}

View File

@ -173,14 +173,20 @@ void NFMModSource::modulateSample()
if (m_demodBufferFill >= m_demodBuffer.size())
{
QList<DataFifo*> *dataFifos = MainCore::instance()->getDataPipes().getFifos(m_channel, "demod");
QList<ObjectPipe*> dataPipes;
MainCore::instance()->getDataPipes().getDataPipes(m_channel, "demod", dataPipes);
if (dataFifos)
if (dataPipes.size() > 0)
{
QList<DataFifo*>::iterator it = dataFifos->begin();
QList<ObjectPipe*>::iterator it = dataPipes.begin();
for (; it != dataFifos->end(); ++it) {
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
for (; it != dataPipes.end(); ++it)
{
DataFifo *fifo = qobject_cast<DataFifo*>((*it)->m_element);
if (fifo) {
fifo->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
}
}
}

View File

@ -280,14 +280,20 @@ void PacketModSource::modulateSample()
if (m_demodBufferFill >= m_demodBuffer.size())
{
QList<DataFifo*> *dataFifos = MainCore::instance()->getDataPipes().getFifos(m_channel, "demod");
QList<ObjectPipe*> dataPipes;
MainCore::instance()->getDataPipes().getDataPipes(m_channel, "demod", dataPipes);
if (dataFifos)
if (dataPipes.size() > 0)
{
QList<DataFifo*>::iterator it = dataFifos->begin();
QList<ObjectPipe*>::iterator it = dataPipes.begin();
for (; it != dataFifos->end(); ++it) {
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
for (; it != dataPipes.end(); ++it)
{
DataFifo *fifo = qobject_cast<DataFifo*>((*it)->m_element);
if (fifo) {
fifo->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
}
}
}

View File

@ -184,19 +184,25 @@ void SSBModSource::modulateSample()
if (m_demodBufferFill >= m_demodBuffer.size())
{
QList<DataFifo*> *dataFifos = MainCore::instance()->getDataPipes().getFifos(m_channel, "demod");
QList<ObjectPipe*> dataPipes;
MainCore::instance()->getDataPipes().getDataPipes(m_channel, "demod", dataPipes);
if (dataFifos)
if (dataPipes.size() > 0)
{
QList<DataFifo*>::iterator it = dataFifos->begin();
QList<ObjectPipe*>::iterator it = dataPipes.begin();
for (; it != dataFifos->end(); ++it)
for (; it != dataPipes.end(); ++it)
{
(*it)->write(
(quint8*) &m_demodBuffer[0],
m_demodBuffer.size() * sizeof(qint16),
m_settings.m_audioBinaural ? DataFifo::DataTypeCI16 : DataFifo::DataTypeI16
);
DataFifo *fifo = qobject_cast<DataFifo*>((*it)->m_element);
if (fifo)
{
fifo->write(
(quint8*) &m_demodBuffer[0],
m_demodBuffer.size() * sizeof(qint16),
m_settings.m_audioBinaural ? DataFifo::DataTypeCI16 : DataFifo::DataTypeI16
);
}
}
}

View File

@ -152,14 +152,20 @@ void WFMModSource::pullOne(Sample& sample)
if (m_demodBufferFill >= m_demodBuffer.size())
{
QList<DataFifo*> *dataFifos = MainCore::instance()->getDataPipes().getFifos(m_channel, "demod");
QList<ObjectPipe*> dataPipes;
MainCore::instance()->getDataPipes().getDataPipes(m_channel, "demod", dataPipes);
if (dataFifos)
if (dataPipes.size() > 0)
{
QList<DataFifo*>::iterator it = dataFifos->begin();
QList<ObjectPipe*>::iterator it = dataPipes.begin();
for (; it != dataFifos->end(); ++it) {
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
for (; it != dataPipes.end(); ++it)
{
DataFifo *fifo = qobject_cast<DataFifo*>((*it)->m_element);
if (fifo) {
fifo->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
}
}
}

View File

@ -50,7 +50,7 @@ DemodAnalyzer::DemodAnalyzer(WebAPIAdapterInterface *webAPIAdapterInterface) :
Feature(m_featureIdURI, webAPIAdapterInterface),
m_spectrumVis(SDR_RX_SCALEF),
m_selectedChannel(nullptr),
m_dataFifo(nullptr)
m_dataPipe(nullptr)
{
qDebug("DemodAnalyzer::DemodAnalyzer: webAPIAdapterInterface: %p", webAPIAdapterInterface);
setObjectName(m_featureId);
@ -88,10 +88,15 @@ void DemodAnalyzer::start()
= DemodAnalyzerWorker::MsgConfigureDemodAnalyzerWorker::create(m_settings, true);
m_worker->getInputMessageQueue()->push(msg);
if (m_dataFifo)
if (m_dataPipe)
{
DemodAnalyzerWorker::MsgConnectFifo *msg = DemodAnalyzerWorker::MsgConnectFifo::create(m_dataFifo, true);
m_worker->getInputMessageQueue()->push(msg);
DataFifo *fifo = qobject_cast<DataFifo*>(m_dataPipe->m_element);
if (fifo)
{
DemodAnalyzerWorker::MsgConnectFifo *msg = DemodAnalyzerWorker::MsgConnectFifo::create(fifo, true);
m_worker->getInputMessageQueue()->push(msg);
}
}
}
@ -99,10 +104,15 @@ void DemodAnalyzer::stop()
{
qDebug("DemodAnalyzer::stop");
if (m_dataFifo)
if (m_dataPipe)
{
DemodAnalyzerWorker::MsgConnectFifo *msg = DemodAnalyzerWorker::MsgConnectFifo::create(m_dataFifo, false);
m_worker->getInputMessageQueue()->push(msg);
DataFifo *fifo = qobject_cast<DataFifo*>(m_dataPipe->m_element);
if (fifo)
{
DemodAnalyzerWorker::MsgConnectFifo *msg = DemodAnalyzerWorker::MsgConnectFifo::create(fifo, false);
m_worker->getInputMessageQueue()->push(msg);
}
}
m_worker->stopWork();
@ -169,8 +179,13 @@ bool DemodAnalyzer::handleMessage(const Message& cmd)
DSPSignalNotification *msg = new DSPSignalNotification(0, m_sampleRate);
m_spectrumVis.getInputMessageQueue()->push(msg);
if (m_dataFifo) {
m_dataFifo->setSize(2*m_sampleRate);
if (m_dataPipe)
{
DataFifo *fifo = qobject_cast<DataFifo*>(m_dataPipe->m_element);
if (fifo) {
fifo->setSize(2*m_sampleRate);
}
}
if (getMessageQueueToGUI())
@ -319,7 +334,8 @@ void DemodAnalyzer::setChannel(ChannelAPI *selectedChannel)
if (m_selectedChannel)
{
DataFifo *fifo = mainCore->getDataPipes().unregisterChannelToFeature(m_selectedChannel, this, "demod");
ObjectPipe *pipe = mainCore->getDataPipes().unregisterProducerToConsumer(m_selectedChannel, this, "demod");
DataFifo *fifo = qobject_cast<DataFifo*>(pipe->m_element);
if ((fifo) && m_worker->isRunning())
{
@ -331,13 +347,18 @@ void DemodAnalyzer::setChannel(ChannelAPI *selectedChannel)
disconnect(messageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleChannelMessageQueue(MessageQueue*)));
}
m_dataFifo = mainCore->getDataPipes().registerChannelToFeature(selectedChannel, this, "demod");
m_dataFifo->setSize(96000);
m_dataPipe = mainCore->getDataPipes().registerProducerToConsumer(selectedChannel, this, "demod");
DataFifo *fifo = qobject_cast<DataFifo*>(m_dataPipe->m_element);
if (m_worker->isRunning())
if (fifo)
{
DemodAnalyzerWorker::MsgConnectFifo *msg = DemodAnalyzerWorker::MsgConnectFifo::create(m_dataFifo, true);
m_worker->getInputMessageQueue()->push(msg);
fifo->setSize(96000);
if (m_worker->isRunning())
{
DemodAnalyzerWorker::MsgConnectFifo *msg = DemodAnalyzerWorker::MsgConnectFifo::create(fifo, true);
m_worker->getInputMessageQueue()->push(msg);
}
}
MessageQueue *messageQueue = mainCore->getMessagePipes().registerChannelToFeature(selectedChannel, this, "reportdemod");

View File

@ -33,7 +33,7 @@ class WebAPIAdapterInterface;
class DemodAnalyzerWorker;
class QNetworkAccessManager;
class QNetworkReply;
class DataFifo;
class ObjectPipe;
namespace SWGSDRangel {
class SWGDeviceState;
@ -201,7 +201,7 @@ private:
ScopeVis m_scopeVis;
QHash<ChannelAPI*, DemodAnalyzerSettings::AvailableChannel> m_availableChannels;
ChannelAPI *m_selectedChannel;
DataFifo *m_dataFifo;
ObjectPipe *m_dataPipe;
int m_sampleRate;
QNetworkAccessManager *m_networkManager;

View File

@ -170,10 +170,15 @@ set(sdrbase_SOURCES
pipes/datapipes.cpp
pipes/datapipescommon.cpp
pipes/datapipesgcworker.cpp
pipes/datafifostore.cpp
pipes/datapipes2.cpp
pipes/datapipes2gcworker.cpp
pipes/messagepipes.cpp
pipes/messagepipescommon.cpp
pipes/messagepipesgcworker.cpp
pipes/pipeendpoint.cpp
pipes/objectpipe.cpp
pipes/objectpipesregistrations.cpp
settings/featuresetpreset.cpp
settings/preferences.cpp
@ -374,12 +379,17 @@ set(sdrbase_HEADERS
pipes/datapipes.h
pipes/datapipescommon.h
pipes/datapipesgcworker.h
pipes/datafifostore.h
pipes/datapipes2.h
pipes/datapipes2gcworker.h
pipes/elementpipescommon.h
pipes/elementpipesgc.h
pipes/messagepipes.h
pipes/messagepipescommon.h
pipes/messagepipesgcworker.h
pipes/pipeendpoint.h
pipes/objectpipe.h
pipes/objectpipesregistrations.h
plugin/plugininterface.h
plugin/pluginapi.h

View File

@ -28,7 +28,7 @@
#include "settings/mainsettings.h"
#include "util/message.h"
#include "pipes/messagepipes.h"
#include "pipes/datapipes.h"
#include "pipes/datapipes2.h"
#include "channel/channelapi.h"
class DeviceSet;
@ -731,7 +731,7 @@ public:
void clearFeatures(FeatureSet *featureSet);
// pipes
MessagePipes& getMessagePipes() { return m_messagePipes; }
DataPipes& getDataPipes() { return m_dataPipes; }
DataPipes2& getDataPipes() { return m_dataPipes; }
friend class MainServer;
friend class MainWindow;
@ -751,7 +751,7 @@ private:
QMap<Feature*, FeatureSet*> m_featuresMap; //!< Feature to feature set map
PluginManager* m_pluginManager;
MessagePipes m_messagePipes;
DataPipes m_dataPipes;
DataPipes2 m_dataPipes;
void debugMaps();
};

View File

@ -0,0 +1,56 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2022 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 "dsp/datafifo.h"
#include "datafifostore.h"
DataFifoStore::DataFifoStore()
{}
DataFifoStore::~DataFifoStore()
{
deleteAllElements();
}
QObject *DataFifoStore::createElement()
{
DataFifo *fifo = new DataFifo();
m_dataFifos.push_back(fifo);
qDebug("DataFifoStore::createElement: %d added", m_dataFifos.size() - 1);
return fifo;
}
void DataFifoStore::deleteElement(QObject *element)
{
int i = m_dataFifos.indexOf((DataFifo*) element);
if (i >= 0)
{
qDebug("DataFifoStore::deleteElement: delte element at %d", i);
delete m_dataFifos[i];
m_dataFifos.removeAt(i);
}
}
void DataFifoStore::deleteAllElements()
{
for (auto& fifo : m_dataFifos) {
delete fifo;
}
m_dataFifos.clear();
}

View File

@ -0,0 +1,42 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2022 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_DATAFIFOSTORE_H_
#define SDRBASE_PIPES_DATAFIFOSTORE_H_
#include <QList>
#include "export.h"
#include "objectpipeelementsstore.h"
class DataFifo;
class SDRBASE_API DataFifoStore : public ObjectPipeElementsStore
{
public:
DataFifoStore();
virtual ~DataFifoStore();
virtual QObject *createElement();
virtual void deleteElement(QObject*);
private:
void deleteAllElements();
QList<DataFifo*> m_dataFifos;
};
#endif // SDRBASE_PIPES_DATAFIFOSTORE_H_

View File

@ -0,0 +1,68 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2022 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 "dsp/datafifo.h"
#include "datapipes2.h"
#include "datapipes2gcworker.h"
DataPipes2::DataPipes2() :
m_registrations(&m_dataFifoStore)
{
m_gcWorker = new DataPipes2GCWorker(m_registrations);
m_gcWorker->moveToThread(&m_gcThread);
startGC();
}
DataPipes2::~DataPipes2()
{
if (m_gcWorker->isRunning()) {
stopGC();
}
m_gcWorker->deleteLater();
}
ObjectPipe *DataPipes2::registerProducerToConsumer(const QObject *producer, const QObject *consumer, const QString& type)
{
return m_registrations.registerProducerToConsumer(producer, consumer, type);
}
ObjectPipe *DataPipes2::unregisterProducerToConsumer(const QObject *producer, const QObject *consumer, const QString& type)
{
return m_registrations.unregisterProducerToConsumer(producer, consumer, type);
}
void DataPipes2::getDataPipes(const QObject *producer, const QString& type, QList<ObjectPipe*>& pipes)
{
return m_registrations.getPipes(producer, type, pipes);
}
void DataPipes2::startGC()
{
qDebug("DataPipes2::startGC");
m_gcWorker->startWork();
m_gcThread.start();
}
void DataPipes2::stopGC()
{
qDebug("DataPipes2::stopGC");
m_gcWorker->stopWork();
m_gcThread.quit();
m_gcThread.wait();
}

View File

@ -0,0 +1,55 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2022 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_DATAPIPES2_H_
#define SDRBASE_PIPES_DATAPIPES2_H_
#include <QObject>
#include <QThread>
#include "export.h"
#include "objectpipesregistrations.h"
#include "datafifostore.h"
class DataFifo;
class DataPipes2GCWorker;
class SDRBASE_API DataPipes2 : public QObject
{
Q_OBJECT
public:
DataPipes2();
DataPipes2(const DataPipes2&) = delete;
DataPipes2& operator=(const DataPipes2&) = delete;
~DataPipes2();
ObjectPipe *registerProducerToConsumer(const QObject *producer, const QObject *consumer, const QString& type);
ObjectPipe *unregisterProducerToConsumer(const QObject *producer, const QObject *consumer, const QString& type);
void getDataPipes(const QObject *producer, const QString& type, QList<ObjectPipe*>& pipes);
private:
DataFifoStore m_dataFifoStore;
ObjectPipesRegistrations m_registrations;
QThread m_gcThread; //!< Garbage collector thread
DataPipes2GCWorker *m_gcWorker; //!< Garbage collector
void startGC(); //!< Start garbage collector
void stopGC(); //!< Stop garbage collector
};
#endif // SDRBASE_PIPES_DATAPIPES2_H_

View File

@ -0,0 +1,46 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2022 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 "dsp/datafifo.h"
#include "datapipes2gcworker.h"
DataPipes2GCWorker::DataPipes2GCWorker(ObjectPipesRegistrations& objectPipesRegistrations) :
m_running(false),
m_objectPipesRegistrations(objectPipesRegistrations)
{}
DataPipes2GCWorker::~DataPipes2GCWorker()
{}
void DataPipes2GCWorker::startWork()
{
connect(&m_gcTimer, SIGNAL(timeout()), this, SLOT(processGC()));
m_gcTimer.start(10000); // collect garbage every 10s
m_running = true;
}
void DataPipes2GCWorker::stopWork()
{
m_running = false;
m_gcTimer.stop();
disconnect(&m_gcTimer, SIGNAL(timeout()), this, SLOT(processGC()));
}
void DataPipes2GCWorker::processGC()
{
m_objectPipesRegistrations.processGC();
}

View File

@ -0,0 +1,49 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2022 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_DATAPIPES2GCWORKER_H_
#define SDRBASE_PIPES_DATAPIPES2GCWORKER_H_
#include <QObject>
#include <QTimer>
#include "export.h"
#include "objectpipesregistrations.h"
class DataFifo;
class SDRBASE_API DataPipes2GCWorker : public QObject
{
Q_OBJECT
public:
DataPipes2GCWorker(ObjectPipesRegistrations& objectPipesRegistrations);
~DataPipes2GCWorker();
void startWork();
void stopWork();
bool isRunning() const { return m_running; }
private:
bool m_running;
QTimer m_gcTimer;
ObjectPipesRegistrations& m_objectPipesRegistrations;
private slots:
void processGC(); //!< Collect garbage
};
#endif // SDRBASE_PIPES_DATAPIPES2GCWORKER_H_

View File

@ -0,0 +1,47 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2022 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 "objectpipe.h"
ObjectPipe::ObjectPipe() :
m_pipeId(0),
m_typeId(0),
m_producer(nullptr),
m_consumer(nullptr),
m_element(nullptr),
m_gcCount(0)
{}
void ObjectPipe::setToBeDeleted(int reason)
{
m_gcCount = 2; // will defer actual deletion by one GC pass
emit toBeDeleted(reason);
}
int ObjectPipe::getGCCount() const {
return m_gcCount;
}
int ObjectPipe::decreaseGCCount()
{
if (m_gcCount > 0) {
return m_gcCount--;
} else {
return m_gcCount;
}
}

View File

@ -0,0 +1,51 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2022 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_OBJECTPIPE_H_
#define SDRBASE_PIPES_OBJECTPIPE_H_
#include <QObject>
#include "export.h"
class SDRBASE_API ObjectPipe : public QObject
{
Q_OBJECT
public:
ObjectPipe();
ObjectPipe(const ObjectPipe&) = default;
ObjectPipe& operator=(const ObjectPipe&) = default;
void setToBeDeleted(int reason);
int getGCCount() const;
int decreaseGCCount();
unsigned int m_pipeId;
int m_typeId;
const QObject *m_producer;
const QObject *m_consumer;
QObject *m_element;
signals:
void toBeDeleted(int reason);
private:
int m_gcCount;
};
#endif // SDRBASE_PIPES_OBJECTPIPE_H_

View File

@ -0,0 +1,30 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2022 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_OBJECTPIPESELEMENT_H_
#define SDRBASE_PIPES_OBJECTPIPESELEMENT_H_
class QObject;
class ObjectPipeElementsStore
{
public:
virtual QObject *createElement() = 0;
virtual void deleteElement(QObject*) = 0;
};
#endif // SDRBASE_PIPES_OBJECTPIPESELEMENT_H_

View File

@ -0,0 +1,236 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2022 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 "objectpipesregistrations.h"
ObjectPipesRegistrations::ObjectPipesRegistrations(ObjectPipeElementsStore *objectPipeElementsStore) :
m_typeCount(0),
m_pipeId(0),
m_objectPipeElementsStore(objectPipeElementsStore),
m_mutex(QMutex::Recursive)
{}
ObjectPipesRegistrations::~ObjectPipesRegistrations()
{}
ObjectPipe *ObjectPipesRegistrations::registerProducerToConsumer(const QObject *producer, const QObject *consumer, const QString& type)
{
int typeId;
QMutexLocker mlock(&m_mutex);
if (m_typeIds.contains(type))
{
typeId = m_typeIds.value(type);
}
else
{
typeId = m_typeCount++;
m_typeIds.insert(type, typeId);
m_types.insert(typeId, type);
}
for (auto& pipe : m_pipes) // check if pipe exists already - there is a unique pipe per producer, consumer and type
{
if ((producer == pipe->m_producer) && (consumer == pipe->m_consumer) && (typeId == pipe->m_typeId)) {
return pipe;
}
}
QObject *element = m_objectPipeElementsStore->createElement();
m_pipes.push_back(new ObjectPipe());
m_pipes.back()->m_pipeId = ++m_pipeId;
m_pipes.back()->m_typeId = typeId;
m_pipes.back()->m_producer = producer;
m_pipes.back()->m_consumer = consumer;
m_pipes.back()->m_element = element;
m_producerPipes[producer].push_back(m_pipes.back());
m_consumerPipes[consumer].push_back(m_pipes.back());
m_typeIdPipes[typeId].push_back(m_pipes.back());
m_producerAndTypeIdPipes[std::make_tuple(producer, typeId)].push_back(m_pipes.back());
m_pipeMap[std::make_tuple(producer, consumer, typeId)] = m_pipes.back();
connect(producer, SIGNAL(destroyed(QObject*)), this, SLOT(removeProducer(QObject*)));
connect(consumer, SIGNAL(destroyed(QObject*)), this, SLOT(removeConsumer(QObject*)));
return m_pipes.back();
}
ObjectPipe *ObjectPipesRegistrations::unregisterProducerToConsumer(const QObject *producer, const QObject *consumer, const QString& type)
{
ObjectPipe *pipe = nullptr;
if (m_typeIds.contains(type))
{
int typeId = m_typeIds.value(type);
if (m_pipeMap.contains(std::make_tuple(producer, consumer, typeId)))
{
pipe = m_pipeMap[std::make_tuple(producer, consumer, typeId)];
m_producerPipes[producer].removeAll(pipe);
m_consumerPipes[consumer].removeAll(pipe);
m_typeIdPipes[typeId].removeAll(pipe);
m_producerAndTypeIdPipes[std::make_tuple(producer, typeId)].removeAll(pipe);
if (m_producerPipes[producer].size() == 0) {
m_producerPipes.remove(producer);
}
if (m_consumerPipes[consumer].size() == 0) {
m_consumerPipes.remove(consumer);
}
if (m_typeIdPipes[typeId].size() == 0) {
m_typeIdPipes.remove(typeId);
}
if (m_producerAndTypeIdPipes[std::make_tuple(producer, typeId)].size() == 0) {
m_producerAndTypeIdPipes.remove(std::make_tuple(producer, typeId));
}
pipe->setToBeDeleted(PipeDeletionReason::PipeDeleted);
}
}
return pipe;
}
void ObjectPipesRegistrations::getPipes(const QObject *producer, const QString& type, QList<ObjectPipe*>& pipes)
{
QMutexLocker mlock(&m_mutex);
if (m_typeIds.contains(type))
{
if (m_producerAndTypeIdPipes.contains(std::make_tuple(producer, m_typeIds[type]))) {
pipes = m_producerAndTypeIdPipes[std::make_tuple(producer, m_typeIds[type])];
}
}
}
void ObjectPipesRegistrations::processGC()
{
qDebug("ObjectPipesRegistrations::processGC");
QMutexLocker mlock(&m_mutex);
typename QList<ObjectPipe*>::iterator itPipe = m_pipes.begin();
while (itPipe != m_pipes.end())
{
if ((*itPipe)->getGCCount() > 0) // scheduled for deletion
{
if ((*itPipe)->decreaseGCCount() == 0) // delete on this pass
{
m_objectPipeElementsStore->deleteElement((*itPipe)->m_element);
delete *itPipe;
itPipe = m_pipes.erase(itPipe);
}
else
{
++itPipe;
}
}
}
}
void ObjectPipesRegistrations::removeProducer(QObject *producer)
{
qDebug("ObjectPipesRegistrations::removeProducer");
QMutexLocker mlock(&m_mutex);
if (m_producerPipes.contains(producer) && (m_producerPipes[producer].size() != 0))
{
const QList<ObjectPipe*>& pipeList = m_producerPipes[producer];
for (auto& pipe : pipeList)
{
for (const auto& consumer : m_consumerPipes.keys()) {
m_consumerPipes[consumer].removeAll(pipe);
}
for (const auto& typeId : m_typeIdPipes.keys()) {
m_typeIdPipes[typeId].removeAll(pipe);
}
pipe->setToBeDeleted(PipeDeletionReason::PipeProducerDeleted);
}
m_producerPipes.remove(producer);
}
typename QMap<std::tuple<const QObject*, const QObject*, int>, ObjectPipe*>::iterator itP = m_pipeMap.begin();
while (itP != m_pipeMap.end())
{
if (std::get<0>(itP.key())) {
itP = m_pipeMap.erase(itP);
} else {
++itP;
}
}
typename QMap<std::tuple<const QObject*, int>, QList<ObjectPipe*>>::iterator itPT = m_producerAndTypeIdPipes.begin();
while (itPT != m_producerAndTypeIdPipes.end())
{
if (std::get<0>(itPT.key()) == producer) {
itPT = m_producerAndTypeIdPipes.erase(itPT);
} else {
++itPT;
}
}
}
void ObjectPipesRegistrations::removeConsumer(QObject *consumer)
{
qDebug("ObjectPipesRegistrations::removeConsumer");
QMutexLocker mlock(&m_mutex);
if (m_consumerPipes.contains(consumer) && (m_consumerPipes[consumer].size() != 0))
{
QList<ObjectPipe*>& pipeList = m_consumerPipes[consumer];
for (auto& pipe : pipeList)
{
for (const auto& producer : m_producerPipes.keys()) {
m_producerPipes[producer].removeAll(pipe);
}
for (const auto& typeId : m_typeIdPipes.keys()) {
m_typeIdPipes[typeId].removeAll(pipe);
}
for (const auto& producerAndTypeId : m_producerAndTypeIdPipes.keys()) {
m_producerAndTypeIdPipes[producerAndTypeId].removeAll(pipe);
}
pipe->setToBeDeleted(PipeDeletionReason::PipeConsumerDeleted);
}
m_consumerPipes.remove(consumer);
}
typename QMap<std::tuple<const QObject*, const QObject*, int>, ObjectPipe*>::iterator it = m_pipeMap.begin();
while (it != m_pipeMap.end())
{
if (std::get<1>(it.key()) == consumer) {
it = m_pipeMap.erase(it);
} else {
++it;
}
}
}

View File

@ -0,0 +1,75 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2022 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_OBJECTPIPESREGISTRATION_H_
#define SDRBASE_PIPES_OBJECTPIPESREGISTRATION_H_
#include <QObject>
#include <QHash>
#include <QMap>
#include <QPair>
#include <QSet>
#include <QString>
#include <QMutex>
#include <tuple>
#include "export.h"
#include "objectpipe.h"
#include "objectpipeelementsstore.h"
class SDRBASE_API ObjectPipesRegistrations : public QObject
{
Q_OBJECT
public:
enum PipeDeletionReason
{
PipeProducerDeleted,
PipeConsumerDeleted,
PipeDeleted
};
ObjectPipesRegistrations(ObjectPipeElementsStore *objectPipeElementsStore);
~ObjectPipesRegistrations();
ObjectPipe *registerProducerToConsumer(const QObject *producer, const QObject *consumer, const QString& type);
ObjectPipe *unregisterProducerToConsumer(const QObject *producer, const QObject *consumer, const QString& type);
void getPipes(const QObject *producer, const QString& type, QList<ObjectPipe*>& pipes);
void processGC();
private slots:
void removeProducer(QObject *producer);
void removeConsumer(QObject *consumer);
private:
QHash<QString, int> m_typeIds;
QMap<int, QString> m_types;
int m_typeCount;
unsigned int m_pipeId;
ObjectPipeElementsStore *m_objectPipeElementsStore;
QList<ObjectPipe*> m_pipes;
QMap<const QObject*, QList<ObjectPipe*>> m_producerPipes;
QMap<const QObject*, QList<ObjectPipe*>> m_consumerPipes;
QMap<int, QList<ObjectPipe*>> m_typeIdPipes;
QMap<std::tuple<const QObject*, int>, QList<ObjectPipe*>> m_producerAndTypeIdPipes;
QMap<std::tuple<const QObject*, const QObject*, int>, ObjectPipe*> m_pipeMap;
QMutex m_mutex;
};
#endif // SDRBASE_PIPES_OBJECTPIPESREGISTRATION_H_