Dispatcher-Pipeline: arrangement of builder types
...it turns out that we actually do not need to wrap TreeExplorer on the builder types, because basically there is only a single active builder type, and the complete processing pipeline can be assembled in a single terminal function. The type rebinding problem can thus be solved just by a simple marker struct, which inherits from a template parameter
This commit is contained in:
parent
71ea10bf21
commit
4601c6350e
6 changed files with 140 additions and 75 deletions
|
|
@ -100,11 +100,12 @@ namespace engine {
|
|||
void
|
||||
CalcPlanContinuation::performJobPlanningChunk(FrameCnt nextStartFrame)
|
||||
{
|
||||
TimeAnchor refPoint(timings_, nextStartFrame);
|
||||
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1301
|
||||
JobPlanningSequence jobs = dispatcher_.onCalcStream(modelPort_, channel_)
|
||||
.establishNextJobs(refPoint);
|
||||
|
||||
Job nextChunkOfPlanning = buildFollowUpJobFrom (refPoint);
|
||||
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1301 TimeAnchor refPoint(timings_, nextStartFrame);
|
||||
|
||||
UNIMPLEMENTED ("the actual meat: access the scheduler and fed those jobs");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,14 +40,6 @@ namespace engine {
|
|||
FrameSequencer::~FrameSequencer() { }
|
||||
|
||||
|
||||
/** @todo WIP */
|
||||
Dispatcher::JobBuilder
|
||||
Dispatcher::onCalcStream (ModelPort modelPort, uint channel)
|
||||
{
|
||||
JobBuilder builder = {this, modelPort,channel};
|
||||
return builder;
|
||||
}
|
||||
|
||||
|
||||
/** @todo WIP */
|
||||
FrameCoord
|
||||
|
|
|
|||
|
|
@ -110,53 +110,24 @@ namespace engine {
|
|||
}
|
||||
};
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1301 : obsolete
|
||||
public: //////////////////////////////////////////////////////////////////OOO TODO not public; need a way to pick up the result type
|
||||
struct PipeFrameTick;
|
||||
struct PipeSelector;
|
||||
struct PipeExpander;
|
||||
struct PipePlanner;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1301 : obsolete
|
||||
using FrameNrIter = lib::NumIter<FrameCnt>;
|
||||
|
||||
struct PipelineBuilder
|
||||
: FrameNrIter
|
||||
{
|
||||
Dispatcher* dispatcher;
|
||||
Timings timings;
|
||||
ModelPort port;
|
||||
DataSink sink;
|
||||
|
||||
auto
|
||||
timeRange (Time start, Time after)
|
||||
{
|
||||
auto frame = [&](Time t){ return timings.getBreakPointAfter(t); };
|
||||
auto reset = [&](auto i){ static_cast<FrameNrIter&>(*this) = i; };
|
||||
|
||||
reset (lib::eachNum (frame(start), frame(after)));
|
||||
return lib::treeExplore (move(*this))
|
||||
.transform ([&](FrameCnt frameNr) -> TimeVar //////////////////////////////TICKET #1261 : transform-iterator unable to handle immutable time
|
||||
{
|
||||
return timings.getFrameStartAt (frameNr);
|
||||
});
|
||||
}
|
||||
};
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1301 : obsolete
|
||||
|
||||
|
||||
public:
|
||||
virtual ~Dispatcher(); ///< this is an interface
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1301 : obsolete
|
||||
JobBuilder onCalcStream (ModelPort modelPort, uint channel);
|
||||
PipeSelector forCalcStream (Timings timings);
|
||||
|
||||
PipelineBuilder forCalcStream(Timings timings, ModelPort port, DataSink sink)
|
||||
template<class IT>
|
||||
class PlanningPipeline
|
||||
: public IT
|
||||
{
|
||||
return PipelineBuilder{FrameNrIter(), this, timings, port, sink};
|
||||
}
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1301 : obsolete
|
||||
PipeFrameTick forCalcStream (Timings timings);
|
||||
|
||||
|
||||
};
|
||||
|
||||
protected:
|
||||
/** core dispatcher operation: based on the coordinates of a reference point,
|
||||
|
|
@ -226,42 +197,56 @@ namespace engine {
|
|||
++frameNr;
|
||||
currPoint = timings.getFrameStartAt (frameNr);
|
||||
}
|
||||
|
||||
|
||||
/** Builder Function: start frame sequence */
|
||||
auto
|
||||
timeRange (Time start, Time after)
|
||||
{
|
||||
stopPoint = after;
|
||||
frameNr = timings.getBreakPointAfter(start);
|
||||
currPoint = timings.getFrameStartAt (frameNr);
|
||||
|
||||
// start iterator pipeline based on this as »state core«
|
||||
return lib::treeExplore (move(*this));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
inline Dispatcher::PipeFrameTick
|
||||
Dispatcher::forCalcStream(Timings timings)
|
||||
{
|
||||
return PipeFrameTick{this, timings};
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////OOO need better solution for type rebinding
|
||||
using Builder = decltype( declval<Dispatcher::PipeFrameTick>().timeRange (declval<Time>(), declval<Time>()));
|
||||
template<class FUN>
|
||||
using FunRes_t = typename lib::meta::_Fun<FUN>::Ret;
|
||||
//using Builder = decltype( declval<Dispatcher::PipeFrameTick>().timeRange (declval<Time>(), declval<Time>()));
|
||||
|
||||
|
||||
/**
|
||||
* Job-planning Step-2: select data feed connection between ModelPort
|
||||
* and DataSink; this entails to select the actually active Node pipeline
|
||||
*/
|
||||
struct Dispatcher::PipeSelector
|
||||
: Builder
|
||||
: Dispatcher::PipeFrameTick
|
||||
{
|
||||
|
||||
/** Builder Function: start frame sequence */
|
||||
PipeSelector
|
||||
timeRange (Time start, Time after)
|
||||
{
|
||||
stopPoint = after;
|
||||
frameNr = timings.getBreakPointAfter(start);
|
||||
currPoint = timings.getFrameStartAt (frameNr);
|
||||
|
||||
return move(*this); // expected to invoke buildFeed(port,sink)
|
||||
}
|
||||
|
||||
/** Builder Function: setup processing feed ModelPort -> DataSink */
|
||||
auto
|
||||
buildFeed (mobject::ModelPort port, play::DataSink sink)
|
||||
{
|
||||
|
||||
// start iterator pipeline based on this as »state core«
|
||||
auto pipeline = lib::treeExplore (move(*this));
|
||||
|
||||
using PipeIter = decltype(pipeline);
|
||||
return PlanningPipeline<PipeIter>{move (pipeline)};
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
inline Dispatcher::PipeSelector
|
||||
Dispatcher::forCalcStream(Timings timings)
|
||||
{
|
||||
return PipeSelector{this, timings};
|
||||
}
|
||||
|
||||
/**
|
||||
* Job-planning Step-3: monadic depth-first exploration of Prerequisites
|
||||
|
|
|
|||
|
|
@ -173,6 +173,7 @@ namespace test {
|
|||
TimeAnchor refPoint(timings, START_FRAME);
|
||||
CHECK (refPoint == Time::ZERO + Duration(10, FrameRate::PAL));
|
||||
|
||||
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1301
|
||||
FrameCoord coordinates = dispatcher.onCalcStream (modelPort,CHANNEL)
|
||||
.relativeFrameLocation (refPoint, 15);
|
||||
CHECK (coordinates.absoluteNominalTime == Time(0,1));
|
||||
|
|
@ -187,8 +188,7 @@ namespace test {
|
|||
|
||||
Job frameJob = executionPlan.createJobFor (coordinates);
|
||||
CHECK (frameJob.getNominalTime() == coordinates.absoluteNominalTime);
|
||||
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1275
|
||||
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1275
|
||||
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1301
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -200,6 +200,7 @@ namespace test {
|
|||
void
|
||||
verify_standardDispatcherUsage()
|
||||
{
|
||||
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1301
|
||||
Dispatcher& dispatcher = mockDispatcher();
|
||||
ModelPort modelPort (getTestPort());
|
||||
Timings timings (FrameRate::PAL);
|
||||
|
|
@ -217,6 +218,7 @@ namespace test {
|
|||
|
||||
Duration coveredTime (Offset(refPoint, last(plannedChunk).getNominalTime()));
|
||||
CHECK (coveredTime >= timings.getPlanningChunkDuration());
|
||||
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1301
|
||||
|
||||
///TODO nachfolgendes muß komplett umgeschrieben werden
|
||||
///TODO definieren, wie das scheduler-interface angesprochen wird
|
||||
|
|
|
|||
|
|
@ -152,6 +152,7 @@ namespace test {
|
|||
/** @test use the Dispatcher interface (mocked) to generate a frame »beat«
|
||||
* - demonstrate explicitly the mapping of a (frame) number sequence
|
||||
* onto a sequence of time points with the help of time quantisation
|
||||
* - use the Dispatcher API to produce the same frame time sequence
|
||||
* @remark this is the foundation to generate top-level frame render jobs
|
||||
*/
|
||||
void
|
||||
|
|
@ -171,12 +172,12 @@ namespace test {
|
|||
|
||||
MockDispatcher dispatcher;
|
||||
play::Timings timings (FrameRate::PAL);
|
||||
auto [port,sink] = dispatcher.getDummyConnection(0);
|
||||
|
||||
auto pipeline = dispatcher.forCalcStream(timings)
|
||||
.timeRange(Time{200,0}, Time{FSecs{1,2}});
|
||||
|
||||
CHECK (materialise (pipeline)
|
||||
CHECK (materialise (
|
||||
treeExplore (
|
||||
dispatcher.forCalcStream(timings)
|
||||
.timeRange(Time{200,0}, Time{500,0}) // Note: end point is exclusive
|
||||
))
|
||||
== "200ms-240ms-280ms-320ms-360ms-400ms-440ms-480ms"_expect);
|
||||
}
|
||||
|
||||
|
|
@ -187,6 +188,8 @@ namespace test {
|
|||
void
|
||||
accessTopLevelJobTicket()
|
||||
{
|
||||
MockDispatcher dispatcher;
|
||||
auto [port,sink] = dispatcher.getDummyConnection(0);
|
||||
UNIMPLEMENTED ("transform into job ticket access");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -73690,8 +73690,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
<arrowlink COLOR="#32c808" DESTINATION="ID_1438204358" ENDARROW="Default" ENDINCLINATION="283;12;" ID="Arrow_ID_1706669462" STARTARROW="None" STARTINCLINATION="280;20;"/>
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685744060666" ID="ID_676050987" MODIFIED="1685744074319" TEXT="für Anwendung von TreeExplorer-Builder-Funktionen">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node COLOR="#5b280f" CREATED="1685744060666" ID="ID_676050987" MODIFIED="1685833565946" TEXT="für Anwendung von TreeExplorer-Builder-Funktionen">
|
||||
<icon BUILTIN="button_cancel"/>
|
||||
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1685809751146" ID="ID_1263839813" MODIFIED="1685809769709" TEXT="über Sequenz von dedizierten Builder-Typen lösen">
|
||||
<icon BUILTIN="yes"/>
|
||||
</node>
|
||||
|
|
@ -73700,9 +73700,91 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
<node CREATED="1685809782637" ID="ID_1994330949" MODIFIED="1685809800179" TEXT="(inline)-Funktionen sind erst nach dem Typ definiert"/>
|
||||
<node CREATED="1685809800830" ID="ID_835161833" MODIFIED="1685809812910" TEXT="decltype kann erst auf vollständigen Typ angewendet werden"/>
|
||||
<node CREATED="1685809816376" ID="ID_1605798061" MODIFIED="1685809838809" TEXT="brauche aber den decltype zu Beginn des nächsten Binder-Typs"/>
|
||||
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1685809839549" ID="ID_97735774" MODIFIED="1685809855277" TEXT="wo kann ich diesen Schlonz sauber unterbringen?">
|
||||
<node COLOR="#990033" CREATED="1685809839549" ID="ID_97735774" MODIFIED="1685831728915" TEXT="wo kann ich diesen Schlonz sauber unterbringen?">
|
||||
<icon BUILTIN="help"/>
|
||||
<icon BUILTIN="button_cancel"/>
|
||||
<node COLOR="#5b280f" CREATED="1685830984120" ID="ID_1114059991" MODIFIED="1685831038447" TEXT="eine Traits-Klasse geht hier nicht">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
...weil sie erst nach den Builder-Typen definiert werden kann, aber bereits vor ihnen gebraucht wird
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<icon BUILTIN="button_cancel"/>
|
||||
</node>
|
||||
<node COLOR="#5b280f" CREATED="1685830893511" ID="ID_293887488" MODIFIED="1685831715741" TEXT="künstlich Templates einfügen?">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
...weil man dadruch von der Definitionsreihenfolge entkoppeln kann
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<icon BUILTIN="button_cancel"/>
|
||||
</node>
|
||||
<node COLOR="#5b280f" CREATED="1685830943935" ID="ID_340189220" MODIFIED="1685836711378" TEXT="Funktionspointer und Rückgabewert von der Signatur abgreifen?">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
geht, ist aber alles andere als klar, da man zunächst den Member-Fun-Pointer abgreifen muß, und dann von diesem den <b><font color="#4d1e6d">decltype</font></b> ziehen (und erst damit kann man <font face="Monospaced">lib::meta::_Fun</font> anwenden)
|
||||
</p>
|
||||
<br/>
|
||||
<p>
|
||||
<font color="#62322e" face="Monospaced" size="2">
|
||||
  using Pointer = decltype(&Dispatcher::PipeFrameTick::timeRange);<br/>
|
||||
  using ResType = lib::meta::_Fun<Pointer>::Ret;<br/>
|
||||
 <br/>
|
||||
  struct Dispatcher::PipeSelector<br/>
|
||||
    : ResType<br/>
|
||||
    {<br/>
|
||||
      ...<br/>
|
||||
    };
|
||||
</font>
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<icon BUILTIN="button_cancel"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node COLOR="#435e98" CREATED="1685830854298" ID="ID_1539456468" MODIFIED="1685833560849" TEXT="anders herum: brauchen wir überhaupt Zugang zum TreeExplorer-Builder?">
|
||||
<font NAME="SansSerif" SIZE="12"/>
|
||||
<icon BUILTIN="help"/>
|
||||
<node CREATED="1685831255381" ID="ID_300704569" MODIFIED="1685831305089" TEXT="⟶ die Idee war heuristisch — wird aber gar nicht gebraucht"/>
|
||||
<node CREATED="1685831075727" ID="ID_1734873256" MODIFIED="1685831104437" TEXT="letztlich passiert der ganze Pipelie-Bau jetzt an einer einzigen Stelle"/>
|
||||
<node CREATED="1685831111935" ID="ID_1008108972" MODIFIED="1685831156798" TEXT="und zwar vor dem Expander wird schon der »FrameDropper« gebraucht"/>
|
||||
</node>
|
||||
<node COLOR="#5b280f" CREATED="1685833510263" ID="ID_1962899865" MODIFIED="1685833556706">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
<b>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">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685833591596" ID="ID_1247414372" MODIFIED="1685833619292" TEXT="der übernimmt den Iterator vom fertigen TreeExplorer">
|
||||
<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 übergeben">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
|
|
|
|||
Loading…
Reference in a new issue