Threads vs. Queues lifetimes, cleanups.

- Ideally Queues must outlive the threads using them, but wasn't done so. Yes, std::shared_ptr them!
- Now queues are always valid in the context of the threads using them.
- No longer need tedious queues deallocation by the original owner.
- Misc cleanups.
This commit is contained in:
vsonnier 2017-08-13 18:49:47 +02:00
parent 98c7c30aee
commit c64baab99d
31 changed files with 162 additions and 153 deletions

View File

@ -32,6 +32,8 @@ IMPLEMENT_APP(CubicSDR)
#include "ActionDialog.h"
#include <memory>
//#ifdef ENABLE_DIGITAL_LAB
//// console output buffer for windows
@ -290,17 +292,17 @@ bool CubicSDR::OnInit() {
// Visual Data
spectrumVisualThread = new SpectrumVisualDataThread();
pipeIQVisualData = new DemodulatorThreadInputQueue();
pipeIQVisualData = std::make_shared<DemodulatorThreadInputQueue>();
pipeIQVisualData->set_max_num_items(1);
pipeWaterfallIQVisualData = new DemodulatorThreadInputQueue();
pipeWaterfallIQVisualData = std::make_shared<DemodulatorThreadInputQueue>();
pipeWaterfallIQVisualData->set_max_num_items(128);
getSpectrumProcessor()->setInput(pipeIQVisualData);
getSpectrumProcessor()->setHideDC(true);
// I/Q Data
pipeSDRIQData = new SDRThreadIQDataQueue();
pipeSDRIQData = std::make_shared<SDRThreadIQDataQueue>();
pipeSDRIQData->set_max_num_items(100);
sdrThread = new SDRThread();
@ -313,7 +315,7 @@ bool CubicSDR::OnInit() {
sdrPostThread->setOutputQueue("IQDataOutput", pipeWaterfallIQVisualData);
#if CUBICSDR_ENABLE_VIEW_SCOPE
pipeAudioVisualData = new DemodulatorThreadOutputQueue();
pipeAudioVisualData = std::make_shared<DemodulatorThreadOutputQueue>();
pipeAudioVisualData->set_max_num_items(1);
scopeProcessor.setInput(pipeAudioVisualData);
@ -323,7 +325,7 @@ bool CubicSDR::OnInit() {
#if CUBICSDR_ENABLE_VIEW_DEMOD
demodVisualThread = new SpectrumVisualDataThread();
pipeDemodIQVisualData = new DemodulatorThreadInputQueue();
pipeDemodIQVisualData = std::make_shared<DemodulatorThreadInputQueue>();
pipeDemodIQVisualData->set_max_num_items(1);
if (getDemodSpectrumProcessor()) {
@ -478,15 +480,6 @@ int CubicSDR::OnExit() {
delete demodVisualThread;
demodVisualThread = nullptr;
delete pipeIQVisualData;
pipeIQVisualData = nullptr;
delete pipeAudioVisualData;
pipeAudioVisualData = nullptr;
delete pipeSDRIQData;
pipeSDRIQData = nullptr;
delete m_glContext;
m_glContext = nullptr;
@ -795,15 +788,15 @@ SpectrumVisualProcessor *CubicSDR::getDemodSpectrumProcessor() {
}
}
DemodulatorThreadOutputQueue* CubicSDR::getAudioVisualQueue() {
DemodulatorThreadOutputQueuePtr CubicSDR::getAudioVisualQueue() {
return pipeAudioVisualData;
}
DemodulatorThreadInputQueue* CubicSDR::getIQVisualQueue() {
DemodulatorThreadInputQueuePtr CubicSDR::getIQVisualQueue() {
return pipeIQVisualData;
}
DemodulatorThreadInputQueue* CubicSDR::getWaterfallVisualQueue() {
DemodulatorThreadInputQueuePtr CubicSDR::getWaterfallVisualQueue() {
return pipeWaterfallIQVisualData;
}

View File

@ -107,10 +107,10 @@ public:
SpectrumVisualProcessor *getSpectrumProcessor();
SpectrumVisualProcessor *getDemodSpectrumProcessor();
DemodulatorThreadOutputQueue* getAudioVisualQueue();
DemodulatorThreadInputQueue* getIQVisualQueue();
DemodulatorThreadInputQueue* getWaterfallVisualQueue();
DemodulatorThreadInputQueue* getActiveDemodVisualQueue();
DemodulatorThreadOutputQueuePtr getAudioVisualQueue();
DemodulatorThreadInputQueuePtr getIQVisualQueue();
DemodulatorThreadInputQueuePtr getWaterfallVisualQueue();
DemodulatorThreadInputQueuePtr getActiveDemodVisualQueue();
DemodulatorMgr &getDemodMgr();
BookmarkMgr &getBookmarkMgr();
@ -197,12 +197,12 @@ private:
SpectrumVisualDataThread *spectrumVisualThread = nullptr;
SpectrumVisualDataThread *demodVisualThread = nullptr;
SDRThreadIQDataQueue* pipeSDRIQData = nullptr;
DemodulatorThreadInputQueue* pipeIQVisualData = nullptr;
DemodulatorThreadOutputQueue* pipeAudioVisualData = nullptr;
DemodulatorThreadInputQueue* pipeDemodIQVisualData = nullptr;
DemodulatorThreadInputQueue* pipeWaterfallIQVisualData = nullptr;
DemodulatorThreadInputQueue* pipeActiveDemodIQVisualData = nullptr;
SDRThreadIQDataQueuePtr pipeSDRIQData = nullptr;
DemodulatorThreadInputQueuePtr pipeIQVisualData = nullptr;
DemodulatorThreadOutputQueuePtr pipeAudioVisualData = nullptr;
DemodulatorThreadInputQueuePtr pipeDemodIQVisualData = nullptr;
DemodulatorThreadInputQueuePtr pipeWaterfallIQVisualData = nullptr;
DemodulatorThreadInputQueuePtr pipeActiveDemodIQVisualData = nullptr;
ScopeVisualProcessor scopeProcessor;

View File

@ -3,6 +3,7 @@
#include "IOThread.h"
#include <typeinfo>
#include <memory>
#define SPIN_WAIT_SLEEP_MS 5
@ -68,32 +69,32 @@ void IOThread::terminate() {
stopping.store(true);
};
void IOThread::onBindOutput(std::string /* name */, ThreadQueueBase* /* threadQueue */) {
void IOThread::onBindOutput(std::string /* name */, ThreadQueueBasePtr /* threadQueue */) {
};
void IOThread::onBindInput(std::string /* name */, ThreadQueueBase* /* threadQueue */) {
void IOThread::onBindInput(std::string /* name */, ThreadQueueBasePtr /* threadQueue */) {
};
void IOThread::setInputQueue(std::string qname, ThreadQueueBase *threadQueue) {
void IOThread::setInputQueue(std::string qname, ThreadQueueBasePtr threadQueue) {
std::lock_guard < std::mutex > lock(m_queue_bindings_mutex);
input_queues[qname] = threadQueue;
this->onBindInput(qname, threadQueue);
};
ThreadQueueBase *IOThread::getInputQueue(std::string qname) {
ThreadQueueBasePtr IOThread::getInputQueue(std::string qname) {
std::lock_guard < std::mutex > lock(m_queue_bindings_mutex);
return input_queues[qname];
};
void IOThread::setOutputQueue(std::string qname, ThreadQueueBase *threadQueue) {
void IOThread::setOutputQueue(std::string qname, ThreadQueueBasePtr threadQueue) {
std::lock_guard < std::mutex > lock(m_queue_bindings_mutex);
output_queues[qname] = threadQueue;
this->onBindOutput(qname, threadQueue);
};
ThreadQueueBase *IOThread::getOutputQueue(std::string qname) {
ThreadQueueBasePtr IOThread::getOutputQueue(std::string qname) {
std::lock_guard < std::mutex > lock(m_queue_bindings_mutex);
return output_queues[qname];
};

View File

@ -175,17 +175,17 @@ public:
//If wait < 0, the wait in infinite until the thread dies.
bool isTerminated(int waitMs = 0);
virtual void onBindOutput(std::string name, ThreadQueueBase* threadQueue);
virtual void onBindInput(std::string name, ThreadQueueBase* threadQueue);
virtual void onBindOutput(std::string name, ThreadQueueBasePtr threadQueue);
virtual void onBindInput(std::string name, ThreadQueueBasePtr threadQueue);
void setInputQueue(std::string qname, ThreadQueueBase *threadQueue);
ThreadQueueBase *getInputQueue(std::string qname);
void setOutputQueue(std::string qname, ThreadQueueBase *threadQueue);
ThreadQueueBase *getOutputQueue(std::string qname);
void setInputQueue(std::string qname, ThreadQueueBasePtr threadQueue);
ThreadQueueBasePtr getInputQueue(std::string qname);
void setOutputQueue(std::string qname, ThreadQueueBasePtr threadQueue);
ThreadQueueBasePtr getOutputQueue(std::string qname);
protected:
std::map<std::string, ThreadQueueBase *, map_string_less> input_queues;
std::map<std::string, ThreadQueueBase *, map_string_less> output_queues;
std::map<std::string, ThreadQueueBasePtr, map_string_less> input_queues;
std::map<std::string, ThreadQueueBasePtr, map_string_less> output_queues;
//this protects against concurrent changes in input/output bindings: get/set/Input/OutPutQueue
std::mutex m_queue_bindings_mutex;

View File

@ -73,7 +73,7 @@ static int audioCallback(void *outputBuffer, void * /* inputBuffer */, unsigned
//Zero output buffer in all cases: this allow to mute audio if no AudioThread data is
//actually active.
memset(out, 0, nBufferFrames * 2 * sizeof(float));
::memset(out, 0, nBufferFrames * 2 * sizeof(float));
AudioThread *src = (AudioThread *) userData;
@ -424,8 +424,8 @@ void AudioThread::run() {
setupDevice((outputDevice.load() == -1) ? (dac.getDefaultOutputDevice()) : outputDevice.load());
// std::cout << "Audio thread started." << std::endl;
inputQueue = static_cast<AudioThreadInputQueue *>(getInputQueue("AudioDataInput"));
inputQueue = std::static_pointer_cast<AudioThreadInputQueue>(getInputQueue("AudioDataInput"));
//Infinite loop, witing for commands or for termination
while (!stopping) {
@ -451,7 +451,7 @@ void AudioThread::run() {
if (inputQueue != nullptr) {
inputQueue->flush();
}
//Nullify currentInput...
currentInput = nullptr;
@ -499,7 +499,6 @@ void AudioThread::setActive(bool state) {
// Activity state changing, clear any inputs
if(inputQueue) {
inputQueue->flush();
}
active = state;

View File

@ -52,10 +52,13 @@ public:
typedef ThreadBlockingQueue<AudioThreadInputPtr> AudioThreadInputQueue;
typedef ThreadBlockingQueue<AudioThreadCommand> AudioThreadCommandQueue;
typedef std::shared_ptr<AudioThreadInputQueue> AudioThreadInputQueuePtr;
typedef std::shared_ptr<AudioThreadCommandQueue> AudioThreadCommandQueuePtr;
class AudioThread : public IOThread {
public:
AudioThreadInputPtr currentInput;
AudioThreadInputQueue *inputQueue;
AudioThreadInputQueuePtr inputQueue;
std::atomic_uint audioQueuePtr;
std::atomic_uint underflowCount;
std::atomic_bool initialized;

View File

@ -103,6 +103,10 @@ public:
typedef std::shared_ptr<DemodulatorThreadIQData> DemodulatorThreadIQDataPtr;
typedef std::shared_ptr<DemodulatorThreadPostIQData> DemodulatorThreadPostIQDataPtr;
typedef ThreadBlockingQueue< DemodulatorThreadIQDataPtr > DemodulatorThreadInputQueue;
typedef ThreadBlockingQueue< DemodulatorThreadPostIQDataPtr > DemodulatorThreadPostInputQueue;
typedef ThreadBlockingQueue<DemodulatorThreadIQDataPtr> DemodulatorThreadInputQueue;
typedef ThreadBlockingQueue<DemodulatorThreadPostIQDataPtr> DemodulatorThreadPostInputQueue;
typedef ThreadBlockingQueue<DemodulatorThreadControlCommand> DemodulatorThreadControlCommandQueue;
typedef std::shared_ptr<DemodulatorThreadInputQueue> DemodulatorThreadInputQueuePtr;
typedef std::shared_ptr<DemodulatorThreadPostInputQueue> DemodulatorThreadPostInputQueuePtr;
typedef std::shared_ptr<DemodulatorThreadControlCommandQueue> DemodulatorThreadControlCommandQueuePtr;

View File

@ -1,6 +1,7 @@
// Copyright (c) Charles J. Cliffe
// SPDX-License-Identifier: GPL-2.0+
#include <memory>
#include "DemodulatorInstance.h"
#include "CubicSDR.h"
@ -52,9 +53,9 @@ DemodulatorInstance::DemodulatorInstance() {
label.store(new std::string("Unnamed"));
user_label.store(new std::wstring());
pipeIQInputData = new DemodulatorThreadInputQueue;
pipeIQInputData = std::make_shared<DemodulatorThreadInputQueue>();
pipeIQInputData->set_max_num_items(100);
pipeIQDemodData = new DemodulatorThreadPostInputQueue;
pipeIQDemodData = std::make_shared< DemodulatorThreadPostInputQueue>();
pipeIQInputData->set_max_num_items(100);
audioThread = new AudioThread();
@ -63,10 +64,10 @@ DemodulatorInstance::DemodulatorInstance() {
demodulatorPreThread->setInputQueue("IQDataInput",pipeIQInputData);
demodulatorPreThread->setOutputQueue("IQDataOutput",pipeIQDemodData);
pipeAudioData = new AudioThreadInputQueue;
pipeAudioData = std::make_shared< AudioThreadInputQueue>();
pipeAudioData->set_max_num_items(10);
threadQueueControl = new DemodulatorThreadControlCommandQueue;
threadQueueControl = std::make_shared< DemodulatorThreadControlCommandQueue>();
threadQueueControl->set_max_num_items(2);
demodulatorThread = new DemodulatorThread(this);
@ -85,15 +86,9 @@ DemodulatorInstance::~DemodulatorInstance() {
delete audioThread;
delete demodulatorThread;
delete demodulatorPreThread;
delete pipeIQInputData;
delete pipeIQDemodData;
delete threadQueueControl;
delete pipeAudioData;
// wxGetApp().getBookmarkMgr().updateActiveList();
}
void DemodulatorInstance::setVisualOutputQueue(DemodulatorThreadOutputQueue *tQueue) {
void DemodulatorInstance::setVisualOutputQueue(DemodulatorThreadOutputQueuePtr tQueue) {
demodulatorThread->setOutputQueue("AudioVisualOutput", tQueue);
}
@ -131,8 +126,6 @@ void DemodulatorInstance::run() {
#endif
active = true;
// wxGetApp().getBookmarkMgr().updateActiveList();
}
void DemodulatorInstance::updateLabel(long long freq) {
@ -492,7 +485,7 @@ DemodVisualCue *DemodulatorInstance::getVisualCue() {
return &visualCue;
}
DemodulatorThreadInputQueue *DemodulatorInstance::getIQInputDataPipe() {
DemodulatorThreadInputQueuePtr DemodulatorInstance::getIQInputDataPipe() {
return pipeIQInputData;
}

View File

@ -48,7 +48,7 @@ public:
DemodulatorInstance();
~DemodulatorInstance();
void setVisualOutputQueue(DemodulatorThreadOutputQueue *tQueue);
void setVisualOutputQueue(DemodulatorThreadOutputQueuePtr tQueue);
void run();
void terminate();
@ -111,7 +111,7 @@ public:
DemodVisualCue *getVisualCue();
DemodulatorThreadInputQueue *getIQInputDataPipe();
DemodulatorThreadInputQueuePtr getIQInputDataPipe();
ModemArgInfoList getModemArgs();
std::string readModemSetting(std::string setting);
@ -131,12 +131,12 @@ public:
#endif
private:
DemodulatorThreadInputQueue* pipeIQInputData;
DemodulatorThreadPostInputQueue* pipeIQDemodData;
AudioThreadInputQueue *pipeAudioData;
DemodulatorThreadInputQueuePtr pipeIQInputData;
DemodulatorThreadPostInputQueuePtr pipeIQDemodData;
AudioThreadInputQueuePtr pipeAudioData;
DemodulatorPreThread *demodulatorPreThread;
DemodulatorThread *demodulatorThread;
DemodulatorThreadControlCommandQueue *threadQueueControl;
DemodulatorThreadControlCommandQueuePtr threadQueueControl;
//protects child thread creation and termination
std::mutex m_thread_control_mutex;

View File

@ -23,10 +23,10 @@ DemodulatorPreThread::DemodulatorPreThread(DemodulatorInstance *parent) : IOThre
freqShifter = nco_crcf_create(LIQUID_VCO);
shiftFrequency = 0;
workerQueue = new DemodulatorThreadWorkerCommandQueue;
workerQueue = std::make_shared<DemodulatorThreadWorkerCommandQueue>();
workerQueue->set_max_num_items(2);
workerResults = new DemodulatorThreadWorkerResultQueue;
workerResults = std::make_shared<DemodulatorThreadWorkerResultQueue>();
workerResults->set_max_num_items(100);
workerThread = new DemodulatorWorkerThread();
@ -65,8 +65,8 @@ void DemodulatorPreThread::run() {
ReBuffer<DemodulatorThreadPostIQData> buffers("DemodulatorPreThreadBuffers");
iqInputQueue = static_cast<DemodulatorThreadInputQueue*>(getInputQueue("IQDataInput"));
iqOutputQueue = static_cast<DemodulatorThreadPostInputQueue*>(getOutputQueue("IQDataOutput"));
iqInputQueue = std::static_pointer_cast<DemodulatorThreadInputQueue>(getInputQueue("IQDataInput"));
iqOutputQueue = std::static_pointer_cast<DemodulatorThreadPostInputQueue>(getOutputQueue("IQDataOutput"));
std::vector<liquid_float_complex> in_buf_data;
std::vector<liquid_float_complex> out_buf_data;
@ -359,7 +359,7 @@ void DemodulatorPreThread::terminate() {
DemodulatorWorkerThreadCommand command;
//VSO: blocking push :
workerQueue->push(command);
//wait blocking for termination here, it could be long with lots of modems and we MUST terminate properly,
//else better kill the whole application...
workerThread->isTerminated(5000);
@ -370,12 +370,6 @@ void DemodulatorPreThread::terminate() {
delete workerThread;
workerThread = nullptr;
delete workerResults;
workerResults = nullptr;
delete workerQueue;
workerQueue = nullptr;
}
Modem *DemodulatorPreThread::getModem() {

View File

@ -6,6 +6,7 @@
#include <queue>
#include <vector>
#include <atomic>
#include <memory>
#include "CubicSDRDefs.h"
#include "DemodDefs.h"
@ -78,9 +79,9 @@ protected:
DemodulatorWorkerThread *workerThread;
std::thread *t_Worker;
DemodulatorThreadWorkerCommandQueue *workerQueue;
DemodulatorThreadWorkerResultQueue *workerResults;
DemodulatorThreadWorkerCommandQueuePtr workerQueue;
DemodulatorThreadWorkerResultQueuePtr workerResults;
DemodulatorThreadInputQueue* iqInputQueue;
DemodulatorThreadPostInputQueue* iqOutputQueue;
DemodulatorThreadInputQueuePtr iqInputQueue;
DemodulatorThreadPostInputQueuePtr iqOutputQueue;
};

View File

@ -35,13 +35,13 @@ DemodulatorThread::~DemodulatorThread() {
releaseSquelchLock(demodInstance);
}
void DemodulatorThread::onBindOutput(std::string name, ThreadQueueBase *threadQueue) {
void DemodulatorThread::onBindOutput(std::string name, ThreadQueueBasePtr threadQueue) {
if (name == "AudioVisualOutput") {
//protects because it may be changed at runtime
std::lock_guard < std::mutex > lock(m_mutexAudioVisOutputQueue);
audioVisOutputQueue = static_cast<DemodulatorThreadOutputQueue*>(threadQueue);
audioVisOutputQueue = std::static_pointer_cast<DemodulatorThreadOutputQueue>(threadQueue);
}
}
@ -75,9 +75,9 @@ void DemodulatorThread::run() {
// std::cout << "Demodulator thread started.." << std::endl;
iqInputQueue = static_cast<DemodulatorThreadPostInputQueue*>(getInputQueue("IQDataInput"));
audioOutputQueue = static_cast<AudioThreadInputQueue*>(getOutputQueue("AudioDataOutput"));
threadQueueControl = static_cast<DemodulatorThreadControlCommandQueue *>(getInputQueue("ControlQueue"));
iqInputQueue = std::static_pointer_cast<DemodulatorThreadPostInputQueue>(getInputQueue("IQDataInput"));
audioOutputQueue = std::static_pointer_cast<AudioThreadInputQueue>(getOutputQueue("AudioDataOutput"));
threadQueueControl = std::static_pointer_cast<DemodulatorThreadControlCommandQueue>(getInputQueue("ControlQueue"));
ModemIQData modemData;
@ -234,7 +234,7 @@ void DemodulatorThread::run() {
//At that point, capture the current state of audioVisOutputQueue in a local
//variable, and works with it with now on until the next while-turn.
DemodulatorThreadOutputQueue* localAudioVisOutputQueue = nullptr;
DemodulatorThreadOutputQueuePtr localAudioVisOutputQueue = nullptr;
{
std::lock_guard < std::mutex > lock(m_mutexAudioVisOutputQueue);
localAudioVisOutputQueue = audioVisOutputQueue;

View File

@ -5,6 +5,7 @@
#include <queue>
#include <vector>
#include <memory>
#include "DemodDefs.h"
#include "AudioThread.h"
@ -12,6 +13,8 @@
typedef ThreadBlockingQueue<AudioThreadInputPtr> DemodulatorThreadOutputQueue;
typedef std::shared_ptr<DemodulatorThreadOutputQueue> DemodulatorThreadOutputQueuePtr;
#define DEMOD_VIS_SIZE 2048
#define DEMOD_SIGNAL_MIN -30
#define DEMOD_SIGNAL_MAX 30
@ -24,7 +27,7 @@ public:
DemodulatorThread(DemodulatorInstance *parent);
virtual ~DemodulatorThread();
void onBindOutput(std::string name, ThreadQueueBase *threadQueue);
void onBindOutput(std::string name, ThreadQueueBasePtr threadQueue);
void run();
void terminate();
@ -62,10 +65,10 @@ protected:
Modem *cModem = nullptr;
ModemKit *cModemKit = nullptr;
DemodulatorThreadPostInputQueue* iqInputQueue = nullptr;
AudioThreadInputQueue *audioOutputQueue = nullptr;
DemodulatorThreadOutputQueue* audioVisOutputQueue = nullptr;
DemodulatorThreadControlCommandQueue *threadQueueControl = nullptr;
DemodulatorThreadPostInputQueuePtr iqInputQueue = nullptr;
AudioThreadInputQueuePtr audioOutputQueue = nullptr;
DemodulatorThreadOutputQueuePtr audioVisOutputQueue = nullptr;
DemodulatorThreadControlCommandQueuePtr threadQueueControl = nullptr;
//protects the audioVisOutputQueue dynamic binding change at runtime (in DemodulatorMgr)
std::mutex m_mutexAudioVisOutputQueue;

View File

@ -10,7 +10,7 @@
#define HEARTBEAT_CHECK_PERIOD_MICROS (50 * 1000)
DemodulatorWorkerThread::DemodulatorWorkerThread() : IOThread(),
commandQueue(NULL), resultQueue(NULL), cModem(nullptr), cModemKit(nullptr) {
commandQueue(nullptr), resultQueue(nullptr), cModem(nullptr), cModemKit(nullptr) {
}
DemodulatorWorkerThread::~DemodulatorWorkerThread() {
@ -20,8 +20,8 @@ void DemodulatorWorkerThread::run() {
// std::cout << "Demodulator worker thread started.." << std::endl;
commandQueue = static_cast<DemodulatorThreadWorkerCommandQueue *>(getInputQueue("WorkerCommandQueue"));
resultQueue = static_cast<DemodulatorThreadWorkerResultQueue *>(getOutputQueue("WorkerResultQueue"));
commandQueue = std::static_pointer_cast<DemodulatorThreadWorkerCommandQueue>(getInputQueue("WorkerCommandQueue"));
resultQueue = std::static_pointer_cast<DemodulatorThreadWorkerResultQueue>(getOutputQueue("WorkerResultQueue"));
while (!stopping) {
bool filterChanged = false;

View File

@ -5,7 +5,7 @@
#include <queue>
#include <vector>
#include <memory>
#include "liquid/liquid.h"
#include "AudioThread.h"
#include "ThreadBlockingQueue.h"
@ -72,6 +72,9 @@ public:
typedef ThreadBlockingQueue<DemodulatorWorkerThreadCommand> DemodulatorThreadWorkerCommandQueue;
typedef ThreadBlockingQueue<DemodulatorWorkerThreadResult> DemodulatorThreadWorkerResultQueue;
typedef std::shared_ptr<DemodulatorThreadWorkerCommandQueue> DemodulatorThreadWorkerCommandQueuePtr;
typedef std::shared_ptr<DemodulatorThreadWorkerResultQueue> DemodulatorThreadWorkerResultQueuePtr;
class DemodulatorWorkerThread : public IOThread {
public:
@ -80,11 +83,11 @@ public:
virtual void run();
void setCommandQueue(DemodulatorThreadWorkerCommandQueue *tQueue) {
void setCommandQueue(DemodulatorThreadWorkerCommandQueuePtr tQueue) {
commandQueue = tQueue;
}
void setResultQueue(DemodulatorThreadWorkerResultQueue *tQueue) {
void setResultQueue(DemodulatorThreadWorkerResultQueuePtr tQueue) {
resultQueue = tQueue;
}
@ -92,8 +95,8 @@ public:
protected:
DemodulatorThreadWorkerCommandQueue *commandQueue;
DemodulatorThreadWorkerResultQueue *resultQueue;
DemodulatorThreadWorkerCommandQueuePtr commandQueue;
DemodulatorThreadWorkerResultQueuePtr resultQueue;
Modem *cModem;
ModemKit *cModemKit;
std::string cModemType;

View File

@ -27,11 +27,12 @@ SpectrumVisualProcessor *FFTVisualDataThread::getProcessor() {
}
void FFTVisualDataThread::run() {
DemodulatorThreadInputQueue *pipeIQDataIn = static_cast<DemodulatorThreadInputQueue *>(getInputQueue("IQDataInput"));
SpectrumVisualDataQueue *pipeFFTDataOut = static_cast<SpectrumVisualDataQueue *>(getOutputQueue("FFTDataOutput"));
DemodulatorThreadInputQueuePtr pipeIQDataIn = std::static_pointer_cast<DemodulatorThreadInputQueue>(getInputQueue("IQDataInput"));
SpectrumVisualDataQueuePtr pipeFFTDataOut = std::static_pointer_cast<SpectrumVisualDataQueue>(getOutputQueue("FFTDataOutput"));
fftQueue.set_max_num_items(100);
fftQueue->set_max_num_items(100);
pipeFFTDataOut->set_max_num_items(100);
//FFT distributor plumbing:
@ -39,10 +40,10 @@ void FFTVisualDataThread::run() {
fftDistrib.setInput(pipeIQDataIn);
//The FFT distributor has actually 1 output only, so it doesn't distribute at all :)
fftDistrib.attachOutput(&fftQueue);
fftDistrib.attachOutput(fftQueue);
//FFT Distributor output is ==> SpectrumVisualProcessor input.
wproc.setInput(&fftQueue);
wproc.setInput(fftQueue);
wproc.attachOutput(pipeFFTDataOut);
wproc.setup(DEFAULT_FFT_SIZE);

View File

@ -2,7 +2,7 @@
// SPDX-License-Identifier: GPL-2.0+
#pragma once
#include <memory>
#include "IOThread.h"
#include "SpectrumVisualProcessor.h"
#include "FFTDataDistributor.h"
@ -20,7 +20,7 @@ public:
protected:
FFTDataDistributor fftDistrib;
DemodulatorThreadInputQueue fftQueue;
DemodulatorThreadInputQueuePtr fftQueue = std::make_shared<DemodulatorThreadInputQueue>();
SpectrumVisualProcessor wproc;
std::atomic_int linesPerSecond;

View File

@ -28,6 +28,8 @@ typedef std::shared_ptr<ScopeRenderData> ScopeRenderDataPtr;
typedef ThreadBlockingQueue<ScopeRenderDataPtr> ScopeRenderDataQueue;
typedef std::shared_ptr<ScopeRenderDataQueue> ScopeRenderDataQueuePtr;
class ScopeVisualProcessor : public VisualProcessor<AudioThreadInput, ScopeRenderData> {
public:
ScopeVisualProcessor();

View File

@ -24,6 +24,7 @@ public:
typedef std::shared_ptr<SpectrumVisualData> SpectrumVisualDataPtr;
typedef ThreadBlockingQueue<SpectrumVisualDataPtr> SpectrumVisualDataQueue;
typedef std::shared_ptr<SpectrumVisualDataQueue> SpectrumVisualDataQueuePtr;
class SpectrumVisualProcessor : public VisualProcessor<DemodulatorThreadIQData, SpectrumVisualData> {
public:

View File

@ -21,7 +21,10 @@ public:
typedef ThreadBlockingQueue<InputDataTypePtr> VisualInputQueueType;
typedef ThreadBlockingQueue<OutputDataTypePtr> VisualOutputQueueType;
typedef typename std::vector< VisualOutputQueueType *>::iterator outputs_i;
typedef std::shared_ptr<VisualInputQueueType> VisualInputQueueTypePtr;
typedef std::shared_ptr<VisualOutputQueueType> VisualOutputQueueTypePtr;
typedef typename std::vector< VisualOutputQueueTypePtr >::iterator outputs_i;
virtual ~VisualProcessor() {
}
@ -35,8 +38,8 @@ public:
bool isOutputEmpty() {
std::lock_guard < std::recursive_mutex > busy_lock(busy_update);
for (outputs_i it = outputs.begin(); it != outputs.end(); it++) {
if ((*it)->full()) {
for (VisualOutputQueueTypePtr single_output : outputs) {
if (single_output->full()) {
return false;
}
}
@ -46,8 +49,8 @@ public:
bool isAnyOutputEmpty() {
std::lock_guard < std::recursive_mutex > busy_lock(busy_update);
for (outputs_i it = outputs.begin(); it != outputs.end(); it++) {
if (!(*it)->full()) {
for (VisualOutputQueueTypePtr single_output : outputs) {
if (!(single_output)->full()) {
return true;
}
}
@ -55,7 +58,7 @@ public:
}
//Set a (new) 'input' queue for incoming data.
void setInput(VisualInputQueueType *vis_in) {
void setInput(VisualInputQueueTypePtr vis_in) {
std::lock_guard < std::recursive_mutex > busy_lock(busy_update);
input = vis_in;
@ -63,14 +66,14 @@ public:
//Add a vis_out queue where to consumed 'input' data will be
//dispatched by distribute().
void attachOutput(VisualOutputQueueType *vis_out) {
void attachOutput(VisualOutputQueueTypePtr vis_out) {
// attach an output queue
std::lock_guard < std::recursive_mutex > busy_lock(busy_update);
outputs.push_back(vis_out);
}
//reverse of attachOutput(), removed an existing attached vis_out.
void removeOutput(VisualOutputQueueType *vis_out) {
void removeOutput(VisualOutputQueueTypePtr vis_out) {
// remove an output queue
std::lock_guard < std::recursive_mutex > busy_lock(busy_update);
@ -108,20 +111,20 @@ protected:
//We will try to distribute 'output' among all 'outputs',
//so 'output' will a-priori be shared among all 'outputs'.
for (outputs_i it = outputs.begin(); it != outputs.end(); it++) {
for (VisualOutputQueueTypePtr single_output : outputs) {
//'output' can fail to be given to an outputs_i,
//using a blocking push, with a timeout
if (!(*it)->push(item, timeout, errorMessage)) {
if (!(single_output)->push(item, timeout, errorMessage)) {
//TODO : trace ?
}
}
}
//the incoming data queue
VisualInputQueueType *input = nullptr;
VisualInputQueueTypePtr input = nullptr;
//the n-outputs where to process()-ed data is distribute()-ed.
std::vector<VisualOutputQueueType *> outputs;
std::vector<VisualOutputQueueTypePtr> outputs;
//protects input and outputs, must be recursive because of re-entrance
std::recursive_mutex busy_update;

View File

@ -7,6 +7,7 @@
#include <vector>
#include <deque>
#include <memory>
//50 ms
#define HEARTBEAT_CHECK_PERIOD_MICROS (50 * 1000)
@ -179,10 +180,10 @@ void SDRPostThread::run() {
// std::cout << "SDR post-processing thread started.." << std::endl;
iqDataInQueue = static_cast<SDRThreadIQDataQueue*>(getInputQueue("IQDataInput"));
iqDataOutQueue = static_cast<DemodulatorThreadInputQueue*>(getOutputQueue("IQDataOutput"));
iqVisualQueue = static_cast<DemodulatorThreadInputQueue*>(getOutputQueue("IQVisualDataOutput"));
iqActiveDemodVisualQueue = static_cast<DemodulatorThreadInputQueue*>(getOutputQueue("IQActiveDemodVisualDataOutput"));
iqDataInQueue = std::static_pointer_cast<SDRThreadIQDataQueue>(getInputQueue("IQDataInput"));
iqDataOutQueue = std::static_pointer_cast<DemodulatorThreadInputQueue>(getOutputQueue("IQDataOutput"));
iqVisualQueue = std::static_pointer_cast<DemodulatorThreadInputQueue>(getOutputQueue("IQVisualDataOutput"));
iqActiveDemodVisualQueue = std::static_pointer_cast<DemodulatorThreadInputQueue>(getOutputQueue("IQActiveDemodVisualDataOutput"));
while (!stopping) {
SDRThreadIQDataPtr data_in;

View File

@ -23,10 +23,10 @@ public:
void setIQVisualRange(long long frequency, int bandwidth);
protected:
SDRThreadIQDataQueue *iqDataInQueue;
DemodulatorThreadInputQueue *iqDataOutQueue;
DemodulatorThreadInputQueue *iqVisualQueue;
DemodulatorThreadInputQueue *iqActiveDemodVisualQueue;
SDRThreadIQDataQueuePtr iqDataInQueue;
DemodulatorThreadInputQueuePtr iqDataOutQueue;
DemodulatorThreadInputQueuePtr iqVisualQueue;
DemodulatorThreadInputQueuePtr iqActiveDemodVisualQueue;
//protects access to demodulators lists and such
std::mutex busy_demod;

View File

@ -191,7 +191,7 @@ void SDRThread::assureBufferMinSize(SDRThreadIQData * dataOut, size_t minSize) {
//Called in an infinite loop, read SaopySDR device to build
// a 'this.numElems' sized batch of samples (SDRThreadIQData) and push it into iqDataOutQueue.
//this batch of samples is built to represent 1 frame / TARGET_DISPLAY_FPS.
void SDRThread::readStream(SDRThreadIQDataQueue* iqDataOutQueue) {
void SDRThread::readStream(SDRThreadIQDataQueuePtr iqDataOutQueue) {
int flags;
long long timeNs;
@ -365,9 +365,10 @@ void SDRThread::readStream(SDRThreadIQDataQueue* iqDataOutQueue) {
}
void SDRThread::readLoop() {
SDRThreadIQDataQueue* iqDataOutQueue = static_cast<SDRThreadIQDataQueue*>( getOutputQueue("IQDataOutput"));
SDRThreadIQDataQueuePtr iqDataOutQueue = std::static_pointer_cast<SDRThreadIQDataQueue>( getOutputQueue("IQDataOutput"));
if (iqDataOutQueue == NULL) {
if (iqDataOutQueue == nullptr) {
return;
}

View File

@ -41,12 +41,13 @@ public:
};
typedef std::shared_ptr<SDRThreadIQData> SDRThreadIQDataPtr;
typedef ThreadBlockingQueue<SDRThreadIQDataPtr> SDRThreadIQDataQueue;
typedef std::shared_ptr<SDRThreadIQDataQueue> SDRThreadIQDataQueuePtr;
class SDRThread : public IOThread {
private:
bool init();
void deinit();
void readStream(SDRThreadIQDataQueue* iqDataOutQueue);
void readStream(SDRThreadIQDataQueuePtr iqDataOutQueue);
void readLoop();
public:

View File

@ -25,6 +25,8 @@
class ThreadQueueBase {
};
typedef std::shared_ptr<ThreadQueueBase> ThreadQueueBasePtr;
/** A thread-safe asynchronous blocking queue */
template<typename T>
class ThreadBlockingQueue : public ThreadQueueBase {

View File

@ -34,7 +34,7 @@ wxEND_EVENT_TABLE()
ScopeCanvas::ScopeCanvas(wxWindow *parent, std::vector<int> dispAttrs) : InteractiveCanvas(parent, dispAttrs), ppmMode(false), ctr(0), ctrTarget(0), dragAccel(0), helpTip("") {
glContext = new ScopeContext(this, &wxGetApp().GetContext(this));
inputData.set_max_num_items(2);
inputData->set_max_num_items(2);
bgPanel.setFill(GLPanel::GLPANEL_FILL_GRAD_Y);
bgPanel.setSize(1.0, 0.5f);
bgPanel.setPosition(0.0, -0.5f);
@ -105,7 +105,7 @@ void ScopeCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) {
const wxSize ClientSize = GetClientSize();
ScopeRenderDataPtr avData;
while (inputData.try_pop(avData)) {
while (inputData->try_pop(avData)) {
if (!avData->spectrum) {
@ -233,8 +233,8 @@ void ScopeCanvas::OnIdle(wxIdleEvent &event) {
event.RequestMore();
}
ScopeRenderDataQueue *ScopeCanvas::getInputQueue() {
return &inputData;
ScopeRenderDataQueuePtr ScopeCanvas::getInputQueue() {
return inputData;
}
void ScopeCanvas::OnMouseMoved(wxMouseEvent& event) {

View File

@ -8,6 +8,7 @@
#include <vector>
#include <queue>
#include <memory>
#include "ScopeContext.h"
#include "ScopeVisualProcessor.h"
@ -42,7 +43,7 @@ public:
void setHelpTip(std::string tip);
ScopeRenderDataQueue *getInputQueue();
ScopeRenderDataQueuePtr getInputQueue();
private:
void OnPaint(wxPaintEvent& event);
@ -54,7 +55,7 @@ private:
void OnMouseEnterWindow(wxMouseEvent& event);
void OnMouseLeftWindow(wxMouseEvent& event);
ScopeRenderDataQueue inputData;
ScopeRenderDataQueuePtr inputData = std::make_shared<ScopeRenderDataQueue>();
ScopePanel scopePanel;
GLPanel parentPanel;
SpectrumPanel spectrumPanel;

View File

@ -37,7 +37,7 @@ SpectrumCanvas::SpectrumCanvas(wxWindow *parent, std::vector<int> dispAttrs) :
glContext = new PrimaryGLContext(this, &wxGetApp().GetContext(this));
visualDataQueue.set_max_num_items(1);
visualDataQueue->set_max_num_items(1);
SetCursor(wxCURSOR_SIZEWE);
scaleFactor = 1.0;
@ -55,7 +55,7 @@ void SpectrumCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) {
const wxSize ClientSize = GetClientSize();
SpectrumVisualDataPtr vData;
if (visualDataQueue.try_pop(vData)) {
if (visualDataQueue->try_pop(vData)) {
if (vData) {
spectrumPanel.setPoints(vData->spectrum_points);
@ -286,8 +286,8 @@ void SpectrumCanvas::attachWaterfallCanvas(WaterfallCanvas* canvas_in) {
waterfallCanvas = canvas_in;
}
SpectrumVisualDataQueue *SpectrumCanvas::getVisualDataQueue() {
return &visualDataQueue;
SpectrumVisualDataQueuePtr SpectrumCanvas::getVisualDataQueue() {
return visualDataQueue;
}
void SpectrumCanvas::OnMouseRightDown(wxMouseEvent& event) {

View File

@ -5,6 +5,7 @@
#include <vector>
#include <queue>
#include <memory>
#include "InteractiveCanvas.h"
#include "PrimaryGLContext.h"
@ -44,7 +45,7 @@ public:
void setScaleFactorEnabled(bool en);
void setFFTSize(int fftSize);
SpectrumVisualDataQueue *getVisualDataQueue();
SpectrumVisualDataQueuePtr getVisualDataQueue();
private:
void OnPaint(wxPaintEvent& event);
@ -70,7 +71,7 @@ private:
int bwChange;
bool resetScaleFactor, scaleFactorEnabled;
SpectrumVisualDataQueue visualDataQueue;
SpectrumVisualDataQueuePtr visualDataQueue = std::make_shared<SpectrumVisualDataQueue>();
// event table
wxDECLARE_EVENT_TABLE();

View File

@ -99,7 +99,7 @@ void WaterfallCanvas::processInputQueue() {
while (lpsIndex >= targetVis) {
SpectrumVisualDataPtr vData;
if (visualDataQueue.try_pop(vData)) {
if (visualDataQueue->try_pop(vData)) {
if (vData) {
if (vData->spectrum_points.size() == fft_size * 2) {
@ -880,8 +880,8 @@ void WaterfallCanvas::OnMouseRightReleased(wxMouseEvent& event) {
mouseZoom = 1.0;
}
SpectrumVisualDataQueue *WaterfallCanvas::getVisualDataQueue() {
return &visualDataQueue;
SpectrumVisualDataQueuePtr WaterfallCanvas::getVisualDataQueue() {
return visualDataQueue;
}
void WaterfallCanvas::updateCenterFrequency(long long freq) {
@ -915,7 +915,7 @@ void WaterfallCanvas::setLinesPerSecond(int lps) {
linesPerSecond = lps;
//empty all
visualDataQueue.flush();
visualDataQueue->flush();
}
void WaterfallCanvas::setMinBandwidth(int min) {

View File

@ -8,7 +8,7 @@
#include <vector>
#include <queue>
#include <memory>
#include "InteractiveCanvas.h"
#include "MouseTracker.h"
#include "SpectrumCanvas.h"
@ -31,7 +31,7 @@ public:
void attachSpectrumCanvas(SpectrumCanvas *canvas_in);
void processInputQueue();
SpectrumVisualDataQueue *getVisualDataQueue();
SpectrumVisualDataQueuePtr getVisualDataQueue();
void setLinesPerSecond(int lps);
void setMinBandwidth(int min);
@ -88,7 +88,8 @@ private:
float scaleMove;
int dragBW;
SpectrumVisualDataQueue visualDataQueue;
SpectrumVisualDataQueuePtr visualDataQueue = std::make_shared<SpectrumVisualDataQueue>();
Timer gTimer;
double lpsIndex;
bool preBuf;