Support for multiple InsightWorker threads. We now have three InsightWorker threads as opposed to one

This commit is contained in:
Nav
2022-09-08 16:07:22 +01:00
parent 77cd13bf46
commit 1ddff3c2a4
4 changed files with 42 additions and 29 deletions

View File

@@ -42,7 +42,7 @@ Bloom and thus the connected AVR target. The DebugServer runs on a dedicated thr
##### Insight ##### Insight
Insight is a graphical user interface that provides insight into the connected target. It presents the target's Insight is a graphical user interface that provides insight into the connected target. It presents the target's
memories, GPIO pin states & registers, along with the ability to manipulate them. Insight occupies Bloom's main thread memories, GPIO pin states & registers, along with the ability to manipulate them. Insight occupies Bloom's main thread
and employs a single worker thread for background tasks. Unlike other components within Bloom, Insight relies heavily and employs several worker threads for background tasks. Unlike other components within Bloom, Insight relies heavily
on the Qt framework for its GUI capabilities and other useful utilities. See source code in src/Insight/ for more. on the Qt framework for its GUI capabilities and other useful utilities. See source code in src/Insight/ for more.
##### SignalHandler ##### SignalHandler

View File

@@ -45,7 +45,6 @@ namespace Bloom
try { try {
this->startup(); this->startup();
this->workerThread->start();
this->setThreadState(ThreadState::READY); this->setThreadState(ThreadState::READY);
Logger::info("Insight ready"); Logger::info("Insight ready");
this->application.exec(); this->application.exec();
@@ -179,20 +178,31 @@ namespace Bloom
this->mainWindow->setInsightConfig(this->insightConfig); this->mainWindow->setInsightConfig(this->insightConfig);
this->mainWindow->setEnvironmentConfig(this->environmentConfig); this->mainWindow->setEnvironmentConfig(this->environmentConfig);
// Prepare worker thread // Construct and start worker threads
this->workerThread = new QThread(); for (std::uint8_t i = 0; i < Insight::INSIGHT_WORKER_COUNT; ++i) {
this->workerThread->setObjectName("IW" + QString::number(this->insightWorker->id)); auto* insightWorker = new InsightWorker();
this->insightWorker->moveToThread(this->workerThread); auto* workerThread = new QThread();
QObject::connect(this->workerThread, &QThread::started, this->insightWorker, &InsightWorker::startup);
QObject::connect(this->workerThread, &QThread::finished, this->insightWorker, &QObject::deleteLater);
QObject::connect(this->workerThread, &QThread::finished, this->workerThread, &QThread::deleteLater);
this->mainWindow->init(this->targetControllerConsole.getTargetDescriptor()); workerThread->setObjectName("IW" + QString::number(insightWorker->id));
insightWorker->moveToThread(workerThread);
QObject::connect(workerThread, &QThread::started, insightWorker, &InsightWorker::startup);
QObject::connect(workerThread, &QThread::finished, insightWorker, &QObject::deleteLater);
QObject::connect(workerThread, &QThread::finished, workerThread, &QThread::deleteLater);
QObject::connect(this->insightWorker, &InsightWorker::ready, this, [this] { this->insightWorkersById[insightWorker->id] = std::pair(insightWorker, workerThread);
// TODO: Remove this hack. Find a better way to trigger the latest version check.
if (i == 0) {
QObject::connect(insightWorker, &InsightWorker::ready, this, [this] {
this->checkBloomVersion(); this->checkBloomVersion();
}); });
}
Logger::debug("Starting InsightWorker" + std::to_string(insightWorker->id) + " thread");
workerThread->start();
}
this->mainWindow->init(this->targetControllerConsole.getTargetDescriptor());
this->mainWindow->show(); this->mainWindow->show();
} }
@@ -205,11 +215,15 @@ namespace Bloom
this->mainWindow->close(); this->mainWindow->close();
if (this->workerThread != nullptr && this->workerThread->isRunning()) { for (auto& [workerId, workerPair] : this->insightWorkersById) {
Logger::debug("Stopping InsightWorker thread"); auto* workerThread = workerPair.second;
this->workerThread->quit();
Logger::debug("Waiting for InsightWorker thread to stop"); if (workerThread != nullptr && workerThread->isRunning()) {
this->workerThread->wait(); Logger::debug("Stopping InsightWorker" + std::to_string(workerId) + " thread");
workerThread->quit();
Logger::debug("Waiting for InsightWorker" + std::to_string(workerId) + " thread to stop");
workerThread->wait();
}
} }
this->application.exit(0); this->application.exit(0);
@@ -237,7 +251,7 @@ namespace Bloom
} }
); );
this->insightWorker->queueTask(versionQueryTask); InsightWorker::queueTask(versionQueryTask);
} }
void Insight::onInsightWindowActivated() { void Insight::onInsightWindowActivated() {

View File

@@ -2,6 +2,10 @@
#include <QtCore> #include <QtCore>
#include <QApplication> #include <QApplication>
#include <cstdint>
#include <map>
#include <utility>
#include <QThread>
#include "src/Helpers/Thread.hpp" #include "src/Helpers/Thread.hpp"
#include "src/Helpers/Paths.hpp" #include "src/Helpers/Paths.hpp"
@@ -62,6 +66,7 @@ namespace Bloom
void shutdown(); void shutdown();
private: private:
static constexpr std::uint8_t INSIGHT_WORKER_COUNT = 3;
std::string qtApplicationName = "Bloom"; std::string qtApplicationName = "Bloom";
std::array<char*, 1> qtApplicationArgv = {this->qtApplicationName.data()}; std::array<char*, 1> qtApplicationArgv = {this->qtApplicationName.data()};
int qtApplicationArgc = 1; int qtApplicationArgc = 1;
@@ -75,7 +80,9 @@ namespace Bloom
EventListener& eventListener; EventListener& eventListener;
QApplication application; QApplication application;
InsightWorker* insightWorker = new InsightWorker();
std::map<decltype(InsightWorker::id), std::pair<InsightWorker*, QThread*>> insightWorkersById;
InsightWindow* mainWindow = new InsightWindow( InsightWindow* mainWindow = new InsightWindow(
this->environmentConfig, this->environmentConfig,
this->insightConfig, this->insightConfig,
@@ -86,12 +93,6 @@ namespace Bloom
Targets::TargetState lastTargetState = Targets::TargetState::UNKNOWN; Targets::TargetState lastTargetState = Targets::TargetState::UNKNOWN;
InsightSignals* insightSignals = InsightSignals::instance(); InsightSignals* insightSignals = InsightSignals::instance();
/**
* Insight consists of two threads - the main thread where the main Qt event loop runs (for the GUI), and
* a single worker thread to handle any blocking/time-expensive operations.
*/
QThread* workerThread = nullptr;
void startup(); void startup();
/** /**

View File

@@ -12,8 +12,6 @@ namespace Bloom
using Bloom::Targets::TargetState; using Bloom::Targets::TargetState;
void InsightWorker::startup() { void InsightWorker::startup() {
Logger::debug("Starting InsightWorker" + std::to_string(this->id) + " thread");
QObject::connect( QObject::connect(
InsightSignals::instance(), InsightSignals::instance(),
&InsightSignals::taskQueued, &InsightSignals::taskQueued,