Block-Flow: implement iteration and expansion of ExtentFamily

The low-level allocator is basically implemented now,
but we still need to check thoroughly that the tricky
wrap-around and expansion logic behaves sane...
(see #1311)
This commit is contained in:
Fischlurch 2023-07-11 03:52:24 +02:00
parent 3b929cf014
commit 6409e0eb36
3 changed files with 148 additions and 51 deletions

View file

@ -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 <string>
#include <algorithm>
@ -62,6 +62,8 @@ namespace mem {
// using util::isnil;
// using std::string;
using util::unConst;
template<typename T, size_t siz>
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<Extent, IdxLink>;
iterator
active()
/** allow transparent iteration of Extents,
* with the ability to expand storage */
struct iterator
: lib::IterStateWrapper<Extent, IdxLink>
{
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<T,siz>;

View file

@ -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);
}

View file

@ -78759,8 +78759,20 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<node CREATED="1688394900403" ID="ID_1380392473" MODIFIED="1688394919878" TEXT="underlying sequence-of-extents">
<icon BUILTIN="info"/>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1688434736501" ID="ID_1334906045" MODIFIED="1688434766802" TEXT="simpleUsage">
<icon BUILTIN="pencil"/>
<node COLOR="#338800" CREATED="1689039624159" ID="ID_257531084" MODIFIED="1689039682802" TEXT="simpleUsage">
<icon BUILTIN="button_ok"/>
<node COLOR="#338800" CREATED="1689039632758" ID="ID_860446703" MODIFIED="1689039686682" TEXT="einen Extent allozieren">
<icon BUILTIN="button_ok"/>
</node>
<node COLOR="#338800" CREATED="1689039639893" ID="ID_911206707" MODIFIED="1689039686682" TEXT="darauf zugreifen">
<icon BUILTIN="button_ok"/>
</node>
<node COLOR="#338800" CREATED="1689039651644" ID="ID_367791963" MODIFIED="1689039686682" TEXT="daten dort speichern">
<icon BUILTIN="button_ok"/>
</node>
</node>
<node COLOR="#338800" CREATED="1688434736501" ID="ID_1334906045" MODIFIED="1689039700401" TEXT="use_and_drop">
<icon BUILTIN="button_ok"/>
<node COLOR="#338800" CREATED="1688434743454" ID="ID_722620082" MODIFIED="1688434762609" TEXT="ExtentFamily erzeugen mit pre-Allocation">
<icon BUILTIN="button_ok"/>
</node>
@ -78768,16 +78780,19 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<icon BUILTIN="button_ok"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1688863035539" ID="ID_557979292" MODIFIED="1688864962621" TEXT="belegen und Aufr&#xe4;umen">
<icon BUILTIN="flag-yellow"/>
<node COLOR="#338800" CREATED="1688862915795" ID="ID_871871038" MODIFIED="1689039755286" TEXT="iteration">
<icon BUILTIN="button_ok"/>
<node COLOR="#338800" CREATED="1688862977234" ID="ID_1512460521" MODIFIED="1689039752912" TEXT="anfangs leer">
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1688862915795" ID="ID_871871038" MODIFIED="1688862919588" TEXT="iteration">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1688862977234" ID="ID_1512460521" MODIFIED="1688862993698" TEXT="iteration er&#xf6;ffnet weitere Extents">
<icon BUILTIN="flag-yellow"/>
<node COLOR="#338800" CREATED="1689039733704" ID="ID_332511670" MODIFIED="1689039751902" TEXT="mehrere Extents allozieren">
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1688862995665" ID="ID_469578407" MODIFIED="1688863007703" TEXT="man kann erneut &#xfc;ber Extents iterieren">
<icon BUILTIN="flag-yellow"/>
<node COLOR="#338800" CREATED="1689039741903" ID="ID_1941955701" MODIFIED="1689039751902" TEXT="kann dar&#xfc;ber iterieren und zugreifen">
<icon BUILTIN="button_ok"/>
</node>
<node COLOR="#338800" CREATED="1688862995665" ID="ID_469578407" MODIFIED="1689039754452" TEXT="man kann erneut &#xfc;ber Extents iterieren">
<icon BUILTIN="button_ok"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1688863046274" ID="ID_121256425" MODIFIED="1688863054657" TEXT="iteration mit wrap-around">
@ -79146,7 +79161,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1688398888563" ID="ID_1767596073" MODIFIED="1688398901315" TEXT="Iteration">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1688437541022" ID="ID_1493417420" MODIFIED="1688437566889" TEXT="kann man &#xfc;berhaupt iterieren ohne einen TransformIterator zu verwenden?">
<node COLOR="#435e98" CREATED="1688437541022" ID="ID_1493417420" MODIFIED="1689039356340" TEXT="kann man &#xfc;berhaupt iterieren ohne einen TransformIterator zu verwenden?">
<icon BUILTIN="help"/>
<node CREATED="1688509701330" ID="ID_1512622255" MODIFIED="1688509710564" TEXT="ja: ganz banal">
<icon BUILTIN="ksmiletris"/>
@ -79164,9 +79179,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</html></richcontent>
<icon BUILTIN="button_cancel"/>
<node CREATED="1688855104720" ID="ID_1636566408" MODIFIED="1689031065833" TEXT="Daten: (backlink, vector-iterator)"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1689026769252" ID="ID_363731350" MODIFIED="1689027040463" TEXT="Darstellung aktuelle Position">
<icon BUILTIN="info"/>
<node COLOR="#435e98" CREATED="1689026777681" ID="ID_1655807971" MODIFIED="1689027361378" TEXT="Alternativen">
<node COLOR="#5b280f" CREATED="1689026769252" ID="ID_363731350" MODIFIED="1689039350930" TEXT="Darstellung aktuelle Position">
<icon BUILTIN="info"/>
<node CREATED="1689026784432" ID="ID_1042302869" MODIFIED="1689027351109" TEXT="Pointer-to-Extent">
<icon BUILTIN="button_cancel"/>
@ -79196,7 +79209,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<node CREATED="1689030599955" ID="ID_58790531" MODIFIED="1689030607021" TEXT="zwingende Anforderung for Iter-Adapter"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1689027131702" ID="ID_1127616936" MODIFIED="1689030666355" TEXT="Wrapper um vector-Index">
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1689027131702" ID="ID_1127616936" MODIFIED="1689039321312" TEXT="Wrapper um vector-Index">
<linktarget COLOR="#dbe0e6" DESTINATION="ID_1127616936" ENDARROW="Default" ENDINCLINATION="-76;-82;" ID="Arrow_ID_675619664" SOURCE="ID_767307889" STARTARROW="None" STARTINCLINATION="-70;4;"/>
<icon BUILTIN="idea"/>
<node CREATED="1689027160679" ID="ID_614736589" MODIFIED="1689027174644" TEXT="transportiert die korrekten ValueType-Bindings"/>
@ -79211,8 +79224,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1689027131702" ID="ID_1742317518" MODIFIED="1689031165000">
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1689027131702" ID="ID_1742317518" MODIFIED="1689039300547">
<richcontent TYPE="NODE"><html>
<head></head>
<body>
@ -79261,7 +79273,9 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
<node CREATED="1689033583097" ID="ID_1997196983" MODIFIED="1689033762303" TEXT="index != after_">
<richcontent TYPE="NOTE"><html>
<head></head>
<head>
</head>
<body>
<p>
Damit vermeide ich, einen speziellen Marker-Wert zu verwenden;
@ -79273,43 +79287,79 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</html></richcontent>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1689033417616" ID="ID_693772805" MODIFIED="1689033418875" TEXT="yield()">
<icon BUILTIN="flag-yellow"/>
<node COLOR="#338800" CREATED="1689033417616" ID="ID_693772805" MODIFIED="1689039303674" TEXT="yield()">
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1689033420391" ID="ID_215666589" MODIFIED="1689033424535" TEXT="iterNext()">
<icon BUILTIN="flag-yellow"/>
<node COLOR="#338800" CREATED="1689033420391" ID="ID_215666589" MODIFIED="1689039305089" TEXT="iterNext()">
<icon BUILTIN="button_ok"/>
</node>
</node>
<node CREATED="1689027160679" ID="ID_1264158766" MODIFIED="1689027174644" TEXT="transportiert die korrekten ValueType-Bindings"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1689027175765" ID="ID_840159062" MODIFIED="1689027276564" TEXT="&#xfc;berladenen operator*()">
<icon BUILTIN="flag-yellow"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1689027269752" ID="ID_1830447052" MODIFIED="1689027276565" TEXT="operator bool()">
<icon BUILTIN="flag-yellow"/>
</node>
<node CREATED="1689027281735" ID="ID_1510788566" MODIFIED="1689027287635" TEXT="getIndex()">
<node CREATED="1689027160679" ID="ID_1264158766" MODIFIED="1689039299783" TEXT="transportiert die korrekten ValueType-Bindings"/>
<node COLOR="#435e98" CREATED="1689027281735" ID="ID_1510788566" MODIFIED="1689039540675" TEXT="getIndex()">
<icon BUILTIN="idea"/>
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1689039482634" HGAP="38" ID="ID_1887337658" MODIFIED="1689039494139" TEXT="ist das eine gute Idee?" VSHIFT="4">
<icon BUILTIN="help"/>
<node CREATED="1689039495217" ID="ID_805558518" MODIFIED="1689039504691" TEXT="Index-Nummern sind nicht stabil"/>
<node CREATED="1689039505457" ID="ID_1147505758" MODIFIED="1689039522417" TEXT="es gibt keinen Subscript-Operator"/>
<node CREATED="1689039529419" ID="ID_1472411724" MODIFIED="1689039536175" TEXT="&#x27f9; eigentlich nutzlos f&#xfc;r den client"/>
</node>
</node>
<node COLOR="#338800" CREATED="1689039476259" ID="ID_1771002787" MODIFIED="1689039481030" TEXT="expandAlloc()">
<icon BUILTIN="button_ok"/>
</node>
</node>
</node>
<node COLOR="#435e98" CREATED="1688509796132" ID="ID_361634809" MODIFIED="1688853056871" TEXT="fragt sich blo&#xdf;: wird &#xfc;berhaupt ein Iterator gebraucht?">
<arrowlink COLOR="#7e3acf" DESTINATION="ID_836380061" ENDARROW="Default" ENDINCLINATION="47;-174;" ID="Arrow_ID_166794449" STARTARROW="None" STARTINCLINATION="-280;14;"/>
<node CREATED="1688852868967" ID="ID_1480472415" MODIFIED="1688853067930" TEXT="Antwort: ja &#x2014; und zwar integriert mit dem Wachstum">
<node CREATED="1688852868967" ID="ID_1480472415" MODIFIED="1689036951117" TEXT="Antwort: ja &#x2014; und zwar um Wachstum nahtlos zu erm&#xf6;glichen">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
...da wir den Platz im EpochGuard bereits anderweitig komplett aussch&#246;pfen, mu&#223; die ExtentFamily auch beim Navigieren &#252;ber die Sequenz der Epochen hinweg helfen. Und im Besonderen eine Navigation &#252;ber das Ende hinaus mu&#223; <b>transparent eine Erweiterung der Allokation</b>&#160; bewirken. Habe mich entschlossen, die Limitierung als Ausnahme/Exteption zu definieren, so da&#223; im Regelfall die ExtentFamily einfach immer weiter wachsen soll
...da wir den Platz im EpochGuard bereits anderweitig komplett aussch&#246;pfen, mu&#223; die ExtentFamily auch beim Navigieren &#252;ber die Sequenz der Epochen hinweg helfen. Und im Besonderen eine Navigation &#252;ber das Ende hinaus mu&#223; <b>nahtlos eine Erweiterung der Allokation</b>&#160; erm&#246;glichen. Habe mich entschlossen, die Limitierung als Ausnahme/Exception zu definieren, so da&#223; im Regelfall die ExtentFamily einfach immer weiter wachsen soll
</p>
</body>
</html></richcontent>
<icon BUILTIN="forward"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1688853104969" ID="ID_1620391720" MODIFIED="1688853131602" TEXT="Iteration mu&#xdf; transparent &#xfc;ber Allokations-Erweiterung / &#xdc;berlauf hinweggehen">
<node COLOR="#435e98" CREATED="1688853104969" ID="ID_1620391720" MODIFIED="1689039292684" TEXT="nach Iterations-Ende mu&#xdf; nahtlos eine Allokations-Erweiterung folgen k&#xf6;nnen">
<icon BUILTIN="yes"/>
</node>
<node COLOR="#435e98" CREATED="1689037074376" ID="ID_732439061" MODIFIED="1689037112236" TEXT="automatisch die Allokation expandieren?">
<icon BUILTIN="help"/>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1689037090654" ID="ID_316316225" MODIFIED="1689037110364" TEXT="Antwort: m&#xf6;glich aber keine gute Idee">
<icon BUILTIN="yes"/>
</node>
<node CREATED="1689037113635" ID="ID_365095083" MODIFIED="1689037126924" TEXT="das w&#xfc;rde vom normalen Verhalten eines Iterators abweichen"/>
<node CREATED="1689037127777" ID="ID_1976747885" MODIFIED="1689037212763" TEXT="der Iterator k&#xf6;nnte damit nicht mehr ohne Mutation verwendet werden">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
...das hei&#223;t, es k&#246;nnte kein &#187;for each&#171; mehr geben, weil die Iteration bis zum Out-of-Memory weiterliefe. K&#246;nnte man machen, sollte man aber nicht so machen
</p>
</body>
</html></richcontent>
<icon BUILTIN="clanbomber"/>
</node>
<node CREATED="1689037221020" ID="ID_682907224" MODIFIED="1689037297470">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
stattdessen Allokations-Erweiterung auf dem Iterator anbieten: <font face="Monospaced" color="#902ca2">expandAlloc()</font>
</p>
</body>
</html></richcontent>
<icon BUILTIN="idea"/>
</node>
</node>
</node>
</node>
<node COLOR="#338800" CREATED="1688398893220" ID="ID_675575195" MODIFIED="1688960070966" TEXT="belegen / freigeben">