Library: analyse options for passing a deleter function

The fundamental decision is that we want to have a single generic front-end,
meaning that we must jump dynamically into a configured deleter function.
And on top of that comes the additional requirement that ''some allocators''
are in fact tied to a specific instance, while other allocators are monostate.

However, we can distinguish both by probing if the allocator can be default constructed,
and if a default constructed allocator is equivalent to the currently used alloctor instance.

If this test fails, we must indeed maintain a single allocator instance,
and (to avoid overengineering for this rather special use case) we will
place this allocator instance into heap memory then, with a self-cleanup mechanism
On the other hand, all monostate allocators can be handled through static trapolines.
This commit is contained in:
Fischlurch 2024-06-05 23:45:30 +02:00
parent 802fef9b7c
commit 98d5b2962c
2 changed files with 206 additions and 9 deletions

View file

@ -50,7 +50,7 @@ namespace lib {
{
union Manager
{
typedef void (*Deleter) (void*, size_t);
typedef void (*Deleter) (void*, size_t, size_t);
bool unmanaged :1;
Deleter deleter;
@ -89,7 +89,7 @@ namespace lib {
*/
template<class I>
class Several
: util::MoveAssign
// : util::MoveAssign ////////////////////////////////////////OOO fundamental design mismatch with intended builder usage!
{
protected:
using Bucket = ArrayBucket<I>*;
@ -98,6 +98,9 @@ namespace lib {
Bucket data_{nullptr};
public:
~Several() noexcept
try { discardData(); }
ERROR_LOG_AND_IGNORE (progress, "clean-up Several data")
size_t
size() const
@ -131,6 +134,25 @@ namespace lib {
friend auto begin (Several const& svl) { return svl.begin();}
friend auto end (Several const& svl) { return svl.end(); }
private:
void
discardData()
{
if (data_ and not data_->manager.unmanaged)
{
if (data_->manager.deleter)
{
(*data_->manager.deleter) (data_, size_, data_->spread);
}
else
{
for (size_t i=0; i<size_; ++i)
operator [](i).~I();
////////////////////////////////////////////OOO really a good idea to invoke the std::allocator_traits directly here??
}
}
}
};

View file

@ -81389,16 +81389,19 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</p>
</body>
</html></richcontent>
<arrowlink COLOR="#e60034" DESTINATION="ID_1919181051" ENDARROW="Default" ENDINCLINATION="128;-86;" ID="Arrow_ID_1515063982" STARTARROW="None" STARTINCLINATION="-310;11;"/>
</node>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#f8f1cb" COLOR="#a50125" CREATED="1715533495624" HGAP="13" ID="ID_1919181051" MODIFIED="1715533550646" STYLE="bubble" TEXT="das ist ein schwerwiegendes Hindernis f&#xfc;r das gesamte Design" VSHIFT="5">
<node BACKGROUND_COLOR="#f8f1cb" COLOR="#a50125" CREATED="1715533495624" HGAP="13" ID="ID_1919181051" MODIFIED="1717594840302" STYLE="bubble" TEXT="das ist ein schwerwiegendes Hindernis f&#xfc;r das gesamte Design" VSHIFT="5">
<edge COLOR="#fe0606"/>
<linktarget COLOR="#e60034" DESTINATION="ID_1919181051" ENDARROW="Default" ENDINCLINATION="128;-86;" ID="Arrow_ID_1515063982" SOURCE="ID_252143573" STARTARROW="None" STARTINCLINATION="-310;11;"/>
<font NAME="SansSerif" SIZE="14"/>
<icon BUILTIN="clanbomber"/>
<node CREATED="1715618831175" HGAP="41" ID="ID_891863283" MODIFIED="1715618893746" STYLE="fork" TEXT="Auswege..." VSHIFT="41">
<edge COLOR="#6a3645" STYLE="linear"/>
<arrowlink COLOR="#982b52" DESTINATION="ID_1189594619" ENDARROW="Default" ENDINCLINATION="-919;-125;" ID="Arrow_ID_1251242601" STARTARROW="None" STARTINCLINATION="338;767;"/>
<node CREATED="1715618937215" ID="ID_975786159" MODIFIED="1715619229829" TEXT="Tag oder Allocator-Link in jeder Instanz">
<richcontent TYPE="NOTE"><html>
<head/>
@ -81849,6 +81852,135 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<node CREATED="1716909012702" ID="ID_1876994172" MODIFIED="1716909016713" TEXT="const-correctness">
<node CREATED="1716909019405" ID="ID_1406909807" MODIFIED="1716909042294" TEXT="ein const Several&lt;X&gt; ist ein Several&lt;const X&gt;"/>
</node>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1717594749496" ID="ID_390432519" MODIFIED="1717594763711" TEXT="Allokator-Problem gewaltsam l&#xf6;sen">
<icon BUILTIN="yes"/>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1717594765625" ID="ID_1189594619" MODIFIED="1717594883249" TEXT="das Problem">
<linktarget COLOR="#982b52" DESTINATION="ID_1189594619" ENDARROW="Default" ENDINCLINATION="-919;-125;" ID="Arrow_ID_1251242601" SOURCE="ID_891863283" STARTARROW="None" STARTINCLINATION="338;767;"/>
<icon BUILTIN="forward"/>
<node CREATED="1717594935958" ID="ID_858921465" MODIFIED="1717594952495" TEXT="wenn Allokation explizit an eine bestimmte Service-Instanz gebunden ist"/>
<node CREATED="1717594965146" ID="ID_619350952" MODIFIED="1717595004457" TEXT="irdendwo mu&#xdf; dann ein Backlink explizit in jede Conainer-Instanz gebracht werden"/>
<node CREATED="1717595006261" ID="ID_1556981419" MODIFIED="1717595028222" TEXT="und der Container-Typ, alsauch die Konstruktion mu&#xdf; eigens verdrahtet werden"/>
</node>
<node CREATED="1717595036364" ID="ID_1823793120" MODIFIED="1717595041590" TEXT="L&#xf6;sungsansatz">
<icon BUILTIN="idea"/>
<node CREATED="1717595044784" ID="ID_1559818606" MODIFIED="1717595074989" TEXT="wir akzeptieren die Notwendigkeit eines Backlink-Pointers f&#xfc;r jede Instanz"/>
<node CREATED="1717595077747" ID="ID_698525218" MODIFIED="1717595094005" TEXT="allerdings bringen wir diesen Backlink-Pointer in der Daten-Allokation mit unter"/>
<node CREATED="1717595102201" ID="ID_1585335172" MODIFIED="1717595123239" TEXT="und l&#xf6;sen rein dynamisch auf &#x27f9; Container-Typ bleibt generisch"/>
<node CREATED="1717595147522" ID="ID_1598402284" MODIFIED="1717595160516" TEXT="die Verdrahtung wird komplett in den Builder verschoben"/>
<node CREATED="1717595164991" ID="ID_46981034" MODIFIED="1717595294457">
<richcontent TYPE="NODE"><html>
<head/>
<body>
<p>
g&#252;nstigenfalls bleibt der Backlink dann<i>&#160;inaktiv</i>
</p>
</body>
</html></richcontent>
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
hei&#223;t: er kann zwar nicht wegfallen (weil sich das dann im Typ ausdr&#252;cken w&#252;rde) &#8212; aber der Pointer bleibt dann NULL und der Container f&#228;llt auf Standard-Verhalten zur&#252;ck
</p>
</body>
</html>
</richcontent>
<node CREATED="1717595296327" ID="ID_312816298" MODIFIED="1717595311329" TEXT="entweder er macht Standard-Heap-Allokationen"/>
<node CREATED="1717595311917" ID="ID_1199827778" MODIFIED="1717595477064" TEXT="oder er de-alloziert &#xfc;berhaupt nicht">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
....das ist ein besonders relevanter use-case, n&#228;mlich wenn wir einen Allocation-Cluster verwenden; in diesem Fall wird anfangs vom Builder der Speicher zugeteilt, und dann sp&#228;ter einfach &#8222;fallen gelassen&#8220;. Aufgrund einer allgemeinen Lifecycle-Argumentation kann zu einem sp&#228;teren Zeitpunkt der gesamte Allocation-Cluster<i>&#160;ohne weitere Aufr&#228;um-Aktivit&#228;ten</i>&#160;verworfen werden. Das ist wie ein Garbage-Collector ohne Garbage-Collection &#9786;
</p>
</body>
</html></richcontent>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#f8f1cb" COLOR="#a50125" CREATED="1717595132644" ID="ID_450689056" MODIFIED="1717595604710" TEXT="spezielle Probleme verbleiben...">
<icon BUILTIN="messagebox_warning"/>
<node CREATED="1717595496517" ID="ID_1721370451" MODIFIED="1717595511854" TEXT="man mu&#xdf; einen Funktions-Pointer auf eine Delete-Funktion bereitstellen"/>
<node CREATED="1717595512394" ID="ID_1248004805" MODIFIED="1717595535123" TEXT="diese Funktion mu&#xdf; &#x201e;irgendwo residieren&#x201c;"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1717595555989" ID="ID_1131600026" MODIFIED="1717595597589" TEXT="&#x27f9; erkennen ob diese Funktion statisch bereitstellbar ist">
<font NAME="SansSerif" SIZE="12"/>
<icon BUILTIN="yes"/>
<node CREATED="1717595622928" ID="ID_674949727" MODIFIED="1717595800427" TEXT="Kriterium: der Allokator hat (k)eine eigene Identit&#xe4;t">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
Das ist die Quintessenz. Hat er eine eigene Identit&#228;t, so mu&#223; er eigens konstruiert werden und damit eigens verdrahtet sein &#8212; und wir brauchen <i>genau diese Allokator-Instanz</i>&#160;zur De-Allokation.
</p>
</body>
</html></richcontent>
</node>
<node CREATED="1717595644801" ID="ID_1133839830" MODIFIED="1717596036662" TEXT="reduziert auf: der Allokator ist default-konstruierbar">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
Zun&#228;chst einmal ist das eine logische Abschw&#228;chung, und keine Verst&#228;rkung. Daher ist diese Bedingung <i>logisch nicht &#228;quivalent </i>zur vorgenannten Voraussetzung (eigene Identit&#228;t). Jedoch l&#228;&#223;t sich dieses Kriterium nachsch&#228;rfen: man fordert, da&#223; der Allokator default-Konstruierbar ist, und da&#223; eine default-konstruierte Instanz mit dem gegebenen Allokator &#228;quivalent ist (gem&#228;&#223; C++ Konventionen pr&#252;fbar durch den Vergleichsoperator).
</p>
<p>
</p>
<p>
Wenn dieser Test <i>scheitert, </i>dann <b>mu&#223; die Allokator-Instanz erhalten bleiben<i>.</i></b>
</p>
</body>
</html>
</richcontent>
<icon BUILTIN="yes"/>
</node>
</node>
<node CREATED="1717596043540" ID="ID_1749303300" MODIFIED="1717596058446" TEXT="wenn nicht: dann auf den Heap legen mit Selbstzerst&#xf6;rung">
<icon BUILTIN="yes"/>
<node CREATED="1717596059913" ID="ID_1522877853" MODIFIED="1717596065581" TEXT="ja... das ist eine gewaltsame L&#xf6;sung"/>
<node CREATED="1717596069392" ID="ID_837902411" MODIFIED="1717596142481" TEXT="sie ist zweifellos verbesserbar">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
z.B. durch einen Meta-Allokator, wie z.B. ein statisch vorgehaltener Puffer....
</p>
</body>
</html></richcontent>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1717596145494" HGAP="22" ID="ID_51239584" MODIFIED="1717596166256" TEXT="&#xbb;premature optimisation&#xab;" VSHIFT="4">
<icon BUILTIN="stop-sign"/>
</node>
</node>
<node CREATED="1717596180493" ID="ID_600061844" MODIFIED="1717596206754" TEXT="macht sich zunutze: der Deleter wird pro Container genau einmal aufgerufen">
<icon BUILTIN="idea"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1717596235650" ID="ID_608819565" MODIFIED="1717596532860" TEXT="Implementierung">
<linktarget COLOR="#549cbc" DESTINATION="ID_608819565" ENDARROW="Default" ENDINCLINATION="152;866;" ID="Arrow_ID_190880203" SOURCE="ID_492608922" STARTARROW="None" STARTINCLINATION="-139;-10;"/>
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1717596241009" ID="ID_770727824" MODIFIED="1717596250200" TEXT="Erkennungs-Mechanismus">
<icon BUILTIN="flag-yellow"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1717596251272" ID="ID_33871958" MODIFIED="1717596257784" TEXT="statisches Trampolin">
<icon BUILTIN="flag-yellow"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1717596259159" ID="ID_1839960110" MODIFIED="1717596303613" TEXT="einmal-Funktor">
<icon BUILTIN="flag-yellow"/>
<node COLOR="#435e98" CREATED="1717596309134" ID="ID_239011587" MODIFIED="1717596403567" TEXT="sowas hab ich doch erst k&#xfc;rzlich implementiert....">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
In der Tat: siehe special-job-fun.hpp
</p>
</body>
</html>
</richcontent>
<icon BUILTIN="idea"/>
</node>
</node>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#f8f1cb" COLOR="#a50125" CREATED="1716936826666" ID="ID_1382882363" MODIFIED="1716936834769" TEXT="Problem: Objekte verschieben">
<icon BUILTIN="messagebox_warning"/>
<node CREATED="1716936845950" ID="ID_715653412" MODIFIED="1716936862044" TEXT="eigentlich darf man das nur bei trivial kopierbaren Objekten">
@ -81957,8 +82089,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
die C-Funktion <font face="Monospaced">realloc()</font>&#160;kann zwar scheinbar &#8222;zaubern&#8220;, ist aber tats&#228;chlich auf Hilfe vom Allokator angewiesen, insofern dieser sich intern gewisse zus&#228;tzliche Reserven sichert. Und wenn seine Resevern nicht reichen, dann wird sofort woanders alloziert und alles per <font face="Monospaced">memmove()</font>&#160; umkopiert....
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node CREATED="1717536217204" ID="ID_248984018" MODIFIED="1717536532662" TEXT="...sondern erzeugt das gleiche Verhalten direkt">
<richcontent TYPE="NOTE"><html>
@ -81968,8 +82099,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
Tats&#228;chlich kann <font face="Monospaced">std::vector()</font>&#160;dasselbe besser machen, da er ggfs move-Konstruktoren aufrufen und au&#223;erdem als zus&#228;tzliche Heuristik die aktuelle Gr&#246;&#223;e des Vektors heranziehen kann, um eine angemessene Reserve bereitzustellen; au&#223;erdem ist die Gr&#246;&#223;e der Reserve direkt auf das API herausgef&#252;hrt.
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node CREATED="1717536629978" ID="ID_1567771113" MODIFIED="1717536675032" TEXT="Hilfsmittel: Typ-Weiche und std::move_iterator">
<arrowlink COLOR="#47a78d" DESTINATION="ID_237185972" ENDARROW="Default" ENDINCLINATION="-91;252;" ID="Arrow_ID_1124696583" STARTARROW="None" STARTINCLINATION="674;41;"/>
@ -82063,7 +82193,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
<node CREATED="1717543060128" ID="ID_1973537913" MODIFIED="1717543071098" TEXT="Handler">
<node CREATED="1717543072032" ID="ID_1791379026" MODIFIED="1717543076568" TEXT="getDeleter()">
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1717546372010" ID="ID_231852526" MODIFIED="1717546386695" TEXT="kl&#xe4;ren: wie wird er konkret vernendet?">
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1717546372010" ID="ID_231852526" MODIFIED="1717596420967" TEXT="kl&#xe4;ren: wie wird er konkret verwendet?">
<icon BUILTIN="help"/>
<node CREATED="1717546388726" ID="ID_1089262988" MODIFIED="1717546407495" TEXT="mu&#xdf; einen Pointer auf ein Trampolin speichern k&#xf6;nnen"/>
<node CREATED="1717546408121" ID="ID_1274735212" MODIFIED="1717546425197" TEXT="mu&#xdf; den Allokator mit einbinden">
@ -82072,12 +82202,54 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<node BACKGROUND_COLOR="#f8f1cb" COLOR="#a50125" CREATED="1717546661817" ID="ID_999124001" MODIFIED="1717546671561" TEXT="wir haben NUR einen Pointer in der Storage vorgesehen">
<icon BUILTIN="messagebox_warning"/>
</node>
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1717546728089" ID="ID_549532304" MODIFIED="1717546740840" TEXT="wer verwaltet dann die Allokator-Instanz?">
<node COLOR="#435e98" CREATED="1717546728089" ID="ID_549532304" MODIFIED="1717596648356" TEXT="wer verwaltet dann die Allokator-Instanz?">
<icon BUILTIN="help"/>
<node CREATED="1717596434496" ID="ID_448986316" LINK="#ID_1919181051" MODIFIED="1717596478754" TEXT="das ist ein verbleibendes schwieriges Design-Problem"/>
<node CREATED="1717596484971" ID="ID_492608922" MODIFIED="1717596543212" TEXT="es wird &#xbb;gewaltsam&#xab; gel&#xf6;st">
<arrowlink COLOR="#549cbc" DESTINATION="ID_608819565" ENDARROW="Default" ENDINCLINATION="152;866;" ID="Arrow_ID_190880203" STARTARROW="None" STARTINCLINATION="-139;-10;"/>
<icon BUILTIN="yes"/>
</node>
<node BACKGROUND_COLOR="#c8c0b6" COLOR="#480f69" CREATED="1717596554232" ID="ID_783972029" MODIFIED="1717596645209">
<richcontent TYPE="NODE"><html>
<head/>
<body>
<p>
<u>Fazit</u>:
</p>
<p>
&#160;entweder sie ist statisch &#8212;
</p>
<p>
&#160;oder es ist eine <i>selbstzerst&#246;rende </i>Heap-Allokation
</p>
</body>
</html>
</richcontent>
</node>
</node>
</node>
</node>
<node CREATED="1717632428656" ID="ID_798550383" MODIFIED="1717632452224" TEXT="es sind zwei Aufgaben">
<icon BUILTIN="messagebox_warning"/>
<node CREATED="1717632436379" ID="ID_1675424007" MODIFIED="1717632444245" TEXT="Objekte destruieren"/>
<node CREATED="1717632444817" ID="ID_362040312" MODIFIED="1717632448869" TEXT="Speicher freigeben"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1717632477490" ID="ID_83921320" MODIFIED="1717632530750" TEXT="beide Aufgaben m&#xfc;ssen in das Trampolin">
<icon BUILTIN="flag-yellow"/>
<node CREATED="1717632816553" ID="ID_719956571" MODIFIED="1717632856947" TEXT="geht leider nicht anders...">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
weil der Several-Container selber nur den Spread kennt, aber keine konkrete Typ-Info mehr hat
</p>
</body>
</html>
</richcontent>
<icon BUILTIN="smily_bad"/>
</node>
</node>
</node>
<node CREATED="1717543083078" ID="ID_530261806" MODIFIED="1717543114805" TEXT="getMover()"/>
</node>
@ -82086,6 +82258,9 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1716914864769" ID="ID_966642586" MODIFIED="1716914906125" TEXT="Builder-Operationen">
<icon BUILTIN="pencil"/>
<node BACKGROUND_COLOR="#f8f1cb" COLOR="#a50125" CREATED="1717634297656" ID="ID_330412196" MODIFIED="1717634315310" TEXT="Problem: Container soll move-only sein">
<icon BUILTIN="messagebox_warning"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1716914869721" ID="ID_756769385" MODIFIED="1716914902541" TEXT="basis-Allokation">
<icon BUILTIN="flag-yellow"/>
</node>