explicate the JobPlanningSequence definition

..causing the compiler to instantiate the
involved templates, i.e. get the complete
pipeline definition through the compiler
This commit is contained in:
Fischlurch 2012-09-01 17:33:42 +02:00
parent b52a1a8366
commit 062e1bbdc1
4 changed files with 45 additions and 15 deletions

View file

@ -175,9 +175,11 @@ namespace lib {
typedef typename SRC::reference reference;
typedef typename SRC::pointer pointer;
/** Metafunction: the resulting type when binding a functor of type FUN */
/** Metafunction: the resulting type when binding ("flat mapping")
* a functor of type FUN. Basically the result of binding a function
* is again an IterExplorer (with an "expanded" state core type) */
template<class FUN>
struct Binding
struct FlatMapped
{
typedef IterExplorer<_COM_<IterExplorer,FUN>, _COM_> Type;
};
@ -210,11 +212,11 @@ namespace lib {
* of the result iterator.
*/
template<class FUN>
IterExplorer<_COM_<IterExplorer,FUN>, _COM_>
typename FlatMapped<FUN>::Type
operator >>= (FUN explorer)
{
typedef _COM_<IterExplorer,FUN> Combinator; // instantiation of the combinator strategy
typedef IterExplorer<Combinator, _COM_> ResultsIter; // result IterExplorer using that instance as state core
typedef typename FlatMapped<FUN>::Type ResultsIter; // result IterExplorer using that instance as state core
return ResultsIter (
Combinator (explorer // build a new iteration state core

View file

@ -230,6 +230,13 @@ namespace meta{
typedef typename FunctionSignature<function<SIG> >::Ret Ret;
typedef typename FunctionSignature<function<SIG> >::Args Args;
};
/** Specialisation when using a function reference */
template<typename SIG>
struct _Fun<SIG&>
{
typedef typename FunctionSignature<function<SIG> >::Ret Ret;
typedef typename FunctionSignature<function<SIG> >::Args Args;
};
/** Specialisation for passing a functor */
template<typename SIG>
struct _Fun<function<SIG> >

View file

@ -28,6 +28,7 @@
//#include "proc/state.hpp"
#include "proc/engine/job.hpp"
#include "proc/engine/job-ticket.hpp"
#include "proc/engine/time-anchor.hpp"
//#include "proc/engine/frame-coord.hpp"
//#include "lib/time/timevalue.hpp"
//#include "lib/time/timequant.hpp"
@ -190,7 +191,7 @@ namespace engine {
return this->wrapping(*prerequisites);
// explanation: PlanningState represents a sequence of successive planning points.
// actually this is implemented by switching an embedded JobPlanning element
// through a sequence of states. Thus the initial state of the investigation
// through a sequence of states. Thus the initial state of an investigation
// (which is a JobPlanning) can stand-in for the sequence of prerequisites
}
@ -210,10 +211,10 @@ namespace engine {
inline PlanningState
expandPrerequisites (PlanningState const& calculationStep)
expandPrerequisites (JobPlanning const& calculationStep)
{
PlanningState newSubEvaluation(
calculationStep->discoverPrerequisites());
calculationStep.discoverPrerequisites());
return newSubEvaluation;
}
@ -233,11 +234,18 @@ namespace engine {
*/
class PlanningStepGenerator
{
engine::TimeAnchor anchor_;
public:
typedef JobPlanning value_type;
typedef JobPlanning& reference;
typedef JobPlanning * pointer;
// PlanningStepGenerator() { }
PlanningStepGenerator(engine::TimeAnchor startPoint)
: anchor_(startPoint)
{ }
/* === Iteration control API for IterStateWrapper== */
@ -261,8 +269,14 @@ namespace engine {
};
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #827
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #827
typedef PlanningState (*SIG_expandPrerequisites) (JobPlanning const&);
typedef lib::IterExplorer<PlanningStepGenerator
,lib::iter_explorer::RecursiveSelfIntegration> JobPlanningChunkStartPoint;
typedef JobPlanningChunkStartPoint::FlatMapped<SIG_expandPrerequisites>::Type ExpandedPlanningSequence;
@ -270,11 +284,18 @@ namespace engine {
* @todo 6/12 WIP-WIP-WIP how to prepare jobs for scheduling
*/
class JobPlanningSequence
: public lib::IterExplorer<PlanningStepGenerator
,lib::iter_explorer::RecursiveSelfIntegration>
: public ExpandedPlanningSequence
{
public:
// JobPlanningSequence() { }
JobPlanningSequence(engine::TimeAnchor startPoint)
: ExpandedPlanningSequence(
JobPlanningChunkStartPoint(
PlanningStepGenerator(startPoint))
>>= expandPrerequisites)
{ }
};

View file

@ -2797,15 +2797,15 @@ From experiences with other middle scale projects, I prefer having the test code
[img[Example: Interfaces/Namespaces of the ~Session-Subsystems|uml/fig130053.png]]
</pre>
</div>
<div title="JobTicket" modifier="Ichthyostega" modified="201204290241" created="201202120018" tags="spec Rendering draft" changecount="12">
<pre>The actual media data is rendered by [[individually scheduled render jobs|RenderJob]]. When preparing such jobs, in order to [[dispatch|FrameDispatcher]] the individual frames calculations required to make a given [[stream of calculations|CalcStream]] happen, a ''node planning phase'' is performed. The goal is to find out
<div title="JobTicket" modifier="Ichthyostega" modified="201208311625" created="201202120018" tags="spec Rendering draft" changecount="14">
<pre>The actual media data is rendered by [[individually scheduled render jobs|RenderJob]]. All these calculations together implement a [[stream of calculations|CalcStream]], as demanded and directed by the PlayProcess. During the preparation of playback, a ''node planning phase'' is performed, to arrange for [[dispatching|FrameDispatcher]] the individual calculations per frame. The goal of these //preparations//&amp;nbsp; is to find out
* what channel(s) to pull
* what prerequisites to prepare
* what parameters to provide
The result of this planning phase is the {{{JobTicket}}}, a complete ''execution plan''.
This planning is uniform for each segment and treated for all channels together, resulting in a nested tree structure of sub job tickets, allocated and stored alongside with the processing nodes and wiring descriptors to form the segment's data and descriptor network. Job tickets are //higher order functions:// entering a concrete frame number and channel into a given job ticket will produce an actual job descriptor, which in itself is again a function, to be invoked through the scheduler when it's time to trigger the actual calculations.
This planning is uniform for each [[segment|Segmentation]] and treated for all channels together, resulting in a nested tree structure of sub job tickets, allocated and stored alongside with the processing nodes and wiring descriptors to form the segment's data and descriptor network. Job tickets are //higher order functions:// entering a concrete frame number and channel into a given job ticket will produce an actual job descriptor, which in itself is again a function, to be invoked through the scheduler when it's time to trigger the actual calculations.
!Structure of the render Jobs created
!Structure of the Render Jobs created
To be more precise: in the general case, invoking the ~JobTicket with a given frame number will produce //multiple jobs// -- typically each frame rendering will require at least one further source media frame; and because Lumiera render jobs will //never block waiting on IO,// this source media access will be packaged as a separate [[resource retrieving job|ResourceJob]], to be treated specifically by the scheduler.
To support the generation of multiple dependent jobs, a ~JobTicket might refer to further ~JobTickets corresponding to the prerequisites. These prerequisite ~JobTickets are the result of a classical recursive descent call into the top level ProcNode, to perform the planning step. There is always an 1:1 relation between actual jobs generated and the corresponding tickets. More precisely, for each possible job to generate there is a suitable ''job closure'', representing exactly the context information necessary to get that job started. To stress that point: a ProcNode might be configured such as to perform a series of recursive invocations of other prerequisite nodes right away (especially when those recursive invocations correspond just to further CPU bound calculations) -- yet still there is only //one//&amp;nbsp; ~JobTicket, because there will be only one Job to invoke the whole sequence. On the other hand, when there is a prerequisite requiring an operation to be scheduled separately, a corresponding separate {{{JobClosure}}} will be referred.