From 946f7c17f777186202f2e9016229bdd8eac47de6 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Thu, 13 Jul 2023 03:41:24 +0200 Subject: [PATCH] Block-Flow: implement opening a new Epoch ..this is the most simple case, where no Epochs are opened yet ..add diagnostics to inspect alloc count and deadlines ..add accessors for the first/last underlying Extent --- src/vault/gear/block-flow.hpp | 63 ++++++++++++++++++++++---- src/vault/mem/extent-family.hpp | 4 ++ tests/vault/gear/block-flow-test.cpp | 15 ++++-- tests/vault/mem/extent-family-test.cpp | 4 ++ wiki/thinkPad.ichthyo.mm | 63 ++++++++++++++++++-------- 5 files changed, 120 insertions(+), 29 deletions(-) diff --git a/src/vault/gear/block-flow.hpp b/src/vault/gear/block-flow.hpp index 726d9de79..00d13f594 100644 --- a/src/vault/gear/block-flow.hpp +++ b/src/vault/gear/block-flow.hpp @@ -57,7 +57,7 @@ //#include "lib/symbol.hpp" #include "lib/time/timevalue.hpp" #include "lib/nocopy.hpp" -//#include "lib/util.hpp" +#include "lib/util.hpp" //#include #include @@ -66,16 +66,22 @@ namespace vault{ namespace gear { -// using util::isnil; + using util::isnil; // using std::string; using lib::time::Time; + using lib::time::TimeVar; + using lib::time::Duration; + using lib::time::FrameRate; namespace {// hard-wired parametrisation const size_t EPOCH_SIZ = 100; const size_t ACTIVITIES_PER_FRAME = 10; + const size_t FRAMES_PER_EPOCH = EPOCH_SIZ/ACTIVITIES_PER_FRAME; const size_t INITIAL_FRAMES = 50; const size_t INITIAL_ALLOC = 1 + (INITIAL_FRAMES * ACTIVITIES_PER_FRAME) / EPOCH_SIZ; + const Duration INITIAL_EPOCH_STEP{FRAMES_PER_EPOCH * FrameRate{50}.duration()}; + /** raw allocator to provide a sequence of Extents to place Activity records */ using Allocator = mem::ExtentFamily; } @@ -124,6 +130,12 @@ namespace gear { } // default copyable + Instant& + deadline() + { + return data_.condition.dead; + } + bool hasFreeSlot() { // see C++ § 5.9 : comparison of pointers within same array @@ -167,12 +179,21 @@ namespace gear { : util::NonCopyable { Allocator alloc_; + TimeVar epochStep_; public: BlockFlow() : alloc_{INITIAL_ALLOC} + , epochStep_{INITIAL_EPOCH_STEP} { } + Duration + currEpochStep() const + { + return Duration{epochStep_}; + } + + /** * Local handle to allow allocating a collection of Activities, * all sharing a common deadline. Internally, these records are @@ -185,6 +206,10 @@ namespace gear { Allocator::iterator extent; public: + AllocatorHandle(Allocator::iterator slot) + : extent{slot} + { } + template Activity& create (ARGS&& ...args) @@ -196,8 +221,7 @@ namespace gear { Epoch& currEpoch() { - REQUIRE (bool(extent)); - return static_cast (*extent); + return asEpoch(extent); } void* @@ -217,7 +241,17 @@ namespace gear { AllocatorHandle until (Time deadline) { - UNIMPLEMENTED ("search through existing Epochs to locate the latest one to support given deadline"); + if (isnil (alloc_)) + {//just create new Epoch one epochStep ahead + alloc_.openNew(); + Epoch& newEpoch = Epoch::implantInto (alloc_.first()); + newEpoch.gate().deadline() = deadline + Time{epochStep_}; + return AllocatorHandle{alloc_.begin()}; + } + else + { + UNIMPLEMENTED ("search through existing Epochs to locate the latest one to support given deadline"); + } } void @@ -227,7 +261,20 @@ namespace gear { } private: - /////////////////// + /** @internal use a raw allocator Extent as Epoch (unchecked cast) */ + static Epoch& + asEpoch (Allocator::iterator slot) + { + REQUIRE (bool(slot)); + return asEpoch (*slot); + } + + static Epoch& + asEpoch (Allocator::Extent& extent) + { + return static_cast (extent); + } + /// „backdoor“ to watch internals from tests friend class FlowDiagnostic; @@ -251,8 +298,8 @@ namespace gear { : flow_{theFlow} { } -// size_t first() { return exFam_.start_; } -// size_t last() { return exFam_.after_; } + Time first() { return Time{BlockFlow::asEpoch(flow_.alloc_.first()).gate().deadline()}; } + Time last() { return Time{BlockFlow::asEpoch(flow_.alloc_.last() ).gate().deadline()}; } size_t cntEpochs() { return watch(flow_.alloc_).active(); } size_t poolSize() { return watch(flow_.alloc_).size(); } }; diff --git a/src/vault/mem/extent-family.hpp b/src/vault/mem/extent-family.hpp index c637855c3..429f0de73 100644 --- a/src/vault/mem/extent-family.hpp +++ b/src/vault/mem/extent-family.hpp @@ -231,6 +231,10 @@ namespace mem { friend iterator end (ExtentFamily& exFam) { return exFam.end(); } + bool empty() const { return start_ == after_; } + Extent& last() const { return access((after_+extents_.size()-1) % extents_.size()); } ///< @warning undefined behaviour when empty + Extent& first() const { return access(start_); } ///< @warning undefined behaviour when empty + private: /* ====== storage management implementation ====== */ bool diff --git a/tests/vault/gear/block-flow-test.cpp b/tests/vault/gear/block-flow-test.cpp index d128f7f08..877e0a77a 100644 --- a/tests/vault/gear/block-flow-test.cpp +++ b/tests/vault/gear/block-flow-test.cpp @@ -30,6 +30,7 @@ #include "vault/gear/block-flow.hpp" //#include "lib/time/timevalue.hpp" //#include "lib/format-cout.hpp" +#include "lib/test/diagnostic-output.hpp" ////////////////////////////////TODO //#include "lib/util.hpp" //#include @@ -73,18 +74,26 @@ namespace test { /** @test TODO demonstrate a simple usage scenario - * @todo WIP 7/23 ⟶ define ⟶ implement + * @todo WIP 7/23 ⟶ ✔define ⟶ 🔁implement */ void simpleUsage() { BlockFlow bFlow; Time deadline = randTime(); + Activity& tick = bFlow.until(deadline).create(); - ///////////////////////////////////////////////////////////////////////////////OOO diagnostic function to check allocation + CHECK (tick.verb_ == Activity::TICK); + CHECK (1 == watch(bFlow).cntEpochs()); + CHECK (watch(bFlow).first() > deadline); + CHECK (watch(bFlow).first() - deadline == bFlow.currEpochStep()); +SHOW_EXPR(watch(bFlow).cntEpochs()); +SHOW_EXPR(watch(bFlow).poolSize()); +SHOW_EXPR(watch(bFlow).first()); bFlow.discardBefore (deadline + Time{0,5}); - ///////////////////////////////////////////////////////////////////////////////OOO diagnostic function to check de-allocation +SHOW_EXPR(watch(bFlow).cntEpochs()); + CHECK (0 == watch(bFlow).cntEpochs()); } diff --git a/tests/vault/mem/extent-family-test.cpp b/tests/vault/mem/extent-family-test.cpp index 2c660b243..9b7ba7008 100644 --- a/tests/vault/mem/extent-family-test.cpp +++ b/tests/vault/mem/extent-family-test.cpp @@ -120,12 +120,14 @@ namespace test { iteration() { Extents extents{5}; + CHECK (isnil (extents)); Iter it = extents.begin(); CHECK (isnil (it)); // no extents provided yet extents.openNew(2); // allot two extents for active use CHECK (it); CHECK (0 == it.getIndex()); + CHECK (isSameObject(*it, extents.first())); Extent& extent{*it}; CHECK (10 == extent.size()); @@ -139,6 +141,7 @@ namespace test { CHECK (1 == it.getIndex()); Extent& nextEx{*it}; CHECK (not isSameObject(extent, nextEx)); + CHECK (isSameObject(nextEx, extents.last())); nextEx[5] = extent[2] + 1; CHECK (num == extent[2]); CHECK (num+1 == nextEx[5]); @@ -261,6 +264,7 @@ namespace test { Extents extents{5}; + CHECK ( extents.empty()); CHECK ( 0 == watch(extents).first()); CHECK ( 0 == watch(extents).last()); CHECK ( 0 == watch(extents).active()); diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 2123a56b9..c51a7d6b3 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -77933,7 +77933,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + @@ -78764,17 +78764,17 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - + + - - + + - - + + - - + + @@ -79635,8 +79635,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - + + @@ -79660,14 +79660,14 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - - + + + + - - - + + + @@ -79759,6 +79759,33 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + + + + + + + + + + + + + + + + + + + + + + + +