WIP introduce a new kind of job closure to perform the planning

this might help solving that gordian knot related to the TimeAnchor,
the Dispatcher and the introduction of a possible playback strategy
This commit is contained in:
Fischlurch 2013-06-02 03:09:18 +02:00
parent 082822fde8
commit 723096d3f2
6 changed files with 194 additions and 15 deletions

View file

@ -0,0 +1,39 @@
/*
CalcPlanContinuation - closure for planning a chunk of jobs
Copyright (C) Lumiera.org
2013, Hermann Vosseler <Ichthyostega@web.de>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* *****************************************************/
#include "proc/engine/calc-plan-continuation.hpp"
//#include "lib/frameid.hpp"
//#include "proc/state.hpp"
namespace proc {
namespace engine {
/** */
}} // namespace engine

View file

@ -0,0 +1,137 @@
/*
CALC-PLAN-CONTINUATION.hpp - closure for planning a chunk of jobs
Copyright (C) Lumiera.org
2013, Hermann Vosseler <Ichthyostega@web.de>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef PROC_ENGINE_CALC_PLAN_CONTINUATION_H
#define PROC_ENGINE_CALC_PLAN_CONTINUATION_H
#include "proc/common.hpp"
#include "proc/mobject/model-port.hpp"
#include "proc/engine/time-anchor.hpp"
#include "proc/engine/frame-coord.hpp"
#include "proc/engine/job-ticket.hpp"
#include "proc/engine/dispatcher.hpp"
#include "proc/engine/job.hpp"
#include "proc/play/timings.hpp"
#include "lib/time/timevalue.hpp"
#include <boost/noncopyable.hpp>
//#include <tr1/functional>
namespace proc {
namespace engine {
// using std::tr1::function;
using mobject::ModelPort;
// using lib::time::TimeSpan;
// using lib::time::FSecs;
// using lib::time::Time;
/**
* Special job to perform the job planning.
* This closure extends the existing planning of frame jobs to add a chunk
* of additional future jobs. Included with this chunk will be a recursive
* self re-invocation to trigger planning of the next chunk. Overall, this
* planning process is determined and controlled by the CalcStream owning
* this closure.
*
* @todo 5/13 still WIP -- write type comment
*/
class CalcPlanContinuation
: public JobClosure
, boost::noncopyable
{
Dispatcher* dispatcher_;
TimeAnchor refPoint_;
const ModelPort modelPort_;
const uint channel_;
/* === JobClosure Interface === */
JobKind
getJobKind() const
{
return META_JOB;
}
bool
verify (Time nominalJobTime) const
{
UNIMPLEMENTED ("verify the planning coordinates");
return false;
}
void
invokeJobOperation (JobParameter parameter)
{
UNIMPLEMENTED ("representation of the job functor, especially the invocation instance idea for this planning chunk");
}
void
signalFailure (JobParameter parameter)
{
UNIMPLEMENTED ("what needs to be done when a planning continuation cant be invoked?");
}
public:
/**
* @todo
*/
CalcPlanContinuation(play::Timings const& timings
,Dispatcher& dispatcher
,ModelPort modelPort
,int64_t startFrame
,uint channel)
: dispatcher_(&dispatcher)
, refPoint_(TODO)
, modelPort_(modelPort)
, channel_(channel)
{
UNIMPLEMENTED ("how to set up the initial playback start point");
}
Job
initiateRenderPlanning ()
{
UNIMPLEMENTED ("setup of the initial planning job");
}
private:
void
performJobPlanningChunk()
{
UNIMPLEMENTED ("the actual meat: do the planning for a chunk of jobs");
}
};
}} // namespace proc::engine
#endif

View file

@ -28,6 +28,7 @@
#include "lib/error.hpp"
#include "proc/play/timings.hpp"
#include "proc/engine/calc-plan-continuation.hpp"
//#include "include/dummy-player-facade.h"
//#include "include/display-facade.h"
//#include "common/instancehandle.hpp"
@ -81,16 +82,17 @@ namespace engine{
* the underlying jobs. The only way to create a CalcStream
* properly is to retrieve it from the factory functions
* of the EngineService. At that point, the corresponding
* jobs will be configured and enqueued.
* jobs will already be configured and enqueued.
*/
class CalcStream
{
RenderEnvironmentClosure* env_;
RenderEnvironmentClosure* eng_;
play::Timings timings_;
engine::CalcPlanContinuation* plan_;
protected:
CalcStream (RenderEnvironmentClosure& abstractEngine)
: env_(&abstractEngine)
: eng_(&abstractEngine)
{ }
friend class EngineService;
@ -98,16 +100,14 @@ namespace engine{
public:
CalcStream()
: env_(0)
: eng_(0)
, plan_(0)
, timings_()
{ }
CalcStream (CalcStream const& o)
: env_(o.env_)
, timings_(o.timings_)
{ }
~CalcStream() { }
// using standard copy operations
};

View file

@ -86,8 +86,6 @@ namespace engine {
JobBuilder& establishNextJobs (TimeAnchor refPoint);
JobBuilder& prepareContinuation (function<void(TimeAnchor)> delayedAction);
operator JobPlanningSequence()
{
TimeAnchor nextPlanningAnchor = refPoint_.buildNextAnchor();
@ -122,6 +120,11 @@ namespace engine {
////////TODO: immediate point to consider: the time anchor is responsible for the real timing calculations. But how to introduce the play strategy *here* ?
////////////TODO: the solution is simple: get rid of the additional job placed magically into the chunk
//////////// instead, provide a dedicated API function to create exactly that job
//////////// and *enclosed* into a specialised JobClosure subclass, embody the code for the follow-up
//////////// As a corollary: the scheduling deadline should be defined right *within* the job!
virtual JobTicket& accessJobTicket (ModelPort, TimeValue nominalTime) =0;
};

View file

@ -218,7 +218,7 @@ namespace test {
CHECK (!isnil (jobs));
vector<Job> plannedChunk;
lib::append_all (jobs, plannedChunk); //////////////////////////TODO probably can't do it this way; rather the JobPlanningSequence is infinite and only partially evaluated
lib::append_all (jobs, plannedChunk);
Duration coveredTime (Offset(refPoint, last(plannedChunk).getNominalTime()));
CHECK (coveredTime >= timings.getPlanningChunkDuration());
@ -265,6 +265,7 @@ namespace test {
void
check_ContinuationBuilder()
{
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #880
Dispatcher& dispatcher = mockDispatcher();
ModelPort modelPort (getTestPort());
Timings timings (FrameRate::PAL);
@ -291,7 +292,6 @@ namespace test {
continuation.triggerJob();
CHECK (continuation_has_been_triggered);
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #880
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #880
}

View file

@ -5172,13 +5172,13 @@ We //do employ//&amp;nbsp; some virtual calls for the buffer management in order
@@clear(right):display(block):@@
</pre>
</div>
<div title="RenderJob" modifier="Ichthyostega" created="201202162156" modified="201202162316" tags="spec Rendering">
<div title="RenderJob" modifier="Ichthyostega" created="201202162156" modified="201305310017" tags="spec Rendering" changecount="1">
<pre>An unit of operation, to be [[scheduled|Scheduler]] for calculating media frame data just in time.
Within each CalcStream, render jobs are produced by the associated FrameDispatcher, based on the corresponding JobTicket used as blue print (execution plan).
!Anatomy of a render job
Basically, each render job is a //closure// -- hiding all the prepared, extended execution context and allowing the scheduler to trigger the job as a simple function.
When activated, by virtue of this closure, the actual ''node invocation'' is constructed, which is a private and safe execution environment for the actual calculations. This (mostly stack based) environment embodies a StateProxy, acting as communication hub for accessing anything possibly stateful within the larger scope of the currently ongoing render process. The node invocation sequence is what actually implements the ''pulling of data'': on exit, all cacluated data is expected to be available in the output buffers. Typically (but not necessarily) each node embodies a ''calculation function'', holding the actual data processing algorithm.
When activated, by virtue of this closure, the concrete ''node invocation'' is constructed, which is a private and safe execution environment for the actual frame data calculations. This (mostly stack based) environment embodies a StateProxy, acting as communication hub for accessing anything possibly stateful within the larger scope of the currently ongoing render process. The node invocation sequence is what actually implements the ''pulling of data'': on exit, all cacluated data is expected to be available in the output buffers. Typically (but not necessarily) each node embodies a ''calculation function'', holding the actual data processing algorithm.
!{{red{open questions 2/12}}}
* what are the job's actual parameters?