clarify and settle the relation between Dispatcher and PlanningStepGenerator
the solution is to introduce a superinterface and let Dispatcher augment that with the specific parts. This way, the Job planning only has to rely on the rather generic stuff (TimeAnchor, FrameCoord) NOTE: this commit makes the whole JobPlanning machinery compilable for the first time!
This commit is contained in:
parent
3300d00cc8
commit
44435fd1db
6 changed files with 87 additions and 41 deletions
|
|
@ -30,7 +30,8 @@
|
|||
namespace proc {
|
||||
namespace engine {
|
||||
|
||||
Dispatcher::~Dispatcher() { } // emit VTable here....
|
||||
Dispatcher::~Dispatcher() { } // emit VTables and Typeinfo here....
|
||||
FrameSequencer::~FrameSequencer() { }
|
||||
|
||||
|
||||
/** */
|
||||
|
|
@ -65,17 +66,8 @@ namespace engine {
|
|||
UNIMPLEMENTED ("wrap already planned jobs, appending a continuation to pick up later");
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/** */
|
||||
JobTicket&
|
||||
Dispatcher::accessJobTicket (FrameCoord const& frameID)
|
||||
{
|
||||
UNIMPLEMENTED ("figure out and create the actual JobTicket, for the current segment and the given port");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -49,20 +49,40 @@ namespace engine {
|
|||
// class ExitNode;
|
||||
|
||||
/**
|
||||
* @todo 11/11 extremely fuzzy at the moment
|
||||
* Internal abstraction: a service within the engine
|
||||
* for translating a logical calculation stream (corresponding to a PlayProcess)
|
||||
* into a sequence of individual RenderJob entries for calculations and data access.
|
||||
* The actual implementation of this service is tied to the low-level-model, i.e.
|
||||
* the render nodes network. The Dispatcher service is used to implement the CalcStreams
|
||||
* during playback and rendering; there will be a continuous, chunk-wise proceeding
|
||||
* evaluation and planning of new jobs, which can then be handed over to the Scheduler
|
||||
* for time-bound activation.
|
||||
*
|
||||
* \par usage considerations
|
||||
* the asynchronous and ongoing nature of the render process mandates to avoid a central
|
||||
* instance for operating this planning process. Instead, each chunk of planned jobs
|
||||
* contains a continuation job, which -- on activation -- will pick up the planning
|
||||
* of the next chunk. The Dispatcher interface was shaped to support this process,
|
||||
* with a local JobBuilder to be used within the continuation job, and a TimeAnchor
|
||||
* to represent the continuation point. All the complexities of planning jobs are
|
||||
* hidden within the JobPlanningSequence, which, for the purpose of dispatching
|
||||
* a series of jobs just looks like a sequence of job descriptors
|
||||
*
|
||||
* @todo 10/12 still WIP, but conceptually settled by now
|
||||
*/
|
||||
class Dispatcher
|
||||
: boost::noncopyable
|
||||
: public FrameLocator
|
||||
{
|
||||
struct JobBuilder
|
||||
{
|
||||
Dispatcher& dispatcher_;
|
||||
TimeAnchor refPoint_;
|
||||
ModelPort modelPort_;
|
||||
uint channel_;
|
||||
|
||||
/////TODO need storage for the continuation
|
||||
|
||||
FrameCoord relativeFrameLocation (TimeAnchor refPoint, uint frameCountOffset);
|
||||
FrameCoord relativeFrameLocation (TimeAnchor refPoint, uint frameCountOffset =0);
|
||||
|
||||
JobBuilder& establishNextJobs (TimeAnchor refPoint);
|
||||
|
||||
|
|
@ -70,11 +90,10 @@ namespace engine {
|
|||
|
||||
operator JobPlanningSequence()
|
||||
{
|
||||
UNIMPLEMENTED ("how to represent the closure for defining and scheduling jobs");
|
||||
TODO ("build the continuation job if necessary, wrap the sequence");
|
||||
|
||||
////////TODO: use a closure based on FrameCoord plus a back-reference to the Dispatcher.
|
||||
//////////// Thus actually we need a *generator* for a sequence of FrameCoord
|
||||
//////////// This generator is then wrapped up into an evaluation-Monad (IterExplorer)
|
||||
return JobPlanningSequence(
|
||||
relativeFrameLocation(refPoint_), dispatcher_);
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -84,11 +103,12 @@ namespace engine {
|
|||
|
||||
JobBuilder onCalcStream (ModelPort modelPort, uint channel);
|
||||
|
||||
JobTicket& accessJobTicket (FrameCoord const&);
|
||||
|
||||
protected:
|
||||
virtual FrameCoord locateRelative (FrameCoord, uint frameCountOffset) =0;
|
||||
virtual FrameCoord locateRelative (TimeAnchor, uint frameCountOffset) =0;
|
||||
virtual FrameCoord locateRelative (TimeAnchor, uint frameCountOffset) =0; //////////TODO is this really an interface operation, or just a convenience shortcut?
|
||||
|
||||
virtual JobTicket& accessJobTicket (ModelPort, TimeValue nominalTime) =0;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ namespace engine {
|
|||
//using lib::time::TimeSpan;
|
||||
using lib::time::Duration;
|
||||
//using lib::time::FSecs;
|
||||
using lib::time::Time;
|
||||
using lib::time::TimeVar;
|
||||
//
|
||||
// class ExitNode;
|
||||
|
||||
|
|
@ -50,7 +50,7 @@ namespace engine {
|
|||
* A frame render job can be characterised by
|
||||
* - the nominal (timeline) time of the frame
|
||||
* - the corresponding frame-number
|
||||
* - the real wall-clock time of expected delivery
|
||||
* - the real wall-clock time of expected delivery//////////////TODO : might be handy, but not sure if this information is substantial here
|
||||
* - timing constraints (e.g. latency to observe) //////////////TODO : not clear if we repeat this information here
|
||||
* - the actual node to pull data from
|
||||
* - the segment holding that node //////////////TODO : is this information really required??
|
||||
|
|
@ -64,7 +64,7 @@ namespace engine {
|
|||
{
|
||||
|
||||
public:
|
||||
Time absoluteNominalTime;
|
||||
TimeVar absoluteNominalTime;
|
||||
int64_t absoluteFrameNumber;
|
||||
|
||||
ModelPort modelPort;
|
||||
|
|
|
|||
|
|
@ -28,8 +28,8 @@
|
|||
//#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 "proc/engine/time-anchor.hpp"
|
||||
#include "proc/engine/frame-coord.hpp"
|
||||
//#include "lib/time/timevalue.hpp"
|
||||
//#include "lib/time/timequant.hpp"
|
||||
//#include "lib/meta/function.hpp"
|
||||
|
|
@ -226,7 +226,27 @@ namespace engine {
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Abstraction: a Facility to establish frame coordinates
|
||||
* and identify and access the execution plan for this frame.
|
||||
* @see Dispatcher the service interface actually used
|
||||
*/
|
||||
class FrameLocator
|
||||
: public FrameSequencer
|
||||
{
|
||||
public:
|
||||
|
||||
JobTicket&
|
||||
getJobTicketFor (FrameCoord location)
|
||||
{
|
||||
return accessJobTicket (location.modelPort, location.absoluteNominalTime);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual JobTicket& accessJobTicket (ModelPort, TimeValue nominalTime) =0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Generate a sequence of starting points for Job planning,
|
||||
|
|
@ -240,25 +260,22 @@ namespace engine {
|
|||
*/
|
||||
class PlanningStepGenerator
|
||||
{
|
||||
engine::FrameSequencer* locationGenerator_;
|
||||
engine::FrameCoord current_;
|
||||
FrameLocator* locationGenerator_;
|
||||
FrameCoord currentLocation_;
|
||||
|
||||
public:
|
||||
typedef JobPlanning value_type;
|
||||
typedef JobPlanning& reference;
|
||||
typedef JobPlanning * pointer;
|
||||
|
||||
// PlanningStepGenerator() { }
|
||||
|
||||
PlanningStepGenerator(engine::TimeAnchor startPoint)
|
||||
: anchor_(startPoint)
|
||||
PlanningStepGenerator(FrameCoord startPoint, FrameLocator& locator)
|
||||
: locationGenerator_(&locator)
|
||||
, currentLocation_(startPoint)
|
||||
{ }
|
||||
//////////////////////////////////////////////////////////////TODO actually we need two distinct services
|
||||
//////////////////////////////////////////////////////////////TODO - getting the next FrameCoord
|
||||
//////////////////////////////////////////////////////////////TODO - getting the JobTicket for this location
|
||||
//////////////////////////////////////////////////////////////TODO Actually, the Dispatcher would provide exactly those services,
|
||||
//////////////////////////////////////////////////////////////TODO but depending on the Dispatcher constitutes a cyclic dependency.
|
||||
//////////////////////////////////////////////////////////////TODO There seems to be a problem hidden somewhere in this design.
|
||||
|
||||
// default copyable
|
||||
|
||||
|
||||
/* === Iteration control API for IterStateWrapper== */
|
||||
|
||||
|
|
@ -325,10 +342,10 @@ namespace engine {
|
|||
public:
|
||||
// JobPlanningSequence() { }
|
||||
|
||||
JobPlanningSequence(engine::TimeAnchor startPoint)
|
||||
JobPlanningSequence(engine::FrameCoord startPoint, FrameLocator& locator)
|
||||
: ExpandedPlanningSequence(
|
||||
JobPlanningChunkStartPoint(
|
||||
PlanningStepGenerator(startPoint))
|
||||
PlanningStepGenerator(startPoint,locator))
|
||||
>>= expandPrerequisites)
|
||||
{ }
|
||||
|
||||
|
|
|
|||
|
|
@ -63,8 +63,9 @@ namespace builder {
|
|||
: boost::noncopyable
|
||||
{
|
||||
|
||||
/////////////////////////////////////////////////TODO: placeholder code
|
||||
/////////////////////////////////////////////////TODO: see the planned structure at http://lumiera.org/wiki/renderengine.html#Fixture
|
||||
typedef ID<Pipe> PID;
|
||||
// typedef ID<Struct> StID;
|
||||
|
||||
public:
|
||||
|
||||
|
|
|
|||
|
|
@ -83,6 +83,22 @@ namespace test {
|
|||
{
|
||||
UNIMPLEMENTED ("dummy implementation of the core dispatch operation");
|
||||
}
|
||||
FrameCoord
|
||||
locateRelative (FrameCoord, uint frameCountOffset)
|
||||
{
|
||||
UNIMPLEMENTED ("dummy implementation of the core dispatch operation");
|
||||
}
|
||||
FrameCoord
|
||||
locateRelative (TimeAnchor, uint frameCountOffset)
|
||||
{
|
||||
UNIMPLEMENTED ("dummy implementation of the core dispatch operation");
|
||||
}
|
||||
|
||||
JobTicket&
|
||||
accessJobTicket (ModelPort, TimeValue nominalTime)
|
||||
{
|
||||
UNIMPLEMENTED ("dummy implementation of the model backbone / segmentation");
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
|
|
@ -153,7 +169,7 @@ namespace test {
|
|||
CHECK (coordinates.modelPort == modelPort);
|
||||
CHECK (coordinates.channelNr == channel);
|
||||
|
||||
JobTicket& executionPlan = dispatcher.accessJobTicket (coordinates);
|
||||
JobTicket& executionPlan = dispatcher.getJobTicketFor (coordinates);
|
||||
CHECK (executionPlan.isValid());
|
||||
|
||||
Job frameJob = executionPlan.createJobFor (coordinates); //////////////////////////////TODO this is wrong: we never create a single job!
|
||||
|
|
@ -184,11 +200,11 @@ namespace test {
|
|||
|
||||
// Verify the planned Jobs
|
||||
|
||||
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #880
|
||||
CHECK (!isnil (jobs));
|
||||
vector<Job> plannedChunk;
|
||||
lib::append_all (jobs, plannedChunk);
|
||||
|
||||
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #880
|
||||
uint chunksize = plannedChunk.size();
|
||||
CHECK (chunksize == timings.getPlanningChunkSize());
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue