Scheduler: providing the execution-context

The Activity-Language can be defined by abstracting away
some crucial implementation functionality as part of an generic
»ExecutionCtx«, which in the end will be provided by the Scheduler.

But how actually?
We want to avoid unnecessary indirections, and ideally we also want
a concise formulation in-code. Here I'm exploring the idea to let the
scheduler itself provide the ExecutionCtx-operations as member functions,
employing some kind of "compile-time duck-typing"

This seems to work, but breaks the poor-man's preliminary "Concept" check...
This commit is contained in:
Fischlurch 2023-10-21 01:01:00 +02:00
parent 26b2e6f1bd
commit 0d2d8c3413
4 changed files with 184 additions and 9 deletions

View file

@ -604,7 +604,7 @@ namespace gear {
activity::Proc
Activity::activate (Time now, EXE& executionCtx)
{
activity::_verify_usable_as_ExecutionContext<EXE>();
// activity::_verify_usable_as_ExecutionContext<EXE>();
switch (verb_) {
case INVOKE:
@ -651,7 +651,7 @@ namespace gear {
activity::Proc
Activity::dispatch (Time now, EXE& executionCtx)
{
activity::_verify_usable_as_ExecutionContext<EXE>();
// activity::_verify_usable_as_ExecutionContext<EXE>();
switch (verb_) {
case NOTIFY:
@ -681,7 +681,7 @@ namespace gear {
activity::Proc
Activity::notify (Time now, EXE& executionCtx)
{
activity::_verify_usable_as_ExecutionContext<EXE>();
// activity::_verify_usable_as_ExecutionContext<EXE>();
switch (verb_) {
case GATE:

View file

@ -65,8 +65,9 @@ namespace gear {
namespace { // Scheduler default config
const auto IDLE_WAIT = 20ms;
const size_t DISMISS_CYCLES = 100;
const auto IDLE_WAIT = 20ms; ///< sleep-recheck cycle for workers deemed _idle_
const size_t DISMISS_CYCLES = 100; ///< number of wait cycles before an idle worker terminates completely
Offset POLL_WAIT_DELAY{FSecs(1,1000)}; ///< delay until re-evaluating a condition previously found unsatisfied
}
@ -166,9 +167,73 @@ namespace gear {
{
UNIMPLEMENTED("die harder");
}
/** @internal expose a binding for Activity execution */
class ExecutionCtx;
};
/**
* @remark when due, the scheduled Activities are performed within the
* [Activity-Language execution environment](\ref ActivityLang::dispatchChain());
* some aspects of Activity _activation_ however require external functionality,
* which for the purpose of language definition was abstracted as _Execution-context._
* The implementation of these binding functions fills in relevant external effects and
* is in fact supplied by the implementation internals of the scheduler itself.
*/
class Scheduler::ExecutionCtx
: private Scheduler
{
public:
static ExecutionCtx&
from (Scheduler& self)
{
return static_cast<ExecutionCtx&> (self);
}
/* ==== Implementation of the Concept ExecutionCtx ==== */
/** λ-post: */
activity::Proc
post (Time when, Activity& chain, ExecutionCtx& ctx)
{
return layer2_.postDispatch (&chain, when, ctx, layer1_);
}
void
work (Time, size_t)
{
UNIMPLEMENTED ("λ-work");
}
void
done (Time, size_t)
{
UNIMPLEMENTED ("λ-done");
}
activity::Proc
tick (Time)
{
UNIMPLEMENTED ("λ-tick");
}
Offset
getWaitDelay()
{
return POLL_WAIT_DELAY;
}
Time
getSchedTime()
{
UNIMPLEMENTED ("access scheduler Time");
}
};
}} // namespace vault::gear
#endif /*SRC_VAULT_GEAR_SCHEDULER_H_*/

View file

@ -119,7 +119,7 @@ namespace test {
const string CTX_DONE{"CTX-done"};
const string CTX_TICK{"CTX-tick"};
Offset POLL_DELAY{FSecs(1)};
Offset POLL_WAIT_DELAY{FSecs(1)};
Time SCHED_TIME_MARKER{555,5}; ///< marker value for "current scheduler time" used in tests
}
@ -563,7 +563,7 @@ namespace test {
_DiagnosticFun<SIG_done>::Type done;
_DiagnosticFun<SIG_tick>::Type tick;
function<Offset()> getWaitDelay = [] { return POLL_DELAY; };
function<Offset()> getWaitDelay = [] { return POLL_WAIT_DELAY; };
function<Time()> getSchedTime = [this]{ return SCHED_TIME_MARKER;};
FakeExecutionCtx (ActivityDetector& detector)

View file

@ -80285,9 +80285,55 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<node COLOR="#338800" CREATED="1690490297125" ID="ID_1766901032" MODIFIED="1690490313350" TEXT="Vorgriff auf Concepts: Signaturen statisch pr&#xfc;fen">
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#f8f1cb" COLOR="#a50125" CREATED="1697849524591" ID="ID_747589769" MODIFIED="1697849564995" TEXT="statische Pr&#xfc;fung schwierig">
<icon BUILTIN="messagebox_warning"/>
<node CREATED="1697849570913" ID="ID_155562107" MODIFIED="1697849610947" TEXT="ging gut solange ich stets Functor-Objekte verwendet hatte">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
...also solange ich nur mit Unit-Tests gearbeitet habe
</p>
</body>
</html>
</richcontent>
</node>
</node>
</node>
<node COLOR="#338800" CREATED="1690068793535" ID="ID_1906823317" MODIFIED="1697844595733" TEXT="ist tats&#xe4;chlich implementiert durch den Scheduler selber">
<arrowlink COLOR="#e6ffa8" DESTINATION="ID_1020998473" ENDARROW="Default" ENDINCLINATION="-1456;-96;" ID="Arrow_ID_1485027520" STARTARROW="None" STARTINCLINATION="-811;38;"/>
<icon BUILTIN="idea"/>
<node CREATED="1697844218566" ID="ID_290060192" MODIFIED="1697844248833" TEXT="die entscheidenden externen Effekte"/>
<node CREATED="1697844230190" ID="ID_1228967510" MODIFIED="1697844240670" TEXT="(mal abgesehen vom JobFunctor)"/>
<node CREATED="1697844259176" ID="ID_142974884" MODIFIED="1697844537005">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
im Besonderen <b>&#955;-post</b>&#160;ist im Grunde
</p>
<p>
der Scheduler-Service <i>&#252;berhaupt</i>
</p>
</body>
</html>
</richcontent>
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
...n&#228;mlich die F&#228;higkeit, einen Activity-chain zu einem geplanten Zeitpunkt oder auf Signal hin auszuf&#252;hren &#8212; und diese F&#228;higkeit mu&#223; selbstverst&#228;ndlich der Sprache selber zu Gebote stehen, damit sie komplexe Aktionsmuster flexibel ausdr&#252;cken kann
</p>
</body>
</html>
</richcontent>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1690068793535" ID="ID_1906823317" MODIFIED="1692286273670" TEXT="ist implementiert durch die ActivityLang selber">
<icon BUILTIN="flag-yellow"/>
</node>
<node COLOR="#338800" CREATED="1692286145852" ID="ID_596906210" MODIFIED="1692370174170" TEXT="Fake-Setup f&#xfc;r Tests (ActivityDetector)">
<arrowlink COLOR="#433d62" DESTINATION="ID_902152915" ENDARROW="Default" ENDINCLINATION="656;-38;" ID="Arrow_ID_644734597" STARTARROW="None" STARTINCLINATION="1154;77;"/>
@ -81817,6 +81863,67 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</html></richcontent>
</node>
<node CREATED="1697758577471" ID="ID_805214343" MODIFIED="1697758585886" TEXT="dagegen BlockFlow ist eine externe Komponente"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1697844012851" ID="ID_1020998473" MODIFIED="1697844595733" TEXT="Execution-Context tats&#xe4;chlich bereitstellen">
<linktarget COLOR="#e6ffa8" DESTINATION="ID_1020998473" ENDARROW="Default" ENDINCLINATION="-1456;-96;" ID="Arrow_ID_1485027520" SOURCE="ID_1906823317" STARTARROW="None" STARTINCLINATION="-811;38;"/>
<icon BUILTIN="forward"/>
<node CREATED="1697844618383" ID="ID_988917685" MODIFIED="1697844647556" TEXT="f&#xfc;r den Test wurde der stets nur gemockt">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
es gen&#252;gte, an diesen Stellen die Ausf&#252;hrung der abstrahierten Aktionen zu loggen
</p>
</body>
</html>
</richcontent>
</node>
<node CREATED="1697844649091" ID="ID_939726274" MODIFIED="1697844696080" TEXT="als Abstraktion wurde (bewu&#xdf;t) ein Template-Parameter gew&#xe4;hlt"/>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1697844697092" ID="ID_766922475" MODIFIED="1697845768002" TEXT="kokretes Funktions-Binding">
<icon BUILTIN="pencil"/>
<node CREATED="1697844724057" ID="ID_1038347556" MODIFIED="1697844734323" TEXT="wieder ein &#xe4;hnliches Problem wie bei der WorkForce-Config"/>
<node CREATED="1697844740488" ID="ID_1999540950" MODIFIED="1697844761716" TEXT="hier aber einfacher: es wird stets nur eine Referenz ben&#xf6;tigt">
<icon BUILTIN="idea"/>
</node>
<node CREATED="1697844763748" ID="ID_1789360174" MODIFIED="1697845607548">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
&#10233; <i>der Scheduler selber</i>&#160;kann diese Rolle <b>generisch</b>&#160;&#252;bernehmen
</p>
</body>
</html>
</richcontent>
</node>
<node CREATED="1697845608675" ID="ID_610860781" MODIFIED="1697845760326" TEXT="noch sauberer: ein Sub-Interface-Mapping">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<ul>
<li>
eine Subklasse, die aber <b>private</b>&#160;vom Scheduler erbt
</li>
<li>
sie bietet selber eine Downcast-Accessor-Funktion
</li>
<li>
eigene Datenfelder sind nicht erlaubt (Slicing)
</li>
<li>
aber beliebige Member-Funktionen, die sich frei aus dem (protected)-Scope des Schedulers bedienen k&#246;nnen
</li>
</ul>
</body>
</html></richcontent>
</node>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1697763699242" ID="ID_272943268" MODIFIED="1697763810547" TEXT="EngineObserver-Schnittstelle">
<arrowlink COLOR="#4f3156" DESTINATION="ID_1642973256" ENDARROW="Default" ENDINCLINATION="-628;-472;" ID="Arrow_ID_1213898118" STARTARROW="None" STARTINCLINATION="-1771;162;"/>
@ -86787,6 +86894,9 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<node CREATED="1697758391611" ID="ID_124711923" MODIFIED="1697758397083" TEXT="F&#xe4;lle">
<node CREATED="1697758425500" ID="ID_1450418166" MODIFIED="1697758430911" TEXT="simpleUsage">
<node CREATED="1697758440737" ID="ID_1211803424" MODIFIED="1697758454084" TEXT="zeigt hier vor allem was man braucht"/>
<node COLOR="#338800" CREATED="1697842432420" ID="ID_1052962927" MODIFIED="1697842447753" TEXT="Scheduler l&#xe4;&#xdf;t sich instantiieren">
<icon BUILTIN="button_ok"/>
</node>
</node>
</node>
</node>