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();
if (this->insightConfig.insightEnabled) {
this->insight = std::make_unique<Insight>(this->eventManager);
this->insight->setProjectConfig(this->projectConfig);
this->insight->setEnvironmentConfig(this->environmentConfig);
this->insight->setInsightConfig(this->insightConfig);
if (this->insightConfig->insightEnabled) {
this->insight = std::make_unique<Insight>(
this->eventManager,
this->projectConfig.value(),
this->environmentConfig.value(),
this->insightConfig.value()
);
/*
* 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)
);
this->projectConfig = this->extractConfig();
Logger::configure(this->projectConfig);
this->projectConfig = Application::extractConfig();
Logger::configure(this->projectConfig.value());
// Start signal handler
this->blockAllSignalsOnCurrentThread();
@@ -101,21 +103,30 @@ void Application::startup() {
Logger::info("Selected environment: \"" + this->selectedEnvironmentName + "\"");
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
if (!projectConfig.environments.contains(this->selectedEnvironmentName)) {
if (!this->projectConfig->environments.contains(this->selectedEnvironmentName)) {
throw InvalidConfig("Environment (\"" + this->selectedEnvironmentName + "\") not found in configuration.");
}
this->environmentConfig = projectConfig.environments.at(this->selectedEnvironmentName);
this->insightConfig = this->environmentConfig.insightConfig.value_or(this->projectConfig.insightConfig);
this->environmentConfig = this->projectConfig->environments.at(this->selectedEnvironmentName);
if (this->environmentConfig.debugServerConfig.has_value()) {
this->debugServerConfig = this->environmentConfig.debugServerConfig.value();
if (this->environmentConfig->insightConfig.has_value()) {
this->insightConfig = this->environmentConfig->insightConfig.value();
} else if (this->projectConfig.debugServerConfig.has_value()) {
this->debugServerConfig = this->projectConfig.debugServerConfig.value();
} else if (this->projectConfig->insightConfig.has_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 {
throw InvalidConfig("Debug server configuration missing.");
@@ -269,12 +280,15 @@ int Application::initProject() {
}
void Application::startTargetController() {
this->targetController.setProjectConfig(this->projectConfig);
this->targetController.setEnvironmentConfig(this->environmentConfig);
this->targetController = std::make_unique<TargetController>(
this->eventManager,
this->projectConfig.value(),
this->environmentConfig.value()
);
this->targetControllerThread = std::thread(
&TargetController::run,
std::ref(this->targetController)
this->targetController.get()
);
auto tcStateChangeEvent = this->applicationEventListener->waitForEvent<Events::TargetControllerThreadStateChanged>();
@@ -285,7 +299,7 @@ void Application::startTargetController() {
}
void Application::stopTargetController() {
auto targetControllerState = this->targetController.getThreadState();
auto targetControllerState = this->targetController->getThreadState();
if (targetControllerState == ThreadState::STARTING || targetControllerState == ThreadState::READY) {
this->eventManager.triggerEvent(std::make_shared<Events::ShutdownTargetController>());
this->applicationEventListener->waitForEvent<Events::TargetControllerThreadStateChanged>(
@@ -302,15 +316,11 @@ void Application::stopTargetController() {
void Application::startDebugServer() {
auto supportedDebugServers = this->getSupportedDebugServers();
if (!supportedDebugServers.contains(this->debugServerConfig.name)) {
throw Exceptions::InvalidConfig("DebugServer \"" + this->debugServerConfig.name + "\" not found.");
if (!supportedDebugServers.contains(this->debugServerConfig->name)) {
throw Exceptions::InvalidConfig("DebugServer \"" + this->debugServerConfig->name + "\" not found.");
}
this->debugServer = supportedDebugServers.at(this->debugServerConfig.name)();
this->debugServer->setProjectConfig(this->projectConfig);
this->debugServer->setEnvironmentConfig(this->environmentConfig);
this->debugServer->setDebugServerConfig(this->debugServerConfig);
this->debugServer = supportedDebugServers.at(this->debugServerConfig->name)();
Logger::info("Selected DebugServer: " + this->debugServer->getName());
this->debugServerThread = std::thread(

View File

@@ -49,7 +49,12 @@ namespace Bloom
{
"avr-gdb-rsp",
[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.
*
* 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;
/**
@@ -133,10 +142,10 @@ namespace Bloom
*
* See ProjectConfig.hpp for more on this.
*/
ProjectConfig projectConfig;
EnvironmentConfig environmentConfig;
DebugServerConfig debugServerConfig;
InsightConfig insightConfig;
std::optional<ProjectConfig> projectConfig;
std::optional<EnvironmentConfig> environmentConfig;
std::optional<DebugServerConfig> debugServerConfig;
std::optional<InsightConfig> insightConfig;
/**
* The project environment selected by the user.

View File

@@ -28,21 +28,19 @@ namespace Bloom::DebugServers
class DebugServer: public Thread
{
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;
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.
*/

View File

@@ -26,7 +26,12 @@ namespace Bloom::DebugServers::Gdb
class AvrGdbRsp: public GdbRspDebugServer
{
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 {
return "AVR GDB Remote Serial Protocol Debug Server";

View File

@@ -36,7 +36,12 @@ namespace Bloom::DebugServers::Gdb
class GdbRspDebugServer: public DebugServer
{
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 {
return "GDB Remote Serial Protocol DebugServer";

View File

@@ -37,8 +37,16 @@ namespace Bloom
*
* @param eventManager
*/
explicit Insight(EventManager& eventManager):
explicit Insight(
EventManager& eventManager,
const ProjectConfig& projectConfig,
const EnvironmentConfig& environmentConfig,
const InsightConfig& insightConfig
):
eventManager(eventManager),
projectConfig(projectConfig),
environmentConfig(environmentConfig),
insightConfig(insightConfig),
application(
(
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.
*/
@@ -80,7 +76,11 @@ namespace Bloom
QApplication application;
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(
this->eventManager,

View File

@@ -27,7 +27,17 @@ using Bloom::Targets::TargetPackage;
using Bloom::Targets::TargetPinDescriptor;
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->setWindowTitle("Bloom Insight");
this->setMinimumSize(1000, 500);

View File

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

View File

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