Lumiera  0.pre.03
»edit your freedom«
scheduler-activity-test.cpp
Go to the documentation of this file.
1 /*
2  SchedulerActivity(Test) - verify activities processed in the scheduler
3 
4  Copyright (C)
5  2023, Hermann Vosseler <Ichthyostega@web.de>
6 
7   **Lumiera** is free software; you can redistribute it and/or modify it
8   under the terms of the GNU General Public License as published by the
9   Free Software Foundation; either version 2 of the License, or (at your
10   option) any later version. See the file COPYING for further details.
11 
12 * *****************************************************************/
13 
19 #include "lib/test/run.hpp"
20 #include "lib/test/test-helper.hpp"
21 #include "activity-detector.hpp"
23 #include "vault/real-clock.hpp"
24 #include "lib/time/timevalue.hpp"
25 #include "lib/format-cout.hpp"
26 
27 
28 using test::Test;
29 using lib::time::Time;
30 using lib::time::FSecs;
31 
32 
33 namespace vault{
34 namespace gear {
35 namespace test {
36 
37 
38 
39  /*****************************************************************/
45  {
46 
47  virtual void
48  run (Arg)
49  {
50  seedRand();
51 
52  simpleUsage();
53 
62 
63  termBuilder();
64  dispatchChain();
65 
70  }
71 
72 
74  void
76  {
77  // Activities are »POD with constructor«
79  CHECK (start.verb_ == Activity::WORKSTART);
80  CHECK (start.next == nullptr);
81  CHECK (start.data_.timing.instant == Time::NEVER);
82  CHECK (start.data_.timing.quality == 0);
83 
84  // use the ActivityDetector for test instrumentation...
85  ActivityDetector detector;
86 
87  // Activities can be invoked within an ExecutionContext
88  Time now = RealClock::now();
89  start.activate (now, detector.executionCtx);
90 
91  // In this case, activation causes invocation of λ-work on the context
92  CHECK (detector.verifyInvocation("CTX-work").arg(now, 0));
93 
94 // cout << detector.showLog()<<endl; // HINT: use this for investigation...
95  }
96 
97 
98 
106  void
108  {
109  Activity chain;
110  Activity post{Time{0,11}, Time{0,22}, &chain};
111  CHECK (chain.is (Activity::TICK));
112  CHECK (post .is (Activity::POST));
113  CHECK (Time(0,11) == post.data_.timeWindow.life);
114  CHECK (Time(0,22) == post.data_.timeWindow.dead);
115  CHECK ( & chain == post.next);
116 
117  ActivityDetector detector;
118  Time tt{5,5};
119  post.activate (tt, detector.executionCtx);
120 
121  CHECK (detector.verifyInvocation("CTX-post").arg("11.000","22.000", "Act(POST", "≺test::CTX≻"));
122  }
123 
124 
125 
131  void
133  {
134  ActivityDetector detector;
135 
136  uint64_t x1=rani(), x2=rani();
137  Time nomTime = lib::test::randTime();
138  Activity feed{x1,x2};
139  Activity feed2{x1+1,x1+2};
140  feed.next = &feed2;
141  Activity invoke{detector.buildMockJobFunctor("job"), nomTime, feed};
142 
143  Time realTime = RealClock::now();
144  CHECK (activity::PASS == invoke.activate (realTime, detector.executionCtx));
145 
146  CHECK (detector.verifyInvocation ("job").arg(nomTime, x1));
147  }
148 
149 
150 
161  void
163  {
164  Activity chain;
165  Activity notify{&chain};
166 
167  ActivityDetector detector;
168  Time tt{111,11};
169  notify.activate (tt, detector.executionCtx);
170  CHECK (detector.verifyInvocation("CTX-post").arg("11.111", Time::NEVER, "Act(TICK", "≺test::CTX≻"));
171 
172  detector.incrementSeq();
173  // now we use a `GATE` as target
174  Time ts{333,33};
175  Time td{555,55};
176  Activity gate{1,td};
177  notify.data_.notification.target = &gate;
178  notify.data_.notification.timing = ts; // start time hint can be packaged into the notification
179 
180  notify.activate (tt, detector.executionCtx);
181  CHECK (detector.verifySeqIncrement(1)
182  .beforeInvocation("CTX-post").arg("33.333", "55.555", "Act(GATE", "≺test::CTX≻"));
183  // NOTE: △△△ start △△△ deadline
184  }
185 
186 
187 
192  void
194  {
195  Activity chain;
196  Activity gate{0};
197  gate.next = &chain;
198 
199  ActivityDetector detector;
200  Activity& wiring = detector.buildGateWatcher (gate);
201 
202  Time tt{333,33};
203  CHECK (activity::PASS == wiring.activate (tt, detector.executionCtx));
204  CHECK (detector.verifyInvocation("tap-GATE").arg("33.333 ⧐ Act(GATE"));
205  }
206 
207 
208 
212  void
214  {
215  Activity chain;
216  Activity gate{0, Time{333,33}};
217  gate.next = &chain;
218 
219  ActivityDetector detector;
220  Activity& wiring = detector.buildGateWatcher (gate);
221 
222  Time t1{330,33}; // still before the deadline
223  Time t2{333,33}; // exactly at deadline => rejected
224  Time t3{335,33}; // after the deadline => rejected
225 
226  CHECK (activity::PASS == wiring.activate (t1, detector.executionCtx));
227  CHECK (detector.verifyInvocation("tap-GATE").arg("33.330 ⧐ Act(GATE").seq(0));
228 
229  detector.incrementSeq();
230  CHECK (activity::SKIP == wiring.activate (t2, detector.executionCtx));
231  CHECK (detector.verifyInvocation("tap-GATE").arg("33.333 ⧐ Act(GATE").seq(1));
232 
233  detector.incrementSeq();
234  CHECK (activity::SKIP == wiring.activate (t3, detector.executionCtx));
235  CHECK (detector.verifyInvocation("tap-GATE").arg("33.335 ⧐ Act(GATE").seq(2));
236  }
237 
238 
239 
247  void
249  {
250  Activity chain;
251  Activity gate{23};
252  gate.next = &chain;
253 
254  ActivityDetector detector;
255  Activity& wiring = detector.buildGateWatcher (gate);
256 
257  Time tt{333,33};
258  CHECK (activity::SKIP == wiring.activate (tt, detector.executionCtx));
259  CHECK (23 == gate.data_.condition.rest); // prerequisite-count not altered
260 
261  CHECK (detector.verifyInvocation("tap-GATE").arg("33.333 ⧐ Act(GATE"));
262  }
263 
264 
265 
273  void
275  {
276  Activity chain;
277  Activity gate{23};
278  gate.next = &chain;
279 
280  ActivityDetector detector;
281  Activity& entrance = detector.buildGateWatcher (gate);
282 
283  Time tt{333,33};
284  CHECK (activity::SKIP == entrance.dispatch (tt, detector.executionCtx));
285  CHECK (22 == gate.data_.condition.rest); // prerequisite-count decremented
286 
287  CHECK (detector.verifyInvocation("tap-GATE").arg("33.333 --notify-↯> Act(GATE"));
288  }
289 
290 
291 
302  void
304  {
305  Time tt{333,33};
306  Time td{555,55};
307 
308  Activity chain;
309  Activity gate{1,td};
310  gate.next = &chain;
311  // Conditionals in the gate block invocations
312  CHECK (gate.data_.condition.isHold());
313  CHECK (gate.data_.condition.rest == 1);
314  CHECK (gate.data_.condition.dead == td);
315 
316  ActivityDetector detector;
317  Activity& entrance = detector.buildGateWatcher (gate);
318 
319  // an attempt to activate blocks (returning SKIP, nothing else happens)
320  CHECK (activity::SKIP == entrance.activate (tt, detector.executionCtx));
321  CHECK (1 == gate.data_.condition.rest); // unchanged (and locked)...
322  CHECK (detector.verifyInvocation("tap-GATE").arg("33.333 ⧐ Act(GATE"));
323 
324  detector.incrementSeq();
325  // Gate receives a notification from some prerequisite Activity
326  CHECK (activity::PASS == entrance.dispatch(tt, detector.executionCtx));
327  CHECK (0 == gate.data_.condition.rest); // condition has been decremented...
328 
329  CHECK (detector.verifyInvocation("tap-GATE").seq(0).arg("33.333 ⧐ Act(GATE")
330  .beforeInvocation("tap-GATE").seq(1).arg("33.333 --notify-↯> Act(GATE"));
331  CHECK (gate.data_.condition.dead == Time::MIN);
332 
333  detector.incrementSeq();
334  Time ttt{444,44};
335  // when another activation happens later, it is blocked to prevent double activation
336  CHECK (activity::SKIP == entrance.activate (ttt, detector.executionCtx));
337  CHECK (detector.verifyInvocation("tap-GATE").seq(2).arg("44.444 ⧐ Act(GATE"));
338  CHECK (detector.ensureNoInvocation("CTX-post").seq(2)
339  .afterInvocation("tap-GATE").seq(2));
340  CHECK (gate.data_.condition.dead == Time::MIN);
341 
342  detector.incrementSeq();
343  // even a further notification has no effect now....
344  CHECK (activity::SKIP == entrance.dispatch (ttt, detector.executionCtx));
345  // conditionals were not touched:
346  CHECK (gate.data_.condition.dead == Time::MIN);
347  CHECK (gate.data_.condition.rest == 0);
348  // the log shows the further notification (at Seq=3) but no dispatch happens anymore
349  CHECK (detector.verifySeqIncrement(3)
350  .beforeInvocation("tap-GATE").seq(3).arg("44.444 --notify-↯> Act(GATE"));
351 
352 // cout << detector.showLog()<<endl; // HINT: use this for investigation...
353  }
354 
355 
356 
363  void
365  {
366  ActivityDetector detector;
367 
368  BlockFlowAlloc bFlow;
369  ActivityLang activityLang{bFlow};
370 
371  Time start{0,1};
372  Time dead{0,10};
373  Activity* act{nullptr};
374  {
375  auto term = activityLang.buildCalculationJob (detector.buildMockJob(), start,dead);
376 
377  act = & term.post();
378  }// NOTE: generated Activity chain remains valid after term goes out of scope
379 
380  // Values reported for the BlockFlow allocator look sane...
381  CHECK (watch(bFlow).cntElm() == 7); // POST, GATE, WORKSTART, INVOKE, FEED, FEED, WORKSTOP
382  CHECK (watch(bFlow).cntEpochs() == 1); // all placed into a single epoch...
383  CHECK (watch(bFlow).find(*act) > dead); // which terminates shortly after the given deadline
384  CHECK (watch(bFlow).find(*act) < dead+Time(500,0));
385 
386  // Time window parameters have been included
387  CHECK (act->is (Activity::POST));
388  CHECK (start == act->data_.timeWindow.life);
389  CHECK (dead == act->data_.timeWindow.dead);
390 
391  // sane wiring, leading to an INVOCATE eventually
392  while (not act->is (Activity::INVOKE))
393  act = act->next;
394 
395  CHECK (act->is (Activity::INVOKE));
396  CHECK (watch(bFlow).find(*act) != Time::NEVER); // can also be found within the BlockFlow allocator
397 
398  // this invocation is properly defined and executable
399  Time now{55,5};
400  CHECK (activity::PASS == act->activate (now, detector.executionCtx));
401  CHECK (detector.verifyInvocation("mockJob"));
402  }
403 
404 
405 
416  void
418  {
419  Time tt{11,1};
420  Time td{22,2};
421  Activity tick;
422  Activity gate{0,td};
423  gate.next = &tick;
424  Activity post{tt, &gate};
425  // so now we have POST ⟶ GATE ⟶ TICK;
426 
427  ActivityDetector detector;
428  detector.executionCtx.getSchedTime = [&]{ return tt; };
429  // insert instrumentation to trace activation
430  detector.watchGate (post.next, "Gate");
431 
432  CHECK (activity::PASS == ActivityLang::dispatchChain (&post, detector.executionCtx)); // start execution (case/seq == 0)
433  CHECK (detector.verifyInvocation("Gate") .arg("1.011 ⧐ Act(GATE") // ...first the Gate was activated
434  .beforeInvocation("after-Gate").arg("1.011 ⧐ Act(TICK") // ...then activation passed out of Gate...
435  .beforeInvocation("CTX-tick") .arg("1.011")); // ...and finally the TICK invoked the λ-tick
436 
437  detector.incrementSeq();
438  gate.data_.condition.incDependencies(); // Gate is blocked
439  CHECK (activity::PASS == ActivityLang::dispatchChain (&post, detector.executionCtx)); // start execution (case/seq == 1)
440  CHECK (detector.verifyInvocation("Gate").seq(1).arg("1.011 ⧐ Act(GATE")); // ...the Gate was activated, but blocked...
441  CHECK (detector.ensureNoInvocation("after-Gate").seq(1) // verify activation was not passed out behind Gate
442  .afterInvocation("Gate").seq(1));
443  CHECK (detector.ensureNoInvocation("CTX-tick").seq(1) // verify also the λ-tick was not invoked this time
444  .afterInvocation("Gate").seq(1));
445 
446  detector.incrementSeq();
447  // Notification via instrumented connection to the Gate (activate(NOTIFY) -> λ-post(target) -> notify GATE
448  CHECK (activity::PASS == ActivityLang::dispatchChain (post.next, detector.executionCtx)); // dispatch a notification (case/seq == 2)
449  CHECK (0 == gate.data_.condition.rest); // Effect of the notification is to decrement the latch
450  CHECK (detector.verifyInvocation("Gate") .seq(2).arg("1.011 --notify-↯> Act(GATE") // ...notification dispatched towards the Gate
451  .beforeInvocation("after-Gate").seq(2).arg("1.011 ⧐ Act(TICK") // ...this opened the Gate, passing activation...
452  .beforeInvocation("CTX-tick") .seq(2).arg("1.011")); // ...to the chain, finally invoking λ-tick
453  }
454 
455 
456 
457 
462  void
464  {
465  Time nominal{7,7};
466 
467  Time start{0,1};
468  Time dead{0,10};
469 
470  ActivityDetector detector;
471  Job testJob{detector.buildMockJob("testJob", nominal, 12345)};
472 
473  TimeVar now = Time{5,5};
474  detector.executionCtx.getSchedTime = [&]{ // increase "current" time on each access
475  now += FSecs(1,20);
476  return now;
477  };
478  BlockFlowAlloc bFlow;
479  ActivityLang activityLang{bFlow};
480 
481  // Build the Activity-Term for a simple calculation job...
482  Activity& anchor = activityLang.buildCalculationJob (testJob, start,dead)
483  .post(); // retrieve the entrance point to the chain
484 
485  // insert instrumentation to trace activation
486  detector.watchGate (anchor.next, "theGate");
487 
488  CHECK (activity::PASS == ActivityLang::dispatchChain (&anchor, detector.executionCtx));
489 
490  CHECK (detector.verifyInvocation("theGate").arg("5.105 ⧐ Act(GATE")
491  .beforeInvocation("after-theGate").arg("⧐ Act(WORKSTART")
492  .beforeInvocation("CTX-work").arg("5.155","")
493  .beforeInvocation("testJob") .arg("7.007",12345)
494  .beforeInvocation("CTX-done").arg("5.355",""));
495  }
496 
497 
498 
506  void
508  {
509  Time nominal{7,7};
510  Time start{0,1};
511  Time dead{0,10};
512 
513  ActivityDetector detector;
514  Job testJob{detector.buildMockJob("testJob", nominal, 12345)};
515 
516  BlockFlowAlloc bFlow;
517  ActivityLang activityLang{bFlow};
518 
519  // emulate a blocking prerequisite dependency
520  Activity trigger{Activity::NOTIFY};
521 
522  // Build the Activity-Term...
523  auto term = activityLang.buildCalculationJob (testJob, start,dead)
524  .expectNotification (trigger) // ...require notification from prerequisite
525  .requireDirectActivation(); // ...additionally insert inhibition to avoid activation
526  // before the primary-chain has been scheduled
527  Activity& anchor = term.post();
528  CHECK (anchor.is (Activity::POST));
529  CHECK (anchor.next->is (Activity::NOTIFY));
530  CHECK (anchor.next->next->is (Activity::GATE));
531  CHECK (anchor.next->next->next->is (Activity::WORKSTART));
532  CHECK (anchor.next->next->next->next->is (Activity::INVOKE));
533  CHECK (anchor.next->next->next->next->next->is (Activity::FEED));
534  CHECK (anchor.next->next->next->next->next->next->is (Activity::FEED));
535  CHECK (anchor.next->next->next->next->next->next->next->is (Activity::WORKSTOP));
536  CHECK (anchor.next->next->next->next->next->next->next->next == nullptr);
537 
538  // insert test-instrumentation to trace activation
539  detector.watchGate (anchor.next->next, "theGate");
540  detector.insertActivationTap(trigger.data_.notification.target, "trigger");
541  detector.insertActivationTap(anchor.next->data_.notification.target, "deBlock");
542 
543  // rig the λ-post to forward dispatch as expected in real usage
544  detector.executionCtx.post.implementedAs(
545  [&](Time, Time, Activity* postedAct, auto& ctx)
546  {
547  return ActivityLang::dispatchChain (postedAct, ctx);
548  });
549 
551  CHECK (activity::PASS == ActivityLang::dispatchChain (&trigger, detector.executionCtx));
552  CHECK (detector.verifyInvocation("CTX-post").seq(0).arg("01.000","10.000","trigger","≺test::CTX≻") // notification is POSTed (with time and deadline from target)
553  .beforeInvocation("trigger") .seq(0).arg("5.555 --notify-↯> Act(GATE") // notification dispatched to the Gate (note: now using curr-sched-time 5.555)
554  .arg("<2, until 0:00:10.000")); // Note: the Gate-latch expects 2 notifications
555  CHECK (detector.ensureNoInvocation("testJob") // ==> the latch was decremented but no invocation yet
556  .afterInvocation("trigger"));
557 
559  detector.incrementSeq();
560  CHECK (activity::PASS == ActivityLang::dispatchChain (&anchor, detector.executionCtx));
561  CHECK (detector.verifyInvocation("CTX-post").seq(1).arg("01.000","10.000","deBlock","≺test::CTX≻") // at begin, the internal self-notification is POSTed (with time and deadline this chain)
562  .beforeInvocation("deBlock") .seq(1).arg("5.555 --notify-↯> Act(GATE") // and this call is immediately dispatched towards the Gate (using curr-sched-time 5.555)
563  .arg("<1, until 0:00:10.000") // Note: at this point, the Gate-latch expects 1 notifications ==> latch decremented, Gate OPENS
564  .beforeInvocation("after-theGate") .arg("5.555 ⧐ Act(WORKSTART") // ...causing the activation to pass behind the Gate
565  .beforeInvocation("CTX-work").seq(1).arg("5.555","") // ...through WORKSTART
566  .beforeInvocation("testJob") .seq(1).arg("7.007",12345) // ...then invoke the JobFunctor itself (with the nominal Time{7,7})
567  .beforeInvocation("CTX-done").seq(1).arg("5.555","") // ...and finally the WORKSTOP
568  .beforeInvocation("theGate") .seq(1).arg("5.555 ⧐ Act(GATE") // RETURN to the primary-chain activation (after the internal self-notification)
569  .arg("<0, until -85401592:56:01.825")); // -- however, after opening the Gate, the notification has blocked it permanently
570  CHECK (detector.ensureNoInvocation("testJob") // ==> thus no further (redundant) activation of the JobFunctor
571  .afterInvocation("CTX-done").seq(1));
572 
573  detector.incrementSeq();
574  CHECK (activity::PASS == ActivityLang::dispatchChain (&trigger, detector.executionCtx)); // and any further external trigger is likewise blocked:
575  CHECK (detector.verifyInvocation("CTX-post").seq(2).arg("01.000",Time::NEVER,"trigger","≺test::CTX≻") // notification is POSTed (in the real Scheduler the deadline will block already here)
576  .beforeInvocation("trigger") .seq(2).arg("5.555 --notify-↯> Act(GATE") // ... but even if it would reach the Gate...
577  .arg("<0, until -85401592:56:01.825")); // ... the Gate has been closed permanently (by setting the deadline to Time::MIN)
578  CHECK (detector.ensureNoInvocation("testJob") // ==> no further invocation
579  .afterInvocation("trigger").seq(2));
580 
581 // cout << detector.showLog()<<endl; // HINT: use this for investigation...
582  }
583 
584 
585 
591  void
593  {
594  Time nominal{7,7};
595  Time start{0,1};
596  Time dead{0,10};
597 
598  ActivityDetector detector;
599  Job loadJob{detector.buildMockJob("loadJob", nominal, 12345)};
600  Job calcJob{detector.buildMockJob("calcJob")};
601 
602  BlockFlowAlloc bFlow;
603  ActivityLang activityLang{bFlow};
604 
605  auto followup = activityLang.buildCalculationJob (calcJob, start,dead);
606  auto loadTerm = activityLang.buildAsyncLoadJob (loadJob, start,dead)
607  .appendNotificationTo (followup);
608 
609  Activity& anchor = loadTerm.post();
610  Activity& notify = loadTerm.callback();
611 
612  CHECK (anchor.is (Activity::POST));
613  CHECK (anchor.next->is (Activity::WORKSTART));
614  CHECK (anchor.next->next->is (Activity::INVOKE));
615  CHECK (anchor.next->next->next->is (Activity::FEED));
616  CHECK (anchor.next->next->next->next->is (Activity::FEED));
617  CHECK (anchor.next->next->next->next->next == nullptr); // Note: chain is severed here
618 
619  CHECK (notify.is (Activity::WORKSTOP)); // ...WORKSTOP will be emitted from callback
620  CHECK (notify.next->is (Activity::NOTIFY)); // ...followed by notification of dependent job(s)
621  CHECK (notify.next->next == nullptr);
622 
623  CHECK (notify.next->data_.notification.target == followup.post().next); // was wired to the GATE of the follow-up activity Term
624  CHECK (followup.post().next->is (Activity::GATE));
625 
626  // rig the λ-post to forward dispatch as expected in real usage
627  detector.executionCtx.post.implementedAs(
628  [&](Time, Time, Activity* postedAct, auto& ctx)
629  {
630  return ActivityLang::dispatchChain (postedAct, ctx);
631  });
632 
633 
635  CHECK (activity::PASS == ActivityLang::dispatchChain (&anchor, detector.executionCtx));
636  CHECK (detector.verifyInvocation("CTX-work").seq(0).arg("5.555", "") // activation of WORKSTART
637  .beforeInvocation("loadJob") .seq(0).arg("7.007", 12345)); // activation of JobFunctor
638  CHECK (detector.ensureNoInvocation("CTX-done").seq(0) // IO operation just runs, no further activity yet
639  .afterInvocation("loadJob").seq(0));
640 
641 
643  detector.incrementSeq();
644  CHECK (activity::PASS == ActivityLang::dispatchChain (&notify, detector.executionCtx));
645  CHECK (detector.verifyInvocation("CTX-done").seq(1).arg("5.555", "") // activation of WORKSTOP via callback
646  .beforeInvocation("CTX-post").seq(1).arg("01.00","10.00","GATE","≺test::CTX≻") // the notification posts the GATE of the follow-up chain
647  .beforeInvocation("CTX-work").seq(1).arg("5.555", "") // GATE passes -> activation of the follow-up work commences
648  .beforeInvocation("calcJob") .seq(1)
649  .beforeInvocation("CTX-done").seq(1).arg("5.555", ""));
650  }
651 
652 
653 
661  void
663  {
664  Time nominal{7,7};
665  Time start{0,1};
666  Time dead{0,10};
667 
668  ActivityDetector detector;
669  Job testJob{detector.buildMockJob("metaJob", nominal, 12345)};
670 
671  BlockFlowAlloc bFlow;
672  ActivityLang activityLang{bFlow};
673 
674  // Build Activity-Term with a chain defining a meta-job...
675  Activity& anchor = activityLang.buildMetaJob (testJob, start,dead)
676  .post();
677 
678  CHECK (anchor.is (Activity::POST));
679  CHECK (anchor.next->is (Activity::INVOKE));
680  CHECK (anchor.next->next->is (Activity::FEED));
681  CHECK (anchor.next->next->next->is (Activity::FEED));
682  CHECK (anchor.next->next->next->next == nullptr);
683 
684  // insert test-instrumentation
685  detector.insertActivationTap(anchor.next);
686 
687  CHECK (activity::PASS == ActivityLang::dispatchChain (&anchor, detector.executionCtx));
688 
689  CHECK (detector.verifyInvocation("tap-INVOKE").arg("5.555 ⧐ Act(INVOKE")
690  .beforeInvocation("metaJob") .arg("7.007",12345));
691  }
692  };
693 
694 
696  LAUNCHER (SchedulerActivity_test, "unit engine");
697 
698 
699 
700 }}} // namespace vault::gear::test
a mutable time value, behaving like a plain number, allowing copy and re-accessing ...
Definition: timevalue.hpp:232
signal start of some processing and transition grooming mode ⟼ *work mode
Definition: activity.hpp:233
Record to describe an Activity, to happen within the Scheduler&#39;s control flow.
Definition: activity.hpp:226
Automatically use custom string conversion in C++ stream output.
Definition: run.hpp:40
Activity & insertActivationTap(Activity *&wiring, string id="")
build ActivationProbe to record each activation before passing it to the subject
correspondingly signal end of some processing
Definition: activity.hpp:234
supply additional payload data for a preceding Activity
Definition: activity.hpp:238
int rani(uint bound=_iBOUND())
Definition: random.hpp:135
activity::Proc activate(Time now, EXE &executionCtx)
Core Operation: Activate and perform this Activity.
Definition: activity.hpp:626
Lumiera&#39;s internal time value datatype.
Definition: timevalue.hpp:299
post a message providing a chain of further time-bound Activities
Definition: activity.hpp:237
Abstract Base Class for all testcases.
Definition: run.hpp:53
Term builder and execution framework to perform chains of scheduler Activities.
ActivityMatch & seq(uint seqNr)
qualifier: additionally require the indicated sequence number
Diagnostic context to record and evaluate activations within the Scheduler.
Simplistic test class runner.
void seedRand()
draw a new random seed from a common nucleus, and re-seed the default-Gen.
Definition: suite.cpp:211
A language framework to define and interconnect scheduler activity verbs.
boost::rational< int64_t > FSecs
rational representation of fractional seconds
Definition: timevalue.hpp:220
A collection of frequently used helper functions to support unit testing.
activity::Proc dispatch(Time now, EXE &executionCtx)
Entrance point for an activation, which has been dispatched indirectly through the dispatch and/or pr...
Definition: activity.hpp:676
uint incrementSeq()
increment the internal invocation sequence number
probe window + count-down; activate next Activity, else re-schedule
Definition: activity.hpp:236
Activity * next
Activities are organised into chains to represent relations based on verbs.
Definition: activity.hpp:249
Diagnostic setup to instrument and observe Activity activations.
internal engine »heart beat« for internal maintenance hook(s)
Definition: activity.hpp:240
dispatch a JobFunctor into a worker thread
Definition: activity.hpp:232
push a message to another Activity
Definition: activity.hpp:235
static const Time NEVER
border condition marker value. NEVER >= any time value
Definition: timevalue.hpp:314
static activity::Proc dispatchChain(Activity *chain, EXE &executionCtx)
Execution Framework: dispatch performance of a chain of Activities.
Individual frame rendering task, forwarding to a closure.
Definition: job.h:268
a family of time value like entities and their relationships.
Front-end for simplified access to the current wall clock time.
ActivityMatch & arg(ARGS const &...args)
qualifier: additionally match the function arguments
Vault-Layer implementation namespace root.