From 86a909b85081bcba4e9e21fd1ee2244da283f452 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Mon, 6 Nov 2023 22:54:19 +0100 Subject: [PATCH] Scheduler: implement the render job builder ...simply by delegating to the underlying builder notation on activity::Term as provided by the Activity-Language --- src/vault/gear/scheduler.hpp | 69 ++++++++++--- tests/vault/gear/scheduler-service-test.cpp | 10 +- wiki/thinkPad.ichthyo.mm | 105 ++++++++++++++++---- 3 files changed, 151 insertions(+), 33 deletions(-) diff --git a/src/vault/gear/scheduler.hpp b/src/vault/gear/scheduler.hpp index dc5125413..9d78ef947 100644 --- a/src/vault/gear/scheduler.hpp +++ b/src/vault/gear/scheduler.hpp @@ -117,6 +117,7 @@ //#include "lib/util.hpp" //#include +#include #include @@ -145,44 +146,50 @@ namespace gear { } - + class Scheduler; class ScheduleSpec + : util::MoveAssign { Job job_; + TimeVar start_{Time::ANYTIME}; + TimeVar death_{Time::NEVER}; + ManifestationID manID_{}; + bool isCompulsory_{false}; + + Scheduler& theScheduler_; + std::optional term_; public: - ScheduleSpec (Job job) + ScheduleSpec (Scheduler& sched, Job job) : job_{job} + , theScheduler_{sched} + , term_{std::nullopt} { } ScheduleSpec - startOffset (microseconds microTicks) + startOffset (microseconds afterNow) { - UNIMPLEMENTED ("start offset"); + start_ = RealClock::now() + _uTicks(afterNow); return move(*this); } ScheduleSpec - lifeWindow (microseconds microTicks) + lifeWindow (microseconds afterStart) { - UNIMPLEMENTED ("deadline relative to starts"); + death_ = start_ + _uTicks(afterStart); return move(*this); } ScheduleSpec manifestation (ManifestationID manID) { - UNIMPLEMENTED ("store manifestation-ID"); + manID_ = manID; return move(*this); } - ScheduleSpec - post() - { - UNIMPLEMENTED ("build chain and hand-over into queue"); - return move(*this); - } + /** build Activity chain and hand-over to the Scheduler. */ + ScheduleSpec post(); }; @@ -286,12 +293,16 @@ namespace gear { /** - * + * Render Job builder: start definition of a schedule + * to invoke the given Job. Use the functions on the returned builder + * to fill in the details of the schedule; defining a start point and + * a deadline is mandatory. Issue this schedule then by invoking `post()` + * @warning the deadline is also used to manage the allocation. */ ScheduleSpec defineSchedule (Job job) { - UNIMPLEMENTED("wrap the ActivityTerm"); + return ScheduleSpec{*this, job}; } @@ -365,6 +376,9 @@ namespace gear { class ExecutionCtx; friend class ExecutionCtx; + /** the Job builder is allowed to allocate and dispatch */ + friend class ScheduleSpec; + /** open private backdoor for tests */ friend class test::SchedulerService_test; }; @@ -452,6 +466,31 @@ namespace gear { + /** @note after invoking this terminal operation, + * the schedule is defined and will be triggered + * when start time arrives. However, before reaching + * this trigger point, the embedded activity::Term can + * still be augmented and dependencies can be established. + * @remark This ScheduleSpec builder is disposable (and can be moved), + * while the actual Activities are allocated into the BlockFlow, + * where they are guaranteed to live until reaching the deadline. + */ + inline ScheduleSpec + ScheduleSpec::post() + { + term_ = move( + theScheduler_ + .activityLang_ + .buildCalculationJob (job_, start_,death_)); + //set up new schedule by retrieving the Activity-chain... + theScheduler_.postChain ({term_->post(), start_ + , death_ + , manID_ + , isCompulsory_}); + return move(*this); + } + + /** * Enqueue for time-bound execution, possibly dispatch immediately. * This is the »main entrance« to get some Activity scheduled. diff --git a/tests/vault/gear/scheduler-service-test.cpp b/tests/vault/gear/scheduler-service-test.cpp index 69aa211af..73008e630 100644 --- a/tests/vault/gear/scheduler-service-test.cpp +++ b/tests/vault/gear/scheduler-service-test.cpp @@ -459,7 +459,11 @@ namespace test { ActivityDetector detector; Job testJob{detector.buildMockJob("testJob", nominal, 1337)}; + auto anchor = RealClock::now(); + auto offset = [&](Time when =RealClock::now()){ return _raw(when) - _raw(anchor); }; +////////////////////////////////// CHECK (scheduler.empty()); +SHOW_EXPR(offset()) scheduler.defineSchedule(testJob) .startOffset(200us) .lifeWindow (1ms) @@ -468,11 +472,15 @@ namespace test { CHECK (not scheduler.empty()); CHECK (detector.ensureNoInvocation("testJob")); +SHOW_EXPR(offset()) sleep_for(400us); CHECK (detector.ensureNoInvocation("testJob")); +SHOW_EXPR(offset()) - CHECK (activity::PASS == scheduler.getWork()); + auto res= scheduler.getWork(); +SHOW_EXPR(res) +// CHECK (activity::PASS == scheduler.getWork()); CHECK (scheduler.empty()); cout << detector.showLog()< + + @@ -82075,20 +82077,26 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + - + + + - - - - + + + + + + + + @@ -82106,17 +82114,73 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - + + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ Im Moment stehe ich for der Aufgabe, einen Scheduler-Mechanismus zu bauen, dessen konkrete Einsatzszenarien derzeit bestenfalls abschätzbar sind. Daher muß ich mir vor allem Erweiterungspunkte und Flexibilität schaffen. Wenn später einmal die Verwendungen der Engine weitgehend komplett überschaubar sind (einschließlich Hardware-Einbindung), dann wäre es sehr wohl denkbar, die Builder-Syntax und ggfs. sogar Teile der Activity-Language zu konsolidieren und festzulegen in wenige, explizite Funktionen auf dem Scheduler-API... +

+ +
+
+
+ + + + +

+ ⟶ Iter-explorer +

+

+ ⟶ Format-util +

+

+ ⟶ meta/trait +

+

+ ⟹ für Implementierungs-Code ist das nicht weiter auffällig (die halbe Code-Basis includiert indirekt diese Header) +

+ +
+
+
@@ -84494,7 +84558,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + @@ -92178,12 +92242,19 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - + + + + + + + + + + + + - -