diff --git a/src/steam/fixture/segmentation.cpp b/src/steam/fixture/segmentation.cpp index 071e51b3c..fed194384 100644 --- a/src/steam/fixture/segmentation.cpp +++ b/src/steam/fixture/segmentation.cpp @@ -64,7 +64,7 @@ namespace fixture { * - similar for the end point: if the definition is omitted, the new Segment * will cover the time range until the next Segmen's start * - if upper/lower boundaries can not be established, the covered range will be - * expanded from Time::ANYTIME up to Time::ANYTIME in as fitting current context + * expanded from Time::ANYTIME up to Time::NEVER, taking into account the current context * - after start and end point have been established by the above rules, the actual * splicing operation will be determined; either an existing Segment is replaced * altogether, or it is trimmed to fit, or the new Segment is inserted, thereby diff --git a/src/vault/gear/activity.hpp b/src/vault/gear/activity.hpp index 1f8ad14a3..65756dddc 100644 --- a/src/vault/gear/activity.hpp +++ b/src/vault/gear/activity.hpp @@ -49,8 +49,9 @@ #include "vault/common.hpp" #include "vault/gear/job.h" #include "lib/time/timevalue.hpp" +#include "lib/meta/function.hpp" //#include "lib/symbol.hpp" -//#include "lib/util.hpp" +#include "lib/util.hpp" //#include @@ -63,31 +64,62 @@ namespace gear { // using util::isnil; // using std::string; - /** - * Wrapper to hold Time values in trivially constructible union. - * By an unfortunate design decision, lib::time::Time values are - * non-copyable, which prevents placing them into POD data - * - * @todo 7/2023 this decision should be revised //////////////////////////////////////////////////////////TICKET #1261 : reconsider (im)mutability of time entities - */ - class Instant + class Activity; + + + namespace activity { ///< special definitions for the Scheduler activity language + + /** + * Wrapper to hold Time values in trivially constructible union. + * By an unfortunate design decision, lib::time::Time values are + * non-copyable, which prevents placing them into POD data + * + * @todo 7/2023 this decision should be revised //////////////////////////////////////////////////////////TICKET #1261 : reconsider (im)mutability of time entities + */ + class Instant + { + int64_t microTick_; + + public: + Instant() =default; // @suppress("Class members should be properly initialized") + + Instant(TimeValue time) + : microTick_{_raw(time)} + { } + + operator TimeVar() const + { + return TimeValue{microTick_}; + } + + // default copy acceptable + }; + + + /** + * Definition to emulate a _Concept_ for the *Execution Context*. + * The Execution Context need to be passed to any Activity _activation;_ + * it provides the _bindings_ for functionality defined only on a conceptual + * level, and provided by an opaque implementation (actually the Scheduler) + */ + template + constexpr void + _check_is_usable_as_ExecutionContext () { - int64_t microTick_; +#define ASSERT_MEMBER_FUNCTOR(_EXPR_, _SIG_) \ + static_assert (lib::meta::has_Sig(), \ + "Execution-Context: " STRINGIFY(_FUN_) " expect function with signature: " STRINGIFY(_SIG_)); - public: - Instant() =default; // @suppress("Class members should be properly initialized") - Instant(TimeValue time) - : microTick_{_raw(time)} - { } + EXE const& ctx = std::declval(); - operator TimeVar() const - { - return TimeValue{microTick_}; - } + ASSERT_MEMBER_FUNCTOR (ctx.post, void(Activity&, EXE&)); + - // default copy acceptable - }; +#undef ASSERT_MEMBER_FUNCTOR + } + + }//(End)namespace activity @@ -101,6 +133,8 @@ namespace gear { */ class Activity { + using Instant = activity::Instant; + public: /** All possible kinds of activities */ enum Verb {INVOKE ///< dispatch a JobFunctor into a worker thread diff --git a/src/vault/gear/block-flow.cpp b/src/vault/gear/block-flow.cpp deleted file mode 100644 index 7dd61d52c..000000000 --- a/src/vault/gear/block-flow.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/* - BlockFlow - specialised custom allocator to manage scheduler data - - Copyright (C) Lumiera.org - 2023, Hermann Vosseler - - 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. - -* *****************************************************/ - -/** @file block-flow.cpp - ** Implementation details of the custom memory manager backing scheduler operation. - ** - ** @note currently the greatest challenge is de-allocation - ** - ** @see ////TODO_test usage example - ** - ** @todo WIP-WIP-WIP 6/2023 »Playback Vertical Slice« - ** - */ - - -#include "vault/gear/block-flow.hpp" -//#include "lib/symbol.hpp" -//#include "include/logging.h" - -//#include - -//using std::string; -//using util::isnil; - - -namespace vault{ -namespace gear { - - namespace { // internal details - - } // internal details - - - -// NA::~NA() { } - - - - - /** - */ - -}} // namespace vault::gear diff --git a/src/vault/gear/block-flow.hpp b/src/vault/gear/block-flow.hpp index ac7c709f0..9ca875afc 100644 --- a/src/vault/gear/block-flow.hpp +++ b/src/vault/gear/block-flow.hpp @@ -251,7 +251,7 @@ namespace gear { } // default copyable - Instant& + activity::Instant& deadline() { return data_.condition.dead; diff --git a/wiki/renderengine.html b/wiki/renderengine.html index 5d3b46e23..3b3bad75f 100644 --- a/wiki/renderengine.html +++ b/wiki/renderengine.html @@ -6858,7 +6858,7 @@ At first sight the link between asset and clip-MO is a simple logical relation b {{red{Note 1/2015}}} several aspects regarding the relation of clips and single/multichannel media are not yet settled. There is a preliminary implementation in the code base, but it is not sure yet how multichnnel media will actually be modelled. Currently, we tend to treat the channel multiplicity rather as a property of the involved media, i.e we have //one// clip object. -
+
//Render Activities define the execution language of the render engine.//
 The [[Scheduler]] maintains the ability to perform these Activities, in a time-bound fashion, observing dependency relations; activities allow for notification of completed work, tracking of dependencies, timing measurements, re-scheduling of other activities -- and last but not least the dispatch of actual [[render jobs|RenderJob]]. Activities are what is actually enqueued with priority in the scheduler implementation, they are planned for a »µ-tick slot«, activated once when the activation time is reached, and then forgotten. Each Activity is a //verb//, but can be inhibited by conditions and carry operation object data. Formally, activating an Activity equates to a predication, and the subject of that utterance is »the render process«.
 
@@ -6886,10 +6886,17 @@ Activities are processed within a //performance critical part of the application
 While Activities are logically polymorphic, they are implemented as »POD with constructor« -- meaning that they are classes with [[standard layout|https://en.cppreference.com/w/cpp/named_req/StandardLayoutType]] and at least a [[trivial destructor|https://en.cppreference.com/w/cpp/language/destructor#Trivial_destructor]], allowing to just place them into a memory block and forget about them (without need to call any non-trivial functions). The ''Argument data'' depends on the //actual verb// and is thus placed into a union, with access functions to ensure proper usage of the data fields (while it is always possible to access the data field directly). Since Activities are allocated a lot, small memory footprint is favoured, and thus some significant information -- notably the //time window// for activation of each Activity -- is defined //contextually.//
 
 Activities are organised into ''chains'', allowing to express relations based on their respective verbs.
-There are //standard usage patters,// hard coded into the {{{ActivityLang}}} and expected by the {{{SchedulerCommutator}}}, to express all relevant patterns of operational logic necessary to represent time-bound and dependent playback and render tasks.
+There are //standard usage patters,// hard coded into the {{{ActivityLang}}} and expected by the {{{SchedulerCommutator}}}, to express all relevant [[patterns of operational logic|RenderOperationLogic]] necessary to represent time-bound and dependent playback and render tasks.
 
 !The Activity Language
 While the Activities are low-level primitives and can be handled directly by the scheduler, any actual rendering invocation must arrange several Activities into a suitable chain of operations. Thus the actual rendering invocation can be seen as a //sentence of the Activity Language.// Formally speaking, it is a //symbolic term.// Not every possible term (and thus sentence) leads to semantically sound behaviour, and thus the ''Scheduler Interface Setup'' is organised in the form of a //builder notation to construct viable Activity terms.// {{{vault::gear::ActivityLang}}} provides the framework for such builder invocations, and allows to create such terms as transient objects -- connected to the durable {{{Activity}}} records allocated into the [[»BlockFlow« memory manager|SchedulerMemory]] backing the Scheduler operation. The language term is thus a front-end, and exposes suitable extension and configuration points for the JobPlanningPipeline to instruct the necessary Scheduler operations to enact a specific [[render Job|RenderJob]].
+
+The //meaning// of Activities can be understood on two levels. For one, there is the abstract, //conceptual level:// Each Activity represents a verb to express something //performed by »the render process«// -- which in turn appears as a combination and connection of these elementary expressions. Activity verbs can be linked together in a limited number of ways
+* chaining means sequencing -- first //this// Activity, followed by //that// Activity
+* guarding means inhibiting and releasing -- once the prerequisites of a {{{GATE}}} have been ticket off, and unless the deadline is violated
+* notification implies a trigger -- an impulse, either to //decrement// a {{{GATE}}} or to //activate// another Activity
+* posting anchors a pattern -- a complete structure of further Activities is put underway, possibly with an explicit //start time// and //deadline.//
+However, the //meaning// of Activities can also be understood at the //operational level:// This is what the [[operational logic of Activity execution|RenderOperationLogic]] entails, what is implemented as interpretation of the Activity Language and what is actually backed and implemented by the [[Scheduler]].
 
@@ -7030,6 +7037,77 @@ __see also__ &rarr; additional [[implementation details|RenderImplDetails]] &rarr; [[Memory management for render nodes|ManagementRenderNodes]] &rarr; the protocol [[how to operate the nodes|NodeOperationProtocol]] + +
+
+
//The operational logic of Activity execution is the concrete service provided by the [[Scheduler]] to implement interwoven [[render Activities|RenderActivity]] and [[Job  execution|RenderJob]].//
+* logically, each {{{Activity}}} record represents a //verb// to describe some act performed by »the render process«
+* the {{{ActivityLang}}} provides a //builder notation// to build „sentences of activities“ and it sets the framework for //execution// of Activities
+* the ''Scheduler Layer-2'' ({{{SchedulerCommutator}}}) backs this //language execution// with the elementary //effects// to setup the processing
+* the ''Scheduler Layer-1'' ({{{SchedulerInvocation}}}) provides the low-level coordination and invocation mechanics to launch [[render Jobs|RenderJob]].
+
+!Framework for Activity execution
+The individual {{{Activity}}} records serve as atomic execution elements; an Activity can be invoked once, either by time-bound trigger in the Scheduler's priority queue, or by receiving an activation message (directly when in //management mode,// indirectly through the invocation queue else). The data structure of the {{{Activity}}} record (&rarr; [[description|RenderActivity]]) is maintained by the [[»block flow« memory allocation scheme|SchedulerMemory]] and can be considered stable and available (within the logical limits of its definition, which means until the overarching deadline has passed). The ''activation'' of an Activity causes the invocation of a hard-wired execution logic, taking into account the //type field// of the actual {{{Activity}}} record to be »performed«. This hard-wired logic however can be differentiated into a //generic// part (implemented directly in {{{class Activity}}}) and a //contextual// part, which is indirected through a ''λ-binding'', passed as ''execution context'', yet actually implemented by functions of ''Scheduler Layer-2''.
+!!!execution patterns
+Since the render engine can be considered performance critical, only a fixed set of //operational patterns// is supported, implemented with a minimum of indirections and thus with limited configurability. It seems indicated to confine the scope of this operational logic to a finite low-level horizon, assuming that //all relevant high-level render activities// can actually be expressed in terms of these fundamental patters, in combination with an opaque JobFunctor.
+;Frame render Job
+:Invocaton of a ~CPU-bound calculation function working in-memory to generate data into output buffers
+:* {{{POST}}} : defines the ''contextual timing parameters'', which are the //start time// and the //deadline//
+:** causes a chain of Activities to be put in action
+:** these Activities are chained-up (hooked onto the {{{next}}} pointer)
+:** depending on the //invocation context...//
+:*** in ''grooming mode'' (i.e. the current worker holds the {{{GroomingToken}}}) the follow-up activation happens synchronously
+:*** in ''work mode'' (i.e. the {{{GroomingToken}}} has been dropped) the Scheduler internals //must not be altered;// the chain has to be dispatched
+:** ⟹ the Activity Language invokes the ''λ-post''
+:* {{{GATE}}} : provides a check-point to ensure the preconditions are met
+:** the current //wall-clock-time// is checked against the //deadline//
+:** moreover, a //prerequisite count// is checked, allowing passage only if the count has been ticked off to zero
+:** while surpassing the deadline simply obliterates all chained Activities, unmet prerequisites cause a spinning delay-and-recheck
+:** the count-down of prerequisites is caused by receiving a ''notification'' (either externally, or from a {{{NOTIFY}}}-Activity)
+:** receiving such a notification causes re-evaluation of the condition and possibly activation of the chain
+:** ⟹ the Activity Language evaluates the condition (prerequisite ≡ 0 and before deadline)
+:*** when still blocked, the {{{GATE}}} is re-issued through invocation of ''λ-post'' with a re-check delay
+:*** otherwise the chained Activities are activated
+:* {{{TIMESTART}}} : mark the start of ''render calculations'' and leave the ''grooming mode''
+:** the current time and a payload argument is emitted as message -- for self-regulation of the render engine
+:** the {{{GroomingToken}}} is dropped, allowing other [[workers|SchedulerWorker]] to enter grooming mode and to retrieve further jobs.
+:** ⟹ the Activity Language invokes the ''λ-start''
+            INVOKE
+            FEED
+            TIMESTOP
+            (optional) NOTIFY
+        Ankerpunkte
+            Gate wird nur bei Bedarf eingeschleift
+            dies muß aber vor dem Instruct() passieren
+    Media-Decoder-Job
+        zu erstellen
+            IO-Trigger
+                POST
+                    Zeitfenster aus Job-Planning
+                    frühestmoglich Start-Zeit / Deadline
+                (optional) GATE
+                TIMESTART
+                    das ist der Gefahrenübergang
+                INVOKE
+                FEED
+            IO-Callback
+                (ggfs: Callback-entrance Closure)
+                TIMESTOP
+                NOTIFY
+        Ankerpunkte
+            Gate nur bei Bedarf
+            Flag für Asynchronen Job
+    Planungs-Job
+        zu erstellen
+            Achtung: hier kein Übergang in die Hintergrundverarbeitung
+            POST
+            INVOKE
+            FEED
+    Tick
+        einfache Builder-Funktion
+        wird nur einmal erzeugt
+        reproduziert sich dann selbst
+
 
@@ -7071,7 +7149,7 @@ Later on we expect a distinct __query subsystem__ to emerge, presumably embeddin &rarr; QuantiserImpl
-
+
//Invoke and control the dependency and time based execution of  [[render jobs|RenderJob]]//
 The Scheduler acts as the central hub in the implementation of the RenderEngine and coordinates the //processing resources// of the application. Regarding architecture, the Scheduler is located in the Vault-Layer and //running// the Scheduler is equivalent to activating the »Vault Subsystem«. An EngineFaçade acts as entrance point, providing high-level render services to other parts of the application: [[render jobs|RenderJob]] can be activated under various timing and dependency constraints. Internally, the implementation is segregated into two layers
 ;Layer-2: Coordination
@@ -7086,6 +7164,8 @@ Time bound delivery of media data is an important aspect of editing and playback
 This leads to the observation that every render or playback process has to deal with rather incompatible processing patterns and trends: for one, processing has to start as soon as the event of an completed I/O-operation is published, yet on the other hand, limited computational resources must be distributed and prioritised in a way suitable to deliver the completed data as close as possible to a pre-established timing deadline, under the constraint of limited in-memory buffer capacity. The //control structure// of such a render engine is thus not only a time based computation plan -- first and foremost it should be conceived as an asynchronous messaging system, with the ability however to prioritise some messages based on urgency or approaching deadlines.
 
 The time-based ordering and prioritisation of [[render activities|RenderActivity]] is thus used as a //generic medium and agent// to support and implement complex interwoven computational tasks. On the layer-1 mentioned above, a combination of a lock-free dispatch queue is used, feeding into a single threaded priority queue organised by temporal deadlines. Most render activities are lightweight and entail quick updates to some state flags, while certain activities are extremely long running -- and those are shifted into worker threads based on priority.
+&rarr; [[the Activity-Language|RenderActivity]]
+&rarr; [[implementing Activities|RenderOperationLogic]]
 
 !Usage pattern
 The [[Language of render activities|RenderActivity]] forms the interface to the scheduler -- new activities are defined as //terms// and handed over to the scheduler. This happens as part of the ongoing job planning activities -- and thus will be performed //from within jobs managed by the scheduler.// Thus the access to the scheduler happens almost entirely from within the scheduler's realm itself, and is governed by the usage scheme of the [[Workers|SchedulerWorker]].
diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm
index 01e09f31a..0663ded0c 100644
--- a/wiki/thinkPad.ichthyo.mm
+++ b/wiki/thinkPad.ichthyo.mm
@@ -77982,7 +77982,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + + @@ -77998,10 +77999,14 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + @@ -78168,7 +78173,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + @@ -78177,6 +78182,19 @@ Date:   Thu Apr 20 18:53:17 2023 +0200

+ + + + + + + + + + + + +
@@ -78271,7 +78289,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + + @@ -78368,6 +78387,201 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ Hier keine zusätzliche Steuer-Logik einführen! +

+

+ die Zeitplanung muß eben gut genug sein! +

+ +
+ + +
+ + + + + + +

+ Während einer Wartezeit auf re-Test kann nicht erkannt werden, ob der Nachfolgejob vielleicht inzwischen schon arbeiten könnte; somit besteht einerseits die Gefahr, Ressourcen zu verschwenden (re-Test Activities müssen von Workern im Management-Modus (single-threaded) abgearbeitet werden), andererseits Ressourcen ungenützt zu lassen (Worker könnte sich schlafen legen, obwohl der wartende Nachfolge-Job bereits ausführbar wäre und genau von diesem Worker behandelt werden könnte. Das ist ein klassischer Zielkonflikt, und läuft auf die Forderung hinaus, nur so häufig zu prüfen, wie die Engine im Schnitt ohnehin freie Kapazität hätte. Ansatz: ∅ Job-Zeit geteilt durch Zahl der Worker. Und das dann noch mal zwei oder drei, um etwas Puffer zu schaffen... +

+ +
+
+ + + +
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + + +

+ bewirkt anderswo einen Trigger +

+ +
+
+ + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
@@ -78742,6 +78956,18 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + + +

+ konkretes operationales Verhalten des Schedulers, der Concurrency- und Worker-Steuerung +

+ +
+ +
@@ -78760,8 +78986,10 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + + + @@ -81332,7 +81560,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + +