diff --git a/src/proc/engine/job-ticket.hpp b/src/proc/engine/job-ticket.hpp index 838d073ad..8fb4034ff 100644 --- a/src/proc/engine/job-ticket.hpp +++ b/src/proc/engine/job-ticket.hpp @@ -45,6 +45,27 @@ namespace engine { // //class ExitNode; + /** + * a job closure represents the execution context of a job. + * This allows us to enqueue simple job-"functions" with the scheduler. + * By virtue of the JobClosure-pointer, embedded into #lumiera_jobDefinition, + * the invocation of such a job may re-gain the full context, including the + * actual ProcNode to pull and further specifics, like the media channel. + */ + class JobClosure + : public lumiera_jobClosure + { + public: + + bool + verify (Time nominalJobTime) const + { + UNIMPLEMENTED ("access the underlying JobTicket and verify the given job time is within the relevant timeline segment"); + return false; + } + }; + + /** * execution plan for pulling a specific exit node. * Usable as blue print for generating actual render jobs. @@ -81,7 +102,7 @@ namespace engine { JobsPlanning createJobsFor (FrameCoord coordinates) { - UNIMPLEMENTED ("job planning and generation") + UNIMPLEMENTED ("job planning and generation"); } bool diff --git a/src/proc/engine/job.cpp b/src/proc/engine/job.cpp index 9cb97c088..0af1b192f 100644 --- a/src/proc/engine/job.cpp +++ b/src/proc/engine/job.cpp @@ -21,6 +21,18 @@ * *****************************************************/ +/** @file job.cpp + ** Implementation of render job invocation. + ** Within this translation unit, the actual invocation of a frame rendering + ** job takes place, after reconstruction of the job's execution environment (closure). + ** + ** @see JobTicket + ** @see ProcNode + ** @see nodeinvocation.hpp + ** + */ + + #include "proc/engine/job.hpp" #include "proc/engine/job-ticket.hpp" @@ -29,7 +41,14 @@ namespace proc { namespace engine { namespace { // Details... - + + inline JobClosure& + myClosure (const Job * const self) + { + ASSERT (self); + ASSERT (self->jobClosure); + return *static_cast (self->jobClosure); + } } // (END) Details... @@ -41,18 +60,31 @@ namespace engine { /** @todo WIP-WIP 2/12 */ void - Job::triggerJob (lumiera_jobParameter param) const + Job::triggerJob () const { UNIMPLEMENTED ("how to access the JobTicket and build the RenderInvocation"); } void - Job::signalFailure (lumiera_jobParameter) const + Job::signalFailure () const { UNIMPLEMENTED ("how to organise job failure and abortion"); } - + + + /** Render Job self verification. + * performs a parameter consistency check + * including a call-back to the defining JobTicket + */ + bool + Job::isValid() const + { + return this->jobClosure + && this->parameter.invoKey > 0 + && myClosure(this).verify (getNominalTime()); + ; + } }} // namespace proc::engine @@ -61,30 +93,28 @@ namespace { using proc::engine::Job; inline Job& - forwardInvocation (LumieraJobClosure jobFunctor) + forwardInvocation (lumiera_jobDefinition& jobDef) { - Job* job = static_cast (jobFunctor); + Job& job = static_cast (jobDef); - REQUIRE (job); - REQUIRE (job->isValid()); - return *job; + REQUIRE (job.isValid()); + return job; } } + extern "C" { /* ==== implementation C interface for job invocation ======= */ void -lumiera_job_invoke (LumieraJobClosure jobFunctor, lumiera_jobParameter param) +lumiera_job_invoke (lumiera_jobDefinition jobDef) { - forwardInvocation(jobFunctor).triggerJob (param); + forwardInvocation(jobDef).triggerJob(); } void -lumiera_job_failure (LumieraJobClosure jobFunctor, lumiera_jobParameter param) +lumiera_job_failure (lumiera_jobDefinition jobDef) { - forwardInvocation(jobFunctor).signalFailure (param); + forwardInvocation(jobDef).signalFailure(); } - - } diff --git a/src/proc/engine/job.hpp b/src/proc/engine/job.hpp index 711dad1a7..c184b77e4 100644 --- a/src/proc/engine/job.hpp +++ b/src/proc/engine/job.hpp @@ -68,24 +68,37 @@ typedef struct lumiera_jobParameter_struct lumiera_jobParameter; typedef lumiera_jobParameter* LumieraJobParameter; +/** complete definition of an individual job */ +struct lumiera_jobDefinition_struct + { + LumieraJobClosure jobClosure; + lumiera_jobParameter parameter; + }; +typedef struct lumiera_jobDefinition_struct lumiera_jobDefinition; + + /** * descriptor record used by the scheduler to organise job invocation. - * The invocation parameter and job closure necessary to invoke this - * job as a function is embedded into this descriptor. + * The actual job's definition, i.e. the invocation parameter and + * the closure necessary to invoke the job as a function + * is embedded (by value) into this descriptor. + * + * @note while this descriptor as such is self-contained, + * the referred LumieraJobClosure needs to be allocated + * and managed separately. Indeed, this closure happens + * to live within the segment data, as part of the JobTicket. */ struct lumiera_jobDescriptor_struct { gavl_time_t when; + JobState jobState; + + lumiera_jobDefinition jobDefinition; /* == Job prerequisites == */ LList waiting; LList failed; LList completed; - - JobState jobstate; - - LumieraJobClosure jobClosure; - lumiera_jobParameter parameter; }; typedef struct lumiera_jobDescriptor_struct lumiera_jobDescriptor; typedef lumiera_jobDescriptor* LumieraJobDescriptor; @@ -109,61 +122,57 @@ namespace engine { //using lib::time::TimeSpan; //using lib::time::Duration; //using lib::time::FSecs; +using lib::time::TimeValue; using lib::time::Time; // //class ExitNode; /** * Frame rendering task, represented as closure. - * This functor encodes all information necessary to actually - * trigger and invoke the rendering operation. It will be embedded - * by reference into a job descriptor and then enqueued with the scheduler + * This functor encodes all information necessary to trigger + * and invoke the actual rendering operation. It will be embedded + * by value into a job descriptor and then enqueued with the scheduler * for invocation just in time. The job interface exposes everything necessary * to plan, handle, schedule and abort jobs. The implementation refers to the * concrete "execution plan" encoded into the corresponding engine::JobTicket. - * The latter is embedded into the storage for segment of the low-level model - * and thus is shared for all frames and channels within this part of the - * timeline. Thus, the lumiera_jobParameter struct contains the "moving parts" - * changing for each individual job. + * The latter is embedded into the storage for one segment of the low-level model + * and thus is shared for all frames and channels within this part of the timeline. + * Thus, the lumiera_jobParameter struct contains the "moving parts" + * different for each \em individual job. * - * @todo 1/12 WIP-WIP-WIP defining the invocation sequence and render jobs + * @todo 2/12 WIP-WIP-WIP defining the invocation sequence and render jobs */ class Job - : public lumiera_jobClosure + : public lumiera_jobDefinition { public: - //////////////////////////////TODO: value semantics or turn this into an interface? Job() { - UNIMPLEMENTED ("job representation, planning and scheduling"); + UNIMPLEMENTED ("job creation, planning and scheduling"); } // using standard copy operations - void triggerJob (lumiera_jobParameter) const; - void signalFailure (lumiera_jobParameter) const; + void triggerJob() const; + void signalFailure() const; Time getNominalTime() const { - UNIMPLEMENTED ("job representation, planning and scheduling"); + return Time (TimeValue(parameter.nominalTime)); } InvocationInstanceID getInvocationInstanceID() const { - UNIMPLEMENTED ("job representation, planning and scheduling"); + return this->parameter.invoKey; } - bool - isValid() const - { - UNIMPLEMENTED ("validity self check"); - } + bool isValid() const; }; @@ -179,14 +188,14 @@ extern "C" { /** trigger execution of a specific job, * assuming availability of all prerequisites */ -void lumiera_job_invoke (LumieraJobClosure, lumiera_jobParameter); +void lumiera_job_invoke (lumiera_jobDefinition); /** signal inability to invoke this job * @todo decide what and how to communicate details of the failure * @remarks the purpose of this function is to allow for reliable checkpoints * within the network of dependent jobs invocations, even after * missing deadlines or aborting a sequence of jobs */ -void lumiera_job_failure (LumieraJobClosure, lumiera_jobParameter); +void lumiera_job_failure (lumiera_jobDefinition); diff --git a/tests/components/proc/engine/dispatcher-interface-test.cpp b/tests/components/proc/engine/dispatcher-interface-test.cpp index 758ad4d7e..be2c4bf91 100644 --- a/tests/components/proc/engine/dispatcher-interface-test.cpp +++ b/tests/components/proc/engine/dispatcher-interface-test.cpp @@ -32,11 +32,13 @@ #include "lib/time/timevalue.hpp" #include "lib/time/timequant.hpp" #include "lib/singleton.hpp" +#include "lib/util.hpp" //#include //#include using test::Test; +using util::isnil; //using std::cout; //using std::rand;