Dispatcher-Pipeline: clean setup for builder and pipeline types

..this is now the third attempt, and it seems this one leads to a
clean solution for the type rebinding problem, while also allowing
to unit-test each step in isolation.

The idea is to layer a *templated* builder class on top,
but to slice it away in each step, re-assemble the pipeline
and decorate a new builder instance on top. The net result
is a tightly interconnected processing pipeline without
any spurious interspersed leftovers from the builder,
while all intermediate steps are fully operational
and can thus be unit-tested...
This commit is contained in:
Fischlurch 2023-06-05 02:52:10 +02:00
parent 41a8c7ec1a
commit a5b3a16f3e
3 changed files with 220 additions and 77 deletions

View file

@ -113,6 +113,7 @@ namespace engine {
struct PipeFrameTick;
struct PipeExpander;
template<class IT>
struct PipelineBuilder;
@ -120,7 +121,7 @@ namespace engine {
public:
virtual ~Dispatcher(); ///< this is an interface
PipelineBuilder forCalcStream (Timings timings);
PipelineBuilder<PipeFrameTick> forCalcStream (Timings timings);
template<class IT>
class PlanningPipeline
@ -189,6 +190,7 @@ namespace engine {
FrameCnt frameNr{0};
/* === state protocol API for IterStateWrapper === */
bool
checkPoint() const
@ -208,55 +210,80 @@ namespace engine {
++frameNr;
currPoint = timings.getFrameStartAt (frameNr);
}
};
/**
* Job-planning Step-3: monadic depth-first exploration of Prerequisites
*/
struct Dispatcher::PipeExpander
{};
/**
* Job-planning Step-2: select data feed connection between ModelPort
* and DataSink; this entails to select the actually active Node pipeline
*/
struct Dispatcher::PipelineBuilder
: PipeFrameTick
{
/** Builder: start frame sequence */
PipelineBuilder
timeRange (Time start, Time after)
protected:
void
activate (Time start, Time after)
{
stopPoint = after;
frameNr = timings.getBreakPointAfter(start);
currPoint = timings.getFrameStartAt (frameNr);
return move(*this); // expected to invoke buildFeed(port,sink)
}
};
/**
* A Builder wrapper, allowing to build a Job-planning pipeline
* step by step, while supplying contextual information from the CalcStream.
* @remark This builder is created from \ref Dispatcher::forCalcStream, and thus
* internally wired back to the `Dispatcher` implementation, to access the
* Fixture and low-level-Model data-structures to back generated render Jobs.
* Client code is expected to invoke all builder functions consecutively,
* and then place the result into the CalcStream for generating render Jobs.
*/
template<class SRC>
struct Dispatcher::PipelineBuilder
: SRC
{
/** Terminal builder: setup processing feed ModelPort -> DataSink */
/**
* Builder: start frame sequence
*/
auto
buildFeed (mobject::ModelPort port, play::DataSink sink)
timeRange (Time start, Time after)
{
using TicketDepend = std::pair<JobTicket const*, JobTicket const*>;
// start iterator pipeline based on this as »state core«
auto pipeline = lib::treeExplore (frameTickCore())
.transform([port,sink](PipeFrameTick& core) -> TicketDepend
PipelineBuilder::activate (start,after);
return buildPipeline (lib::treeExplore (move(*this)));
} // expected next to invoke pullFrom(port,sink)
/** Package a Ticket together with a direct dependency,
* to allow setup of schedule times in downstream processing */
using TicketDepend = std::pair<JobTicket const*, JobTicket const*>;
/**
* Builder: connect to the JobTicket defining the actual processing
* for the nominal time of this frame and the given ModelPort
*/
auto
pullFrom (mobject::ModelPort port)
{
return buildPipeline (
this->transform([port](PipeFrameTick& core) -> TicketDepend
{
FrameCoord frame; ///////////////////////////////////////////OOO need a better ctor for FrameCoord
frame.absoluteNominalTime = core.currPoint;
frame.modelPort = port;
return {& core.dispatcher->getSinkTicketFor(sink)
return {nullptr
,& core.dispatcher->getJobTicketFor(frame)
};
})
.expand([](TicketDepend& currentLevel)
}));
}
/**
* Builder: cause a exhaustive depth-first search
* to recursively discover all prerequisites of each
* top-level JobTicket
*/
auto
expandPrerequisites()
{
return buildPipeline (
this->expand([](TicketDepend& currentLevel)
{
JobTicket const* parent = currentLevel.second;
return lib::transformIterator (parent->getPrerequisites(0)
@ -266,27 +293,50 @@ namespace engine {
}
);
})
.expandAll()
/////////////////////////////////////////////////////////////////////////////OOO do Step-4 here: build JobPlanning
;
.expandAll());
}
/**
* Terminal builder: setup processing feed to the given DataSink.
* @return Iterator to pull a sequence of render jobs, ready for processing
*/
auto
feedTo (play::DataSink sink)
{
auto pipeline = this->transform([sink](TicketDepend& currentLevel)
{
return currentLevel.second; ///////////////////////////////OOO construct a JobPlanning here
});
using PipeIter = decltype(pipeline);
return PlanningPipeline<PipeIter>{move (pipeline)};
}
protected:
PipeFrameTick&&
frameTickCore()
/** @internal type rebinding helper to move the given tree-Explorer pipeline
* and layer a new PipelineBuilder subclass on top.
* @note TreeExplorer itself is defined in a way to always strip away any existing
* top-level TreeExplorer, then add a new processing layer and finally
* place a new TreeExplorer layer on top. Taken together, this setup will
* *slice away* the actual PipelineBuilder layer, move the resulting pipeline
* into the next building step and finally produce a cleanly linked processing
* pipeline without any interspersed builders. Yet still, partially constructed
* pipelines are valid iterators and can be unit tested in isolation.
*/
template<class PIP>
PipelineBuilder<PIP>
buildPipeline(PIP&& treeExplorer)
{
return move (static_cast<PipeFrameTick>(*this));
return PipelineBuilder<PIP> {move (treeExplorer)};
}
};
inline Dispatcher::PipelineBuilder
inline Dispatcher::PipelineBuilder<Dispatcher::PipeFrameTick>
Dispatcher::forCalcStream(Timings timings)
{
return PipelineBuilder{this, timings};
return PipelineBuilder<PipeFrameTick> {this, timings};
}

View file

@ -4291,7 +4291,7 @@ Thus an invocation trail represents one specific path leading to the invocation
''Note'': {{red{future plans and visions -- no clear and distinct meaning -- as of 4/21}}}
</pre>
</div>
<div title="JobPlanningPipeline" creator="Ichthyostega" modifier="Ichthyostega" created="202305260209" modified="202306031539" tags="operational Rendering draft" changecount="6">
<div title="JobPlanningPipeline" creator="Ichthyostega" modifier="Ichthyostega" created="202305260209" modified="202306050043" tags="operational Rendering draft" changecount="7">
<pre>//Depth-first evaluation pipeline used in the FrameDispatcher to generate the next chunk of [[render jobs|RenderJob]]//
This is an implementation structure backed and established by the [[Dispatcher|FrameDispatcher]] and operated by the {{{RenderDrive}}} core of each CalcStream, where it is assembled by a //builder notation// -- backed by the {{{TreeExplorer}}} iterator pipeline framework; besides the typical filter and transform operations, the latter offers an »expansion« mechanism to integrate a //monadic exhaustive depth-first search,// allowing to pick up all prerequisites of a given calculation step by step within a local planning context.
@ -4299,12 +4299,14 @@ This is an implementation structure backed and established by the [[Dispatcher|F
;frame-tick
:establish a sequence of frame start times
;selector
:choose suitable data feed connection between ModelPort and {{{DataSink}}};
:choose a suitable ModelPort and associated JobTicket;
:this entails to select the actually active ProcNode pipeline
;expander
:monadic depth-first exploration of calculation prerequisites
;job-planning
:collect the complete planning context and determine time frame
:*especially add a {{{DataSink}}} specification to the JobFunctor closure
:*and evaluate the dependency structure from the //exploration step// to establish Job deadlines
</pre>
</div>
<div title="JobTicket" modifier="Ichthyostega" created="201202120018" modified="202305111241" tags="spec Rendering draft" changecount="4">

View file

@ -73755,6 +73755,28 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</html></richcontent>
<icon BUILTIN="button_cancel"/>
</node>
<node COLOR="#435e98" CREATED="1685924688158" ID="ID_240274736" MODIFIED="1685924850417" TEXT="L&#xf6;sung: eine Template-Builder-Klasse oben dr&#xfc;ber layern">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
das l&#246;st ganz elegant beide Probleme
</p>
<ul>
<li>
da es sich um ein Template handelt, findet der Definitions-Check erst sp&#228;ter statt, wenn die tats&#228;chliche Pipeline gebaut wird
</li>
<li>
der jeweilige Quell-Iterator-Typ ist als Template-Parameter gegeben, und kann damit direkt abgegriffen werden und in die n&#228;chste Instanz einflie&#223;en, welche einfach von ihm erbt
</li>
</ul>
</body>
</html></richcontent>
<arrowlink COLOR="#374cb3" DESTINATION="ID_1780288961" ENDARROW="Default" ENDINCLINATION="-23;-87;" ID="Arrow_ID_755591193" STARTARROW="None" STARTINCLINATION="-413;20;"/>
<icon BUILTIN="idea"/>
</node>
</node>
</node>
<node COLOR="#435e98" CREATED="1685830854298" ID="ID_1539456468" MODIFIED="1685833560849" TEXT="anders herum: brauchen wir &#xfc;berhaupt Zugang zum TreeExplorer-Builder?">
@ -73768,26 +73790,81 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<icon BUILTIN="messagebox_warning"/>
</node>
</node>
<node COLOR="#5b280f" CREATED="1685833510263" ID="ID_1962899865" MODIFIED="1685833556706">
<node COLOR="#5b280f" CREATED="1685833510263" ID="ID_1962899865" MODIFIED="1685917704662">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
<b>Fazit</b>: Anwendung von TreeExplorer passiert nur in einem Funktions-Scope
<b>Zwischen-Fazit</b>: Anwendung von TreeExplorer passiert nur in einem Funktions-Scope
</p>
</body>
</html></richcontent>
<icon BUILTIN="stop-sign"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685833568159" ID="ID_1859576493" MODIFIED="1685833588992" TEXT="also brauchen wir nur einen Wrapper-Typ am Ende">
<node COLOR="#5b280f" CREATED="1685833568159" ID="ID_1859576493" MODIFIED="1685924611434" TEXT="also brauchen wir nur einen Wrapper-Typ am Ende">
<icon BUILTIN="button_cancel"/>
<node COLOR="#338800" CREATED="1685833591596" ID="ID_1247414372" MODIFIED="1685924608462" TEXT="der &#xfc;bernimmt den Iterator vom fertigen TreeExplorer">
<icon BUILTIN="button_ok"/>
</node>
<node COLOR="#338800" CREATED="1685833605178" ID="ID_433083338" MODIFIED="1685924609464" TEXT="und zwar kann man diesen dann durchaus per Template-Parameter &#xfc;bergeben">
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1685917734217" ID="ID_1866369353" MODIFIED="1685924647424" TEXT="mehrere Aspekte sind aber problematisch">
<arrowlink COLOR="#5749b9" DESTINATION="ID_531896666" ENDARROW="Default" ENDINCLINATION="13;-50;" ID="Arrow_ID_1545948492" STARTARROW="None" STARTINCLINATION="-222;14;"/>
<icon BUILTIN="messagebox_warning"/>
<node CREATED="1685917742051" ID="ID_1886457132" MODIFIED="1685917751695" TEXT="die einzelnen Schritte sind nicht klar getrennt"/>
<node CREATED="1685917752196" ID="ID_1475349920" MODIFIED="1685917774301" TEXT="speziell die Expand-Funktion ist sehr verwoben mit der Pipeline"/>
<node CREATED="1685917782362" ID="ID_957312796" MODIFIED="1685917858352" TEXT="die Idee mit den k&#xfc;nstlichen Root-Tickets ist nicht gut durchf&#xfc;hrbar">
<linktarget COLOR="#bd2b85" DESTINATION="ID_957312796" ENDARROW="Default" ENDINCLINATION="249;11;" ID="Arrow_ID_1688529545" SOURCE="ID_334221261" STARTARROW="None" STARTINCLINATION="395;0;"/>
<icon BUILTIN="stop-sign"/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1685917872249" ID="ID_531896666" MODIFIED="1685924661892" TEXT="doch nochmal Ansatz mit Builder-Typ versuchen">
<linktarget COLOR="#5749b9" DESTINATION="ID_531896666" ENDARROW="Default" ENDINCLINATION="13;-50;" ID="Arrow_ID_1545948492" SOURCE="ID_1866369353" STARTARROW="None" STARTINCLINATION="-222;14;"/>
<icon BUILTIN="pencil"/>
<node COLOR="#338800" CREATED="1685917908769" ID="ID_614051285" MODIFIED="1685924391262" TEXT="ein spezielles Builder-Template verwenden">
<icon BUILTIN="button_ok"/>
</node>
<node COLOR="#338800" CREATED="1685917990619" ID="ID_1176401324" MODIFIED="1685924592772" TEXT="dieses jeweils nach einem Schritt von der Pipeline wegsch&#xe4;len">
<icon BUILTIN="button_ok"/>
<node CREATED="1685919136874" ID="ID_1780288961" MODIFIED="1685924842956" TEXT="Anordnung">
<linktarget COLOR="#374cb3" DESTINATION="ID_1780288961" ENDARROW="Default" ENDINCLINATION="-23;-87;" ID="Arrow_ID_755591193" SOURCE="ID_240274736" STARTARROW="None" STARTINCLINATION="-413;20;"/>
<node CREATED="1685919141537" ID="ID_1712937407" MODIFIED="1685919145084" TEXT="Pipeline"/>
<node CREATED="1685919145781" ID="ID_1156318589" MODIFIED="1685919150899" TEXT="TreeExplorer"/>
<node CREATED="1685919151624" ID="ID_999213061" MODIFIED="1685919346619" TEXT="Builder">
<linktarget COLOR="#7181ad" DESTINATION="ID_999213061" ENDARROW="Default" ENDINCLINATION="9;34;" ID="Arrow_ID_1530989548" SOURCE="ID_1807352593" STARTARROW="None" STARTINCLINATION="-146;11;"/>
<node CREATED="1685919167547" ID="ID_1354500911" MODIFIED="1685919171225" TEXT="builder-Funktion">
<node CREATED="1685919173044" ID="ID_206249732" MODIFIED="1685919182519" TEXT="sch&#xe4;lt den Builder weg"/>
<node CREATED="1685919183114" ID="ID_1286862952" MODIFIED="1685919192492" TEXT="..indem sie den TreeExplorer verwendet"/>
<node CREATED="1685919291869" ID="ID_1262970496" MODIFIED="1685919303647" TEXT="....welcher sich selbst seinerseits wegsch&#xe4;lt"/>
<node CREATED="1685919305259" ID="ID_1807352593" MODIFIED="1685919355842" TEXT="und legt einen neuen Builder dar&#xfc;ber">
<arrowlink COLOR="#7181ad" DESTINATION="ID_999213061" ENDARROW="Default" ENDINCLINATION="9;34;" ID="Arrow_ID_1530989548" STARTARROW="None" STARTINCLINATION="-146;11;"/>
</node>
</node>
</node>
</node>
<node CREATED="1685924870380" ID="ID_529184023" MODIFIED="1685924873613" TEXT="Endresultat">
<node CREATED="1685924875931" ID="ID_1437755901" MODIFIED="1685924890134" TEXT="PipeFrameTick"/>
<node CREATED="1685924904806" ID="ID_1467750504" MODIFIED="1685924910898" TEXT="pullFrom() - Layer"/>
<node CREATED="1685924911534" ID="ID_1158824789" MODIFIED="1685924918553" TEXT="Expander - Layer"/>
<node CREATED="1685924919165" ID="ID_1384684809" MODIFIED="1685924924928" TEXT="JobPlanning - Layer"/>
<node CREATED="1685924933403" ID="ID_998006413" MODIFIED="1685924963731" TEXT="verpackt in ein PlanningPipeline&lt;IT&gt;"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685918022280" ID="ID_905868944" MODIFIED="1685918037029" TEXT="Generische Expander-Funktion entwickeln">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685833591596" ID="ID_1247414372" MODIFIED="1685833619292" TEXT="der &#xfc;bernimmt den Iterator vom fertigen TreeExplorer">
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685918038261" ID="ID_547403195" MODIFIED="1685918078873" TEXT="kein fester Quell-Argument-Typ">
<icon BUILTIN="flag-yellow"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685833605178" ID="ID_433083338" MODIFIED="1685833619293" TEXT="und zwar kann man diesen dann durchaus per Template-Parameter &#xfc;bergeben">
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685918045844" ID="ID_494675571" MODIFIED="1685918063148" TEXT="soll sich entsprechend auf Root-Level anders verhalten">
<icon BUILTIN="flag-yellow"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685918123634" ID="ID_1372348029" MODIFIED="1685918139283" TEXT="ItemWrapper auf non-copyable Typen anwendbar machen">
<icon BUILTIN="flag-yellow"/>
</node>
</node>
@ -73817,9 +73894,14 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
<node CREATED="1685804229425" ID="ID_1068361872" MODIFIED="1685804229425" TEXT="struct PipeSelector;">
<node CREATED="1685804280614" ID="ID_636246298" MODIFIED="1685804307946" TEXT="w&#xe4;hlt Verbindung zum low-level-Model"/>
<node CREATED="1685804312326" ID="ID_1049622554" MODIFIED="1685804385924" TEXT="neue Idee: &#xbb;FrameDropper&#xab; bereitstellen">
<node COLOR="#5b280f" CREATED="1685804312326" ID="ID_1049622554" MODIFIED="1685925022016" TEXT="neue Idee: &#xbb;FrameDropper&#xab; bereitstellen">
<linktarget COLOR="#fdfed9" DESTINATION="ID_1049622554" ENDARROW="Default" ENDINCLINATION="-118;8;" ID="Arrow_ID_109489850" SOURCE="ID_9551953" STARTARROW="None" STARTINCLINATION="124;-21;"/>
<icon BUILTIN="idea"/>
<icon BUILTIN="button_cancel"/>
<node CREATED="1685917810826" ID="ID_587704623" MODIFIED="1685917818007" TEXT="diese Idee ist nur rein formal"/>
<node CREATED="1685917818415" ID="ID_334221261" MODIFIED="1685917853964" TEXT="es gelingt mir nicht, sie inhaltlich einzubinden">
<arrowlink COLOR="#bd2b85" DESTINATION="ID_957312796" ENDARROW="Default" ENDINCLINATION="249;11;" ID="Arrow_ID_1688529545" STARTARROW="None" STARTINCLINATION="395;0;"/>
</node>
</node>
</node>
<node CREATED="1685804229425" ID="ID_1660231509" MODIFIED="1685804229425" TEXT="struct PipeExpander;">
@ -73858,9 +73940,24 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1681742836996" ID="ID_1790705283" MODIFIED="1684878198471" TEXT="invoke the dispatcher to retrieve the top-level JobTicket">
<icon BUILTIN="full-3"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685843183070" ID="ID_1520386382" MODIFIED="1685843320417" TEXT="L&#xf6;sung f&#xfc;r schichtweises Testen der Pipeline finden">
<node COLOR="#338800" CREATED="1685843183070" ID="ID_1520386382" MODIFIED="1685925294619" TEXT="L&#xf6;sung f&#xfc;r schichtweises Testen der Pipeline finden">
<linktarget COLOR="#f62658" DESTINATION="ID_1520386382" ENDARROW="Default" ENDINCLINATION="147;-261;" ID="Arrow_ID_81911203" SOURCE="ID_164064059" STARTARROW="None" STARTINCLINATION="-591;27;"/>
<icon BUILTIN="flag-yellow"/>
<icon BUILTIN="button_ok"/>
<node CREATED="1685925268894" ID="ID_1603468157" MODIFIED="1685925437087" TEXT="kehre zur urspr&#xfc;nglich geplanten L&#xf6;sung zur&#xfc;ck">
<icon BUILTIN="info"/>
</node>
<node CREATED="1685925279394" ID="ID_523904439" MODIFIED="1685925433781" TEXT="aber jetzt ist es mir endlich gelungen, sie sauber zu konstruieren">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
...und zwar durch den gleichen Template-Slicing-Trick, der auch schon bei TreeExplorer selber so erfolgreich funktioniert: der Builder wird durch ein std::move auf die Basisklasse beschnitten und f&#228;llt dann als Temporary am Ende der Builder-Expressison einfach weg, aber aller relevanter Content ist in das Ergebnis geschoben worden, welches wegen RVO direkt am Zielort konstruiert wird
</p>
</body>
</html></richcontent>
</node>
</node>
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1685843418766" ID="ID_311511953" MODIFIED="1685843432557" TEXT="JobTicket const&amp; oder JobTicket const* &#xfc;bergeben?">
<icon BUILTIN="help"/>
@ -73874,15 +73971,15 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1681742836996" ID="ID_1224963303" MODIFIED="1684878201314" TEXT="expander function to explore prerequisite JobTickets">
<icon BUILTIN="full-4"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685803059992" ID="ID_1436607523" MODIFIED="1685803066369" TEXT="expander-Funktor(einfach)">
<icon BUILTIN="flag-yellow"/>
<node COLOR="#338800" CREATED="1685803059992" ID="ID_1436607523" MODIFIED="1685925254772" TEXT="expander-Funktor(einfach)">
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685803068234" ID="ID_1458286668" MODIFIED="1685803183999" TEXT="Gruppierung mit Dependent">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685803252313" ID="ID_981519455" MODIFIED="1685803288229" TEXT="Problem: Ende des Kind-Levels erkennen">
<node COLOR="#338800" CREATED="1685803068234" ID="ID_1458286668" MODIFIED="1685925250184" TEXT="Gruppierung mit Dependent">
<icon BUILTIN="button_ok"/>
<node COLOR="#435e98" CREATED="1685803252313" ID="ID_981519455" MODIFIED="1685925247927" TEXT="Problem: Ende des Kind-Levels erkennen">
<icon BUILTIN="messagebox_warning"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685803392203" ID="ID_1347930311" MODIFIED="1685803426832" TEXT="Idee: Level-Shift als positional shift in Expander selber einbauen">
<node COLOR="#435e98" CREATED="1685803392203" ID="ID_1347930311" MODIFIED="1685925216605" TEXT="Idee: Level-Shift als positional shift in Expander selber einbauen">
<icon BUILTIN="idea"/>
<node CREATED="1685803432791" ID="ID_612766289" MODIFIED="1685803491700" TEXT="das hei&#xdf;t: die Verklammerung macht der Expander selber">
<richcontent TYPE="NOTE"><html>
@ -73897,15 +73994,16 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</html></richcontent>
</node>
<node CREATED="1685803493398" ID="ID_312364874" MODIFIED="1685803517871" TEXT="&#x27f9; Folge schrittweise verschobener Paare"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685803519291" ID="ID_1625457703" MODIFIED="1685803542875" TEXT="&#x27f9; neue Idee: k&#xfc;nstlichen Root einf&#xfc;hren">
<node COLOR="#5b280f" CREATED="1685803519291" ID="ID_1625457703" MODIFIED="1685925038510" TEXT="&#x27f9; neue Idee: k&#xfc;nstlichen Root einf&#xfc;hren">
<icon BUILTIN="idea"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685803556486" ID="ID_9551953" MODIFIED="1685804392492" TEXT="der mu&#xdf; vom Basis-Iterator-Level k&#xfc;nstlich eingef&#xfc;hrt werden">
<icon BUILTIN="button_cancel"/>
<node COLOR="#5b280f" CREATED="1685803556486" ID="ID_9551953" MODIFIED="1685925058966" TEXT="der mu&#xdf; vom Basis-Iterator-Level k&#xfc;nstlich eingef&#xfc;hrt werden">
<arrowlink COLOR="#fdfed9" DESTINATION="ID_1049622554" ENDARROW="Default" ENDINCLINATION="-118;8;" ID="Arrow_ID_109489850" STARTARROW="None" STARTINCLINATION="124;-21;"/>
<icon BUILTIN="yes"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685803612926" ID="ID_755957373" MODIFIED="1685803714187" TEXT="damit k&#xf6;nnte man nebenbei das Problem der Output-Sink-Steuerung l&#xf6;sen">
<node COLOR="#5b280f" CREATED="1685803612926" ID="ID_755957373" MODIFIED="1685925050534" TEXT="damit k&#xf6;nnte man nebenbei das Problem der Output-Sink-Steuerung l&#xf6;sen">
<arrowlink COLOR="#5f3daf" DESTINATION="ID_87044302" ENDARROW="Default" ENDINCLINATION="265;-32;" ID="Arrow_ID_1548054846" STARTARROW="None" STARTINCLINATION="-44;200;"/>
<icon BUILTIN="flag-yellow"/>
<icon BUILTIN="button_cancel"/>
<node CREATED="1685840292823" ID="ID_1498997864" MODIFIED="1685840301432" TEXT="zweifelhafte Idee">
<icon BUILTIN="smiley-neutral"/>
</node>
@ -73957,19 +74055,12 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
</node>
</node>
<node COLOR="#338800" CREATED="1685925070561" ID="ID_1350090008" MODIFIED="1685925209423" TEXT="bessere L&#xf6;sung : Root-Level markieren">
<icon BUILTIN="button_ok"/>
<node CREATED="1685925085231" ID="ID_1953140621" MODIFIED="1685925089485" TEXT="Pointer verwenden"/>
<node CREATED="1685925161208" ID="ID_517704881" MODIFIED="1685925194593" TEXT="Tupel (parent, current)"/>
<node CREATED="1685925090438" ID="ID_9907786" MODIFIED="1685925207649" TEXT="root &#x27f9; parent ist NULL"/>
</node>
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1685842517449" ID="ID_1001089726" MODIFIED="1685842716924" TEXT="Alternative: k&#xf6;nnte man das in JobTIcket selber verschieben?">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
Es f&#228;llt auf, da&#223; wir einen zweifach geschichteten Transform-Iterator haben. Zun&#228;chst einmal: ein Iterator mu&#223; hier rauskommen, da wir ein monadisches flatMap machen. Aber anstatt diese Paarung mit der jeweilgen Verschiebung erst in der Expander-Funktion zu machen, k&#246;nnte man das auch direkt schon im JobTicket so aufsetzen &#8212; schlie&#223;lich w&#228;re der &#8222;Parent&#8220; auch in diesem Kontext schon ganz nat&#252;rlich gegeben (also das JobTicket selber, dessen prerequisites hier aufgelistet werden)
</p>
</body>
</html></richcontent>
<icon BUILTIN="help"/>
</node>
</node>
</node>