Scheduler: solve the initialisation of WorkForce

Notably I wanted an entirely static and direct binding
to the internals of the Scheduler, which can be completely inlined.
The chosen solution also has the benefit of making the back-reference
to the Scheduler explicitly visible to the reader. This is relevant,
since the Config-Subobject is *copied* into each Worker instance.
This commit is contained in:
Fischlurch 2023-10-20 18:24:50 +02:00
parent 74c97614b3
commit 26b2e6f1bd
3 changed files with 108 additions and 22 deletions

View file

@ -63,9 +63,17 @@ namespace gear {
// using util::isnil;
// using std::string;
namespace { // Scheduler default config
const auto IDLE_WAIT = 20ms;
const size_t DISMISS_CYCLES = 100;
}
/**
* Schedule and coordinate render activities.
/******************************************************//**
* »Scheduler-Service« : coordinate render activities.
* @todo WIP-WIP 6/2023
* @see BlockFlow
* @see SchedulerUsage_test
@ -73,23 +81,30 @@ namespace gear {
class Scheduler
: util::NonCopyable
{
using Setup = work::Config; ////////////////////////////////////////////////////OOO actually need subclass to attach the work-function
/** Binding of worker callbacks to the scheduler implementation */
struct Setup : work::Config
{
Scheduler& scheduler;
activity::Proc doWork() { return scheduler.getWork(); }
void finalHook (bool _) { scheduler.handleWorkerTermination(_);}
};
SchedulerInvocation layer1_;
SchedulerCommutator layer2_;
// WorkForce<Setup> workForce_;
WorkForce<Setup> workForce_;
ActivityLang activityLang_;
LoadController loadControl_;
EngineObserver& engineObserver_;
public:
explicit
Scheduler (BlockFlowAlloc& activityAllocator
,EngineObserver& engineObserver)
: layer1_{}
, layer2_{}
// , workForce_{connectWorkers()}
, workForce_{Setup{IDLE_WAIT, DISMISS_CYCLES, *this}}
, activityLang_{activityAllocator}
, loadControl_{activityAllocator}
, engineObserver_{engineObserver}
@ -139,17 +154,17 @@ namespace gear {
/**
*
*/
void
activity::Proc
getWork()
{
UNIMPLEMENTED("the Worker-Funkction");
}
private:
Setup
connectWorkers()
void
handleWorkerTermination (bool isFailure)
{
UNIMPLEMENTED("build Worker pool operational setup");
UNIMPLEMENTED("die harder");
}
};

View file

@ -72,12 +72,12 @@ namespace gear {
using std::move;
using std::atomic;
using util::unConst;
using std::chrono::milliseconds;
using std::chrono_literals::operator ""ms;
using std::this_thread::sleep_for;
namespace work { ///< Details of WorkForce (worker pool) implementation
using std::chrono::milliseconds;
using std::chrono_literals::operator ""ms;
using SIG_WorkFun = activity::Proc(void); ///< config should define a callable with this signature to perform work
using SIG_FinalHook = void(bool); ///< config should define callable invoked at exit (argument: isFailure)
@ -94,7 +94,6 @@ namespace gear {
struct Config
{
static const size_t COMPUTATION_CAPACITY;
const size_t EXPECTED_MAX_POOL = 1.5*COMPUTATION_CAPACITY;
const milliseconds IDLE_WAIT = 20ms;
const size_t DISMISS_CYCLES = 100;

View file

@ -81765,15 +81765,44 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1693172098402" ID="ID_671792975" MODIFIED="1697553002393" TEXT="Dependency-Injection">
<icon BUILTIN="help"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1693841227130" ID="ID_1537960830" MODIFIED="1697675265270" TEXT="WorkForce einbinden">
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1693841227130" ID="ID_1537960830" MODIFIED="1697818566052" TEXT="WorkForce einbinden">
<arrowlink COLOR="#397cb2" DESTINATION="ID_987966047" ENDARROW="Default" ENDINCLINATION="-962;-41;" ID="Arrow_ID_818972822" STARTARROW="None" STARTINCLINATION="-609;73;"/>
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1697768180196" ID="ID_1541537637" MODIFIED="1697768202330" TEXT="work::Config konstruieren">
<icon BUILTIN="flag-yellow"/>
<icon BUILTIN="pencil"/>
<node BACKGROUND_COLOR="#c8c0b6" COLOR="#435e98" CREATED="1697768180196" ID="ID_1541537637" MODIFIED="1697818152259" TEXT="work::Config konstruieren">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
Schwere Geburt...
</p>
<p>
Irgendwie hatte sich bei mir die Idee mit den Lambdas so festgefressen &#8212; obwohl ich doch schon eingesehen hatte, da&#223; C++ in der Hinsicht (aus gutem Grund) sehr konsequent ist, und keine Hintert&#252;r bietet, um Laufzeit-Bindigns in die statische Ebene &#8222;zu schmuggeln&#8220;. Was mich dann aber auch extrem gest&#246;rt hat, waren die std::function-Felder, in die man die Lambdas speichern m&#252;&#223;te. Es w&#228;re n&#228;mlich eine andere L&#246;sung denkbar, bei der diese Function-Objekte schon in der Basis-Config f&#252;r die WorkForce enthalten sind; damit w&#228;re das Design auch komplett festgelgt (und der Test w&#252;rde sogar einfacher). Trotzdem habe ich eine Abneigung gegen diese Function-Objekte, weil sie eben komplett unn&#246;tig sind, da es sich effektiv um ein <i>statisches Binding </i>handeln sollte. Und das war dann das rettende Stichwort: dann definiert man eben diese Binding-Forwarder als statische Funktionen in einer nested Class, und macht die R&#252;ckreferenz auf den Scheduler explizit. Und mit Aggregat-Initialisierung kann man dann sogar noch die Definition des Konstruktors auslassen
</p>
</body>
</html></richcontent>
<arrowlink COLOR="#f3fea4" DESTINATION="ID_983915877" ENDARROW="Default" ENDINCLINATION="1743;-58;" ID="Arrow_ID_529465664" STARTARROW="None" STARTINCLINATION="822;78;"/>
<icon BUILTIN="smiley-angry"/>
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1697810722994" HGAP="47" ID="ID_720864528" MODIFIED="1697810766219" TEXT="sp&#xe4;ter wird hier eine globale Engine-Parametrisierung einflie&#xdf;en" VSHIFT="-6">
<edge COLOR="#ffdaa4"/>
<icon BUILTIN="hourglass"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1697768205409" ID="ID_489957180" MODIFIED="1697768215224" TEXT="mit dem Load-Controller verbinden">
<icon BUILTIN="flag-yellow"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1697808041495" ID="ID_492054934" MODIFIED="1697808055694" TEXT="mit der Work-Function abstimmen">
<icon BUILTIN="flag-yellow"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1697808056565" ID="ID_10043675" MODIFIED="1697808062704" TEXT="Fehlerbehandlung bedenken">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#f8f1cb" COLOR="#a50125" CREATED="1697808069219" ID="ID_1793076416" MODIFIED="1697808179770" TEXT="Grooming-Token garantiert freigeben">
<arrowlink COLOR="#fe3a8d" DESTINATION="ID_240227471" ENDARROW="Default" ENDINCLINATION="1819;-50;" ID="Arrow_ID_1740525983" STARTARROW="None" STARTINCLINATION="221;16;"/>
<icon BUILTIN="messagebox_warning"/>
</node>
<node BACKGROUND_COLOR="#d2beaf" COLOR="#6920c0" CREATED="1697808219247" ID="ID_1041283707" MODIFIED="1697808253529" TEXT="ungekl&#xe4;rt: HALT an einzelne Worker?">
<icon BUILTIN="bell"/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1697675135117" ID="ID_880133050" MODIFIED="1697675148836" TEXT="ActivityLang + BlockFlow">
<icon BUILTIN="flag-yellow"/>
@ -81799,6 +81828,19 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1697663918107" ID="ID_210862409" MODIFIED="1697675123151" TEXT="Load-Controller vorsehen">
<linktarget COLOR="#75769b" DESTINATION="ID_210862409" ENDARROW="Default" ENDINCLINATION="-667;72;" ID="Arrow_ID_1800712901" SOURCE="ID_464175339" STARTARROW="None" STARTINCLINATION="-540;37;"/>
<icon BUILTIN="flag-pink"/>
<node BACKGROUND_COLOR="#f8f1cb" COLOR="#a50125" CREATED="1697808322602" ID="ID_1787549088" MODIFIED="1697808340997" TEXT="Entwickelt sich wohl in Richtung einer Steuerzentrale">
<icon BUILTIN="messagebox_warning"/>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1697808351773" ID="ID_1501083047" MODIFIED="1697808428660" TEXT="Leistungen">
<icon BUILTIN="info"/>
<icon BUILTIN="pencil"/>
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1697808357389" ID="ID_1714344789" MODIFIED="1697808392696" TEXT="Signal-fusion in gemeinsamen Load-Indikator">
<icon BUILTIN="bell"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1697808402431" ID="ID_1499932709" MODIFIED="1697808419725" TEXT="beobachtet / wei&#xdf; von der WorkForce-St&#xe4;rke">
<icon BUILTIN="flag-yellow"/>
</node>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#c8c0b6" COLOR="#435e98" CREATED="1693172069235" ID="ID_1573845677" MODIFIED="1697675305351" TEXT="Layer-1: SchedulerInvocation"/>
@ -84509,7 +84551,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<node CREATED="1693792157926" ID="ID_429801566" MODIFIED="1693792193345" TEXT="komplett heruntergeregelt &#x27f9; Render-Engine deaktiviert"/>
<node CREATED="1693792250942" ID="ID_1000686206" MODIFIED="1693792285653" TEXT="Obergrenze &#x2259; Hardware-concurrency * Provisionierungs-Faktor"/>
<node CREATED="1693792308542" ID="ID_1678880734" MODIFIED="1693792318777" TEXT="Herunterregeln erfolgt kooperativ"/>
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1693792585515" FOLDED="true" ID="ID_464175339" MODIFIED="1693792605896" TEXT="geplant: dynamische Kapazit&#xe4;tsregelung">
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1693792585515" FOLDED="true" ID="ID_464175339" MODIFIED="1697806953842" TEXT="geplant: dynamische Kapazit&#xe4;tsregelung">
<arrowlink COLOR="#75769b" DESTINATION="ID_210862409" ENDARROW="Default" ENDINCLINATION="-667;72;" ID="Arrow_ID_1800712901" STARTARROW="None" STARTINCLINATION="-540;37;"/>
<icon BUILTIN="hourglass"/>
<node CREATED="1693792629986" ID="ID_1269240792" MODIFIED="1693792648043" TEXT="nur mindest-St&#xe4;rke l&#xe4;uft"/>
@ -84520,10 +84562,21 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<node CREATED="1693792715966" ID="ID_717442289" MODIFIED="1697663859531" TEXT="die &quot;pull-work&quot;-Funkton wird vom Scheduler-Service bereitgestellt"/>
<node CREATED="1697663861416" ID="ID_558783590" MODIFIED="1697663878469" TEXT="...ist aber implementiert mit Funktionalit&#xe4;t von Layer-2"/>
<node CREATED="1693792744114" ID="ID_1037530409" MODIFIED="1693792754452" TEXT="die Schlaf-Periode ist ein (steuer)-Parameter"/>
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1693792760213" FOLDED="true" ID="ID_1223151647" MODIFIED="1694304517016" TEXT="ggfs leicht randomisiert">
<icon BUILTIN="hourglass"/>
<node COLOR="#5b280f" CREATED="1693792760213" ID="ID_1223151647" MODIFIED="1697810671367" TEXT="ggfs leicht randomisiert">
<icon BUILTIN="button_cancel"/>
<node CREATED="1693792791729" ID="ID_649360495" MODIFIED="1693792804966" TEXT="Einsch&#xe4;tzung: das gen&#xfc;gt um Contention zu vermeiden"/>
<node CREATED="1693792900758" ID="ID_1613781033" MODIFIED="1693792927222" TEXT="Vorraussetzung: Arbeitsphase &gt;&gt; Management-Phase"/>
<node CREATED="1697810446431" ID="ID_1168022862" MODIFIED="1697810667289" TEXT="sollte sogar ohne Randomisierung keine Probleme geben">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
Denn jeder Aufruf des Fork-Funktors wird unterschiedlich lang dauern. Und selbst wenn alle Worker idle sind: dann gibt es bei der ersten Runde die Mega-Contention, und danach liegen die Wartezyklen aller Worker leicht gestaffelt. Contention w&#228;re nur dann ein Problem, wenn jemand, der <i>arbeiten k&#246;nnte, </i>vom Arbeiten abgehalten wird.
</p>
</body>
</html></richcontent>
</node>
<node CREATED="1697810678448" ID="ID_1023870178" MODIFIED="1697810695263" TEXT="daher ist IDLE_WAIT nun ein beim Start festgelegter Konfig-Parameter"/>
</node>
</node>
</node>
@ -84666,7 +84719,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</body>
</html></richcontent>
</node>
<node CREATED="1694130437980" ID="ID_1626878133" MODIFIED="1694130721769" TEXT="die Code-Organisation spricht f&#xfc;r den Scheduler-Layer-2">
<node COLOR="#344951" CREATED="1694130437980" ID="ID_1626878133" MODIFIED="1697807837200" TEXT="die Code-Organisation spricht f&#xfc;r den Scheduler-Layer-2">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
@ -84675,6 +84728,23 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</p>
</body>
</html></richcontent>
<node BACKGROUND_COLOR="#c8c0b6" CREATED="1697807481495" ID="ID_1248086116" MODIFIED="1697807804662" TEXT="das hat sich durch die Implementierung etwas relativiert">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
...wie so oft, vor allem getrieben durch die Tests: die Layer wurden zu einer Sammlung von Implementierungs-Bausteienen, welche auch aufeinander aufbauen. Aber die <i>gro&#223;e Verdrahtung </i>habe ich noch vor mir hergeschoben &#8212; sogar so weit, da&#223; Layer-2 selbst keine Referenz auf Layer-1 besitzt (sondern diese f&#252;r jede Funktion hereingereicht bekommt). Damit wird die Verdrahtung nun sternf&#246;rmig, und der Binde-Code ist das, was den &#187;Scheduler-Service&#171; ausmacht
</p>
</body>
</html></richcontent>
<icon BUILTIN="licq"/>
</node>
<node CREATED="1697807495135" ID="ID_1789450412" MODIFIED="1697807816218" TEXT="Thema &#xbb;Binding und Zusammenarbeit&#xab; ist nun Sache des Scheduler-Service">
<icon BUILTIN="yes"/>
</node>
<node COLOR="#525b6f" CREATED="1697807963209" ID="ID_301601079" MODIFIED="1697808004356" TEXT="und: WorkForce selber wird vom Scheduler betrieben und ist eng verdrahtet">
<icon BUILTIN="idea"/>
</node>
</node>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1694130760121" ID="ID_661270953" MODIFIED="1694130794493" TEXT="das Shutdown- und Destruktor-Verhalten ist aber ein Problem f&#xfc;r sich">
<icon BUILTIN="messagebox_warning"/>
@ -84741,6 +84811,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1694016294919" ID="ID_240227471" MODIFIED="1694016354350" TEXT="konkrete Impl mu&#xdf; Grooming-Token freigeben (sonst Deadlock m&#xf6;glich)">
<arrowlink COLOR="#88617a" DESTINATION="ID_688462252" ENDARROW="Default" ENDINCLINATION="118;-18;" ID="Arrow_ID_953966962" STARTARROW="None" STARTINCLINATION="-312;13;"/>
<linktarget COLOR="#fe3a8d" DESTINATION="ID_240227471" ENDARROW="Default" ENDINCLINATION="1819;-50;" ID="Arrow_ID_1740525983" SOURCE="ID_1793076416" STARTARROW="None" STARTINCLINATION="221;16;"/>
<icon BUILTIN="flag-yellow"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1694016398145" ID="ID_1137833465" MODIFIED="1694016416375" TEXT="dar&#xfc;ber k&#xf6;nnen auch fatale Fehler kommuniziert werden">
@ -84819,10 +84890,11 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<head/>
<body>
<p>
C++ zwingt uns dazu, explizit das zu tun was ohnehin getan werden mu&#223;; da jedoch der <i>Typ </i>der Config per Template-Parameter gew&#228;hlt wird, ist komplettes Inlining m&#246;glich; letztlich wird daher nur ein Pointer auf das Scheduler-Objekt in alle Threads kopiert &#8212; <i>exakt das</i>&#160; was wir brauchen
C++ zwingt uns dazu, explizit das zu tun was ohnehin getan werden mu&#223;; da jedoch der <i>Typ </i>der Config per Template-Parameter gew&#228;hlt wird, ist komplettes Inlining m&#246;glich; letztlich wird daher nur ein Pointer auf das Scheduler-Objekt in alle Threads kopiert &#8212; <i>exakt das</i>&#160;was wir brauchen
</p>
</body>
</html></richcontent>
<linktarget COLOR="#f3fea4" DESTINATION="ID_983915877" ENDARROW="Default" ENDINCLINATION="1743;-58;" ID="Arrow_ID_529465664" SOURCE="ID_1541537637" STARTARROW="None" STARTINCLINATION="822;78;"/>
<icon BUILTIN="ksmiletris"/>
</node>
</node>