From 9f78b647314a704e41aab9e8cb3ecc9480418301 Mon Sep 17 00:00:00 2001 From: "keldu.magnus" Date: Tue, 5 Oct 2021 16:40:24 +0200 Subject: [PATCH] merge working. added some noexcept cases --- source/kelgin/async.cpp | 4 +- source/kelgin/async.h | 22 ++------ source/kelgin/async.tmpl.h | 102 ++++++++++++++++++++++++------------- test/async.cpp | 8 +-- 4 files changed, 78 insertions(+), 58 deletions(-) diff --git a/source/kelgin/async.cpp b/source/kelgin/async.cpp index 21949aa..536be82 100644 --- a/source/kelgin/async.cpp +++ b/source/kelgin/async.cpp @@ -36,7 +36,7 @@ void ConveyorEventStorage::setParent(ConveyorStorage *p) { if (/*!parent && */ p && !isArmed() && queued() > 0) { assert(!parent); if (p->space() > 0) { - armNext(); + armLater(); } } @@ -333,7 +333,7 @@ void ConvertConveyorNodeBase::getResult(ErrorOrValue &err_or_val) { getImpl(err_or_val); } -void AttachConveyorNodeBase::getResult(ErrorOrValue &err_or_val) { +void AttachConveyorNodeBase::getResult(ErrorOrValue &err_or_val) noexcept { if (child) { child->getResult(err_or_val); } diff --git a/source/kelgin/async.h b/source/kelgin/async.h index 0067572..3fe42df 100644 --- a/source/kelgin/async.h +++ b/source/kelgin/async.h @@ -574,23 +574,13 @@ public: // Event void fire() override; // ConveyorNode - void getResult(ErrorOrValue &eov) override; + void getResult(ErrorOrValue &eov) noexcept override; // ConveyorStorage - size_t space() const override { return max_store - storage.size(); } - size_t queued() const override { return storage.size(); } - - void childHasFired() override { - if (child && storage.size() < max_store) { - ErrorOr eov; - child->getResult(eov); - storage.push(std::move(eov)); - if (!isArmed()) { - armLater(); - } - } - } + size_t space() const override; + size_t queued() const override; + void childHasFired() override; void parentHasFired() override; }; @@ -603,7 +593,7 @@ public: virtual ~AttachConveyorNodeBase() = default; - void getResult(ErrorOrValue &err_or_val) override; + void getResult(ErrorOrValue &err_or_val) noexcept override; }; template @@ -856,8 +846,6 @@ public: public: void attach(Conveyor conv); - void notifyNextAppendage(); - void governingNodeDestroyed(); }; diff --git a/source/kelgin/async.tmpl.h b/source/kelgin/async.tmpl.h index c35e2a1..a10911d 100644 --- a/source/kelgin/async.tmpl.h +++ b/source/kelgin/async.tmpl.h @@ -4,6 +4,9 @@ #include // Template inlining + +#include + namespace gin { template ConveyorResult execLater(Func &&func) { @@ -86,7 +89,10 @@ std::pair, MergeConveyor> Conveyor::merge() { MergeConveyor node_ref{data}; - return std::make_pair(Conveyor{std::move(merge_node), storage}, + ConveyorStorage *merge_storage = + static_cast(merge_node.get()); + + return std::make_pair(Conveyor{std::move(merge_node), merge_storage}, std::move(node_ref)); } @@ -189,12 +195,38 @@ template void QueueBufferConveyorNode::fire() { } template -void QueueBufferConveyorNode::getResult(ErrorOrValue &eov) { +void QueueBufferConveyorNode::getResult(ErrorOrValue &eov) noexcept { ErrorOr &err_or_val = eov.as(); err_or_val = std::move(storage.front()); storage.pop(); } +template size_t QueueBufferConveyorNode::space() const { + return max_store - storage.size(); +} + +template size_t QueueBufferConveyorNode::queued() const { + return storage.size(); +} + +template void QueueBufferConveyorNode::childHasFired() { + if (child && storage.size() < max_store) { + ErrorOr eov; + child->getResult(eov); + + if (eov.isError()) { + if (eov.error().isCritical()) { + child_storage = nullptr; + } + } + + storage.push(std::move(eov)); + if (!isArmed()) { + armLater(); + } + } +} + template void QueueBufferConveyorNode::parentHasFired() { GIN_ASSERT(parent) { return; } @@ -238,6 +270,7 @@ template void ImmediateConveyorNode::parentHasFired() { } template void ImmediateConveyorNode::fire() { + if (parent) { parent->childHasFired(); if (queued() > 0 && parent->space() > 0) { @@ -280,10 +313,23 @@ template void MergeConveyorNode::getResult(ErrorOrValue &eov) { next_appendage = std::min(appendages.size(), next_appendage); for (size_t i = next_appendage; i < appendages.size(); ++i) { - if (appendages[i]->queued()) { - err_or_val = std::move(appendages + if (appendages[i]->queued() > 0) { + err_or_val = std::move(appendages[i]->error_or_value.value()); + appendages[i]->error_or_value = std::nullopt; + next_appendage = i + 1; + return; } } + for (size_t i = 0; i < next_appendage; ++i) { + if (appendages[i]->queued() > 0) { + err_or_val = std::move(appendages[i]->error_or_value.value()); + appendages[i]->error_or_value = std::nullopt; + next_appendage = i + 1; + return; + } + } + + err_or_val = criticalError("No value in Merge Appendages"); } template void MergeConveyorNode::fire() { @@ -291,21 +337,25 @@ template void MergeConveyorNode::fire() { if (parent) { parent->childHasFired(); - } - if (queued() > 0 && parent->space() > 0) { - armLater(); - } else { - /// @unimplemented search for arm which has remaining elements + if (queued() > 0 && parent->space() > 0) { + armLater(); + } } } -template size_t MergeConveyorNode::space() const { - return error_or_value.has_value() ? 0 : 1; -} +template size_t MergeConveyorNode::space() const { return 0; } template size_t MergeConveyorNode::queued() const { - return error_or_value.has_value() ? 1 : 0; + GIN_ASSERT(data) { return 0; } + + size_t queue_count = 0; + + for (auto &iter : data->appendages) { + queue_count += iter->queued(); + } + + return queue_count; } template void MergeConveyorNode::childHasFired() { @@ -344,14 +394,14 @@ template size_t MergeConveyorNode::Appendage::queued() const { template void MergeConveyorNode::Appendage::getAppendageResult(ErrorOrValue &eov) { - ErrorOr> &eov = eov.as>(); + ErrorOr> &err_or_val = eov.as>(); GIN_ASSERT(queued() > 0) { - eov = criticalError("No element queued in Merge Appendage Node"); + err_or_val = criticalError("No element queued in Merge Appendage Node"); return; } - eov = std::move(error_or_value.value()); + err_or_val = std::move(error_or_value.value()); error_or_value = std::nullopt; } @@ -396,26 +446,6 @@ void MergeConveyorNodeData::attach(Conveyor conveyor) { appendages.push_back(std::move(merge_node_appendage)); } -template void MergeConveyorNodeData::notifyNextAppendage() { - next_appendage = std::min(next_appendage, appendages.size()); - - for (size_t i = next_appendage; i < appendages.size(); ++i) { - if (appendages[i]->childStorageHasElementQueued()) { - appendages[i]->parentHasFired(); - next_appendage = i + 1; - return; - } - } - - for (size_t i = 0; i < next_appendage; ++i) { - if (appendages[i]->childStorageHasElementQueued()) { - appendages[i]->parentHasFired(); - next_appendage = i + 1; - return; - } - } -} - template void MergeConveyorNodeData::governingNodeDestroyed() { appendages.clear(); merger = nullptr; diff --git a/test/async.cpp b/test/async.cpp index f2bec64..01a11db 100644 --- a/test/async.cpp +++ b/test/async.cpp @@ -209,11 +209,13 @@ GIN_TEST("Async Merge"){ cam.second.attach(Conveyor{11}); + cam.second.attach(Conveyor{14}); + size_t elements_passed = 0; bool wrong_value = false; auto sink = cam.first.then([&elements_passed, &wrong_value](int foo){ - if(foo == 10 || foo == 11){ + if(foo == 10 || foo == 11 || 14){ ++elements_passed; }else{ wrong_value = true; @@ -222,7 +224,7 @@ GIN_TEST("Async Merge"){ wait_scope.poll(); - GIN_EXPECT(!wrong_value, "Expected values 10 or 11"); - GIN_EXPECT(elements_passed == 2, std::string{"Expected 2 passed elements, got only "} + std::to_string(elements_passed)); + GIN_EXPECT(!wrong_value, std::string{"Expected values 10 or 11"}); + GIN_EXPECT(elements_passed == 3, std::string{"Expected 2 passed elements, got only "} + std::to_string(elements_passed)); } } \ No newline at end of file