From 2f042ce6c0dceaf42bbeeac361476e00237a8057 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Tue, 22 Aug 2023 20:13:13 +0200 Subject: [PATCH] Activity-Lang: cover all cases of Gate-behaviour TODO: while correct as implemented, the handling of the notification seems questionable, since re-scheduling the chain immediately may lead to multiple invocations of the chain, since it might have been "spinned" and thus re-scheduled already, and we have no way to find out about that --- src/vault/gear/activity.hpp | 7 +- tests/vault/gear/activity-detector-test.cpp | 16 ++-- tests/vault/gear/activity-detector.hpp | 2 +- tests/vault/gear/scheduler-activity-test.cpp | 84 ++++++++++++++++---- wiki/thinkPad.ichthyo.mm | 74 ++++++++++++++--- 5 files changed, 143 insertions(+), 40 deletions(-) diff --git a/src/vault/gear/activity.hpp b/src/vault/gear/activity.hpp index f0867f2fe..aa9cdd101 100644 --- a/src/vault/gear/activity.hpp +++ b/src/vault/gear/activity.hpp @@ -503,7 +503,7 @@ namespace gear { --data_.condition.rest; // maybe the Gate has been opened by this notification? if (data_.condition.isFree(now)) // yes => activate gated chain - return postChain (now, executionCtx); + return postChain (now, executionCtx); ////////////////////////////////////////////////////////TICKET #1319 : really re-scheduler directly? may lead to duplicate invocations! else return activity::PASS; } @@ -519,7 +519,8 @@ namespace gear { activity::Proc dispatchSelfDelayed (Time now, EXE& executionCtx) { - return dispatchSelf (executionCtx.spin(now), executionCtx); + dispatchSelf (executionCtx.spin(now), executionCtx); + return activity::SKIP; } template @@ -569,7 +570,7 @@ namespace gear { * @return activity::Proc indication how to proceed with execution * - activity::PASS continue with regular processing of `next` * - activity::SKIP ignore the rest of the chain, look for new work - * - activity::KILL abort this complete Activity term (timeout) + * - activity::KILL abort this complete Activity term (play change) * - activity::HALT serious problem, stop the Scheduler */ template diff --git a/tests/vault/gear/activity-detector-test.cpp b/tests/vault/gear/activity-detector-test.cpp index 65e5e1c93..aa3681ca2 100644 --- a/tests/vault/gear/activity-detector-test.cpp +++ b/tests/vault/gear/activity-detector-test.cpp @@ -113,11 +113,11 @@ namespace test { auto fun = detector.buildDiagnosticFun ("funny"); uint rnd = rand() % 10000; - ++detector; + detector.incrementSeq(); CHECK (1 == detector.currSeq()); CHECK (detector.ensureNoInvocation ("funny")); - ++detector; + detector.incrementSeq(); CHECK (2 == detector.currSeq()); CHECK (detector.verifySeqIncrement(2)); @@ -133,7 +133,7 @@ namespace test { CHECK (detector.ensureNoInvocation ("funny").seq(5)); // expecting wrong sequence number CHECK (detector.ensureNoInvocation ("funny").arg(rnd).seq(1)); // expecting correct argument, but wrong sequence - ++detector; + detector.incrementSeq(); fun (rnd+1); CHECK (detector.verifyInvocation ("funny").seq(2) .beforeSeqIncrement(3) @@ -174,7 +174,7 @@ namespace test { CHECK (detector.verifyInvocation ("mockJob").arg(nominal, invoKey.part.a)); CHECK (detector.verifyInvocation ("mockJob").timeArg(nominal)); - ++detector; // note: sequence number incremented between invocations + detector.incrementSeq(); // note: sequence number incremented between invocations dummyJob.parameter.nominalTime += 5 * Time::SCALE; // different job parameter (later nominal time point) dummyJob.triggerJob(); @@ -221,7 +221,7 @@ namespace test { CHECK (activity::PASS == ctx.tick(t)); CHECK (detector.verifyInvocation(CTX_TICK).arg(t)); - ++detector; + detector.incrementSeq(); ctx.tick.returning(activity::KILL); CHECK (activity::KILL == ctx.tick(t)); CHECK (detector.verifyInvocation(CTX_TICK).timeArg(t)); @@ -277,7 +277,7 @@ namespace test { Activity& tap = detector.buildActivationTap (invoke); CHECK (tap.next == invoke.next); - ++detector; + detector.incrementSeq(); Time t2{0,2,2}; // now activate through the Tap.... tap.activate(t2, detector.executionCtx); @@ -286,7 +286,7 @@ namespace test { .beforeInvocation(jobID).seq(1).arg(nomTime,12)); // WARNING: can still activate the watched subject directly... - ++detector; + detector.incrementSeq(); Time t3{0,3,3}; invoke.activate (t3, detector.executionCtx); CHECK (detector.verifyInvocation(jobID).seq(2)); // subject invoked @@ -384,7 +384,7 @@ namespace test { Time tt{5,5}; wiring->activate(tt, detector.executionCtx); - ++detector; + detector.incrementSeq(); wiring->next->activate(tt, detector.executionCtx); CHECK (detector.verifyInvocation("tap-GATE").seq(0).timeArg(tt) diff --git a/tests/vault/gear/activity-detector.hpp b/tests/vault/gear/activity-detector.hpp index 85445f263..ea24e2f73 100644 --- a/tests/vault/gear/activity-detector.hpp +++ b/tests/vault/gear/activity-detector.hpp @@ -464,7 +464,7 @@ namespace test { /** increment the internal invocation sequence number */ uint - operator++() + incrementSeq() { ++invocationSeq_; eventLog_.event (MARK_INC, util::toString(invocationSeq_)); diff --git a/tests/vault/gear/scheduler-activity-test.cpp b/tests/vault/gear/scheduler-activity-test.cpp index fa630e456..b3fb0fe07 100644 --- a/tests/vault/gear/scheduler-activity-test.cpp +++ b/tests/vault/gear/scheduler-activity-test.cpp @@ -161,11 +161,10 @@ namespace test { - /** @test TODO behaviour of Activity::NOTIFY + /** @test behaviour of Activity::NOTIFY when _activated_ * - notification is dispatched as special message to an indicated target Activity * - when activated, a `NOTIFY`-Activity _posts itself_ through the Execution Context hook * - this way, further processing will happen in management mode (single threaded) - * @todo WIP 8/23 🔁 define ⟶ implement */ void verifyActivity_Notify_activate() @@ -176,16 +175,15 @@ namespace test { ActivityDetector detector; Time tt{111,11}; notify.activate (tt, detector.executionCtx); - cout << detector.showLog() < rejected + Time t3{335,33}; // after the deadline => rejected + + CHECK (activity::PASS == wiring.activate (t1, detector.executionCtx)); + CHECK (detector.verifyInvocation("tap-GATE").arg("33.330 ⧐ Act(GATE").seq(0)); + + detector.incrementSeq(); + CHECK (activity::SKIP == wiring.activate (t2, detector.executionCtx)); + CHECK (detector.verifyInvocation("tap-GATE").arg("33.333 ⧐ Act(GATE").seq(1)); + + detector.incrementSeq(); + CHECK (activity::SKIP == wiring.activate (t3, detector.executionCtx)); + CHECK (detector.verifyInvocation("tap-GATE").arg("33.335 ⧐ Act(GATE").seq(2)); + cout << detector.showLog() < Act(GATE") + .beforeInvocation("CTX-post").seq(1).arg(tt, "afterGATE", "≺test::CTX≻")); ////////TICKET #1319 : really re-scheduler directly? may lead to duplicate invocations! cout << detector.showLog() < + + + + + + + + + + +

+ wenn wir nun unmittelbar re-dispatchen, +

+

+ könnte der chain zweimal aktiviert werden +

+ +
+ + + +
+
@@ -79083,6 +79106,10 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + +
@@ -79174,7 +79201,28 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + + + + + + + + + +

+ wenn die Nachricht kommt, daß alle Prerequisites erfüllt sind, könnte die Berechnung sofort starten (und den aktuellen Worker nutzen); wenn wir stattdessen nur dekrementieren, verzögert sich die Weiterverarbeitung, bis durch Scheduling oder re-Scheduling das Gate erneut geprüft wird (spinning) +

+ +
+
+ + + + + +
+
@@ -79557,20 +79605,24 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + - - - + + + - - + + - - + + + + + + + + - -