diff --git a/src/vault/mem/extent-family.hpp b/src/vault/mem/extent-family.hpp index 12f4e69e4..18647d87e 100644 --- a/src/vault/mem/extent-family.hpp +++ b/src/vault/mem/extent-family.hpp @@ -30,7 +30,7 @@ ** will fall out of use eventually, and can then be placed back into a buffer of free ** extents. In accordance to overall demand, this reserve buffer can be scaled up ** and down to avoid holding larger amounts of unused memory, while the availability - ** of a baseline amount of memory can be enforced. + ** of a baseline amount of memory can be enforced. ** ** @see ExtentFamily_test ** @see gear::BlockFlow usage example @@ -48,7 +48,7 @@ //#include "lib/symbol.hpp" #include "lib/iter-adapter.hpp" #include "lib/nocopy.hpp" -//#include "lib/util.hpp" +#include "lib/util.hpp" //#include #include @@ -62,6 +62,8 @@ namespace mem { // using util::isnil; // using std::string; + using util::unConst; + template class ExtentDiagnostic; @@ -133,13 +135,13 @@ namespace mem { Extent& yield() const { - UNIMPLEMENTED ("resolve index"); + return exFam->access (index); } void iterNext() { - UNIMPLEMENTED ("Iterate with wrap-around"); + exFam->incWrap (index); } bool @@ -171,10 +173,14 @@ namespace mem { } /** claim next \a cnt extents, possibly allocate. - * @note always allocating slightly in excess + * @remark the index pos previously marked as #after_ + * will always become the first new storage slot. + * @warning in case of #isWrapped, #first_ will be modified + * and thus _any existing indices may be invalidated._ + * @note always allocating slightly in excess */ void - openNew (size_t cnt) + openNew (size_t cnt =1) { if (not canAccomodate (cnt)) {//insufficient reserve -> allocate @@ -208,15 +214,18 @@ namespace mem { } ////////////////////////////////////////////////////////////////////////////TICKET #1316 : should reduce excess allocation (with apropriate damping to avoid oscillations) - /** allow transparent iteration of Extents, expanding storage on demand */ - using iterator = lib::IterStateWrapper; - - - iterator - active() + /** allow transparent iteration of Extents, + * with the ability to expand storage */ + struct iterator + : lib::IterStateWrapper { - UNIMPLEMENTED ("visit all active extents, possibly claim next ones"); - } + size_t getIndex() { return this->stateCore().index; } + void expandAlloc(){ this->stateCore().exFam->openNew();} + }; + + + iterator begin() { return iterator{IdxLink{this, start_}}; } + iterator end() { return iterator{IdxLink{this, after_}}; } private: @@ -230,7 +239,7 @@ namespace mem { size_t activeSlotCnt() const { - REQUIRE (start_ <= extents_.size()); + REQUIRE (start_ < extents_.size()); REQUIRE (after_ <= extents_.size()); return not isWrapped()? after_ - start_ @@ -256,11 +265,28 @@ namespace mem { * @remark using the array cyclically */ void - incWrap (size_t& idx, size_t inc) + incWrap (size_t& idx, size_t inc =1) { idx = (idx+inc) % extents_.size(); } + bool + isValidPos (size_t idx) const + { + REQUIRE (idx < extents_.size()); + REQUIRE (activeSlotCnt() > 0); + + return start_ <= idx + and idx < after_; + } + + Extent& + access (size_t idx) const + { + REQUIRE (isValidPos (idx)); + return unConst(this)->extents_[idx].access(); + } // deliberately const-ness does not cover payload + /// „backdoor“ to watch internals from tests friend class ExtentDiagnostic; diff --git a/tests/vault/mem/extent-family-test.cpp b/tests/vault/mem/extent-family-test.cpp index d4fa7eed0..f3ed55cd9 100644 --- a/tests/vault/mem/extent-family-test.cpp +++ b/tests/vault/mem/extent-family-test.cpp @@ -35,6 +35,7 @@ using test::Test; //using std::move; +using util::isnil; using util::isSameObject; @@ -78,7 +79,8 @@ namespace test { simpleUsage() { Extents extents{5}; - Extent& extent = *extents.active(); + extents.openNew(); + Extent& extent = *extents.begin(); CHECK (10 == extent.size()); int num = rand() % 1000; @@ -123,8 +125,12 @@ namespace test { iteration() { Extents extents{5}; - Iter it = extents.active(); + Iter it = extents.begin(); + CHECK (isnil (it)); + + extents.openNew(2); // allocate two Extents CHECK (it); + CHECK (0 == it.getIndex()); Extent& extent{*it}; CHECK (10 == extent.size()); @@ -135,11 +141,26 @@ namespace test { ++it; CHECK (it); + CHECK (1 == it.getIndex()); Extent& nextEx{*it}; CHECK (not isSameObject(extent, nextEx)); nextEx[5] = extent[2] + 1; CHECK (num == extent[2]); CHECK (num+1 == nextEx[5]); + + ++it; + CHECK (it == extents.end()); + CHECK (isnil (it)); // only two allocated + it.expandAlloc(); // but can expand allocation + CHECK (it); + + // iterate again to verify we get the same memory blocks + it = extents.begin(); + CHECK (isSameObject(*it, extent)); + CHECK ((*it)[2] == num); + ++it; + CHECK (isSameObject(*it, nextEx)); + CHECK ((*it)[5] == num+1); } diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index b746f2cda..a60c786dd 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -78759,8 +78759,20 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - + + + + + + + + + + + + + + @@ -78768,16 +78780,19 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - + + + + - - - - + + - - + + + + + @@ -79146,7 +79161,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + @@ -79164,9 +79179,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - + @@ -79196,7 +79209,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + @@ -79211,8 +79224,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
-
- + @@ -79261,7 +79273,9 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + + +

Damit vermeide ich, einen speziellen Marker-Wert zu verwenden; @@ -79273,43 +79287,79 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - + + - - + + - - - - - - - - + + + + + + + + + + + - +

- ...da wir den Platz im EpochGuard bereits anderweitig komplett ausschöpfen, muß die ExtentFamily auch beim Navigieren über die Sequenz der Epochen hinweg helfen. Und im Besonderen eine Navigation über das Ende hinaus muß transparent eine Erweiterung der Allokation  bewirken. Habe mich entschlossen, die Limitierung als Ausnahme/Exteption zu definieren, so daß im Regelfall die ExtentFamily einfach immer weiter wachsen soll + ...da wir den Platz im EpochGuard bereits anderweitig komplett ausschöpfen, muß die ExtentFamily auch beim Navigieren über die Sequenz der Epochen hinweg helfen. Und im Besonderen eine Navigation über das Ende hinaus muß nahtlos eine Erweiterung der Allokation  ermöglichen. Habe mich entschlossen, die Limitierung als Ausnahme/Exception zu definieren, so daß im Regelfall die ExtentFamily einfach immer weiter wachsen soll

- + + + + + + + + + + + + + +

+ ...das heißt, es könnte kein »for each« mehr geben, weil die Iteration bis zum Out-of-Memory weiterliefe. Könnte man machen, sollte man aber nicht so machen +

+ +
+ +
+ + + + + + +

+ stattdessen Allokations-Erweiterung auf dem Iterator anbieten: expandAlloc() +

+ +
+ +
+