Improved handling of late initialisation for component objects

This commit is contained in:
Nav
2021-12-31 19:45:15 +00:00
parent d24587b992
commit 49383eb448
9 changed files with 109 additions and 72 deletions

View File

@@ -44,11 +44,13 @@ int Application::run(const std::vector<std::string>& arguments) {
this->startup(); this->startup();
if (this->insightConfig.insightEnabled) { if (this->insightConfig->insightEnabled) {
this->insight = std::make_unique<Insight>(this->eventManager); this->insight = std::make_unique<Insight>(
this->insight->setProjectConfig(this->projectConfig); this->eventManager,
this->insight->setEnvironmentConfig(this->environmentConfig); this->projectConfig.value(),
this->insight->setInsightConfig(this->insightConfig); this->environmentConfig.value(),
this->insightConfig.value()
);
/* /*
* Before letting Insight occupy the main thread, process any pending events that accumulated * Before letting Insight occupy the main thread, process any pending events that accumulated
@@ -92,8 +94,8 @@ void Application::startup() {
std::bind(&Application::onShutdownApplicationRequest, this, std::placeholders::_1) std::bind(&Application::onShutdownApplicationRequest, this, std::placeholders::_1)
); );
this->projectConfig = this->extractConfig(); this->projectConfig = Application::extractConfig();
Logger::configure(this->projectConfig); Logger::configure(this->projectConfig.value());
// Start signal handler // Start signal handler
this->blockAllSignalsOnCurrentThread(); this->blockAllSignalsOnCurrentThread();
@@ -101,21 +103,30 @@ void Application::startup() {
Logger::info("Selected environment: \"" + this->selectedEnvironmentName + "\""); Logger::info("Selected environment: \"" + this->selectedEnvironmentName + "\"");
Logger::debug("Number of environments extracted from config: " Logger::debug("Number of environments extracted from config: "
+ std::to_string(this->projectConfig.environments.size())); + std::to_string(this->projectConfig->environments.size()));
// Validate the selected environment // Validate the selected environment
if (!projectConfig.environments.contains(this->selectedEnvironmentName)) { if (!this->projectConfig->environments.contains(this->selectedEnvironmentName)) {
throw InvalidConfig("Environment (\"" + this->selectedEnvironmentName + "\") not found in configuration."); throw InvalidConfig("Environment (\"" + this->selectedEnvironmentName + "\") not found in configuration.");
} }
this->environmentConfig = projectConfig.environments.at(this->selectedEnvironmentName); this->environmentConfig = this->projectConfig->environments.at(this->selectedEnvironmentName);
this->insightConfig = this->environmentConfig.insightConfig.value_or(this->projectConfig.insightConfig);
if (this->environmentConfig.debugServerConfig.has_value()) { if (this->environmentConfig->insightConfig.has_value()) {
this->debugServerConfig = this->environmentConfig.debugServerConfig.value(); this->insightConfig = this->environmentConfig->insightConfig.value();
} else if (this->projectConfig.debugServerConfig.has_value()) { } else if (this->projectConfig->insightConfig.has_value()) {
this->debugServerConfig = this->projectConfig.debugServerConfig.value(); this->insightConfig = this->projectConfig->insightConfig.value();
} else {
throw InvalidConfig("Insight configuration missing.");
}
if (this->environmentConfig->debugServerConfig.has_value()) {
this->debugServerConfig = this->environmentConfig->debugServerConfig.value();
} else if (this->projectConfig->debugServerConfig.has_value()) {
this->debugServerConfig = this->projectConfig->debugServerConfig.value();
} else { } else {
throw InvalidConfig("Debug server configuration missing."); throw InvalidConfig("Debug server configuration missing.");
@@ -269,12 +280,15 @@ int Application::initProject() {
} }
void Application::startTargetController() { void Application::startTargetController() {
this->targetController.setProjectConfig(this->projectConfig); this->targetController = std::make_unique<TargetController>(
this->targetController.setEnvironmentConfig(this->environmentConfig); this->eventManager,
this->projectConfig.value(),
this->environmentConfig.value()
);
this->targetControllerThread = std::thread( this->targetControllerThread = std::thread(
&TargetController::run, &TargetController::run,
std::ref(this->targetController) this->targetController.get()
); );
auto tcStateChangeEvent = this->applicationEventListener->waitForEvent<Events::TargetControllerThreadStateChanged>(); auto tcStateChangeEvent = this->applicationEventListener->waitForEvent<Events::TargetControllerThreadStateChanged>();
@@ -285,7 +299,7 @@ void Application::startTargetController() {
} }
void Application::stopTargetController() { void Application::stopTargetController() {
auto targetControllerState = this->targetController.getThreadState(); auto targetControllerState = this->targetController->getThreadState();
if (targetControllerState == ThreadState::STARTING || targetControllerState == ThreadState::READY) { if (targetControllerState == ThreadState::STARTING || targetControllerState == ThreadState::READY) {
this->eventManager.triggerEvent(std::make_shared<Events::ShutdownTargetController>()); this->eventManager.triggerEvent(std::make_shared<Events::ShutdownTargetController>());
this->applicationEventListener->waitForEvent<Events::TargetControllerThreadStateChanged>( this->applicationEventListener->waitForEvent<Events::TargetControllerThreadStateChanged>(
@@ -302,15 +316,11 @@ void Application::stopTargetController() {
void Application::startDebugServer() { void Application::startDebugServer() {
auto supportedDebugServers = this->getSupportedDebugServers(); auto supportedDebugServers = this->getSupportedDebugServers();
if (!supportedDebugServers.contains(this->debugServerConfig.name)) { if (!supportedDebugServers.contains(this->debugServerConfig->name)) {
throw Exceptions::InvalidConfig("DebugServer \"" + this->debugServerConfig.name + "\" not found."); throw Exceptions::InvalidConfig("DebugServer \"" + this->debugServerConfig->name + "\" not found.");
} }
this->debugServer = supportedDebugServers.at(this->debugServerConfig.name)(); this->debugServer = supportedDebugServers.at(this->debugServerConfig->name)();
this->debugServer->setProjectConfig(this->projectConfig);
this->debugServer->setEnvironmentConfig(this->environmentConfig);
this->debugServer->setDebugServerConfig(this->debugServerConfig);
Logger::info("Selected DebugServer: " + this->debugServer->getName()); Logger::info("Selected DebugServer: " + this->debugServer->getName());
this->debugServerThread = std::thread( this->debugServerThread = std::thread(

View File

@@ -49,7 +49,12 @@ namespace Bloom
{ {
"avr-gdb-rsp", "avr-gdb-rsp",
[this] () -> std::unique_ptr<DebugServers::DebugServer> { [this] () -> std::unique_ptr<DebugServers::DebugServer> {
return std::make_unique<DebugServers::Gdb::AvrGdbRsp>(this->eventManager); return std::make_unique<DebugServers::Gdb::AvrGdbRsp>(
this->eventManager,
this->projectConfig.value(),
this->environmentConfig.value(),
this->debugServerConfig.value()
);
} }
}, },
}; };
@@ -97,8 +102,12 @@ namespace Bloom
* dedicated thread. * dedicated thread.
* *
* See the TargetController class for more on this. * See the TargetController class for more on this.
*
* I could have used std::optional here, for the late initialisation, but given that we're using
* std::unique_ptr for the debug server (for polymorphism), I thought I'd keep it consistent and just use
* std::unique_ptr for lazy loading.
*/ */
TargetController targetController = TargetController(this->eventManager); std::unique_ptr<TargetController> targetController = nullptr;
std::thread targetControllerThread; std::thread targetControllerThread;
/** /**
@@ -133,10 +142,10 @@ namespace Bloom
* *
* See ProjectConfig.hpp for more on this. * See ProjectConfig.hpp for more on this.
*/ */
ProjectConfig projectConfig; std::optional<ProjectConfig> projectConfig;
EnvironmentConfig environmentConfig; std::optional<EnvironmentConfig> environmentConfig;
DebugServerConfig debugServerConfig; std::optional<DebugServerConfig> debugServerConfig;
InsightConfig insightConfig; std::optional<InsightConfig> insightConfig;
/** /**
* The project environment selected by the user. * The project environment selected by the user.

View File

@@ -28,21 +28,19 @@ namespace Bloom::DebugServers
class DebugServer: public Thread class DebugServer: public Thread
{ {
public: public:
explicit DebugServer(EventManager& eventManager): eventManager(eventManager) {}; explicit DebugServer(
EventManager& eventManager,
const ProjectConfig& projectConfig,
const EnvironmentConfig& environmentConfig,
const DebugServerConfig& debugServerConfig
):
eventManager(eventManager),
projectConfig(projectConfig),
environmentConfig(environmentConfig),
debugServerConfig(debugServerConfig) {};
virtual ~DebugServer() = default; virtual ~DebugServer() = default;
void setProjectConfig(const ProjectConfig& projectConfig) {
this->projectConfig = projectConfig;
}
void setEnvironmentConfig(const EnvironmentConfig& environmentConfig) {
this->environmentConfig = environmentConfig;
}
void setDebugServerConfig(const DebugServerConfig& debugServerConfig) {
this->debugServerConfig = debugServerConfig;
}
/** /**
* Entry point for the DebugServer. This must called from a dedicated thread. * Entry point for the DebugServer. This must called from a dedicated thread.
*/ */

View File

@@ -26,7 +26,12 @@ namespace Bloom::DebugServers::Gdb
class AvrGdbRsp: public GdbRspDebugServer class AvrGdbRsp: public GdbRspDebugServer
{ {
public: public:
explicit AvrGdbRsp(EventManager& eventManager): GdbRspDebugServer(eventManager) {}; explicit AvrGdbRsp(
EventManager& eventManager,
const ProjectConfig& projectConfig,
const EnvironmentConfig& environmentConfig,
const DebugServerConfig& debugServerConfig
): GdbRspDebugServer(eventManager, projectConfig, environmentConfig, debugServerConfig) {};
std::string getName() const override { std::string getName() const override {
return "AVR GDB Remote Serial Protocol Debug Server"; return "AVR GDB Remote Serial Protocol Debug Server";

View File

@@ -36,7 +36,12 @@ namespace Bloom::DebugServers::Gdb
class GdbRspDebugServer: public DebugServer class GdbRspDebugServer: public DebugServer
{ {
public: public:
explicit GdbRspDebugServer(EventManager& eventManager): DebugServer(eventManager) {}; explicit GdbRspDebugServer(
EventManager& eventManager,
const ProjectConfig& projectConfig,
const EnvironmentConfig& environmentConfig,
const DebugServerConfig& debugServerConfig
): DebugServer(eventManager, projectConfig, environmentConfig, debugServerConfig) {};
std::string getName() const override { std::string getName() const override {
return "GDB Remote Serial Protocol DebugServer"; return "GDB Remote Serial Protocol DebugServer";

View File

@@ -37,8 +37,16 @@ namespace Bloom
* *
* @param eventManager * @param eventManager
*/ */
explicit Insight(EventManager& eventManager): explicit Insight(
EventManager& eventManager,
const ProjectConfig& projectConfig,
const EnvironmentConfig& environmentConfig,
const InsightConfig& insightConfig
):
eventManager(eventManager), eventManager(eventManager),
projectConfig(projectConfig),
environmentConfig(environmentConfig),
insightConfig(insightConfig),
application( application(
( (
QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts, false), QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts, false),
@@ -49,18 +57,6 @@ namespace Bloom
) )
) {}; ) {};
void setProjectConfig(const ProjectConfig& projectConfig) {
this->projectConfig = projectConfig;
}
void setEnvironmentConfig(const EnvironmentConfig& environmentConfig) {
this->environmentConfig = environmentConfig;
}
void setInsightConfig(const InsightConfig& insightConfig) {
this->insightConfig = insightConfig;
}
/** /**
* Entry point for Insight. * Entry point for Insight.
*/ */
@@ -80,7 +76,11 @@ namespace Bloom
QApplication application; QApplication application;
InsightWorker* insightWorker = new InsightWorker(this->eventManager); InsightWorker* insightWorker = new InsightWorker(this->eventManager);
InsightWindow* mainWindow = new InsightWindow(*(this->insightWorker)); InsightWindow* mainWindow = new InsightWindow(
*(this->insightWorker),
this->environmentConfig,
this->insightConfig
);
TargetControllerConsole targetControllerConsole = TargetControllerConsole( TargetControllerConsole targetControllerConsole = TargetControllerConsole(
this->eventManager, this->eventManager,

View File

@@ -27,7 +27,17 @@ using Bloom::Targets::TargetPackage;
using Bloom::Targets::TargetPinDescriptor; using Bloom::Targets::TargetPinDescriptor;
using Bloom::Targets::TargetMemoryType; using Bloom::Targets::TargetMemoryType;
InsightWindow::InsightWindow(InsightWorker& insightWorker): QMainWindow(nullptr), insightWorker(insightWorker) { InsightWindow::InsightWindow(
InsightWorker& insightWorker,
const EnvironmentConfig& environmentConfig,
const InsightConfig& insightConfig
):
QMainWindow(nullptr),
insightWorker(insightWorker),
environmentConfig(environmentConfig),
targetConfig(environmentConfig.targetConfig),
insightConfig(insightConfig)
{
this->setObjectName("main-window"); this->setObjectName("main-window");
this->setWindowTitle("Bloom Insight"); this->setWindowTitle("Bloom Insight");
this->setMinimumSize(1000, 500); this->setMinimumSize(1000, 500);

View File

@@ -30,7 +30,11 @@ namespace Bloom
Q_OBJECT Q_OBJECT
public: public:
InsightWindow(InsightWorker& insightWorker); InsightWindow(
InsightWorker& insightWorker,
const EnvironmentConfig& environmentConfig,
const InsightConfig& insightConfig
);
void setEnvironmentConfig(const EnvironmentConfig& environmentConfig) { void setEnvironmentConfig(const EnvironmentConfig& environmentConfig) {
this->environmentConfig = environmentConfig; this->environmentConfig = environmentConfig;

View File

@@ -34,15 +34,11 @@ namespace Bloom
class TargetController: public Thread class TargetController: public Thread
{ {
public: public:
explicit TargetController(EventManager& eventManager): eventManager(eventManager) {}; explicit TargetController(
EventManager& eventManager,
void setProjectConfig(const ProjectConfig& projectConfig) { const ProjectConfig& projectConfig,
this->projectConfig = projectConfig; const EnvironmentConfig& environmentConfig
} ): eventManager(eventManager), projectConfig(projectConfig), environmentConfig(environmentConfig) {};
void setEnvironmentConfig(const EnvironmentConfig& environmentConfig) {
this->environmentConfig = environmentConfig;
}
/** /**
* Entry point for the TargetController. * Entry point for the TargetController.