From f04ec72394c4f39ca94514c1bf4694c7acfd20d9 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Thu, 11 Dec 2014 19:07:21 -0500 Subject: [PATCH] Demodulator garbage collection --- CMakeLists.txt | 1 + src/audio/AudioThread.cpp | 9 ++- src/audio/AudioThread.h | 4 +- src/demod/DemodDefs.h | 87 ++++++++++++++++++++++++++ src/demod/DemodulatorMgr.cpp | 93 +++++++++++++++++---------- src/demod/DemodulatorMgr.h | 10 +++ src/demod/DemodulatorThread.cpp | 9 ++- src/demod/DemodulatorThread.h | 107 +++++--------------------------- src/sdr/SDRPostThread.cpp | 33 ++++++++-- src/sdr/SDRPostThread.h | 40 +++--------- 10 files changed, 225 insertions(+), 168 deletions(-) create mode 100644 src/demod/DemodDefs.h diff --git a/CMakeLists.txt b/CMakeLists.txt index cca50c1..fffc75d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -153,6 +153,7 @@ SET (cubicsdr_headers src/demod/DemodulatorThread.h src/demod/DemodulatorWorkerThread.h src/demod/DemodulatorMgr.h + src/demod/DemodDefs.h src/audio/AudioThread.h src/util/Gradient.h src/util/Timer.h diff --git a/src/audio/AudioThread.cpp b/src/audio/AudioThread.cpp index 0a1d812..d64db8f 100644 --- a/src/audio/AudioThread.cpp +++ b/src/audio/AudioThread.cpp @@ -1,9 +1,10 @@ #include "AudioThread.h" #include "CubicSDRDefs.h" #include +#include "DemodulatorThread.h" -AudioThread::AudioThread(AudioThreadInputQueue *inputQueue) : - inputQueue(inputQueue), terminated(false), audio_queue_ptr(0), underflow_count(0) { +AudioThread::AudioThread(AudioThreadInputQueue *inputQueue, DemodulatorThreadCommandQueue* threadQueueNotify) : + inputQueue(inputQueue), terminated(false), audio_queue_ptr(0), underflow_count(0), threadQueueNotify(threadQueueNotify) { } @@ -135,6 +136,10 @@ void AudioThread::threadMain() { } std::cout << "Audio thread done." << std::endl; + + DemodulatorThreadCommand tCmd(DemodulatorThreadCommand::DEMOD_THREAD_CMD_AUDIO_TERMINATED); + tCmd.context = this; + threadQueueNotify->push(tCmd); } void AudioThread::terminate() { diff --git a/src/audio/AudioThread.h b/src/audio/AudioThread.h index 833ba4a..1b3bd11 100644 --- a/src/audio/AudioThread.h +++ b/src/audio/AudioThread.h @@ -15,6 +15,7 @@ #include "AudioThread.h" #include "ThreadQueue.h" #include "RtAudio.h" +#include "DemodDefs.h" class AudioThreadInput { public: @@ -32,7 +33,7 @@ public: std::atomic audio_queue_ptr; std::atomic underflow_count; - AudioThread(AudioThreadInputQueue *inputQueue); + AudioThread(AudioThreadInputQueue *inputQueue, DemodulatorThreadCommandQueue* threadQueueNotify); ~AudioThread(); void threadMain(); @@ -42,5 +43,6 @@ private: AudioThreadInputQueue *inputQueue; RtAudio dac; std::atomic terminated; + DemodulatorThreadCommandQueue* threadQueueNotify; }; diff --git a/src/demod/DemodDefs.h b/src/demod/DemodDefs.h new file mode 100644 index 0000000..fb383a0 --- /dev/null +++ b/src/demod/DemodDefs.h @@ -0,0 +1,87 @@ +#pragma once + +#include "ThreadQueue.h" + +enum DemodulatorType { + DEMOD_TYPE_NULL, + DEMOD_TYPE_AM, + DEMOD_TYPE_FM, + DEMOD_TYPE_LSB, + DEMOD_TYPE_USB +}; + +class DemodulatorThread; +class DemodulatorThreadCommand { +public: + enum DemodulatorThreadCommandEnum { + DEMOD_THREAD_CMD_NULL, + DEMOD_THREAD_CMD_SET_BANDWIDTH, + DEMOD_THREAD_CMD_SET_FREQUENCY, + DEMOD_THREAD_CMD_DEMOD_TERMINATED, + DEMOD_THREAD_CMD_AUDIO_TERMINATED + }; + + DemodulatorThreadCommand() : + cmd(DEMOD_THREAD_CMD_NULL), int_value(0), context(NULL) { + + } + + DemodulatorThreadCommand(DemodulatorThreadCommandEnum cmd) : + cmd(cmd), int_value(0), context(NULL) { + + } + + DemodulatorThreadCommandEnum cmd; + void *context; + int int_value; +}; + +class DemodulatorThreadIQData { +public: + unsigned int frequency; + unsigned int bandwidth; + std::vector data; + + DemodulatorThreadIQData() : + frequency(0), bandwidth(0) { + + } + + DemodulatorThreadIQData(unsigned int bandwidth, unsigned int frequency, + std::vector data) : + data(data), frequency(frequency), bandwidth(bandwidth) { + + } + + ~DemodulatorThreadIQData() { + + } +}; + +class DemodulatorThreadAudioData { +public: + unsigned int frequency; + unsigned int sampleRate; + unsigned char channels; + + std::vector data; + + DemodulatorThreadAudioData() : + sampleRate(0), frequency(0), channels(0) { + + } + + DemodulatorThreadAudioData(unsigned int frequency, unsigned int sampleRate, + std::vector data) : + data(data), sampleRate(sampleRate), frequency(frequency), channels( + 1) { + + } + + ~DemodulatorThreadAudioData() { + + } +}; + +typedef ThreadQueue DemodulatorThreadInputQueue; +typedef ThreadQueue DemodulatorThreadCommandQueue; diff --git a/src/demod/DemodulatorMgr.cpp b/src/demod/DemodulatorMgr.cpp index d5e8313..1588003 100644 --- a/src/demod/DemodulatorMgr.cpp +++ b/src/demod/DemodulatorMgr.cpp @@ -4,28 +4,29 @@ #include "CubicSDR.h" DemodulatorInstance::DemodulatorInstance() : - t_Demod(NULL), t_Audio(NULL), threadQueueDemod(NULL), demodulatorThread(NULL) { + t_Demod(NULL), t_Audio(NULL), threadQueueDemod(NULL), demodulatorThread(NULL), terminated(false), audioTerminated(false), demodTerminated( + false) { threadQueueDemod = new DemodulatorThreadInputQueue; threadQueueCommand = new DemodulatorThreadCommandQueue; - demodulatorThread = new DemodulatorThread(threadQueueDemod); + threadQueueNotify = new DemodulatorThreadCommandQueue; + demodulatorThread = new DemodulatorThread(threadQueueDemod, threadQueueNotify); demodulatorThread->setCommandQueue(threadQueueCommand); audioInputQueue = new AudioThreadInputQueue; - audioThread = new AudioThread(audioInputQueue); + audioThread = new AudioThread(audioInputQueue, threadQueueNotify); demodulatorThread->setAudioInputQueue(audioInputQueue); } DemodulatorInstance::~DemodulatorInstance() { - delete audioThread; - delete t_Audio; + delete demodulatorThread; delete audioInputQueue; delete threadQueueDemod; - delete demodulatorThread; #ifndef __APPLE__ - delete t_Demod; +// delete t_Demod; #endif +// delete t_Audio; } void DemodulatorInstance::setVisualOutputQueue(DemodulatorThreadOutputQueue *tQueue) { @@ -33,27 +34,6 @@ void DemodulatorInstance::setVisualOutputQueue(DemodulatorThreadOutputQueue *tQu } void DemodulatorInstance::run() { - if (t_Demod) { - terminate(); - - delete threadQueueDemod; - delete demodulatorThread; - delete t_Demod; - delete audioThread; - delete audioInputQueue; - delete t_Audio; - - threadQueueDemod = new DemodulatorThreadInputQueue; - threadQueueCommand = new DemodulatorThreadCommandQueue; - demodulatorThread = new DemodulatorThread(threadQueueDemod); - demodulatorThread->setCommandQueue(threadQueueCommand); - - audioInputQueue = new AudioThreadInputQueue; - audioThread = new AudioThread(audioInputQueue); - - demodulatorThread->setAudioInputQueue(audioInputQueue); - } - t_Audio = new std::thread(&AudioThread::threadMain, audioThread); #ifdef __APPLE__ // Already using pthreads, might as well do some custom init.. @@ -124,8 +104,7 @@ DemodulatorInstance *DemodulatorMgr::newThread() { void DemodulatorMgr::terminateAll() { while (demods.size()) { DemodulatorInstance *d = demods.back(); - demods.pop_back(); - d->terminate(); + deleteThread(d); } } @@ -136,7 +115,7 @@ std::vector &DemodulatorMgr::getDemodulators() { void DemodulatorMgr::deleteThread(DemodulatorInstance *demod) { std::vector::iterator i; - i = std::find(demods.begin(),demods.end(),demod); + i = std::find(demods.begin(), demods.end(), demod); if (activeDemodulator == demod) { activeDemodulator = NULL; @@ -152,6 +131,10 @@ void DemodulatorMgr::deleteThread(DemodulatorInstance *demod) { demods.erase(i); demod->terminate(); } + + demods_deleted.push_back(demod); + + garbageCollect(); } std::vector *DemodulatorMgr::getDemodulatorsAt(int freq, int bandwidth) { @@ -197,8 +180,9 @@ void DemodulatorMgr::setActiveDemodulator(DemodulatorInstance *demod, bool tempo activeVisualDemodulator = last; } - activeDemodulator = demod; + + garbageCollect(); } DemodulatorInstance *DemodulatorMgr::getActiveDemodulator() { @@ -212,3 +196,48 @@ DemodulatorInstance *DemodulatorMgr::getLastActiveDemodulator() { return lastActiveDemodulator; } + +void DemodulatorMgr::garbageCollect() { + if (demods_deleted.size()) { + std::vector::iterator i; + + for (i = demods_deleted.begin(); i != demods_deleted.end(); i++) { + if ((*i)->isTerminated()) { + DemodulatorInstance *deleted = (*i); + demods_deleted.erase(i); + + std::cout << "Garbage collected demodulator instance " << deleted->getLabel() << std::endl; + + delete deleted; + return; + } + } + } +} + +bool DemodulatorInstance::isTerminated() { + while (!threadQueueNotify->empty()) { + DemodulatorThreadCommand cmd; + threadQueueNotify->pop(cmd); + + switch (cmd.cmd) { + case DemodulatorThreadCommand::DEMOD_THREAD_CMD_AUDIO_TERMINATED: + audioThread = NULL; + t_Audio->join(); + audioTerminated = true; + break; + case DemodulatorThreadCommand::DEMOD_THREAD_CMD_DEMOD_TERMINATED: + demodulatorThread = NULL; + t_Demod->join(); + demodTerminated = true; + break; + default: + break; + } + } + + terminated = audioTerminated && demodTerminated; + + return terminated; +} + diff --git a/src/demod/DemodulatorMgr.h b/src/demod/DemodulatorMgr.h index 2bed534..388ef3b 100644 --- a/src/demod/DemodulatorMgr.h +++ b/src/demod/DemodulatorMgr.h @@ -11,6 +11,7 @@ public: DemodulatorThreadInputQueue* threadQueueDemod; DemodulatorThreadCommandQueue* threadQueueCommand; + DemodulatorThreadCommandQueue* threadQueueNotify; DemodulatorThread *demodulatorThread; #ifdef __APPLE__ pthread_t t_Demod; @@ -35,8 +36,13 @@ public: std::string getLabel(); void setLabel(std::string labelStr); + bool isTerminated(); + private: std::string label; + bool terminated; + bool demodTerminated; + bool audioTerminated; }; class DemodulatorMgr { @@ -56,8 +62,12 @@ public: DemodulatorInstance *getLastActiveDemodulator(); private: + void garbageCollect(); + std::vector demods; + std::vector demods_deleted; DemodulatorInstance *activeDemodulator; DemodulatorInstance *lastActiveDemodulator; DemodulatorInstance *activeVisualDemodulator; + }; diff --git a/src/demod/DemodulatorThread.cpp b/src/demod/DemodulatorThread.cpp index 10048e0..0febf28 100644 --- a/src/demod/DemodulatorThread.cpp +++ b/src/demod/DemodulatorThread.cpp @@ -3,12 +3,12 @@ #include #ifdef __APPLE__ - #include +#include #endif -DemodulatorThread::DemodulatorThread(DemodulatorThreadInputQueue* pQueue) : +DemodulatorThread::DemodulatorThread(DemodulatorThreadInputQueue* pQueue, DemodulatorThreadCommandQueue* threadQueueNotify) : inputQueue(pQueue), visOutQueue(NULL), terminated(false), initialized(false), audio_resampler(NULL), resample_ratio(1), audio_resample_ratio( - 1), resampler(NULL), commandQueue(NULL), fir_filter(NULL), audioInputQueue(NULL) { + 1), resampler(NULL), commandQueue(NULL), fir_filter(NULL), audioInputQueue(NULL), threadQueueNotify(threadQueueNotify) { float kf = 0.5; // modulation factor fdem = freqdem_create(kf); @@ -249,6 +249,9 @@ void DemodulatorThread::threadMain() { } std::cout << "Demodulator thread done." << std::endl; + DemodulatorThreadCommand tCmd(DemodulatorThreadCommand::DEMOD_THREAD_CMD_DEMOD_TERMINATED); + tCmd.context = this; + threadQueueNotify->push(tCmd); } void DemodulatorThread::terminate() { diff --git a/src/demod/DemodulatorThread.h b/src/demod/DemodulatorThread.h index 7c593e0..850f188 100644 --- a/src/demod/DemodulatorThread.h +++ b/src/demod/DemodulatorThread.h @@ -11,116 +11,36 @@ #include "wx/thread.h" #include "liquid/liquid.h" -#include "AudioThread.h" -#include "ThreadQueue.h" #include "CubicSDRDefs.h" #include "DemodulatorWorkerThread.h" - -enum DemodulatorType { - DEMOD_TYPE_NULL, - DEMOD_TYPE_AM, - DEMOD_TYPE_FM, - DEMOD_TYPE_LSB, - DEMOD_TYPE_USB -}; - -class DemodulatorThreadCommand { -public: - enum DemodulatorThreadCommandEnum { - DEMOD_THREAD_CMD_NULL, - DEMOD_THREAD_CMD_SET_BANDWIDTH, - DEMOD_THREAD_CMD_SET_FREQUENCY - }; - - DemodulatorThreadCommand() : - cmd(DEMOD_THREAD_CMD_NULL), int_value(0) { - - } - - DemodulatorThreadCommand(DemodulatorThreadCommandEnum cmd) : - cmd(cmd), int_value(0) { - - } - - DemodulatorThreadCommandEnum cmd; - int int_value; -}; - -class DemodulatorThreadIQData { -public: - unsigned int frequency; - unsigned int bandwidth; - std::vector data; - - DemodulatorThreadIQData() : - frequency(0), bandwidth(0) { - - } - - DemodulatorThreadIQData(unsigned int bandwidth, unsigned int frequency, - std::vector data) : - data(data), frequency(frequency), bandwidth(bandwidth) { - - } - - ~DemodulatorThreadIQData() { - - } -}; - -class DemodulatorThreadAudioData { -public: - unsigned int frequency; - unsigned int sampleRate; - unsigned char channels; - - std::vector data; - - DemodulatorThreadAudioData() : - sampleRate(0), frequency(0), channels(0) { - - } - - DemodulatorThreadAudioData(unsigned int frequency, unsigned int sampleRate, - std::vector data) : - data(data), sampleRate(sampleRate), frequency(frequency), channels( - 1) { - - } - - ~DemodulatorThreadAudioData() { - - } -}; +#include "DemodDefs.h" class DemodulatorThreadParameters { public: - unsigned int frequency; - unsigned int inputRate; - unsigned int bandwidth; // set equal to disable second stage re-sampling? - unsigned int audioSampleRate; + unsigned int frequency; + unsigned int inputRate; + unsigned int bandwidth; // set equal to disable second stage re-sampling? + unsigned int audioSampleRate; - DemodulatorType demodType; + DemodulatorType demodType; - DemodulatorThreadParameters() : - frequency(0), inputRate(SRATE), bandwidth(200000), audioSampleRate( - AUDIO_FREQUENCY), demodType(DEMOD_TYPE_FM) { + DemodulatorThreadParameters() : + frequency(0), inputRate(SRATE), bandwidth(200000), audioSampleRate( + AUDIO_FREQUENCY), demodType(DEMOD_TYPE_FM) { - } + } - ~DemodulatorThreadParameters() { + ~DemodulatorThreadParameters() { - } + } }; -typedef ThreadQueue DemodulatorThreadInputQueue; typedef ThreadQueue DemodulatorThreadOutputQueue; -typedef ThreadQueue DemodulatorThreadCommandQueue; class DemodulatorThread { public: - DemodulatorThread(DemodulatorThreadInputQueue* pQueue); + DemodulatorThread(DemodulatorThreadInputQueue* pQueue, DemodulatorThreadCommandQueue* threadQueueNotify); ~DemodulatorThread(); #ifdef __APPLE__ @@ -184,4 +104,5 @@ protected: DemodulatorThreadWorkerCommandQueue *workerQueue; DemodulatorThreadWorkerResultQueue *workerResults; + DemodulatorThreadCommandQueue* threadQueueNotify; }; diff --git a/src/sdr/SDRPostThread.cpp b/src/sdr/SDRPostThread.cpp index e052cff..9a9e204 100644 --- a/src/sdr/SDRPostThread.cpp +++ b/src/sdr/SDRPostThread.cpp @@ -4,13 +4,38 @@ #include "CubicSDR.h" SDRPostThread::SDRPostThread() : - iqDataInQueue(NULL), iqDataOutQueue(NULL), iqVisualQueue(NULL), terminated(false) { - dev = NULL; - sample_rate = SRATE; + iqDataInQueue(NULL), iqDataOutQueue(NULL), iqVisualQueue(NULL), terminated(false), dcFilter(NULL), sample_rate(SRATE) { } SDRPostThread::~SDRPostThread() { - rtlsdr_close(dev); +} + +void SDRPostThread::bindDemodulator(DemodulatorInstance *demod) { + demodulators.push_back(demod); +} + +void SDRPostThread::removeDemodulator(DemodulatorInstance *demod) { + if (!demod) { + return; + } + + std::vector::iterator i; + + i = std::find(demodulators.begin(), demodulators.end(), demod); + + if (i != demodulators.end()) { + demodulators.erase(i); + } +} + +void SDRPostThread::setIQDataInQueue(SDRThreadIQDataQueue* iqDataQueue) { + iqDataInQueue = iqDataQueue; +} +void SDRPostThread::setIQDataOutQueue(SDRThreadIQDataQueue* iqDataQueue) { + iqDataOutQueue = iqDataQueue; +} +void SDRPostThread::setIQVisualQueue(SDRThreadIQDataQueue *iqVisQueue) { + iqVisualQueue = iqVisQueue; } void SDRPostThread::threadMain() { diff --git a/src/sdr/SDRPostThread.h b/src/sdr/SDRPostThread.h index 5d79fa0..67edfe1 100644 --- a/src/sdr/SDRPostThread.h +++ b/src/sdr/SDRPostThread.h @@ -5,47 +5,21 @@ class SDRPostThread { public: - rtlsdr_dev_t *dev; - SDRPostThread(); ~SDRPostThread(); - int enumerate_rtl(); + void bindDemodulator(DemodulatorInstance *demod); + void removeDemodulator(DemodulatorInstance *demod); - void bindDemodulator(DemodulatorInstance *demod) { - demodulators.push_back(demod); - } - - void removeDemodulator(DemodulatorInstance *demod) { - if (!demod) { - return; - } - - std::vector::iterator i; - - i = std::find(demodulators.begin(), demodulators.end(), demod); - - if (i != demodulators.end()) { - demodulators.erase(i); - } - } + void setIQDataInQueue(SDRThreadIQDataQueue* iqDataQueue); + void setIQDataOutQueue(SDRThreadIQDataQueue* iqDataQueue); + void setIQVisualQueue(SDRThreadIQDataQueue *iqVisQueue); void threadMain(); - - void setIQDataInQueue(SDRThreadIQDataQueue* iqDataQueue) { - iqDataInQueue = iqDataQueue; - } - void setIQDataOutQueue(SDRThreadIQDataQueue* iqDataQueue) { - iqDataOutQueue = iqDataQueue; - } - void setIQVisualQueue(SDRThreadIQDataQueue *iqVisQueue) { - iqVisualQueue = iqVisQueue; - } - void terminate(); -protected: - uint32_t sample_rate; +protected: + uint32_t sample_rate; std::atomic iqDataOutQueue; std::atomic iqDataInQueue;