Engine: draft a messaging interface for EngineObserver (see #1347)

For now, the `EngineObserver` is defined as an empty shell,
outfitted with a low-level binary message dispatch API.

Messages are keyed by a Symbol, which allows evolution of private message types.
Routing and Addressing is governed by an opaque size_t hash.
The `EngineEvent` data base class provides »4 Slots« of inline binary storage;
concrete subclasses shall define the mapping of actual data into this space
and provide a convenience constructor for events.

For use by the Scheduler, a `WorkTiming`-Event is defined based on this scheme;
this allows to implement the λ-work and λ-done of the Scheduler-`ExecutionCtx`.
These hooks will be invoked at begin and end of any render calculations.
This commit is contained in:
Fischlurch 2023-11-08 03:40:05 +01:00
parent 892099412c
commit 449b5c8f50
4 changed files with 268 additions and 18 deletions

View file

@ -32,11 +32,14 @@
#include "vault/gear/activity-lang.hpp"
#include "lib/format-obj.hpp"
#include "lib/symbol.hpp"
#include "vault/gear/scheduler.hpp"//////////////////////////////////////////////////////////////TODO extract -> scheduler.cpp
#include <string>
#include <boost/functional/hash.hpp> ////////////////////////////////////////////////////////////TODO should be in a scheduler translation-unit / extract scheduler-API
using std::string;
using lib::Symbol;
using lib::time::Time;
using lib::time::TimeValue;
@ -52,6 +55,10 @@ namespace gear {
{
return boost::hash_value (uint32_t{id});
}
Symbol WorkTiming::WORKSTART{"WorkStart"};
Symbol WorkTiming::WORKSTOP {"WorkStop"};
///////////////////////////////////////////////////////////////////////////////////////////////TODO extract scheduler-API

View file

@ -32,6 +32,7 @@
** @see Activity::Verb::WORKSTART
**
** @todo WIP-WIP-WIP 10/2023 »Playback Vertical Slice« created as a stub
** @todo design and implement the EngineObserver as publisher-subscriber... ////////////////////////////////TICKET #1347 : design EngineObserver
**
*/
@ -44,23 +45,78 @@
#include "vault/gear/block-flow.hpp"
#include "vault/gear/scheduler-commutator.hpp"
#include "vault/gear/scheduler-invocation.hpp"
//#include "lib/symbol.hpp"
#include "lib/symbol.hpp"
#include "lib/nocopy.hpp"
//#include "lib/util.hpp"
//#include <string>
#include <utility>
#include <array>
namespace vault{
namespace gear {
using lib::Symbol;
// using util::isnil;
// using std::string;
using std::move;
/**
* Low-level Render Engine event abstracted storage base.
*/
class EngineEvent
{
protected:
static size_t constexpr RAW_SIZ = 3;
using Storage = std::array<int64_t, RAW_SIZ>;
template<class DAT>
union Payload
{
static_assert (sizeof(DAT) <= RAW_SIZ * sizeof(int64_t));
Storage raw;
DAT data;
Payload() : raw{0} { }
Payload (DAT const& d) : data{d} { }
Payload (DAT && dr) : data{move(dr)} { }
// default copy and assignment acceptable
DAT const& operator= (DAT const& d) { data = d; return data; }
DAT const& operator= (DAT && dr) { data = move(dr); return data; }
operator Storage&() { return raw; }
operator Storage&&() { return move(raw); }
};
/** base init for derived classes to implant custom payload */
EngineEvent (Symbol msgID, Storage&& payload)
: message{msgID}
, storage_{move (payload)}
{ }
public:
EngineEvent()
: message{Symbol::BOTTOM}
, storage_{0}
{ }
// default copy and assignment acceptable
Symbol message;
private:
Storage storage_;
};
/**
* Collector and aggregator for performance data.
* @todo WIP-WIP 10/2023 - stub as placeholder for later development
* @todo WIP-WIP 10/2023 - stub as placeholder for later development ////////////////////////////////////TICKET #1347 : design EngineObserver
* @see Scheduler
*/
class EngineObserver
@ -71,6 +127,12 @@ namespace gear {
explicit
EngineObserver()
{ }
void
dispatchEvent (size_t /*address*/, EngineEvent /*event*/)
{
/* TICKET #1347 actually move this event into a dispatcher queue */
}
};

View file

@ -94,7 +94,7 @@
** @see SchedulerCommutator Layer-2
** @see activity.hpp description of »Render Activities«
**
** @todo WIP-WIP 10/2023 »Playback Vertical Slice«
** @todo WIP 11/2023 »Playback Vertical Slice«
**
*/
@ -196,7 +196,7 @@ namespace gear {
/******************************************************//**
* »Scheduler-Service« : coordinate render activities.
* @todo WIP-WIP 10/2023
* @todo WIP 11/2023
* @see BlockFlow
* @see SchedulerUsage_test
*/
@ -387,6 +387,21 @@ namespace gear {
/** work-timing event for performance observation */
class WorkTiming
: public EngineEvent
{
using Payload = EngineEvent::Payload<Time>;
using EngineEvent::EngineEvent;
static Symbol WORKSTART;
static Symbol WORKSTOP;
public:
static WorkTiming start (Time now) { return WorkTiming{WORKSTART, Payload{now}}; }
static WorkTiming stop (Time now) { return WorkTiming{WORKSTOP, Payload{now}}; }
};
/**
* @remark when due, the scheduled Activities are performed within the
* [Activity-Language execution environment](\ref ActivityLang::dispatchChain());
@ -431,16 +446,24 @@ namespace gear {
return scheduler_.layer2_.postDispatch (chainEvent, subCtx, scheduler_.layer1_);
}
/**
* λ-work : transition Managment-Mode -> Work-Mode
* - drop the Grooming-Token (allow concurrent execution from now on)
* - signal start time of actual processing
* @warning current thread is expected to hold the Grooming-Token
*/
void
work (Time, size_t)
work (Time now, size_t qualifier)
{
UNIMPLEMENTED ("λ-work");
scheduler_.layer2_.dropGroomingToken();
scheduler_.engineObserver_.dispatchEvent(qualifier, WorkTiming::start(now));
}
/** λ-done : signal end time of actual processing */
void
done (Time, size_t)
done (Time now, size_t qualifier)
{
UNIMPLEMENTED ("λ-done");
scheduler_.engineObserver_.dispatchEvent(qualifier, WorkTiming::stop(now));
}
activity::Proc

View file

@ -83075,32 +83075,77 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<arrowlink COLOR="#373a76" DESTINATION="ID_1435123962" ENDARROW="Default" ENDINCLINATION="304;54;" ID="Arrow_ID_928822414" STARTARROW="None" STARTINCLINATION="-255;13;"/>
<icon BUILTIN="button_ok"/>
</node>
<node CREATED="1699401804396" ID="ID_1620543415" MODIFIED="1699402101803" TEXT="tendiere dazu, dieses Problem &#x201e;unter den Teppich zu kehren&#x201c;">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
Warum?
</p>
<ul>
<li>
wie gesagt, im normalen Betrieb wird nebenbei die Eingangsqueue mit bedient
</li>
<li>
wenn man den Scheduler neu startet, l&#228;uft gleich einmal der &#187;Tick&#171; und bedient ebenfalls diese Queue
</li>
<li>
das Problem tritt also nur auf, wenn der Scheduler schon l&#228;uft, aber grade idle f&#228;llt
</li>
<li>
und auch nur dann, wenn man neue Tasks von au&#223;en einstellt, nicht aus einem Management-Job
</li>
</ul>
<p>
Und &#8212; <i>last but not least </i>&#8212; die L&#246;sung ist h&#228;sslich und redundant: man m&#252;&#223;te das in die work-Function ganz am Anfang reinh&#228;ngen. Oder zumindest in die Kapazit&#228;ts-Behandlung (im 1. und 3.Block)
</p>
</body>
</html>
</richcontent>
</node>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1697763699242" ID="ID_272943268" MODIFIED="1697763810547" TEXT="EngineObserver-Schnittstelle">
</node>
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1697763699242" ID="ID_272943268" MODIFIED="1699414198627" TEXT="EngineObserver-Schnittstelle">
<arrowlink COLOR="#4f3156" DESTINATION="ID_1642973256" ENDARROW="Default" ENDINCLINATION="-628;-472;" ID="Arrow_ID_1213898118" STARTARROW="None" STARTINCLINATION="-1771;162;"/>
<icon BUILTIN="flag-yellow"/>
<icon BUILTIN="hourglass"/>
<icon BUILTIN="button_ok"/>
<node CREATED="1697763821714" ID="ID_1158248288" MODIFIED="1697763853485" TEXT="vorerst nur eine Senke f&#xfc;r die WORKSTART|STOP-Activities">
<icon BUILTIN="yes"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1698372056954" ID="ID_70592894" MODIFIED="1698372163476" TEXT="&#x3bb;-work einbinden">
<icon BUILTIN="flag-yellow"/>
<node COLOR="#338800" CREATED="1698372056954" ID="ID_70592894" MODIFIED="1699413916193" TEXT="&#x3bb;-work einbinden">
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1698372095829" ID="ID_259045952" MODIFIED="1698372163476" TEXT="&#x3bb;-done einbinden">
<icon BUILTIN="flag-yellow"/>
<node COLOR="#338800" CREATED="1698372095829" ID="ID_259045952" MODIFIED="1699413919539" TEXT="&#x3bb;-done einbinden">
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1698533894187" ID="ID_1515660165" MODIFIED="1698534658603" TEXT="Mediator / Listener f&#xfc;r Betriebszust&#xe4;nde">
<linktarget COLOR="#ea5540" DESTINATION="ID_1515660165" ENDARROW="Default" ENDINCLINATION="-1517;105;" ID="Arrow_ID_1696922321" SOURCE="ID_1227874220" STARTARROW="None" STARTINCLINATION="912;-77;"/>
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#ccb59b" COLOR="#6e2a38" CREATED="1698534009356" ID="ID_538756893" MODIFIED="1698534407291" TEXT="Notwendigkeit zeichnet sich nun klar ab">
<node BACKGROUND_COLOR="#ccb59b" COLOR="#6e2a38" CREATED="1698534009356" ID="ID_538756893" MODIFIED="1699402223566" TEXT="Notwendigkeit zeichnet sich nun klar ab">
<richcontent TYPE="NOTE"><html>
</head>
<head/>
<body>
<p>
Habe einige Zeit gez&#246;gert, aber nun werden die Verkn&#252;pfungen definitiv zu vielf&#228;ltig. Also stellt der EngineObserver so etwas wie einen &#187;R&#252;ck-Kanal&#171; bereit. Leider stellen sich hiermit erneut die gesamten (hinl&#228;nglich bekannten) Probleme bez&#252;glich der Dom&#228;ne eine Benachrichtigungs-Systems. Zu welchem Grad legt das System die Kommunikation fest? Wie offen oder verbindlich sind die Teilnehmer? Wie stark vorherbestimmt sind die Nachrichten-Inhalte? Wieviel Payload ist notwendig?
Habe einige Zeit gez&#246;gert, aber nun werden die Verkn&#252;pfungen definitiv zu vielf&#228;ltig. Also stellt der EngineObserver so etwas wie einen &#187;R&#252;ck-Kanal&#171; bereit. Leider stellen sich hiermit erneut die gesamten (hinl&#228;nglich bekannten) Probleme bez&#252;glich der Dom&#228;ne eines Benachrichtigungs-Systems....
</p>
<ul>
<li>
Zu welchem Grad legt das System die Kommunikation fest?
</li>
<li>
Wie offen oder verbindlich ist der Kreis der Teilnehmer?
</li>
<li>
Wie stark vorherbestimmt sind die Nachrichten-Inhalte?
</li>
<li>
Wieviel Payload ist notwendig?
</li>
</ul>
</body>
</html></richcontent>
<font ITALIC="true" NAME="SansSerif" SIZE="14"/>
@ -83112,6 +83157,12 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<node CREATED="1698544770139" ID="ID_1280127725" MODIFIED="1698544795910" TEXT="k&#xf6;nnte asynchron und demand-driven arbeiten">
<linktarget COLOR="#fefdd9" DESTINATION="ID_1280127725" ENDARROW="Default" ENDINCLINATION="-176;11;" ID="Arrow_ID_187765169" SOURCE="ID_422887207" STARTARROW="None" STARTINCLINATION="-154;-113;"/>
</node>
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1699409794378" ID="ID_1067453951" LINK="#ID_1522099049" MODIFIED="1699409857480" TEXT="#1347 EngineObserver">
<icon BUILTIN="hourglass"/>
</node>
</node>
<node COLOR="#338800" CREATED="1699413952330" ID="ID_518717295" LINK="#ID_1307699016" MODIFIED="1699413989310" TEXT="Entwurf f&#xfc;r das Event-publish-API">
<icon BUILTIN="button_ok"/>
</node>
</node>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1697663918107" ID="ID_210862409" MODIFIED="1697675123151" TEXT="Load-Controller vorsehen">
@ -94866,6 +94917,113 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<icon BUILTIN="idea"/>
</node>
</node>
<node CREATED="1699403193710" ID="ID_1522099049" MODIFIED="1699403198814" TEXT="Design-Skizze">
<node CREATED="1699403199826" ID="ID_1873444035" MODIFIED="1699403208767" TEXT="asyncrhones Messaging"/>
<node CREATED="1699403217120" ID="ID_120723001" MODIFIED="1699403224072" TEXT="eine Eingangs-Dispatch-Queue"/>
<node CREATED="1699403254867" ID="ID_1562054545" MODIFIED="1699403320882" TEXT="Einspeisen von Nachrichten sehr effizient">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
Aufruf&#160;&#160;aus der Berechnung heraus m&#246;glich, d.h. darf h&#246;chstens ein paar &#181;s kosten
</p>
</body>
</html>
</richcontent>
</node>
<node CREATED="1699403383634" ID="ID_72666374" MODIFIED="1699403396396" TEXT="Addresse ist codiert in einen size_t - Hash">
<node CREATED="1699404688180" ID="ID_1754251698" MODIFIED="1699404705526" TEXT="sie repr&#xe4;sentiert einen symbolischen, hierarchischen Endpunkt"/>
<node CREATED="1699404706420" ID="ID_1195678814" MODIFIED="1699404726595" TEXT="plus eine Instanz-Nummer"/>
</node>
<node CREATED="1699404817133" ID="ID_1983952210" MODIFIED="1699404888413" TEXT="Jeder Endpunkt steht f&#xfc;r einen Topic-Publisher">
<node CREATED="1699404897438" ID="ID_1350627589" MODIFIED="1699404910213" TEXT="der Empf&#xe4;nger registriert sich an diesem aber mit einem Funktor"/>
<node CREATED="1699404999507" ID="ID_1908588492" MODIFIED="1699405014485" TEXT="die Instanz-Nummer kann optional in Insanzen dieses Funktors umgesetzt werden"/>
<node CREATED="1699405021926" ID="ID_90980190" MODIFIED="1699405045470" TEXT="es k&#xf6;nnen sich mehrere Empf&#xe4;nger registrieren/derigistrieren (Subscriber-Pattern)"/>
</node>
<node CREATED="1699405149557" ID="ID_1423036678" MODIFIED="1699405164251">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
Empfang/Zustellung laufen <b>single-Threaded</b>
</p>
</body>
</html>
</richcontent>
<node CREATED="1699405165067" ID="ID_229778014" MODIFIED="1699405192201" TEXT="k&#xf6;nnte implementiert sein als ein separater Event-Thread"/>
<node CREATED="1699405193033" ID="ID_1200939317" MODIFIED="1699405209359" TEXT="Alternativ: l&#xe4;uft unter GroomingToken im Scheduler-&#xbb;Tick&#xab;"/>
</node>
<node CREATED="1699405342581" ID="ID_1835834856" MODIFIED="1699405366988" TEXT="die Instanzen....">
<node CREATED="1699405367834" ID="ID_1953811997" MODIFIED="1699405371486" TEXT="sind beliebige Typen"/>
<node CREATED="1699405372065" ID="ID_1589785923" MODIFIED="1699405379612" TEXT="werden vom EngineObserver gemanaged"/>
<node CREATED="1699405382096" ID="ID_1080836669" MODIFIED="1699405396434" TEXT="und k&#xf6;nnen &#xfc;ber die Addressierung in eine Language-Referenz &#xfc;bersetzt werden"/>
<node CREATED="1699405405867" ID="ID_1288409697" MODIFIED="1699405457592" TEXT="Konsequenz: man kann Instanzen effizient ansprechen und dar&#xfc;ber streng typisiert aufrufen"/>
<node CREATED="1699405564607" ID="ID_561422739" MODIFIED="1699405582821" TEXT="&#x27f9; Br&#xfc;cke zwischen &#xbb;Funktor&#xab; und Member-Funktion">
<node CREATED="1699405616896" ID="ID_850366101" MODIFIED="1699405632436" TEXT="Routing via Address-Hashtable"/>
<node CREATED="1699405633054" ID="ID_1875469962" MODIFIED="1699405680754" TEXT="Registrierung mit RTTI-Match und einem indirekten Dispatch"/>
</node>
</node>
<node CREATED="1699405707070" ID="ID_1718899201" MODIFIED="1699405742710">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
<u>Leitbild</u>:&#160;<font face="Monospaced">TimingObservable</font>
</p>
</body>
</html>
</richcontent>
<icon BUILTIN="info"/>
</node>
</node>
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1699409794378" ID="ID_1622814864" MODIFIED="1699409805609" TEXT="#1347 EngineObserver">
<icon BUILTIN="hourglass"/>
</node>
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1699414012828" ID="ID_1909389454" MODIFIED="1699414023170" TEXT="Datenstrukturen anlegen">
<icon BUILTIN="hourglass"/>
<icon BUILTIN="button_ok"/>
<node COLOR="#435e98" CREATED="1699413973971" ID="ID_1307699016" MODIFIED="1699414043369">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
<b>EngineEvent</b>-Basisstruktur
</p>
</body>
</html>
</richcontent>
<icon BUILTIN="info"/>
<node CREATED="1699414045739" ID="ID_3506591" MODIFIED="1699414061765" TEXT="Symbol + bin&#xe4;re opaque Payload"/>
<node CREATED="1699414063936" ID="ID_1879697605" MODIFIED="1699414079359" TEXT="f&#xfc;r Payload einen Union-cast-Mechanismus vorsehen"/>
<node CREATED="1699414084173" ID="ID_701544569" MODIFIED="1699414099911" TEXT="man definiert f&#xfc;r konkrete Events eine Subklasse">
<icon BUILTIN="idea"/>
<node CREATED="1699414102000" ID="ID_928476961" MODIFIED="1699414117317" TEXT="diese spezialisiert das Template Payload&lt;T&gt;"/>
<node CREATED="1699414118433" ID="ID_639697248" MODIFIED="1699414141250" TEXT="T ist ein Tupel / Record mit den zu publizierenden Daten"/>
<node CREATED="1699414142638" ID="ID_529883499" MODIFIED="1699414172640">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
<u>Gr&#246;&#223;enbeschr&#228;nkung</u>: <b>4 &#187;Slots&#171;</b>
</p>
</body>
</html>
</richcontent>
<icon BUILTIN="yes"/>
</node>
</node>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1689468998095" ID="ID_32989316" MODIFIED="1689469005279" TEXT="Selbstregulierung">
<icon BUILTIN="hourglass"/>