From 17d5f14cacdb1ac2363e9a81433a64ce265e3194 Mon Sep 17 00:00:00 2001
From: f4exb <f4exb06@gmail.com>
Date: Sat, 8 Oct 2022 13:20:17 +0200
Subject: [PATCH] Perseus: updated threading model. Part of #1346

---
 plugins/samplesource/perseus/perseusinput.cpp | 45 ++++++++++---------
 plugins/samplesource/perseus/perseusinput.h   |  8 ++--
 2 files changed, 28 insertions(+), 25 deletions(-)

diff --git a/plugins/samplesource/perseus/perseusinput.cpp b/plugins/samplesource/perseus/perseusinput.cpp
index d3d2b3e0b..981e8c1eb 100644
--- a/plugins/samplesource/perseus/perseusinput.cpp
+++ b/plugins/samplesource/perseus/perseusinput.cpp
@@ -18,6 +18,7 @@
 #include <QDebug>
 #include <QNetworkReply>
 #include <QBuffer>
+#include <QThread>
 
 #include "SWGDeviceSettings.h"
 #include "SWGDeviceState.h"
@@ -78,19 +79,26 @@ void PerseusInput::init()
 
 bool PerseusInput::start()
 {
+    QMutexLocker mlock(&m_mutex);
+
     if (m_running) {
-        stop();
+        return true;
     }
 
     // start / stop streaming is done in the thread.
 
+    m_perseusWorkerThread = new QThread();
     m_perseusWorker = new PerseusWorker(m_perseusDescriptor, &m_sampleFifo);
-    m_perseusWorker->moveToThread(&m_perseusWorkerThread);
+    m_perseusWorker->moveToThread(m_perseusWorkerThread);
     qDebug("PerseusInput::start: worker created");
 
+    QObject::connect(m_perseusWorkerThread, &QThread::started, m_perseusWorker, &PerseusWorker::startWork);
+    QObject::connect(m_perseusWorkerThread, &QThread::finished, m_perseusWorker, &QObject::deleteLater);
+    QObject::connect(m_perseusWorkerThread, &QThread::finished, m_perseusWorkerThread, &QThread::deleteLater);
+
     m_perseusWorker->setIQOrder(m_settings.m_iqOrder);
     m_perseusWorker->setLog2Decimation(m_settings.m_log2Decim);
-    startWorker();
+    m_perseusWorkerThread->start();
 
     applySettings(m_settings, true);
     m_running = true;
@@ -100,27 +108,22 @@ bool PerseusInput::start()
 
 void PerseusInput::stop()
 {
-    if (m_perseusWorker)
-    {
-        stopWorker();
-        delete m_perseusWorker;
-        m_perseusWorker = nullptr;
+    QMutexLocker mlock(&m_mutex);
+
+    if (!m_running) {
+        return;
     }
 
     m_running = false;
-}
 
-void PerseusInput::startWorker()
-{
-	m_perseusWorker->startWork();
-	m_perseusWorkerThread.start();
-}
+    if (m_perseusWorkerThread)
+    {
+        m_perseusWorkerThread->quit();
+        m_perseusWorkerThread->wait();
+        m_perseusWorker = nullptr;
+        m_perseusWorkerThread = nullptr;
+    }
 
-void PerseusInput::stopWorker()
-{
-	m_perseusWorker->stopWork();
-	m_perseusWorkerThread.quit();
-	m_perseusWorkerThread.wait();
 }
 
 QByteArray PerseusInput::serialize() const
@@ -336,7 +339,7 @@ bool PerseusInput::applySettings(const PerseusSettings& settings, bool force)
         reverseAPIKeys.append("log2Decim");
         forwardChange = true;
 
-        if (m_perseusWorker)
+        if (m_running)
         {
             m_perseusWorker->setLog2Decimation(settings.m_log2Decim);
             qDebug("PerseusInput: set decimation to %d", (1<<settings.m_log2Decim));
@@ -347,7 +350,7 @@ bool PerseusInput::applySettings(const PerseusSettings& settings, bool force)
     {
         reverseAPIKeys.append("iqOrder");
 
-        if (m_perseusWorker) {
+        if (m_running) {
             m_perseusWorker->setIQOrder(settings.m_iqOrder);
         }
     }
diff --git a/plugins/samplesource/perseus/perseusinput.h b/plugins/samplesource/perseus/perseusinput.h
index 04c776b67..b55b66be8 100644
--- a/plugins/samplesource/perseus/perseusinput.h
+++ b/plugins/samplesource/perseus/perseusinput.h
@@ -21,7 +21,7 @@
 #include <vector>
 
 #include <QNetworkRequest>
-#include <QThread>
+#include <QMutex>
 
 #include "perseus-sdr.h"
 #include "dsp/devicesamplesource.h"
@@ -30,6 +30,7 @@
 
 class QNetworkAccessManager;
 class QNetworkReply;
+class QThread;
 class DeviceAPI;
 class PerseusWorker;
 
@@ -136,16 +137,15 @@ private:
     DeviceAPI *m_deviceAPI;
     QString m_deviceDescription;
     PerseusSettings m_settings;
+    QMutex m_mutex;
     bool m_running;
     PerseusWorker *m_perseusWorker;
-    QThread m_perseusWorkerThread;
+    QThread *m_perseusWorkerThread;
     perseus_descr *m_perseusDescriptor;
     std::vector<uint32_t> m_sampleRates;
     QNetworkAccessManager *m_networkManager;
     QNetworkRequest m_networkRequest;
 
-	void startWorker();
-	void stopWorker();
     bool openDevice();
     void closeDevice();
     void setDeviceCenterFrequency(quint64 freq, const PerseusSettings& settings);