Block-Flow: better setup for iterator implementation

Using a Storage* within a wrapper as "pos" will work,
but is borderline trickery, since it amounts to subverting
the idea behind IterAdapter (which is to encapsulate a target
pointer with some control-logic in the managing container).

Using the same storage size and implementation overhead,
it is much more straight-forward to package the complete
iteration logic into a »State Core«, which in this case
however maintains a back-link to the ExtentFamily.
This commit is contained in:
Fischlurch 2023-07-11 01:53:14 +02:00
parent 3401f18c2c
commit 3b929cf014
3 changed files with 166 additions and 48 deletions

View file

@ -53,8 +53,10 @@
** There are many further ways of building a Lumiera Forward Iterator.
** For example, lib::IterSource exposes a "iterable" source of data elements,
** while hiding the actual container or generator implementation behind a
** VTable call. Besides, there are adapters for the most common usages
** with STL containers, and such iterators can also be combined and
** VTable call. Furthermore, complex processing chains with recursive
** expansion can be built with the \ref IterExporer builder function.
** Besides, there are adapters for the most common usages with STL
** containers, and such iterators can also be combined and
** extended with the help of \ref itertools.hpp
**
** Basically every class in compliance with our specific iterator concept
@ -141,7 +143,7 @@ namespace lib {
* @note it is possible to "hide" a smart-ptr within the CON template parameter.
*
* @tparam POS pointer or similar mutable link to the _current value_.
* Will be `bool()` checked to detect iteration end
* Will be `bool()` checked to detect iteration end, end else dereferenced.
* @tparam CON type of the backing container, which needs to implement two
* extension point functions for iteration control
*
@ -472,7 +474,7 @@ namespace lib {
public:
using IT::IT;
/* === state protocol API for IterStateWrapper === */
/* === state protocol API for IterStateWrapper === */
bool
checkPoint() const
{

View file

@ -109,31 +109,46 @@ namespace mem {
ENSURE (get() != nullptr);
return reinterpret_cast<Extent&> (*get());
}
struct iterator
{
using value_type = Extent;
using reference = Extent&;
using pointer = Extent*;
Storage* storageSlot;
explicit
operator bool() const
{
return bool(storageSlot);
}
Extent&
operator* ()
{
REQUIRE (storageSlot and *storageSlot);
return storageSlot->access();
}
};
};
using Extents = std::vector<Storage>;
using RawIter = typename Storage::iterator;
/**
* Iteration »State Core« based on Extents index position.
* @remark builds upon the specific wrap-around logic for
* cyclic reuse of extent storage and allocation.
*/
struct IdxLink
{
ExtentFamily* exFam{nullptr};
size_t index{0};
/* === state protocol API for IterStateWrapper === */
bool
checkPoint() const
{
return exFam and index != exFam->after_;
}
Extent&
yield() const
{
UNIMPLEMENTED ("resolve index");
}
void
iterNext()
{
UNIMPLEMENTED ("Iterate with wrap-around");
}
bool
operator== (IdxLink const& oi) const
{
return exFam == oi.exFam
and index == oi.index;
}
};
/* ==== Management Data ==== */
@ -194,7 +209,7 @@ namespace mem {
/** allow transparent iteration of Extents, expanding storage on demand */
using iterator = lib::IterAdapter<RawIter, ExtentFamily*>; ////////////////////OOO consider to use a Extent* instead of the RawIter??
using iterator = lib::IterStateWrapper<Extent, IdxLink>;
iterator
@ -247,21 +262,6 @@ namespace mem {
}
/* == Iteration control API (used by IterAdapter via ADL) == */
friend bool
checkPoint (ExtentFamily* exFam, RawIter& pos)
{
UNIMPLEMENTED ("ExtentFamily iteration control: check and adapt position");
}
friend void
iterNext (ExtentFamily* exFam, RawIter& pos)
{
UNIMPLEMENTED ("ExtentFamily iteration control: access next Extent, possibly expand allocation");
}
/// „backdoor“ to watch internals from tests
friend class ExtentDiagnostic<T,siz>;
};

View file

@ -79162,17 +79162,133 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</p>
</body>
</html></richcontent>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1688855104720" ID="ID_1636566408" MODIFIED="1688855162693" TEXT="Daten: (backlink, vector-iterator)">
<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">
<icon BUILTIN="info"/>
<node CREATED="1689026784432" ID="ID_1042302869" MODIFIED="1689027351109" TEXT="Pointer-to-Extent">
<icon BUILTIN="button_cancel"/>
<node CREATED="1689026814051" ID="ID_1924066976" MODIFIED="1689026837699" TEXT="l&#xe4;&#xdf;t sich nur per linearer Suche in eine Index-Pos r&#xfc;ck&#xfc;bersetzen">
<icon BUILTIN="stop-sign"/>
</node>
</node>
<node CREATED="1689026792775" ID="ID_401175300" MODIFIED="1689027354865" TEXT="Pointer-into Vector">
<icon BUILTIN="smiley-neutral"/>
<node CREATED="1689026945439" ID="ID_1984755714" MODIFIED="1689026993610" TEXT="l&#xe4;&#xdf;t sich per Vector-Arrithmetik in einen Index &#xfc;bersetzen">
<icon BUILTIN="idea"/>
</node>
<node CREATED="1689027014382" ID="ID_1063919929" MODIFIED="1689027099065" TEXT="Zugriff bedingt jedoch (ebenfalls) zwei Indirektionen + cast"/>
</node>
<node CREATED="1689026804112" ID="ID_46563966" MODIFIED="1689030533180" TEXT="vector-Index">
<icon BUILTIN="closed"/>
<node CREATED="1689026841988" ID="ID_767307889" MODIFIED="1689030809455" TEXT="w&#xfc;rde direkten Zugang zur Index-wrap-Logik bieten">
<arrowlink COLOR="#dbe0e6" DESTINATION="ID_1127616936" ENDARROW="Default" ENDINCLINATION="-76;-82;" ID="Arrow_ID_675619664" STARTARROW="None" STARTINCLINATION="-70;4;"/>
</node>
<node CREATED="1689026862074" ID="ID_1215574745" MODIFIED="1689027105768" TEXT="daf&#xfc;r w&#xe4;re aber jeder Zugriff eine doppelte Indirektion + cast"/>
<node CREATED="1689026901975" ID="ID_846484908" MODIFIED="1689026931785" TEXT="und man m&#xfc;&#xdf;te den &lt;leer&gt;-Wert speziell codieren"/>
<node CREATED="1689030562169" ID="ID_1734074273" MODIFIED="1689030590655" TEXT="kann eigenst&#xe4;ndig keinen opeartor*() implementieren">
<icon BUILTIN="stop-sign"/>
<node CREATED="1689030595148" ID="ID_1992627492" MODIFIED="1689030598907" TEXT="knock-out">
<icon BUILTIN="closed"/>
</node>
<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">
<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"/>
<node CREATED="1689027175765" ID="ID_925971110" MODIFIED="1689030791255" TEXT="&#xfc;berladenener operator*()"/>
<node CREATED="1689030719932" ID="ID_1685097739" MODIFIED="1689030734403" TEXT="braucht dann aber einen Back-Pointer auf den Container">
<icon BUILTIN="messagebox_warning"/>
</node>
<node CREATED="1689030740438" ID="ID_1138632813" MODIFIED="1689031056300" TEXT="das macht Iter-Adapter insgesamt redundant">
<arrowlink COLOR="#b2ecd1" DESTINATION="ID_1742317518" ENDARROW="Default" ENDINCLINATION="50;-145;" ID="Arrow_ID_403529665" STARTARROW="None" STARTINCLINATION="-100;6;"/>
<icon BUILTIN="idea"/>
</node>
</node>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1689027131702" ID="ID_1742317518" MODIFIED="1689031165000">
<richcontent TYPE="NODE"><html>
<head></head>
<body>
<p style="text-align: center">
&#x2016;&nbsp;StateCore&nbsp;&#x2016;
</p>
<p style="text-align: center">
<font color="#4b0099" face="Monospaced" size="2">(Backlink, Index)</font>
</p>
</body>
</html></richcontent>
<richcontent TYPE="NOTE"><html>
<head></head>
<body>
<p>
Begr&#252;ndung:
</p>
<ul>
<li>
der direkte Zugang zum Index ist nat&#252;rlich und leicht verst&#228;ndlich
</li>
<li>
Performance ist gleich (nicht besonders toll aber voll OK) wie eine Pointer-L&#246;sung
</li>
<li>
und mit dem Marker-Wert mu&#223; ich dann halt leben; Konstante definieren
</li>
</ul>
</body>
</html></richcontent>
<linktarget COLOR="#b2ecd1" DESTINATION="ID_1742317518" ENDARROW="Default" ENDINCLINATION="50;-145;" ID="Arrow_ID_403529665" SOURCE="ID_1138632813" STARTARROW="None" STARTINCLINATION="-100;6;"/>
<icon BUILTIN="idea"/>
<node CREATED="1689027149833" ID="ID_377414010" MODIFIED="1689031006892" TEXT="ExtentFamily::IdxLink">
<node CREATED="1689027249989" ID="ID_576991261" MODIFIED="1689030906333" TEXT="default-konstruierbar mit Leer-Marker"/>
<node CREATED="1688855104720" ID="ID_1006973140" MODIFIED="1689031092768" TEXT="Daten: (backlink, index)"/>
<node CREATED="1689027297484" ID="ID_239188445" MODIFIED="1689030913562" TEXT="Gr&#xf6;&#xdf;e: 2 * size_t"/>
</node>
<node CREATED="1689031016000" ID="ID_1425180137" MODIFIED="1689031041310" TEXT="als StateCore f&#xfc;r IterStateWrapper">
<icon BUILTIN="info"/>
<node COLOR="#338800" CREATED="1689033427830" ID="ID_569709413" MODIFIED="1689033569925" TEXT="braucht operator==()">
<icon BUILTIN="button_ok"/>
</node>
<node CREATED="1689033334323" ID="ID_217766059" MODIFIED="1689033578366" TEXT="checkPoint()">
<node CREATED="1689033579504" ID="ID_1555589201" MODIFIED="1689033581945" TEXT="backlink == null als Abbruchkriterium">
<icon BUILTIN="idea"/>
</node>
<node CREATED="1689033583097" ID="ID_1997196983" MODIFIED="1689033762303" TEXT="index != after_">
<richcontent TYPE="NOTE"><html>
<head></head>
<body>
<p>
Damit vermeide ich, einen speziellen Marker-Wert zu verwenden;
</p>
<p>
In der Tat darf der Index f&#252;r einen aktiven und g&#252;ltigen Extent niemals after_ sein, er mu&#223; entweder davor stehen, oder start_ == after_ und der Container ist leer
</p>
</body>
</html></richcontent>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1689033417616" ID="ID_693772805" MODIFIED="1689033418875" TEXT="yield()">
<icon BUILTIN="flag-yellow"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1688855122802" ID="ID_1154748375" MODIFIED="1688855159922" TEXT="Support in ExtentFamily">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1688855142439" ID="ID_520029458" MODIFIED="1688855157703" TEXT="checkPoint (src,pos)">
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1689033420391" ID="ID_215666589" MODIFIED="1689033424535" TEXT="iterNext()">
<icon BUILTIN="flag-yellow"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1688855167035" ID="ID_599034767" MODIFIED="1688855187689" TEXT="iterNext(src,pos)">
</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()">
<icon BUILTIN="idea"/>
</node>
</node>
</node>