From 54544bbe932afc5269c579de722657382af1e923 Mon Sep 17 00:00:00 2001 From: Andrew Belt Date: Thu, 16 May 2019 14:11:21 -0400 Subject: [PATCH] Use Module::Expander struct for accessing expander messages. --- include/engine/Module.hpp | 63 ++++++++++++++++++++------------------- src/app/RackWidget.cpp | 4 +-- src/engine/Engine.cpp | 55 ++++++++++++++-------------------- src/engine/Module.cpp | 12 ++++---- 4 files changed, 63 insertions(+), 71 deletions(-) diff --git a/include/engine/Module.hpp b/include/engine/Module.hpp index 89590a03..c11c3bd9 100644 --- a/include/engine/Module.hpp +++ b/include/engine/Module.hpp @@ -37,36 +37,39 @@ struct Module { std::vector lights; std::vector paramQuantities; - /** ID of the Module immediately to the left, or -1 if nonexistent. */ - int leftModuleId = -1; - /** Pointer to the left Module, or NULL if nonexistent. */ - Module *leftModule = NULL; - /** Double buffer for receiving messages from the left adjacent module. - If this module intends to receive messages from the left, allocate both message buffers with identical blocks of memory (arrays, structs, etc). - Remember to free the buffer in the Module destructor. - Example: - - leftProducerMessage = new MyModuleMessage; - leftConsumerMessage = new MyModuleMessage; - - Modules must check a foreign module's `model` before attempting to write its message buffer. - Once the module is checked, you can reinterpret_cast its leftProducerMessage for speed. - - Once you write a message, set leftMessageFlipRequested to true, to request that the messages are flipped at the end of the timestep. - Thus, message-passing has 1-sample latency. - - You may choose for the Module to write to its own message buffer for consumption by other modules, i.e. "pull" rather than "push". - As long as this convention is followed by the left module, this is fine. - */ - void *leftProducerMessage = NULL; - void *leftConsumerMessage = NULL; - bool leftMessageFlipRequested = false; - - int rightModuleId = -1; - Module *rightModule = NULL; - void *rightProducerMessage = NULL; - void *rightConsumerMessage = NULL; - bool rightMessageFlipRequested = true; + /** Represents a message-passing channel for an adjacent module. */ + struct Expander { + /** ID of the expander module, or -1 if nonexistent. */ + int moduleId = -1; + /** Pointer to the expander Module, or NULL if nonexistent. */ + Module *module = NULL; + /** Double buffer for receiving messages from the expander module. + If you intend to receive messages from an expander, allocate both message buffers with identical blocks of memory (arrays, structs, etc). + Remember to free the buffer in the Module destructor. + Example: + + rightExpander.producerMessage = new MyExpanderMessage; + rightExpander.consumerMessage = new MyExpanderMessage; + + You must check the expander module's `model` before attempting to write its message buffer. + Once the module is checked, you can reinterpret_cast its producerMessage at no performance cost. + + Producer messages are intended to be write-only. + Consumer messages are intended to be read-only. + + Once you write a message, set messageFlipRequested to true to request that the messages are flipped at the end of the timestep. + This means that message-passing has 1-sample latency. + + You may choose for your Module to instead write to its own message buffer for consumption by other modules, i.e. the expander "pulls" rather than this module "pushing". + As long as this convention is followed by the other module, this is fine. + */ + void *producerMessage = NULL; + void *consumerMessage = NULL; + bool messageFlipRequested = false; + }; + + Expander leftExpander; + Expander rightExpander; /** Seconds spent in the process() method, with exponential smoothing. Only written when CPU timing is enabled, since time measurement is expensive. diff --git a/src/app/RackWidget.cpp b/src/app/RackWidget.cpp index 05405bce..b607ead2 100644 --- a/src/app/RackWidget.cpp +++ b/src/app/RackWidget.cpp @@ -352,8 +352,8 @@ static void RackWidget_updateAdjacent(RackWidget *that) { } ModuleWidget *mw = dynamic_cast(w); - mw->module->rightModuleId = mwRight ? mwRight->module->id : -1; - mw->module->leftModuleId = mwLeft ? mwLeft->module->id : -1; + mw->module->leftExpander.moduleId = mwLeft ? mwLeft->module->id : -1; + mw->module->rightExpander.moduleId = mwRight ? mwRight->module->id : -1; } } diff --git a/src/engine/Engine.cpp b/src/engine/Engine.cpp index c206c72b..83e2e061 100644 --- a/src/engine/Engine.cpp +++ b/src/engine/Engine.cpp @@ -305,39 +305,26 @@ static void Engine_step(Engine *that) { // Flip messages for each module for (Module *module : that->internal->modules) { - if (module->leftMessageFlipRequested) { - std::swap(module->leftProducerMessage, module->leftConsumerMessage); - module->leftMessageFlipRequested = false; + if (module->leftExpander.messageFlipRequested) { + std::swap(module->leftExpander.producerMessage, module->leftExpander.consumerMessage); + module->leftExpander.messageFlipRequested = false; } - if (module->rightMessageFlipRequested) { - std::swap(module->rightProducerMessage, module->rightConsumerMessage); - module->rightMessageFlipRequested = false; + if (module->rightExpander.messageFlipRequested) { + std::swap(module->rightExpander.producerMessage, module->rightExpander.consumerMessage); + module->rightExpander.messageFlipRequested = false; } } } -static void Engine_updateAdjacent(Engine *that, Module *m) { - // Sync leftModule - if (m->leftModuleId >= 0) { - if (!m->leftModule || m->leftModule->id != m->leftModuleId) { - m->leftModule = that->getModule(m->leftModuleId); +static void Engine_updateExpander(Engine *that, Module::Expander *expander) { + if (expander->moduleId >= 0) { + if (!expander->module || expander->module->id != expander->moduleId) { + expander->module = that->getModule(expander->moduleId); } } else { - if (m->leftModule) { - m->leftModule = NULL; - } - } - - // Sync rightModule - if (m->rightModuleId >= 0) { - if (!m->rightModule || m->rightModule->id != m->rightModuleId) { - m->rightModule = that->getModule(m->rightModuleId); - } - } - else { - if (m->rightModule) { - m->rightModule = NULL; + if (expander->module) { + expander->module = NULL; } } } @@ -411,8 +398,10 @@ static void Engine_run(Engine *that) { if (!internal->paused) { std::lock_guard lock(internal->mutex); + // Update expander pointers for (Module *module : internal->modules) { - Engine_updateAdjacent(that, module); + Engine_updateExpander(that, &module->leftExpander); + Engine_updateExpander(that, &module->rightExpander); } // Step modules @@ -532,15 +521,15 @@ void Engine::removeModule(Module *module) { if (paramHandle->moduleId == module->id) paramHandle->module = NULL; } - // Update adjacent modules + // Update expander pointers for (Module *m : internal->modules) { - if (m->leftModule == module) { - m->leftModuleId = -1; - m->leftModule = NULL; + if (m->leftExpander.module == module) { + m->leftExpander.moduleId = -1; + m->leftExpander.module = NULL; } - if (m->rightModule == module) { - m->rightModuleId = -1; - m->rightModule = NULL; + if (m->rightExpander.module == module) { + m->rightExpander.moduleId = -1; + m->rightExpander.module = NULL; } } // Trigger Remove event diff --git a/src/engine/Module.cpp b/src/engine/Module.cpp index 278a3c6a..b5091ff6 100644 --- a/src/engine/Module.cpp +++ b/src/engine/Module.cpp @@ -61,12 +61,12 @@ json_t *Module::toJson() { } // leftModuleId - if (leftModuleId >= 0) - json_object_set_new(rootJ, "leftModuleId", json_integer(leftModuleId)); + if (leftExpander.moduleId >= 0) + json_object_set_new(rootJ, "leftModuleId", json_integer(leftExpander.moduleId)); // rightModuleId - if (rightModuleId >= 0) - json_object_set_new(rootJ, "rightModuleId", json_integer(rightModuleId)); + if (rightExpander.moduleId >= 0) + json_object_set_new(rootJ, "rightModuleId", json_integer(rightExpander.moduleId)); return rootJ; } @@ -115,12 +115,12 @@ void Module::fromJson(json_t *rootJ) { // leftModuleId json_t *leftModuleIdJ = json_object_get(rootJ, "leftModuleId"); if (leftModuleIdJ) - leftModuleId = json_integer_value(leftModuleIdJ); + leftExpander.moduleId = json_integer_value(leftModuleIdJ); // rightModuleId json_t *rightModuleIdJ = json_object_get(rootJ, "rightModuleId"); if (rightModuleIdJ) - rightModuleId = json_integer_value(rightModuleIdJ); + rightExpander.moduleId = json_integer_value(rightModuleIdJ); }