Chain-Load: provide a scheme for repeated init
For context: I've engaged into writing a `LazyInit` helper component, to resolve the inner contradiction between DSL use of `RandomDraw` (implying value semantics) and the design of a processing pipeline, which quite naturally leads to binding by reference into the enclosing implementation. In most cases, this change (to lazy on-demand initialisation) should be transparent for the complete implementation code in `RandomDraw` -- with one notable exception: when configuring an elaborate pipeline, especially with dynamic changes of the probability profile during the simulation run, then then obviously there is the desire to use the existing processing pipeline from the reconfiguration function (in fact it would be quite hard to explain why and where this should be avoided). `LazyInit` breaks this usage scenario, since -- at the time the reconfiguration runs -- now the object is not initialised at all, but holds a »Trojan« functor, which will trigger initialisation eventually. After some headaches and grievances (why am I engaging into such an elaborate solution for such an accidental and marginal topic...), unfortunately it occurred to me that even this problem can be fixed, with yet some further "minimal" adjustments to the scheme: the LazyInit mechanism ''just needs to ensure'' that the init-functor ''sees the same environment as in eager init'' -- that is, it must clear out the »Trojan« first, and it ''could apply any previous pending init function'' fist. That is, with just a minimal change, we possibly build a chain of init functors now, and apply them in given order, so each one sees the state the previous one created -- as if this was just direct eager object manipulation...
This commit is contained in:
parent
04ca79fd65
commit
ed8d9939bd
2 changed files with 182 additions and 2 deletions
|
|
@ -335,6 +335,13 @@ namespace lib {
|
|||
PendingInit
|
||||
prepareInitialiser (std::function<SIG>& targetFunctor, INI&& initialiser)
|
||||
{
|
||||
if (isInit() and targetFunctor)
|
||||
{// object is already »engaged« — no need to delay init
|
||||
using ExpectedArg = _FunArg<INI>;
|
||||
initialiser (static_cast<ExpectedArg> (this));
|
||||
return PendingInit(); // keep engaged; no pending init
|
||||
}
|
||||
// else: prepare delayed init...
|
||||
PendingInit storageHandle{
|
||||
new HeapStorage{
|
||||
buildInitialiserDelegate (targetFunctor, forward<INI> (initialiser))}};
|
||||
|
|
@ -344,12 +351,22 @@ namespace lib {
|
|||
}
|
||||
|
||||
template<class SIG>
|
||||
DelegateType<SIG>*
|
||||
static DelegateType<SIG>*
|
||||
getPointerToDelegate (HeapStorage& buffer)
|
||||
{
|
||||
return reinterpret_cast<DelegateType<SIG>*> (&buffer);
|
||||
}
|
||||
|
||||
template<class SIG>
|
||||
static std::function<SIG>
|
||||
maybeInvoke (PendingInit const& pendingInit, RawAddr location)
|
||||
{
|
||||
if (not pendingInit) // no pending init -> empty TargetFun
|
||||
return std::function<SIG>();
|
||||
auto* pendingDelegate = getPointerToDelegate<SIG>(*pendingInit);
|
||||
return (*pendingDelegate) (location); // invoke to create new TargetFun
|
||||
}
|
||||
|
||||
template<class SIG, class INI>
|
||||
DelegateType<SIG>
|
||||
buildInitialiserDelegate (std::function<SIG>& targetFunctor, INI&& initialiser)
|
||||
|
|
@ -358,12 +375,15 @@ namespace lib {
|
|||
using ExpectedArg = _FunArg<INI>;
|
||||
return DelegateType<SIG>{
|
||||
[performInit = forward<INI> (initialiser)
|
||||
,previousInit = move (pendingInit_)
|
||||
,targetOffset = captureRawAddrOffset (this, &targetFunctor)]
|
||||
(RawAddr location) -> TargetFun&
|
||||
{// apply known offset backwards to find current location of the host object
|
||||
TargetFun* target = relocate<TargetFun> (location, -FUNCTOR_PAYLOAD_OFFSET);
|
||||
LazyInit* self = relocate<LazyInit> (target, -targetOffset);
|
||||
REQUIRE (self);
|
||||
// setup target as it would be with eager init
|
||||
(*target) = maybeInvoke<SIG> (previousInit, location);
|
||||
// invoke init, possibly downcast to derived *self
|
||||
performInit (static_cast<ExpectedArg> (self));
|
||||
self->pendingInit_.reset(); // release storage
|
||||
|
|
|
|||
|
|
@ -97558,7 +97558,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1700878072770" ID="ID_1728628936" MODIFIED="1700878084969" TEXT="Prolbem: ctor-Signatur zweideutig">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
</node>
|
||||
<node CREATED="1700878086446" ID="ID_1368715362" MODIFIED="1700878097543" TEXT="lösen durch ein MarkDisabled() - Tag">
|
||||
<node COLOR="#435e98" CREATED="1700878086446" ID="ID_1368715362" MODIFIED="1700883011557" TEXT="lösen durch ein MarkDisabled() - Tag">
|
||||
<icon BUILTIN="idea"/>
|
||||
</node>
|
||||
</node>
|
||||
|
|
@ -97579,6 +97579,17 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
</richcontent>
|
||||
<arrowlink COLOR="#a11470" DESTINATION="ID_615420321" ENDARROW="Default" ENDINCLINATION="-38;-156;" ID="Arrow_ID_1147775137" STARTARROW="None" STARTINCLINATION="-409;35;"/>
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
<node CREATED="1700883132460" ID="ID_1624384536" MODIFIED="1700883156773" TEXT="des Genaueren: der »Trojaner« sieht wir ein valider Funktor aus"/>
|
||||
<node CREATED="1700883162688" ID="ID_1541865350" MODIFIED="1700883212555" TEXT="sofern sich Initialisierung den bestehenden Funktor aufgreift..."/>
|
||||
<node CREATED="1700883213489" ID="ID_1802613840" MODIFIED="1700883224039" TEXT="...besteht zumindest die Gefahr für Endlosschleifen">
|
||||
<icon BUILTIN="broken-line"/>
|
||||
</node>
|
||||
<node CREATED="1700883266746" ID="ID_541587975" MODIFIED="1700883289794" TEXT="dieses Problem könnte nur durch LazyInit selber addressiert werden">
|
||||
<icon BUILTIN="yes"/>
|
||||
<node CREATED="1700883302425" ID="ID_601939875" MODIFIED="1700883331621" TEXT="isInit()"/>
|
||||
<node CREATED="1700883367516" ID="ID_358220582" MODIFIED="1700883381190" TEXT="hilft nicht bei kaskadierten Aufrufen"/>
|
||||
<node CREATED="1700883887222" ID="ID_1972271604" MODIFIED="1700883898233" TEXT="Nur der Installations-Mechanismus hätte eine Chance"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
|
|
@ -97628,6 +97639,155 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700883451009" ID="ID_1957619208" MODIFIED="1700883468235" TEXT="Analyse: wiederholte / kaskadierte Initialisierungen">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node CREATED="1700883475839" ID="ID_837624106" MODIFIED="1700883477453" TEXT="Ablauf">
|
||||
<node CREATED="1700883822501" ID="ID_402007618" MODIFIED="1700883824872" TEXT="Fall-1">
|
||||
<node CREATED="1700883478738" ID="ID_1745053013" MODIFIED="1700883862198" TEXT="isInit() ⟼ true(leer) + kein Funktor"/>
|
||||
<node CREATED="1700883537958" ID="ID_1244902831" MODIFIED="1700883549760" TEXT="isInit() ⟼ false + Trap"/>
|
||||
<node CREATED="1700883563354" ID="ID_406459173" MODIFIED="1700883580135" TEXT="Trap ⟶ neuer Funktor"/>
|
||||
</node>
|
||||
<node CREATED="1700883585031" ID="ID_785231222" MODIFIED="1700883819027" TEXT="Fall-2">
|
||||
<node CREATED="1700883478738" ID="ID_839435401" MODIFIED="1700883503483" TEXT="isInit() ⟼ true + echter Funktor"/>
|
||||
<node CREATED="1700883537958" ID="ID_1512311774" MODIFIED="1700883549760" TEXT="isInit() ⟼ false + Trap"/>
|
||||
<node CREATED="1700883563354" ID="ID_8356372" MODIFIED="1700883580135" TEXT="Trap ⟶ neuer Funktor"/>
|
||||
</node>
|
||||
<node CREATED="1700883590811" ID="ID_1518533927" MODIFIED="1700883821132" TEXT="Fall-3">
|
||||
<node CREATED="1700883537958" ID="ID_204292878" MODIFIED="1700883549760" TEXT="isInit() ⟼ false + Trap"/>
|
||||
<node CREATED="1700883638446" ID="ID_1317225183" MODIFIED="1700883669832" TEXT="+ neues Delegate + Trap"/>
|
||||
<node CREATED="1700883653890" ID="ID_1572351022" MODIFIED="1700883656190" TEXT="+ ..."/>
|
||||
<node CREATED="1700883563354" ID="ID_536028687" MODIFIED="1700883580135" TEXT="Trap ⟶ neuer Funktor"/>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1700883981242" ID="ID_476427708" MODIFIED="1700883983854" TEXT="Fall-Muster">
|
||||
<node CREATED="1700883997648" ID="ID_279106916" MODIFIED="1700884041366" TEXT="not pendingInit + kein Funktor ⟹ Fall-1"/>
|
||||
<node CREATED="1700884059833" ID="ID_1932722762" MODIFIED="1700884071728" TEXT="not pendingInit + Funktor ⟹ Fall-2">
|
||||
<node CREATED="1700884197594" ID="ID_1851874040" MODIFIED="1700884208296" TEXT="dieser Funktor wäre ein Vorläufer"/>
|
||||
</node>
|
||||
<node CREATED="1700884095741" ID="ID_1167670160" MODIFIED="1700884112957" TEXT="pendingInit + Funktor ⟹ Fall-3">
|
||||
<node CREATED="1700884240680" ID="ID_1327583430" MODIFIED="1700884265507" TEXT="pendingInit zuerst anwenden ⟼ Übergang in Fall-2"/>
|
||||
</node>
|
||||
<node CREATED="1700884114752" ID="ID_364127230" MODIFIED="1700884129803" TEXT="pendingInit + kein Funktor ⟹ LogicBroken"/>
|
||||
</node>
|
||||
<node CREATED="1700884471281" ID="ID_944993217" MODIFIED="1700884475692" TEXT="Lösung...">
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700884476470" ID="ID_1258681625" MODIFIED="1700884494881" TEXT="minimal: sollte gemacht werden">
|
||||
<icon BUILTIN="yes"/>
|
||||
<node CREATED="1700884496384" ID="ID_169506932" MODIFIED="1700884505209" TEXT="vor Aufruf des Initialisers..."/>
|
||||
<node CREATED="1700884506445" ID="ID_14177401" MODIFIED="1700884522694" TEXT="den bestehenden Functor leer machen"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1700884537072" ID="ID_1176504809" MODIFIED="1700925243615" TEXT="erweitert: machbar?">
|
||||
<icon BUILTIN="help"/>
|
||||
<node CREATED="1700884615478" ID="ID_1008762319" MODIFIED="1700884620881" TEXT="Init-Verkettung">
|
||||
<node CREATED="1700884634923" ID="ID_1100836382" MODIFIED="1700884788061" TEXT="bestehenden pendingInit zuerst aufrufen">
|
||||
<linktarget COLOR="#df4480" DESTINATION="ID_1100836382" ENDARROW="Default" ENDINCLINATION="91;0;" ID="Arrow_ID_902131970" SOURCE="ID_1845471747" STARTARROW="None" STARTINCLINATION="91;0;"/>
|
||||
</node>
|
||||
<node CREATED="1700884662223" ID="ID_600393324" MODIFIED="1700884669922" TEXT="damit liegt ein valider Funktor vor"/>
|
||||
<node CREATED="1700884670570" ID="ID_603115571" MODIFIED="1700884678473" TEXT="der aktuelle Initialiser kann diesen verwenden"/>
|
||||
<node CREATED="1700884707938" ID="ID_1487565427" MODIFIED="1700884794311" TEXT="Rekursion">
|
||||
<linktarget COLOR="#b530c5" DESTINATION="ID_1487565427" ENDARROW="Default" ENDINCLINATION="9;34;" ID="Arrow_ID_1425846605" SOURCE="ID_1845471747" STARTARROW="None" STARTINCLINATION="-123;63;"/>
|
||||
<node CREATED="1700884712862" ID="ID_1270371043" MODIFIED="1700884740601" TEXT="einen bestehenden pendingInit in die den adaptierten Initializer"/>
|
||||
<node CREATED="1700884753993" ID="ID_1845471747" MODIFIED="1700884805374" TEXT="dort wird er zuerst aurgerufen">
|
||||
<arrowlink COLOR="#df4480" DESTINATION="ID_1100836382" ENDARROW="Default" ENDINCLINATION="91;0;" ID="Arrow_ID_902131970" STARTARROW="None" STARTINCLINATION="91;0;"/>
|
||||
<arrowlink COLOR="#b530c5" DESTINATION="ID_1487565427" ENDARROW="Default" ENDINCLINATION="9;34;" ID="Arrow_ID_1425846605" STARTARROW="None" STARTINCLINATION="-123;63;"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1700884833301" ID="ID_1023052501" MODIFIED="1700884835988" TEXT="Fall-2">
|
||||
<node CREATED="1700884837024" ID="ID_502217686" MODIFIED="1700884841120" TEXT="der Fall ist speziell"/>
|
||||
<node CREATED="1700884841856" ID="ID_1654607159" MODIFIED="1700884865645" TEXT="das Objekt ist »engaged«, d.h. darf nicht mehr bewegt werden"/>
|
||||
<node CREATED="1700884866732" ID="ID_1005926094" MODIFIED="1700884910994" TEXT="unter diesen Umständen ist gar keine lazy-Init notwendig"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700885072177" ID="ID_1660971679" MODIFIED="1700885098097" TEXT="Antwort: ist ohne großen Aufwand machbar">
|
||||
<icon BUILTIN="yes"/>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1700885100085" ID="ID_1294902012" MODIFIED="1700928226538" TEXT="operational">
|
||||
<icon BUILTIN="list"/>
|
||||
<node CREATED="1700885105797" ID="ID_392736313" MODIFIED="1700885117623" TEXT="beim Aufruf zum Installieren...">
|
||||
<node CREATED="1700885126594" ID="ID_933835878" MODIFIED="1700885357053" TEXT="zuerst den Fall feststellen">
|
||||
<arrowlink COLOR="#517184" DESTINATION="ID_1059814147" ENDARROW="Default" ENDINCLINATION="15;-20;" ID="Arrow_ID_1161089832" STARTARROW="None" STARTINCLINATION="-149;0;"/>
|
||||
<arrowlink COLOR="#5e5a98" DESTINATION="ID_1439092323" ENDARROW="Default" ENDINCLINATION="93;-8;" ID="Arrow_ID_1648939093" STARTARROW="None" STARTINCLINATION="86;0;"/>
|
||||
</node>
|
||||
<node CREATED="1700885175427" ID="ID_1439092323" MODIFIED="1700885335623" TEXT="je nach Fall den Adapter konfigurieren">
|
||||
<linktarget COLOR="#5e5a98" DESTINATION="ID_1439092323" ENDARROW="Default" ENDINCLINATION="93;-8;" ID="Arrow_ID_1648939093" SOURCE="ID_933835878" STARTARROW="None" STARTINCLINATION="86;0;"/>
|
||||
<node CREATED="1700885192462" ID="ID_271012983" MODIFIED="1700885202371" TEXT="Fall-1 : nur Trap entfernen"/>
|
||||
<node CREATED="1700885205327" ID="ID_1557648916" MODIFIED="1700885220502" TEXT="Fall-3 : Trap entfernen + Vorläufer aufrufen"/>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1700885226922" ID="ID_1059814147" MODIFIED="1700885318282" TEXT="Fall-2">
|
||||
<linktarget COLOR="#517184" DESTINATION="ID_1059814147" ENDARROW="Default" ENDINCLINATION="15;-20;" ID="Arrow_ID_1161089832" SOURCE="ID_933835878" STARTARROW="None" STARTINCLINATION="-149;0;"/>
|
||||
<node CREATED="1700885257048" ID="ID_759696290" MODIFIED="1700885270297" TEXT="es liegt bereits ein echter Funktor vor"/>
|
||||
<node CREATED="1700885270910" ID="ID_845153085" MODIFIED="1700885283866" TEXT="den Init-Funktor mit (this) direkt aufrufen"/>
|
||||
<node CREATED="1700885284844" ID="ID_1493413821" MODIFIED="1700925478010" TEXT="keinen pendingInit zurückgeben (Objekt bleibt gesperrt)"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1700885399157" ID="ID_1052362467" MODIFIED="1700928254133" TEXT="Ergänzung der Init-Routine">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700885425170" ID="ID_1390543220" MODIFIED="1700885449554" TEXT="Logik zur Fall-Erkennung">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700885455310" ID="ID_75201701" MODIFIED="1700885475092" TEXT="zusätzlich einen shared_ptr innerhalb vom Adapter vorsehen">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node CREATED="1700885486066" ID="ID_1745928936" MODIFIED="1700885498658">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
<i>darauf </i>kommt es jetzt auch nicht mehr an
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
<node CREATED="1700885514470" ID="ID_1944104952" MODIFIED="1700885786804" TEXT="Hinweis/Warnung: die pending-Functors sind shared">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
Funktor ist Funktor!
|
||||
</p>
|
||||
<p>
|
||||
Deshalb sind sie ja stateless (und müssen auch so bleiben, also nicht mutable). Für jeweils <i>eine Instanz</i> wird ein Funktor einfach »verbrannt«, indem man ihn aufruft und danach das pendingInit leert. Und zwar auf <b>*self</b>  — der Funktor als Solcher bleibt stateless. Wenn ihn noch jemand anders referenziert, dann schön....
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
<node CREATED="1700885787889" ID="ID_532859014" MODIFIED="1700885850873">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
Beim Umkonfigurieren wird der pendingInit <i>verschoben</i>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
und zwar aus dem LazyInit-Objekt in den Adapter hinein. Der use-count bleibt dadurch gleich.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700885870078" ID="ID_1085520028" MODIFIED="1700885900667" TEXT="wenn es einen pendingInit gibt (⟹Fall-3) dann verschieben">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
|
|
|
|||
Loading…
Reference in a new issue