diff --git a/src/steam/engine/dispatcher.hpp b/src/steam/engine/dispatcher.hpp index 8c6cfc2df..2eaf1ee49 100644 --- a/src/steam/engine/dispatcher.hpp +++ b/src/steam/engine/dispatcher.hpp @@ -292,7 +292,7 @@ namespace engine { this->expandAll([](TicketDepend& currentLevel) { JobTicket const* parent = currentLevel.second; - return lib::transformIterator (parent->getPrerequisites(0) + return lib::transformIterator (parent->getPrerequisites() ,[&parent](JobTicket const& prereqTicket) { // parent shifted up to first pos return TicketDepend{parent, &prereqTicket}; diff --git a/src/steam/engine/job-ticket.cpp b/src/steam/engine/job-ticket.cpp index 8749fb468..870f892d2 100644 --- a/src/steam/engine/job-ticket.cpp +++ b/src/steam/engine/job-ticket.cpp @@ -44,69 +44,19 @@ namespace engine { } // (END) Details... -// using mobject::Placement; -// using mobject::session::Effect; - using vault::engine::JobParameter; using vault::engine::JobClosure; - using lib::HashVal; - using lib::unConst; - class FrameJobClosure - : public JobClosure - { - // data members? - - private: /* === JobClosure Interface === */ - - JobKind - getJobKind() const - { - return CALC_JOB; - } - - bool - verify (Time nominalTime, InvocationInstanceID invoKey) const - { - UNIMPLEMENTED ("access the underlying JobTicket and verify the given job time is within the relevant timeline segment"); - return false; - } - - InvocationInstanceID - buildInstanceID (HashVal seed) const override - { - UNIMPLEMENTED ("systematically generate an invoKey, distinct for the nominal time"); - } - - size_t - hashOfInstance (InvocationInstanceID invoKey) const override - { - UNIMPLEMENTED ("interpret the invoKey and create a suitable hash"); - } - - void - invokeJobOperation (JobParameter parameter) override - { - UNIMPLEMENTED ("representation of the job functor"); - } - - - void - signalFailure (JobParameter parameter, JobFailureReason reason) override - { - UNIMPLEMENTED ("what needs to be done when a job cant be invoked?"); - } - - public: - - - }; /** special »do nothing« JobTicket marker */ const JobTicket JobTicket::NOP{}; //////////////////////////////////////////////////////////////TICKET #725 : do we actually need that for the final data structure? + + JobTicket::JobTicket() + : provision_{nopFunctor(), ExitNode::NIL} + { } /** @@ -129,10 +79,8 @@ namespace engine { else { REQUIRE (this->isValid(), "Attempt to generate render job for incomplete or unspecified render plan."); - REQUIRE (coordinates.channelNr < provision_.size(), "Inconsistent Job planning; channel beyond provision"); - Provision const& provision = provision_[coordinates.channelNr]; - JobClosure& functor = static_cast (unConst(provision.jobFunctor)); ////////////////TICKET #1287 : fix actual interface down to JobFunctor (after removing C structs) - InvocationInstanceID invoKey{timeHash (nominalTime, provision.invocationSeed)}; + JobClosure& functor = static_cast (unConst(provision_.jobFunctor)); ////////////////TICKET #1287 : fix actual interface down to JobFunctor (after removing C structs) + InvocationInstanceID invoKey{timeHash (nominalTime, provision_.invocationSeed)}; return Job(functor, invoKey, nominalTime); } @@ -166,12 +114,8 @@ namespace engine { bool JobTicket::verifyInstance (JobFunctor& functor, InvocationInstanceID const& invoKey, Time nominalTime) const { - for (Provision const& p : provision_) - if (util::isSameObject (p.jobFunctor, functor) - and invoKey == timeHash (nominalTime, p.invocationSeed) - ) - return true; - return false; + return util::isSameObject (provision_.jobFunctor, functor) + and invoKey == timeHash (nominalTime, provision_.invocationSeed); } diff --git a/src/steam/engine/job-ticket.hpp b/src/steam/engine/job-ticket.hpp index e66936a6a..2c1edfdb3 100644 --- a/src/steam/engine/job-ticket.hpp +++ b/src/steam/engine/job-ticket.hpp @@ -69,8 +69,6 @@ using lib::OrientationIndicator; using util::isnil; using lib::HashVal; using lib::LUID; -// -//class ExitNode; /** @@ -86,20 +84,19 @@ using lib::LUID; * Job tickets are created by a classical recursive descent call on the exit node, * which figures out everything to be done for generating data from this node. * To turn a JobTicket into an actual job, we need the additional information - * regarding the precise frame number (=nominal time) and the channel number - * to calculate (in case the actual feed is multichannel, which is the default). - * This way, the JobTicket acts as _higher order function:_ a function - * generating on invocation another, specific function (= the job). + * regarding the precise frame number (=nominal time) and a handle for the + * DataSink exposing buffers to output generated data. Thus effectively + * the JobTicket acts as _higher order function:_ a function generating + * on invocation another, specific function (= the job). * * @todo 4/23 WIP-WIP-WIP defining the invocation sequence and render jobs - * @todo maybe the per-channel specialisation can be elided altogether...? */ class JobTicket : util::NonCopyable { struct Prerequisite { - Prerequisite* next{nullptr}; + Prerequisite* next{nullptr}; // for intrusive list JobTicket const& prereqTicket; template @@ -109,14 +106,14 @@ using lib::LUID; }; using Prerequisites = LinkedElements; + /** what handling this task entails */ struct Provision { - Provision* next{nullptr}; - JobFunctor& jobFunctor; - ExitNode const& exitNode; + JobFunctor& jobFunctor; + ExitNode const& exitNode; InvocationInstanceID invocationSeed; - Prerequisites requirements{}; + Prerequisites requirements{}; Provision (JobFunctor& func, ExitNode const& node, HashVal seed =0) : jobFunctor{func} @@ -125,25 +122,15 @@ using lib::LUID; { } /////////////////TICKET #1293 : Hash-Chaining for invocation-ID... size_t hash? or a LUID? }; - - LinkedElements provision_; //////////////////////////////////////////////////TICKET #1297 : retract differentiation into channels here (instead use ModelPorts in the Segment) + /// @internal reference to all information required for actual Job creation + Provision provision_; - template - static LinkedElements buildProvisionSpec (IT); + JobTicket(); ///< @internal as NIL marker, a JobTicket can be empty template - static LinkedElements buildProvisionSpec (ExitNode const&, ALO&); + static Provision buildProvisionSpec (ExitNode const&, ALO&); - private: - JobTicket() { } ///< @internal as NIL marker, a JobTicket can be empty - - protected: - template - JobTicket(IT featureSpec_perChannel) - : provision_{buildProvisionSpec (featureSpec_perChannel)} - { } - public: template JobTicket (ExitNode const& exitNode, ALO& allocator) @@ -151,32 +138,33 @@ using lib::LUID; { } static const JobTicket NOP; - +/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1276 : likely to become obsolete class ExplorationState; friend class ExplorationState; ExplorationState startExploration() const; ////////////////////////////TICKET #1276 : likely to become obsolete ExplorationState discoverPrerequisites (uint channelNr =0) const; ////////////////////////////TICKET #1276 : likely to become obsolete +/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1276 : likely to become obsolete + + Job createJobFor (FrameCoord coordinates) const; auto - getPrerequisites (uint slotNr =0) const + getPrerequisites () const { - return lib::transformIterator (this->empty()? Prerequisites::iterator() - : provision_[slotNr].requirements.begin() - ,[](Prerequisite& prq) -> JobTicket const& + return lib::transformIterator (this->empty()? Prerequisites::const_iterator() + : provision_.requirements.begin() + ,[](Prerequisite const& prq) -> JobTicket const& { return prq.prereqTicket; }); } - Job createJobFor (FrameCoord coordinates) const; - bool empty() const { - return isnil (provision_); + return isnil (provision_.exitNode); } bool @@ -195,6 +183,7 @@ using lib::LUID; }; +/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1276 : likely to become obsolete class JobTicket::ExplorationState { typedef Prerequisites::iterator SubTicketSeq; @@ -288,14 +277,17 @@ using lib::LUID; } } }; +/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1276 : likely to become obsolete /** @internal prepare and assemble the working data structure to build a JobTicket. - * @tparam IT iterator to yield a sequence of specifications for each channel, - * given as `std::pair` of a JobFunctor and a further Sequence of - * JobTicket prerequisites. + * @tparam ALO type of an allocator front-end for generating prerequisite JobTicket(s) + * @param exitNode a (possibly recursive) tree of ExitNode, detailing points where to + * pull and process data from the render nodes network; these can refer + * to nested ExitNodes(s), which need to be processed beforehand, as + * prerequisite for invoking the given (dependent) ExitNode. * @return the final wired instance of the data structure to back the new JobTicket * @remark Note especially that those data structures linked together for use by the * JobTicket are themselves allocated "elsewhere", and need to be attached @@ -306,55 +298,22 @@ using lib::LUID; * frequently after each strike of edit operations, yet traversed * and evaluated on a sub-second scale for ongoing playback. */ - template - inline LinkedElements - JobTicket::buildProvisionSpec (IT featureSpec) - { /* ---- validate parameter type ---- */ - static_assert (lib::meta::can_IterForEach::value); // -- can be iterated - using Spec = typename IT::value_type; - static_assert (lib::meta::is_Tuple()); // -- payload of iterator is a tuple - using Node = typename std::tuple_element<0, Spec>::type; - using Seed = typename std::tuple_element<1, Spec>::type; - using Func = typename std::tuple_element<2, Spec>::type; - using Preq = typename std::tuple_element<3, Spec>::type; - static_assert (lib::meta::is_basically()); // -- first component refers to the ExitNode in the model - static_assert (lib::meta::is_basically()); // -- second component provides a specific seed for Invocation-IDs - static_assert (lib::meta::is_basically()); // -- third component specifies the JobFunctor to use - static_assert (lib::meta::can_IterForEach::value); // -- fourth component is again an iterable sequence - static_assert (std::is_same()); // -- which yields JobTicket prerequisites - REQUIRE (not isnil (featureSpec) - ,"require at least specification for one channel"); - - LinkedElements provisionSpec; //////////////////////////////////////////////////TICKET #1292 : need to pass in Allocator as argument - for ( ; featureSpec; ++featureSpec) ///////////////////////////////////////////////////TICKET #1297 : this additional iteration over channels will go away - { - ExitNode& node = std::get<0> (*featureSpec); - HashVal invoSeed = std::get<1> (*featureSpec); - JobFunctor& func = std::get<2> (*featureSpec); - auto& provision = provisionSpec.emplace (func, node, invoSeed); - for (Preq pre = std::get<3> (*featureSpec); pre; ++pre) - provision.requirements.emplace (*pre); - } - provisionSpec.reverse(); // retain order of given definitions per channel ////////////TICKET #1297 : obsolete; instead we differentiate by OutputSlot in the Segment - ENSURE (not isnil (provisionSpec)); - return provisionSpec; - } template - inline LinkedElements + inline JobTicket::Provision JobTicket::buildProvisionSpec (ExitNode const& exitNode, ALO& allocTicket) { REQUIRE (not isnil (exitNode)); // has valid functor - LinkedElements provisionSpec; HashVal invoSeed = exitNode.getPipelineIdentity(); JobFunctor& func = exitNode.getInvocationFunctor(); - auto& provision = provisionSpec.emplace (func, exitNode, invoSeed); + Provision provisionSpec{func, exitNode, invoSeed}; for (ExitNode const& preNode: exitNode.getPrerequisites()) - provision.requirements.emplace(preNode, allocTicket); ////////////////////////////////////TICKET #1292 : need to pass in generic Allocator as argument + provisionSpec.requirements.emplace(preNode, allocTicket); //////////////////////////////////////////TICKET #1292 : need to pass in generic Allocator as argument return provisionSpec; } - + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1276 : likely to become obsolete /// @deprecated : could be expendable ... likely incurred solely by the use of Monads as design pattern inline JobTicket::ExplorationState JobTicket::startExploration() const @@ -373,13 +332,10 @@ using lib::LUID; inline JobTicket::ExplorationState JobTicket::discoverPrerequisites (uint channelNr) const { - REQUIRE (channelNr < provision_.size() or not isValid()); - - return isnil (provision_)? ExplorationState() - : ExplorationState (provision_[channelNr].requirements); + return empty()? ExplorationState() + : ExplorationState (util::unConst(provision_).requirements); } - - +/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1276 : likely to become obsolete }} // namespace steam::engine diff --git a/tests/core/steam/engine/mock-dispatcher.hpp b/tests/core/steam/engine/mock-dispatcher.hpp index 329618ed9..df0575e1b 100644 --- a/tests/core/steam/engine/mock-dispatcher.hpp +++ b/tests/core/steam/engine/mock-dispatcher.hpp @@ -138,10 +138,6 @@ namespace test { : JobTicket{defineSimpleSpec (seed), allocator()} { } -// template -// MockJobTicket (HashVal seed, IT&& prereq) -// : JobTicket{defineSpec (seed, std::forward (prereq))} -// { } /* ===== Diagnostics ===== */ diff --git a/tests/core/steam/fixture/fixture-segment-test.cpp b/tests/core/steam/fixture/fixture-segment-test.cpp index c7833e073..9b117b54f 100644 --- a/tests/core/steam/fixture/fixture-segment-test.cpp +++ b/tests/core/steam/fixture/fixture-segment-test.cpp @@ -53,7 +53,7 @@ namespace test { /*****************************************************************************//** * @test Verify properties and behaviour of a single Segment in the Segmentation * - construction of a mocked Segment - * - TODO + * - on-demand allocation of a JobTicket for a ModelPort(index) * - TODO * @see steam::fixture::Segment * @see JobPlanningSetup_test diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 065826904..4a52e7867 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -74102,13 +74102,20 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - - - - - + + + + + + + + + + + + + + @@ -74118,14 +74125,16 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + - - - + + + + + - + @@ -74240,12 +74249,21 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + +
- - + + + + + + + + @@ -74279,12 +74297,12 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - + + - - - + + + @@ -74301,7 +74319,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + @@ -74341,16 +74359,17 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + - + + - + @@ -74359,7 +74378,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + @@ -74468,7 +74487,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + + @@ -74483,8 +74503,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - + + @@ -74496,8 +74516,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - + + @@ -74543,22 +74563,22 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + - - + + - + - + - + - + - + @@ -74587,6 +74607,33 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + + + +

+ ursprünglich dachte ich, im Ticket würde intern noch nach einer Channel-ID (für Mehrkanal-Medien) differenziert; die Analyse im Detail ergab jedoch, daß dies stets unter dem Konstrukt »ModelPort« subsummiert werden kann — viele interne Komplexitäten fallen damit weg +

+ +
+ + + + + + + + + + + + + + + + @@ -74938,7 +74985,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- +