diff --git a/src/vault/gear/activity.hpp b/src/vault/gear/activity.hpp index d62e72aa8..61f8acef2 100644 --- a/src/vault/gear/activity.hpp +++ b/src/vault/gear/activity.hpp @@ -101,6 +101,7 @@ namespace gear { // standard copy operations acceptable explicit operator uint32_t() const { return id_;} + explicit operator bool() const { return id_ != 0; } friend bool operator== (ManifestationID const& a, ManifestationID const& b) { return a.id_ == b.id_; } friend bool operator!= (ManifestationID const& a, ManifestationID const& b) { return not (a == b); } diff --git a/src/vault/gear/block-flow.hpp b/src/vault/gear/block-flow.hpp index 4dccb173a..1fc327daa 100644 --- a/src/vault/gear/block-flow.hpp +++ b/src/vault/gear/block-flow.hpp @@ -484,7 +484,7 @@ namespace gear { auto requiredNew = distance / _raw(epochStep_); if (distance % _raw(epochStep_) > 0) ++requiredNew; // fractional: requested deadline lies within last epoch - alloc_.openNew(requiredNew); // Note: epochHandle now points to the first new Epoch + alloc_.openNew(requiredNew); // Note: nextEpoch now points to the first new Epoch for ( ; 0 < requiredNew; --requiredNew) { REQUIRE (nextEpoch); diff --git a/src/vault/gear/scheduler-invocation.hpp b/src/vault/gear/scheduler-invocation.hpp index c57f87335..5b49c1589 100644 --- a/src/vault/gear/scheduler-invocation.hpp +++ b/src/vault/gear/scheduler-invocation.hpp @@ -249,7 +249,8 @@ namespace gear { void activate (ManifestationID manID) { - allowed_.insert (manID); + if (manID) + allowed_.insert (manID); } void diff --git a/src/vault/gear/scheduler.hpp b/src/vault/gear/scheduler.hpp index e605f91fb..36d102479 100644 --- a/src/vault/gear/scheduler.hpp +++ b/src/vault/gear/scheduler.hpp @@ -283,12 +283,51 @@ namespace gear { /** - * + * Set the Scheduler to work on a new CalcStream. + * @param planningJob a »meta-Job« to schedule a chunk of render-Jobs. + * @param manID (optional) a manifestation-ID to be enabled for processing + * @note the planningJob will be dispatched _immediately now,_ which typically + * will cause its dispatch in the current thread (but that is not guaranteed). + * The _deadline_ is also set automatically to a very large leeway (1/10 sec), + * and the new planning job is marked as _compulsory_ — implying that the + * Scheduler will [trigger emergency](\ref #triggerEmergency) if this deadline + * can not be met. Emergency will cause all PlayProcess to be paused. + * @remark it is up to the planning instance to use this mechanism properly; the idea + * is to [place follow-up jobs](\ref #continueMetaJob) repeatedly, always to + * define the next chunk of work jobs. If a ManifestationID is given, then + * obviously the work jobs must use the same ID, since jobs with an ID not + * [explicitly enabled](\ref SchedulerInvocation::activate) will be silently + * discarded (unless the ID is zero, which is always implicitly enabled). + * Moreover, the recommendation is to start planning with at least 20ms + * of remaining headroom, to ensure smooth allocation of capacity. */ void - seedCalcStream() + seedCalcStream (Job planningJob + ,ManifestationID manID = ManifestationID()) { - UNIMPLEMENTED("get it going"); + layer1_.activate(manID); + continueMetaJob (RealClock::now(), planningJob, manID); + } + + + /** + * Place a follow-up job-planning job into the timeline. + */ + void + continueMetaJob (Time nextStart + ,Job planningJob + ,ManifestationID manID = ManifestationID()) + { + bool isCompulsory = true; + Time deadline = nextStart + DUTY_CYCLE_TOLERANCE; + // place the meta-Job into the timeline... + postChain ({activityLang_.buildMetaJob(planningJob, nextStart, deadline) + .post() + , nextStart + , deadline + , manID + , isCompulsory}); + ensureDroppedGroomingToken(); } diff --git a/tests/vault/gear/block-flow-test.cpp b/tests/vault/gear/block-flow-test.cpp index c2a665695..3acdffb11 100644 --- a/tests/vault/gear/block-flow-test.cpp +++ b/tests/vault/gear/block-flow-test.cpp @@ -117,7 +117,7 @@ namespace test { /** @test cover properties and handling of Epochs (low-level) - * - demonstrate that Epoch is placed into an Extent + * - demonstrate that each Epoch is placed into an Extent * - verify that both Extent and Epoch access the same memory block * - demonstrate the standard setup and initialisation of an Epoch * - allocate some Activities into the storage and observe free-managment @@ -191,7 +191,7 @@ namespace test { for (uint i=extent.size()-2; i>1; --i) gate.claimNextSlot(); - // one final slot is left (beyond of the EpochGate itself) + // one final slot is left (beyond the EpochGate itself) CHECK (isSameObject (*gate.next, epoch[1])); CHECK (gate.filledSlots() == EXTENT_SIZ-2); CHECK (gate.hasFreeSlot()); @@ -210,7 +210,6 @@ namespace test { CHECK ( gate.isAlive (Time(999,9))); CHECK (not gate.isAlive (Time(0,10))); CHECK (not gate.isAlive (Time(1,10))); - ////////////////////////////////////////////////////////////////////////////////////////TICKET #1298 : actually use a GATE implementation and then also check the count-down latch } diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 0e4ab3e41..98cd4b60d 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -78650,9 +78650,6 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - @@ -78663,6 +78660,10 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + +
@@ -78948,6 +78949,21 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + + + +

+ ...damit sie das Grooming-Token hat und damit Zugriff auf die Scheduler-Ressourcen. Außerdem ist damit ein konsitenter Rahmen sichergestellt: geplante Startzeiten sollten frühestend 20ms danach beginnen +

+ +
+ + + +
@@ -78974,7 +78990,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + @@ -79765,7 +79781,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + @@ -80235,6 +80251,22 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + + + +

+ beide Probleme lassen sich nicht lösen — +

+

+ ..aber entschärfen.. +

+ +
+ +
@@ -80308,25 +80340,25 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - + + - +

- aus dem Term können die + aus dem Term gehen die

- Instruct-Daten gewonnen werden + Scheduling-Daten hervor

- + @@ -80343,15 +80375,23 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + + + + + + + + + - + @@ -80391,7 +80431,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + @@ -80400,8 +80440,23 @@ Date:   Thu Apr 20 18:53:17 2023 +0200

+ + + + + +

+ ...da nun wirklich jeder Dispatch am Grooming-Token „vorbei muß“  — theoretisch wäre es sogar darstellbar, die eigentliche Job-Planung außerhalb und ohne Grooming-Token zu machen; die neuen Jobs gehen dann eben in die Instruction-Queue. Auch eine Notification (welche das Gate dekrementieren könnte) geht durch das λ-post, welches direkt durch Layer2.postDispatch geht, und damit entweder versucht, das Grooming-Token zu erlangen, oder eben in die Instruct-Queue einstellt +

+ +
+ + + + +
@@ -80411,7 +80466,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + @@ -80423,6 +80478,23 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + + + + + + +

+ und hat damit garantiert das Grooming-Token +

+ +
+ + +
@@ -80433,8 +80505,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - + + @@ -80444,8 +80516,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - + + @@ -80456,8 +80528,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - + + @@ -80509,7 +80581,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + @@ -80591,12 +80663,12 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - + + + - + @@ -80605,8 +80677,13 @@ Date:   Thu Apr 20 18:53:17 2023 +0200

+ + + + - + + @@ -80615,6 +80692,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200

+ @@ -80658,7 +80736,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + + @@ -81122,6 +81201,19 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + + + + + + + + + + @@ -81150,7 +81242,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + + @@ -82015,7 +82108,18 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + + + + + + +

+ das ist das ausschlaggebende Argument: Jemand, der erst mal nur den Scheduler-Header liest, wäre sonst sofort erschlagen von technischen Details, und würde den Wald vor lauter Bäumen nicht mehr sehen. Zumal Scheduler selber nochmal zerlegt wird in einen Header-Anteil und eine eigene translation-unit (scheduler.cpp) +

+ +
+
@@ -82030,7 +82134,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + @@ -82043,7 +82147,35 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + + + + + + + + +

+ ...und zwar wegen der Builder-Notation; wegen der Möglichkeit, später noch Dependencies aufzuschalten, muß der activity::Term im Builder eingebettet sein, also bei der Definition der Builder-Klasse bekannt. Einziger Ausweg wäre, in die äußere Builder-Klasse einen opaque buffer zu legen, und die Implementierung in scheduler.cpp nachzutragen. Diese Lösung halte ich für unnötig komplex (wiewohl sie keinen relevanten Performance-overhead erzeugt) +

+ + +
+
+ + + + + + +

+ ...denn die betreffenden Header sind nicht wirklich schwergewichtig  — im Besonderen da die typischen Clients des SchedulerService selber Implementierungs-Code sind +

+ + +
+
+
@@ -82055,6 +82187,35 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + + + + + +

+ denn dabei handelt es sich nun wirklich um eine zentrale Implementierungs-Funktion, die auch aus der Implementierung heraus aufgerufen wird. Selbst wenn der Optimizer wahrscheinlich die monomorphic optimization beherrscht, macht man sowas einfach nicht. +

+ + +
+
+ + + + + + +

+ ...so ziemlich jede von denen greift in der Implementierung auf die Komponenten im Scheduler zu. +

+ + +
+
+
@@ -82078,6 +82239,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ @@ -82194,8 +82356,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - + + @@ -82261,8 +82423,50 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - + + + + + + + + + + + + + + +

+ also sehr großzügig +

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

+ er ist stets compulsory +

+ + +
+
+
+ + + + + + + + @@ -88964,7 +89168,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + @@ -95083,7 +95287,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + @@ -95414,6 +95618,29 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + + + + + + + + + + +

+ allerdings haben wir jetzt praktisch immer einen direkten Eingang +

+ + +
+
+ + +