mirror of
				https://github.com/cjcliffe/CubicSDR.git
				synced 2025-10-27 11:00:28 -04:00 
			
		
		
		
	THREAD_CLEAN_PART2: Assure correct terminate()/isTerminated(delay)/delete sequence +
Removed the NotifyQueue between DemodulatorInstance participants, actually not needed since DemodulatorInstance::IsTerminated() is explicitly called on some events for cleanups DELETE_CLEANUP: properly nullify deleted pointers when needed
This commit is contained in:
		
							parent
							
								
									cf90a829b0
								
							
						
					
					
						commit
						567d84711f
					
				| @ -293,43 +293,63 @@ int CubicSDR::OnExit() { | |||||||
|     demodMgr.terminateAll(); |     demodMgr.terminateAll(); | ||||||
|      |      | ||||||
|     std::cout << "Terminating SDR thread.." << std::endl; |     std::cout << "Terminating SDR thread.." << std::endl; | ||||||
|     if (!sdrThread->isTerminated()) { |  | ||||||
|     sdrThread->terminate(); |     sdrThread->terminate(); | ||||||
|  |     sdrThread->isTerminated(1000); | ||||||
|  |     | ||||||
|     if (t_SDR) { |     if (t_SDR) { | ||||||
|        t_SDR->join(); |        t_SDR->join(); | ||||||
|     } |     } | ||||||
|     } |     | ||||||
|     std::cout << "Terminating SDR post-processing thread.." << std::endl; |     std::cout << "Terminating SDR post-processing thread.." << std::endl; | ||||||
|     sdrPostThread->terminate(); |     sdrPostThread->terminate(); | ||||||
|     t_PostSDR->join(); |  | ||||||
|      |      | ||||||
|     std::cout << "Terminating Visual Processor threads.." << std::endl; |     std::cout << "Terminating Visual Processor threads.." << std::endl; | ||||||
|     spectrumVisualThread->terminate(); |     spectrumVisualThread->terminate(); | ||||||
|     t_SpectrumVisual->join(); |  | ||||||
| 
 |  | ||||||
|     demodVisualThread->terminate(); |     demodVisualThread->terminate(); | ||||||
|     t_DemodVisual->join(); |  | ||||||
| 
 | 
 | ||||||
|     //Poor man join
 |     //Wait nicely
 | ||||||
|     sdrPostThread->isTerminated(1000); |     sdrPostThread->isTerminated(1000); | ||||||
|     spectrumVisualThread->isTerminated(1000); |     spectrumVisualThread->isTerminated(1000); | ||||||
|     demodVisualThread->isTerminated(1000); |     demodVisualThread->isTerminated(1000); | ||||||
| 
 | 
 | ||||||
|  |     //Then join the thread themselves
 | ||||||
|  |     t_PostSDR->join(); | ||||||
|  |     t_DemodVisual->join(); | ||||||
|  |     t_SpectrumVisual->join(); | ||||||
|  | 
 | ||||||
|  |     //Now only we can delete
 | ||||||
|     delete sdrThread; |     delete sdrThread; | ||||||
|  |     sdrThread = nullptr; | ||||||
| 
 | 
 | ||||||
|     delete sdrPostThread; |     delete sdrPostThread; | ||||||
|  |     sdrPostThread = nullptr; | ||||||
|  | 
 | ||||||
|     delete t_PostSDR; |     delete t_PostSDR; | ||||||
|  |     t_PostSDR = nullptr; | ||||||
| 
 | 
 | ||||||
|     delete t_SpectrumVisual; |     delete t_SpectrumVisual; | ||||||
|  |     t_SpectrumVisual = nullptr; | ||||||
|  | 
 | ||||||
|     delete spectrumVisualThread; |     delete spectrumVisualThread; | ||||||
|  |     spectrumVisualThread = nullptr; | ||||||
|  | 
 | ||||||
|     delete t_DemodVisual; |     delete t_DemodVisual; | ||||||
|  |     t_DemodVisual = nullptr; | ||||||
|  | 
 | ||||||
|     delete demodVisualThread; |     delete demodVisualThread; | ||||||
|  |     demodVisualThread = nullptr; | ||||||
|      |      | ||||||
|     delete pipeIQVisualData; |     delete pipeIQVisualData; | ||||||
|  |     pipeIQVisualData = nullptr; | ||||||
|  | 
 | ||||||
|     delete pipeAudioVisualData; |     delete pipeAudioVisualData; | ||||||
|  |     pipeAudioVisualData = nullptr; | ||||||
|  | 
 | ||||||
|     delete pipeSDRIQData; |     delete pipeSDRIQData; | ||||||
|  |     pipeSDRIQData = nullptr; | ||||||
| 
 | 
 | ||||||
|     delete m_glContext; |     delete m_glContext; | ||||||
|  |     m_glContext = nullptr; | ||||||
| 
 | 
 | ||||||
| #ifdef __APPLE__ | #ifdef __APPLE__ | ||||||
|     AudioThread::deviceCleanup(); |     AudioThread::deviceCleanup(); | ||||||
| @ -427,6 +447,7 @@ void CubicSDR::sdrThreadNotify(SDRThread::SDRThreadState state, std::string mess | |||||||
|     if (state == SDRThread::SDR_THREAD_TERMINATED) { |     if (state == SDRThread::SDR_THREAD_TERMINATED) { | ||||||
|         t_SDR->join(); |         t_SDR->join(); | ||||||
|         delete t_SDR; |         delete t_SDR; | ||||||
|  |         t_SDR = nullptr; | ||||||
|     } |     } | ||||||
|     if (state == SDRThread::SDR_THREAD_FAILED) { |     if (state == SDRThread::SDR_THREAD_FAILED) { | ||||||
|         notifyMessage = message; |         notifyMessage = message; | ||||||
| @ -532,14 +553,15 @@ void CubicSDR::stopDevice(bool store) { | |||||||
|     } |     } | ||||||
|     sdrThread->setDevice(nullptr); |     sdrThread->setDevice(nullptr); | ||||||
| 
 | 
 | ||||||
|     if (!sdrThread->isTerminated()) { |  | ||||||
|     sdrThread->terminate(); |     sdrThread->terminate(); | ||||||
|  |     sdrThread->isTerminated(1000); | ||||||
|  | 
 | ||||||
|     if (t_SDR) { |     if (t_SDR) { | ||||||
|         t_SDR->join(); |         t_SDR->join(); | ||||||
|         delete t_SDR; |         delete t_SDR; | ||||||
|         t_SDR = nullptr; |         t_SDR = nullptr; | ||||||
|     } |     } | ||||||
|     } |      | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void CubicSDR::reEnumerateDevices() { | void CubicSDR::reEnumerateDevices() { | ||||||
| @ -550,12 +572,14 @@ void CubicSDR::reEnumerateDevices() { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void CubicSDR::setDevice(SDRDeviceInfo *dev) { | void CubicSDR::setDevice(SDRDeviceInfo *dev) { | ||||||
|     if (!sdrThread->isTerminated()) { | 
 | ||||||
|     sdrThread->terminate(); |     sdrThread->terminate(); | ||||||
|  |     sdrThread->isTerminated(1000); | ||||||
|  |      | ||||||
|     if (t_SDR) { |     if (t_SDR) { | ||||||
|        t_SDR->join(); |        t_SDR->join(); | ||||||
|        delete t_SDR; |        delete t_SDR; | ||||||
|         } |        t_SDR = nullptr; | ||||||
|     } |     } | ||||||
|      |      | ||||||
|     for (SoapySDR::Kwargs::const_iterator i = settingArgs.begin(); i != settingArgs.end(); i++) { |     for (SoapySDR::Kwargs::const_iterator i = settingArgs.begin(); i != settingArgs.end(); i++) { | ||||||
| @ -872,17 +896,27 @@ RigThread *CubicSDR::getRigThread() { | |||||||
| 
 | 
 | ||||||
| void CubicSDR::initRig(int rigModel, std::string rigPort, int rigSerialRate) { | void CubicSDR::initRig(int rigModel, std::string rigPort, int rigSerialRate) { | ||||||
|     if (rigThread) { |     if (rigThread) { | ||||||
|         if (!rigThread->isTerminated()) { | 
 | ||||||
|         rigThread->terminate(); |         rigThread->terminate(); | ||||||
|  |         rigThread->isTerminated(1000); | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     if (t_Rig && t_Rig->joinable()) { | ||||||
|  |         t_Rig->join(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     //now we can delete
 | ||||||
|  |     if (rigThread) { | ||||||
|  | 
 | ||||||
|         delete rigThread; |         delete rigThread; | ||||||
|         rigThread = nullptr; |         rigThread = nullptr; | ||||||
|     } |     } | ||||||
|     if (t_Rig && t_Rig->joinable()) { |     if (t_Rig) { | ||||||
|         t_Rig->join(); |        | ||||||
|         delete t_Rig; |         delete t_Rig; | ||||||
|         t_Rig = nullptr; |         t_Rig = nullptr; | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|     rigThread = new RigThread(); |     rigThread = new RigThread(); | ||||||
|     rigThread->initRig(rigModel, rigPort, rigSerialRate); |     rigThread->initRig(rigModel, rigPort, rigSerialRate); | ||||||
|     rigThread->setControlMode(wxGetApp().getConfig()->getRigControlMode()); |     rigThread->setControlMode(wxGetApp().getConfig()->getRigControlMode()); | ||||||
| @ -899,14 +933,24 @@ void CubicSDR::stopRig() { | |||||||
|     } |     } | ||||||
|      |      | ||||||
|     if (rigThread) { |     if (rigThread) { | ||||||
|         if (!rigThread->isTerminated()) { |          | ||||||
|         rigThread->terminate(); |         rigThread->terminate(); | ||||||
|  |         rigThread->isTerminated(1000); | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     if (t_Rig && t_Rig->joinable()) { | ||||||
|  |         t_Rig->join();    | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     //now we can delete
 | ||||||
|  |     if (rigThread) { | ||||||
|  | 
 | ||||||
|         delete rigThread; |         delete rigThread; | ||||||
|         rigThread = nullptr; |         rigThread = nullptr; | ||||||
|     } |     } | ||||||
|     if (t_Rig && t_Rig->joinable()) { | 
 | ||||||
|         t_Rig->join(); |     if (t_Rig) { | ||||||
|  |         | ||||||
|         delete t_Rig; |         delete t_Rig; | ||||||
|         t_Rig = nullptr; |         t_Rig = nullptr; | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -180,10 +180,10 @@ private: | |||||||
| 
 | 
 | ||||||
|     DemodulatorMgr demodMgr; |     DemodulatorMgr demodMgr; | ||||||
| 
 | 
 | ||||||
|     long long frequency; |     std::atomic_llong frequency; | ||||||
|     long long offset; |     std::atomic_llong offset; | ||||||
|     int ppm, snap; |     std::atomic_int ppm, snap; | ||||||
|     long long sampleRate; |     std::atomic_llong sampleRate; | ||||||
|     std::atomic_bool agcMode; |     std::atomic_bool agcMode; | ||||||
| 
 | 
 | ||||||
|     SDRThread *sdrThread; |     SDRThread *sdrThread; | ||||||
| @ -224,7 +224,7 @@ private: | |||||||
|     std::atomic_bool soloMode; |     std::atomic_bool soloMode; | ||||||
|     SDRDeviceInfo *stoppedDev; |     SDRDeviceInfo *stoppedDev; | ||||||
| #ifdef USE_HAMLIB | #ifdef USE_HAMLIB | ||||||
|     RigThread *rigThread; |     RigThread* rigThread; | ||||||
|     std::thread *t_Rig; |     std::thread *t_Rig; | ||||||
| #endif | #endif | ||||||
| }; | }; | ||||||
|  | |||||||
| @ -1,4 +1,5 @@ | |||||||
| #include "IOThread.h" | #include "IOThread.h" | ||||||
|  | #include <typeinfo> | ||||||
| 
 | 
 | ||||||
| std::mutex ReBufferGC::g_mutex; | std::mutex ReBufferGC::g_mutex; | ||||||
| std::set<ReferenceCounter *> ReBufferGC::garbage; | std::set<ReferenceCounter *> ReBufferGC::garbage; | ||||||
| @ -122,5 +123,7 @@ bool IOThread::isTerminated(int waitMs) { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     std::cout << "ERROR: thread '" << typeid(*this).name() << "' has not terminated in time ! (> " << waitMs << " ms)" << std::endl; | ||||||
|  | 
 | ||||||
|     return terminated.load(); |     return terminated.load(); | ||||||
| } | } | ||||||
|  | |||||||
| @ -12,7 +12,7 @@ std::map<int, int> AudioThread::deviceSampleRate; | |||||||
| std::map<int, std::thread *> AudioThread::deviceThread; | std::map<int, std::thread *> AudioThread::deviceThread; | ||||||
| 
 | 
 | ||||||
| AudioThread::AudioThread() : IOThread(), | AudioThread::AudioThread() : IOThread(), | ||||||
|         currentInput(NULL), inputQueue(NULL), nBufferFrames(1024), threadQueueNotify(NULL), sampleRate(0) { |         currentInput(NULL), inputQueue(NULL), nBufferFrames(1024), sampleRate(0) { | ||||||
| 
 | 
 | ||||||
| 	audioQueuePtr.store(0);  | 	audioQueuePtr.store(0);  | ||||||
| 	underflowCount.store(0); | 	underflowCount.store(0); | ||||||
| @ -378,7 +378,6 @@ void AudioThread::run() { | |||||||
| //    std::cout << "Audio thread started." << std::endl;
 | //    std::cout << "Audio thread started." << std::endl;
 | ||||||
| 
 | 
 | ||||||
|     inputQueue = static_cast<AudioThreadInputQueue *>(getInputQueue("AudioDataInput")); |     inputQueue = static_cast<AudioThreadInputQueue *>(getInputQueue("AudioDataInput")); | ||||||
|     threadQueueNotify = static_cast<DemodulatorThreadCommandQueue*>(getOutputQueue("NotifyQueue")); |  | ||||||
|      |      | ||||||
|     while (!stopping) { |     while (!stopping) { | ||||||
|         AudioThreadCommand command; |         AudioThreadCommand command; | ||||||
| @ -421,11 +420,6 @@ void AudioThread::run() { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (threadQueueNotify != NULL) { |  | ||||||
|         DemodulatorThreadCommand tCmd(DemodulatorThreadCommand::DEMOD_THREAD_CMD_AUDIO_TERMINATED); |  | ||||||
|         tCmd.context = this; |  | ||||||
|         threadQueueNotify->push(tCmd); |  | ||||||
|     } |  | ||||||
| //    std::cout << "Audio thread done." << std::endl;
 | //    std::cout << "Audio thread done." << std::endl;
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -86,7 +86,6 @@ private: | |||||||
|     RtAudio::StreamOptions opts; |     RtAudio::StreamOptions opts; | ||||||
|     RtAudio::StreamParameters parameters; |     RtAudio::StreamParameters parameters; | ||||||
|     AudioThreadCommandQueue cmdQueue; |     AudioThreadCommandQueue cmdQueue; | ||||||
|     DemodulatorThreadCommandQueue* threadQueueNotify; |  | ||||||
|     int sampleRate; |     int sampleRate; | ||||||
| 
 | 
 | ||||||
| public: | public: | ||||||
|  | |||||||
| @ -10,29 +10,7 @@ | |||||||
| #include "IOThread.h" | #include "IOThread.h" | ||||||
| 
 | 
 | ||||||
| class DemodulatorThread; | class DemodulatorThread; | ||||||
| class DemodulatorThreadCommand { |  | ||||||
| public: |  | ||||||
|     enum DemodulatorThreadCommandEnum { |  | ||||||
|         DEMOD_THREAD_CMD_NULL, |  | ||||||
|         DEMOD_THREAD_CMD_DEMOD_PREPROCESS_TERMINATED, |  | ||||||
|         DEMOD_THREAD_CMD_DEMOD_TERMINATED, |  | ||||||
|         DEMOD_THREAD_CMD_AUDIO_TERMINATED |  | ||||||
|     }; |  | ||||||
| 
 | 
 | ||||||
|     DemodulatorThreadCommand() : |  | ||||||
|             cmd(DEMOD_THREAD_CMD_NULL), context(NULL), llong_value(0) { |  | ||||||
| 
 |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     DemodulatorThreadCommand(DemodulatorThreadCommandEnum cmd) : |  | ||||||
|             cmd(cmd), context(NULL), llong_value(0) { |  | ||||||
| 
 |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     DemodulatorThreadCommandEnum cmd; |  | ||||||
|     void *context; |  | ||||||
|     long long llong_value; |  | ||||||
| }; |  | ||||||
| 
 | 
 | ||||||
| class DemodulatorThreadControlCommand { | class DemodulatorThreadControlCommand { | ||||||
| public: | public: | ||||||
| @ -120,5 +98,4 @@ public: | |||||||
| 
 | 
 | ||||||
| typedef ThreadQueue<DemodulatorThreadIQData *> DemodulatorThreadInputQueue; | typedef ThreadQueue<DemodulatorThreadIQData *> DemodulatorThreadInputQueue; | ||||||
| typedef ThreadQueue<DemodulatorThreadPostIQData *> DemodulatorThreadPostInputQueue; | typedef ThreadQueue<DemodulatorThreadPostIQData *> DemodulatorThreadPostInputQueue; | ||||||
| typedef ThreadQueue<DemodulatorThreadCommand> DemodulatorThreadCommandQueue; |  | ||||||
| typedef ThreadQueue<DemodulatorThreadControlCommand> DemodulatorThreadControlCommandQueue; | typedef ThreadQueue<DemodulatorThreadControlCommand> DemodulatorThreadControlCommandQueue; | ||||||
|  | |||||||
| @ -51,14 +51,12 @@ DemodulatorInstance::DemodulatorInstance() { | |||||||
| 
 | 
 | ||||||
|     pipeIQInputData = new DemodulatorThreadInputQueue; |     pipeIQInputData = new DemodulatorThreadInputQueue; | ||||||
|     pipeIQDemodData = new DemodulatorThreadPostInputQueue; |     pipeIQDemodData = new DemodulatorThreadPostInputQueue; | ||||||
|     pipeDemodNotify = new DemodulatorThreadCommandQueue; |  | ||||||
|      |      | ||||||
|     audioThread = new AudioThread(); |     audioThread = new AudioThread(); | ||||||
|              |              | ||||||
|     demodulatorPreThread = new DemodulatorPreThread(this); |     demodulatorPreThread = new DemodulatorPreThread(this); | ||||||
|     demodulatorPreThread->setInputQueue("IQDataInput",pipeIQInputData); |     demodulatorPreThread->setInputQueue("IQDataInput",pipeIQInputData); | ||||||
|     demodulatorPreThread->setOutputQueue("IQDataOutput",pipeIQDemodData); |     demodulatorPreThread->setOutputQueue("IQDataOutput",pipeIQDemodData); | ||||||
|     demodulatorPreThread->setOutputQueue("NotifyQueue",pipeDemodNotify); |  | ||||||
|              |              | ||||||
|     pipeAudioData = new AudioThreadInputQueue; |     pipeAudioData = new AudioThreadInputQueue; | ||||||
|     threadQueueControl = new DemodulatorThreadControlCommandQueue; |     threadQueueControl = new DemodulatorThreadControlCommandQueue; | ||||||
| @ -66,11 +64,9 @@ DemodulatorInstance::DemodulatorInstance() { | |||||||
|     demodulatorThread = new DemodulatorThread(this); |     demodulatorThread = new DemodulatorThread(this); | ||||||
|     demodulatorThread->setInputQueue("IQDataInput",pipeIQDemodData); |     demodulatorThread->setInputQueue("IQDataInput",pipeIQDemodData); | ||||||
|     demodulatorThread->setInputQueue("ControlQueue",threadQueueControl); |     demodulatorThread->setInputQueue("ControlQueue",threadQueueControl); | ||||||
|     demodulatorThread->setOutputQueue("NotifyQueue",pipeDemodNotify); |  | ||||||
|     demodulatorThread->setOutputQueue("AudioDataOutput", pipeAudioData); |     demodulatorThread->setOutputQueue("AudioDataOutput", pipeAudioData); | ||||||
| 
 | 
 | ||||||
|     audioThread->setInputQueue("AudioDataInput", pipeAudioData); |     audioThread->setInputQueue("AudioDataInput", pipeAudioData); | ||||||
|     audioThread->setOutputQueue("NotifyQueue", pipeDemodNotify); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| DemodulatorInstance::~DemodulatorInstance() { | DemodulatorInstance::~DemodulatorInstance() { | ||||||
| @ -82,7 +78,6 @@ DemodulatorInstance::~DemodulatorInstance() { | |||||||
|     delete demodulatorPreThread; |     delete demodulatorPreThread; | ||||||
|     delete pipeIQInputData; |     delete pipeIQInputData; | ||||||
|     delete pipeIQDemodData; |     delete pipeIQDemodData; | ||||||
|     delete pipeDemodNotify; |  | ||||||
|     delete threadQueueControl; |     delete threadQueueControl; | ||||||
|     delete pipeAudioData; |     delete pipeAudioData; | ||||||
| } | } | ||||||
| @ -151,27 +146,35 @@ void DemodulatorInstance::setLabel(std::string labelStr) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool DemodulatorInstance::isTerminated() { | bool DemodulatorInstance::isTerminated() { | ||||||
|     while (!pipeDemodNotify->empty()) { |  | ||||||
|         DemodulatorThreadCommand cmd; |  | ||||||
|         pipeDemodNotify->pop(cmd); |  | ||||||
| 
 | 
 | ||||||
|         switch (cmd.cmd) { |     //
 | ||||||
|         case DemodulatorThreadCommand::DEMOD_THREAD_CMD_AUDIO_TERMINATED: |     bool audioTerminated = audioThread->isTerminated(); | ||||||
|  |     bool demodTerminated = demodulatorThread->isTerminated(); | ||||||
|  |     bool preDemodTerminated = demodulatorPreThread->isTerminated(); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     //Cleanup the worker threads, if the threads are indeed terminated
 | ||||||
|  |     if (audioTerminated) { | ||||||
|  | 
 | ||||||
|         if (t_Audio) { |         if (t_Audio) { | ||||||
|  | 
 | ||||||
|             t_Audio->join(); |             t_Audio->join(); | ||||||
| 
 | 
 | ||||||
|             delete t_Audio; |             delete t_Audio; | ||||||
|             t_Audio = nullptr; |             t_Audio = nullptr; | ||||||
|         } |         } | ||||||
|             break; |     } | ||||||
|         case DemodulatorThreadCommand::DEMOD_THREAD_CMD_DEMOD_TERMINATED: | 
 | ||||||
|  |     if (demodTerminated) { | ||||||
|  | 
 | ||||||
|         if (t_Demod) { |         if (t_Demod) { | ||||||
|                 #ifdef __APPLE__ | 
 | ||||||
|  | #ifdef __APPLE__ | ||||||
|             pthread_join(t_Demod, nullptr); |             pthread_join(t_Demod, nullptr); | ||||||
|                 #else | #else | ||||||
|             t_Demod->join(); |             t_Demod->join(); | ||||||
|             delete t_Demod; |             delete t_Demod; | ||||||
|                 #endif | #endif | ||||||
|             t_Demod = nullptr; |             t_Demod = nullptr; | ||||||
|         } |         } | ||||||
| #if ENABLE_DIGITAL_LAB | #if ENABLE_DIGITAL_LAB | ||||||
| @ -179,27 +182,22 @@ bool DemodulatorInstance::isTerminated() { | |||||||
|             closeOutput(); |             closeOutput(); | ||||||
|         } |         } | ||||||
| #endif | #endif | ||||||
|             break; |     } | ||||||
|         case DemodulatorThreadCommand::DEMOD_THREAD_CMD_DEMOD_PREPROCESS_TERMINATED: | 
 | ||||||
|  |     if (preDemodTerminated) { | ||||||
|  | 
 | ||||||
|         if (t_PreDemod) { |         if (t_PreDemod) { | ||||||
|                 #ifdef __APPLE__ | 
 | ||||||
|  | #ifdef __APPLE__ | ||||||
|             pthread_join(t_PreDemod, NULL); |             pthread_join(t_PreDemod, NULL); | ||||||
|                 #else | #else | ||||||
|             t_PreDemod->join(); |             t_PreDemod->join(); | ||||||
|             delete t_PreDemod; |             delete t_PreDemod; | ||||||
|                 #endif | #endif | ||||||
|             t_PreDemod = nullptr; |             t_PreDemod = nullptr; | ||||||
|         } |         } | ||||||
|             break; |  | ||||||
|         default: |  | ||||||
|             break; |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     //
 |  | ||||||
|     bool audioTerminated = audioThread->isTerminated(); |  | ||||||
|     bool demodTerminated = demodulatorThread->isTerminated(); |  | ||||||
|     bool preDemodTerminated = demodulatorPreThread->isTerminated(); |  | ||||||
|     |     | ||||||
|     bool terminated = audioTerminated && demodTerminated && preDemodTerminated; |     bool terminated = audioTerminated && demodTerminated && preDemodTerminated; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -47,8 +47,6 @@ public: | |||||||
| 
 | 
 | ||||||
|     void setVisualOutputQueue(DemodulatorThreadOutputQueue *tQueue); |     void setVisualOutputQueue(DemodulatorThreadOutputQueue *tQueue); | ||||||
| 
 | 
 | ||||||
|     DemodulatorThreadCommandQueue *getCommandQueue(); |  | ||||||
| 
 |  | ||||||
|     void run(); |     void run(); | ||||||
|     void terminate(); |     void terminate(); | ||||||
|     std::string getLabel(); |     std::string getLabel(); | ||||||
| @ -131,7 +129,6 @@ protected: | |||||||
|     DemodulatorThreadInputQueue* pipeIQInputData; |     DemodulatorThreadInputQueue* pipeIQInputData; | ||||||
|     DemodulatorThreadPostInputQueue* pipeIQDemodData; |     DemodulatorThreadPostInputQueue* pipeIQDemodData; | ||||||
|     AudioThreadInputQueue *pipeAudioData; |     AudioThreadInputQueue *pipeAudioData; | ||||||
|     DemodulatorThreadCommandQueue* pipeDemodNotify; |  | ||||||
|     DemodulatorPreThread *demodulatorPreThread; |     DemodulatorPreThread *demodulatorPreThread; | ||||||
|     DemodulatorThread *demodulatorThread; |     DemodulatorThread *demodulatorThread; | ||||||
|     DemodulatorThreadControlCommandQueue *threadQueueControl; |     DemodulatorThreadControlCommandQueue *threadQueueControl; | ||||||
|  | |||||||
| @ -148,14 +148,18 @@ void DemodulatorMgr::deleteThread(DemodulatorInstance *demod) { | |||||||
|     if (i != demods.end()) { |     if (i != demods.end()) { | ||||||
|         demods.erase(i); |         demods.erase(i); | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     //Ask for termination
 | ||||||
|     demod->terminate(); |     demod->terminate(); | ||||||
| 
 | 
 | ||||||
|  |     //Do not cleanup immediatly
 | ||||||
|     demods_deleted.push_back(demod); |     demods_deleted.push_back(demod); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| std::vector<DemodulatorInstance *> *DemodulatorMgr::getDemodulatorsAt(long long freq, int bandwidth) { | std::vector<DemodulatorInstance *> DemodulatorMgr::getDemodulatorsAt(long long freq, int bandwidth) { | ||||||
|     std::lock_guard < std::recursive_mutex > lock(demods_busy); |     std::lock_guard < std::recursive_mutex > lock(demods_busy); | ||||||
|     std::vector<DemodulatorInstance *> *foundDemods = new std::vector<DemodulatorInstance *>(); |      | ||||||
|  |     std::vector<DemodulatorInstance *> foundDemods; | ||||||
| 
 | 
 | ||||||
|     for (int i = 0, iMax = demods.size(); i < iMax; i++) { |     for (int i = 0, iMax = demods.size(); i < iMax; i++) { | ||||||
|         DemodulatorInstance *testDemod = demods[i]; |         DemodulatorInstance *testDemod = demods[i]; | ||||||
| @ -167,7 +171,7 @@ std::vector<DemodulatorInstance *> *DemodulatorMgr::getDemodulatorsAt(long long | |||||||
|         long long halfBuffer = bandwidth / 2; |         long long halfBuffer = bandwidth / 2; | ||||||
| 
 | 
 | ||||||
|         if ((freq <= (freqTest + ((testDemod->getDemodulatorType() != "LSB")?halfBandwidthTest:0) + halfBuffer)) && (freq >= (freqTest - ((testDemod->getDemodulatorType() != "USB")?halfBandwidthTest:0) - halfBuffer))) { |         if ((freq <= (freqTest + ((testDemod->getDemodulatorType() != "LSB")?halfBandwidthTest:0) + halfBuffer)) && (freq >= (freqTest - ((testDemod->getDemodulatorType() != "USB")?halfBandwidthTest:0) - halfBuffer))) { | ||||||
|             foundDemods->push_back(testDemod); |             foundDemods.push_back(testDemod); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -14,7 +14,7 @@ public: | |||||||
|     DemodulatorInstance *newThread(); |     DemodulatorInstance *newThread(); | ||||||
|     std::vector<DemodulatorInstance *> &getDemodulators(); |     std::vector<DemodulatorInstance *> &getDemodulators(); | ||||||
|     std::vector<DemodulatorInstance *> getOrderedDemodulators(bool actives = true); |     std::vector<DemodulatorInstance *> getOrderedDemodulators(bool actives = true); | ||||||
|     std::vector<DemodulatorInstance *> *getDemodulatorsAt(long long freq, int bandwidth); |     std::vector<DemodulatorInstance *> getDemodulatorsAt(long long freq, int bandwidth); | ||||||
|     DemodulatorInstance *getPreviousDemodulator(DemodulatorInstance *demod, bool actives = true); |     DemodulatorInstance *getPreviousDemodulator(DemodulatorInstance *demod, bool actives = true); | ||||||
|     DemodulatorInstance *getNextDemodulator(DemodulatorInstance *demod, bool actives = true); |     DemodulatorInstance *getNextDemodulator(DemodulatorInstance *demod, bool actives = true); | ||||||
|     DemodulatorInstance *getLastDemodulator(); |     DemodulatorInstance *getLastDemodulator(); | ||||||
|  | |||||||
| @ -9,7 +9,7 @@ | |||||||
| #include "CubicSDR.h" | #include "CubicSDR.h" | ||||||
| #include "DemodulatorInstance.h" | #include "DemodulatorInstance.h" | ||||||
| 
 | 
 | ||||||
| DemodulatorPreThread::DemodulatorPreThread(DemodulatorInstance *parent) : IOThread(), iqResampler(NULL), iqResampleRatio(1), cModem(nullptr), cModemKit(nullptr), iqInputQueue(NULL), iqOutputQueue(NULL), threadQueueNotify(NULL) | DemodulatorPreThread::DemodulatorPreThread(DemodulatorInstance *parent) : IOThread(), iqResampler(NULL), iqResampleRatio(1), cModem(nullptr), cModemKit(nullptr), iqInputQueue(NULL), iqOutputQueue(NULL) | ||||||
|  { |  { | ||||||
| 	initialized.store(false); | 	initialized.store(false); | ||||||
|     this->parent = parent; |     this->parent = parent; | ||||||
| @ -58,7 +58,6 @@ void DemodulatorPreThread::run() { | |||||||
| 
 | 
 | ||||||
|     iqInputQueue = static_cast<DemodulatorThreadInputQueue*>(getInputQueue("IQDataInput")); |     iqInputQueue = static_cast<DemodulatorThreadInputQueue*>(getInputQueue("IQDataInput")); | ||||||
|     iqOutputQueue = static_cast<DemodulatorThreadPostInputQueue*>(getOutputQueue("IQDataOutput")); |     iqOutputQueue = static_cast<DemodulatorThreadPostInputQueue*>(getOutputQueue("IQDataOutput")); | ||||||
|     threadQueueNotify = static_cast<DemodulatorThreadCommandQueue*>(getOutputQueue("NotifyQueue")); |  | ||||||
|      |      | ||||||
|     std::vector<liquid_float_complex> in_buf_data; |     std::vector<liquid_float_complex> in_buf_data; | ||||||
|     std::vector<liquid_float_complex> out_buf_data; |     std::vector<liquid_float_complex> out_buf_data; | ||||||
| @ -276,11 +275,6 @@ void DemodulatorPreThread::run() { | |||||||
|         tmp->decRefCount(); |         tmp->decRefCount(); | ||||||
|     } |     } | ||||||
|     buffers.purge(); |     buffers.purge(); | ||||||
| 
 |  | ||||||
|     DemodulatorThreadCommand tCmd(DemodulatorThreadCommand::DEMOD_THREAD_CMD_DEMOD_PREPROCESS_TERMINATED); |  | ||||||
|     tCmd.context = this; |  | ||||||
|     threadQueueNotify->push(tCmd); |  | ||||||
| //    std::cout << "Demodulator preprocessor thread done." << std::endl;
 |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void DemodulatorPreThread::setDemodType(std::string demodType) { | void DemodulatorPreThread::setDemodType(std::string demodType) { | ||||||
| @ -346,12 +340,22 @@ void DemodulatorPreThread::terminate() { | |||||||
|     iqInputQueue->push(inp); |     iqInputQueue->push(inp); | ||||||
|     DemodulatorWorkerThreadCommand command(DemodulatorWorkerThreadCommand::DEMOD_WORKER_THREAD_CMD_NULL); |     DemodulatorWorkerThreadCommand command(DemodulatorWorkerThreadCommand::DEMOD_WORKER_THREAD_CMD_NULL); | ||||||
|     workerQueue->push(command); |     workerQueue->push(command); | ||||||
|  |      | ||||||
|     workerThread->terminate(); |     workerThread->terminate(); | ||||||
|  |     workerThread->isTerminated(1000); | ||||||
|  | 
 | ||||||
|     t_Worker->join(); |     t_Worker->join(); | ||||||
|     delete t_Worker; |     delete t_Worker; | ||||||
|  |     t_Worker = nullptr; | ||||||
|  | 
 | ||||||
|     delete workerThread; |     delete workerThread; | ||||||
|  |     workerThread = nullptr; | ||||||
|  | 
 | ||||||
|     delete workerResults; |     delete workerResults; | ||||||
|  |     workerResults = nullptr; | ||||||
|  | 
 | ||||||
|     delete workerQueue; |     delete workerQueue; | ||||||
|  |     workerQueue = nullptr; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Modem *DemodulatorPreThread::getModem() { | Modem *DemodulatorPreThread::getModem() { | ||||||
|  | |||||||
| @ -79,5 +79,4 @@ protected: | |||||||
| 
 | 
 | ||||||
|     DemodulatorThreadInputQueue* iqInputQueue; |     DemodulatorThreadInputQueue* iqInputQueue; | ||||||
|     DemodulatorThreadPostInputQueue* iqOutputQueue; |     DemodulatorThreadPostInputQueue* iqOutputQueue; | ||||||
|     DemodulatorThreadCommandQueue* threadQueueNotify; |  | ||||||
| }; | }; | ||||||
|  | |||||||
| @ -69,7 +69,6 @@ void DemodulatorThread::run() { | |||||||
|     iqInputQueue = static_cast<DemodulatorThreadPostInputQueue*>(getInputQueue("IQDataInput")); |     iqInputQueue = static_cast<DemodulatorThreadPostInputQueue*>(getInputQueue("IQDataInput")); | ||||||
|     audioOutputQueue = static_cast<AudioThreadInputQueue*>(getOutputQueue("AudioDataOutput")); |     audioOutputQueue = static_cast<AudioThreadInputQueue*>(getOutputQueue("AudioDataOutput")); | ||||||
|     threadQueueControl = static_cast<DemodulatorThreadControlCommandQueue *>(getInputQueue("ControlQueue")); |     threadQueueControl = static_cast<DemodulatorThreadControlCommandQueue *>(getInputQueue("ControlQueue")); | ||||||
|     threadQueueNotify = static_cast<DemodulatorThreadCommandQueue*>(getOutputQueue("NotifyQueue")); |  | ||||||
|       |       | ||||||
|     ModemIQData modemData; |     ModemIQData modemData; | ||||||
|      |      | ||||||
| @ -290,13 +289,6 @@ void DemodulatorThread::run() { | |||||||
|     } |     } | ||||||
|     outputBuffers.purge(); |     outputBuffers.purge(); | ||||||
|      |      | ||||||
|     //Guard the cleanup of audioVisOutputQueue properly.
 |  | ||||||
|     std::lock_guard < std::mutex > lock(m_mutexAudioVisOutputQueue); |  | ||||||
|      |  | ||||||
|     DemodulatorThreadCommand tCmd(DemodulatorThreadCommand::DEMOD_THREAD_CMD_DEMOD_TERMINATED); |  | ||||||
|     tCmd.context = this; |  | ||||||
|     threadQueueNotify->push(tCmd); |  | ||||||
|      |  | ||||||
| //    std::cout << "Demodulator thread done." << std::endl;
 | //    std::cout << "Demodulator thread done." << std::endl;
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -56,7 +56,6 @@ protected: | |||||||
|     AudioThreadInputQueue *audioOutputQueue = nullptr; |     AudioThreadInputQueue *audioOutputQueue = nullptr; | ||||||
|     DemodulatorThreadOutputQueue* audioVisOutputQueue = nullptr; |     DemodulatorThreadOutputQueue* audioVisOutputQueue = nullptr; | ||||||
|     DemodulatorThreadControlCommandQueue *threadQueueControl = nullptr; |     DemodulatorThreadControlCommandQueue *threadQueueControl = nullptr; | ||||||
|     DemodulatorThreadCommandQueue* threadQueueNotify = nullptr; |  | ||||||
| 
 | 
 | ||||||
|     //protects the audioVisOutputQueue dynamic binding change at runtime (in DemodulatorMgr)
 |     //protects the audioVisOutputQueue dynamic binding change at runtime (in DemodulatorMgr)
 | ||||||
|     mutable std::mutex m_mutexAudioVisOutputQueue; |     mutable std::mutex m_mutexAudioVisOutputQueue; | ||||||
|  | |||||||
| @ -400,7 +400,6 @@ void GLFont::loadFontOnce() { | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         //2) then load from memory
 |         //2) then load from memory
 | ||||||
|         lodepng::State state; |  | ||||||
|         unsigned error = lodepng::decode(image, imgWidth, imgHeight, raw_image, png_size); |         unsigned error = lodepng::decode(image, imgWidth, imgHeight, raw_image, png_size); | ||||||
| 
 | 
 | ||||||
|         delete[] raw_image; |         delete[] raw_image; | ||||||
|  | |||||||
| @ -492,7 +492,7 @@ void WaterfallCanvas::OnIdle(wxIdleEvent &event) { | |||||||
| void WaterfallCanvas::updateHoverState() { | void WaterfallCanvas::updateHoverState() { | ||||||
|     long long freqPos = getFrequencyAt(mouseTracker.getMouseX()); |     long long freqPos = getFrequencyAt(mouseTracker.getMouseX()); | ||||||
|      |      | ||||||
|     std::vector<DemodulatorInstance *> *demodsHover = wxGetApp().getDemodMgr().getDemodulatorsAt(freqPos, 15000); |     std::vector<DemodulatorInstance *> demodsHover = wxGetApp().getDemodMgr().getDemodulatorsAt(freqPos, 15000); | ||||||
|      |      | ||||||
|     wxGetApp().getDemodMgr().setActiveDemodulator(NULL); |     wxGetApp().getDemodMgr().setActiveDemodulator(NULL); | ||||||
|      |      | ||||||
| @ -505,13 +505,13 @@ void WaterfallCanvas::updateHoverState() { | |||||||
|         } else { |         } else { | ||||||
|             setStatusText("Click and drag to set the current demodulator range."); |             setStatusText("Click and drag to set the current demodulator range."); | ||||||
|         } |         } | ||||||
|     } else if (demodsHover->size() && !shiftDown) { |     } else if (demodsHover.size() && !shiftDown) { | ||||||
|         long near_dist = getBandwidth(); |         long near_dist = getBandwidth(); | ||||||
|          |          | ||||||
|         DemodulatorInstance *activeDemodulator = NULL; |         DemodulatorInstance *activeDemodulator = NULL; | ||||||
|          |          | ||||||
|         for (int i = 0, iMax = demodsHover->size(); i < iMax; i++) { |         for (int i = 0, iMax = demodsHover.size(); i < iMax; i++) { | ||||||
|             DemodulatorInstance *demod = (*demodsHover)[i]; |             DemodulatorInstance *demod = demodsHover[i]; | ||||||
|             long long freqDiff = demod->getFrequency() - freqPos; |             long long freqDiff = demod->getFrequency() - freqPos; | ||||||
|             long halfBw = (demod->getBandwidth() / 2); |             long halfBw = (demod->getBandwidth() / 2); | ||||||
|             long long currentBw = getBandwidth(); |             long long currentBw = getBandwidth(); | ||||||
| @ -574,18 +574,18 @@ void WaterfallCanvas::updateHoverState() { | |||||||
|             mouseTracker.setHorizDragLock(false); |             mouseTracker.setHorizDragLock(false); | ||||||
|             setStatusText("Click and drag to change demodulator frequency; SPACE or numeric key for direct input. [, ] to nudge, M for mute, D to delete, C to center, E to edit label."); |             setStatusText("Click and drag to change demodulator frequency; SPACE or numeric key for direct input. [, ] to nudge, M for mute, D to delete, C to center, E to edit label."); | ||||||
|         } |         } | ||||||
|     } else { |     } | ||||||
|  |     else { | ||||||
|         SetCursor(wxCURSOR_CROSS); |         SetCursor(wxCURSOR_CROSS); | ||||||
|         nextDragState = WF_DRAG_NONE; |         nextDragState = WF_DRAG_NONE; | ||||||
|         if (shiftDown) { |         if (shiftDown) { | ||||||
|             setStatusText("Click to create a new demodulator or hold ALT to drag range, SPACE or numeric key for direct center frequency input."); |             setStatusText("Click to create a new demodulator or hold ALT to drag range, SPACE or numeric key for direct center frequency input."); | ||||||
|         } else { |         } | ||||||
|  |         else { | ||||||
|             setStatusText( |             setStatusText( | ||||||
|                 "Click to set active demodulator frequency or hold ALT to drag range; hold SHIFT to create new.  Right drag or wheel to Zoom.  Arrow keys to navigate/zoom, C to center."); |                 "Click to set active demodulator frequency or hold ALT to drag range; hold SHIFT to create new.  Right drag or wheel to Zoom.  Arrow keys to navigate/zoom, C to center."); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|      |  | ||||||
|     delete demodsHover; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void WaterfallCanvas::OnMouseMoved(wxMouseEvent& event) { | void WaterfallCanvas::OnMouseMoved(wxMouseEvent& event) { | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user