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:
parent
3401f18c2c
commit
3b929cf014
3 changed files with 166 additions and 48 deletions
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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>;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -79162,17 +79162,133 @@ Date:   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äßt sich nur per linearer Suche in eine Index-Pos rückü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äßt sich per Vector-Arrithmetik in einen Index ü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ü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ür wäre aber jeder Zugriff eine doppelte Indirektion + cast"/>
|
||||
<node CREATED="1689026901975" ID="ID_846484908" MODIFIED="1689026931785" TEXT="und man müßte den <leer>-Wert speziell codieren"/>
|
||||
<node CREATED="1689030562169" ID="ID_1734074273" MODIFIED="1689030590655" TEXT="kann eigenstä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="ü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">
|
||||
‖ StateCore ‖
|
||||
</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ündung:
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
der direkte Zugang zum Index ist natürlich und leicht verständlich
|
||||
</li>
|
||||
<li>
|
||||
Performance ist gleich (nicht besonders toll aber voll OK) wie eine Pointer-Lösung
|
||||
</li>
|
||||
<li>
|
||||
und mit dem Marker-Wert muß 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öße: 2 * size_t"/>
|
||||
</node>
|
||||
<node CREATED="1689031016000" ID="ID_1425180137" MODIFIED="1689031041310" TEXT="als StateCore fü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ür einen aktiven und gültigen Extent niemals after_ sein, er muß 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="ü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>
|
||||
|
|
|
|||
Loading…
Reference in a new issue