LUMIERA.clone/src/proc/engine/dispatcher.hpp

135 lines
5.5 KiB
C++
Raw Normal View History

/*
DISPATCHER.hpp - translating calculation streams into frame jobs
Copyright (C) Lumiera.org
2011, 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_DISPATCHER_H
#define PROC_ENGINE_DISPATCHER_H
#include "proc/common.hpp"
2012-02-24 00:29:59 +01:00
#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/job-planning.hpp"
#include "lib/time/timevalue.hpp"
2012-02-04 22:20:21 +01:00
#include <boost/noncopyable.hpp>
#include <functional>
namespace proc {
namespace engine {
using std::function;
2012-02-24 00:29:59 +01:00
using mobject::ModelPort;
using lib::time::FrameCnt;
using lib::time::TimeSpan;
using lib::time::FSecs;
using lib::time::Time;
/**
* 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, together with each chunk of
* planned jobs we generate a continuation job, which -- on activation -- will pick up
* the planning of the next chunk. The Dispatcher interface was shaped especially to
* support this process, with a local JobBuilder for use within the continuation job,
* and a TimeAnchor to represent the continuation point. All the complexities of
* actually planning the 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
: public FrameLocator
{
struct JobBuilder
2012-02-24 00:29:59 +01:00
{
Dispatcher* dispatcher_;
2012-02-24 00:29:59 +01:00
ModelPort modelPort_;
uint channel_;
FrameCoord relativeFrameLocation (TimeAnchor& refPoint, FrameCnt frameCountOffset =0);
JobPlanningSequence
establishNextJobs (TimeAnchor& refPoint)
{
return JobPlanningSequence(
2013-08-18 03:16:49 +02:00
relativeFrameLocation(refPoint),
*dispatcher_);
}
2012-02-24 00:29:59 +01:00
};
public:
2012-02-04 22:20:21 +01:00
virtual ~Dispatcher(); ///< this is an interface
JobBuilder onCalcStream (ModelPort modelPort, uint channel);
2012-02-04 22:20:21 +01:00
protected:
/** core dispatcher operation: based on the coordinates of a reference point,
* establish binding frame number, nominal time and real (wall clock) deadline.
* @return new FrameCoord record (copy), with the nominal time, frame number
* and deadline adjusted in accordance to the given frame offset.
*/
virtual FrameCoord locateRelative (FrameCoord const&, FrameCnt frameOffset) =0;
virtual bool isEndOfChunk (FrameCnt, ModelPort port) =0;
////////TODO: API-1 = just get next frame, without limitations .... CHECK
////////TODO: API-2 = query limitation of planning chunk .... CHECK
////////TODO: API-3 = establish next chunk .... still WIP
////////TODO: Question: why not embedding the time anchor directly within the location generator??
//////// Answer: no this would lead to a huge blob called "the dispatcher"
////////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!
////////////TODO: remaining issues
//////////// - the TimeAnchor needs to be created directly from the JobParameter. No mutable state!
//////////// - but this leads to a lot of duplicated Timings records, unless we rewrite the TimeAnchor to be noncopyable and use a Timings const&
virtual JobTicket& accessJobTicket (ModelPort, TimeValue nominalTime) =0;
};
}} // namespace proc::engine
#endif