diff --git a/src/vault/gear/activity-lang.hpp b/src/vault/gear/activity-lang.hpp index f9c8c9748..700af005c 100644 --- a/src/vault/gear/activity-lang.hpp +++ b/src/vault/gear/activity-lang.hpp @@ -43,6 +43,7 @@ #include "vault/gear/activity.hpp" #include "vault/gear/block-flow.hpp" +#include "vault/gear/activity-term.hpp" //#include "lib/symbol.hpp" //#include "lib/util.hpp" @@ -74,6 +75,18 @@ namespace gear { { } // using default copy/assignment + + private: + /** @internal generate the builder / configurator term */ + activity::Term + setupActivityScheme (activity::Term::Template schemeKind, Time start, Time after) + { + return activity::Term{ mem_.until(after) + , schemeKind + , start + , after + }; + } }; diff --git a/src/vault/gear/activity-term.hpp b/src/vault/gear/activity-term.hpp new file mode 100644 index 000000000..cec89d1b7 --- /dev/null +++ b/src/vault/gear/activity-term.hpp @@ -0,0 +1,114 @@ +/* + ACTIVITY-TERM.hpp - definition language framework for scheduler activities + + Copyright (C) Lumiera.org + 2023, Hermann Vosseler + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + + +/** @file activity-term.hpp + ** A term of the _activity language_ describing interconnected scheduler activities. + ** The activity::Term is created as a transient object in _builder notation,_ and used + ** to lay out the specifics of the planned operations necessary to calculate a single + ** frame or to carry out some administrative task. The actual \ref Activity verbs are + ** allocated independently, within the BlockFlow allocation scheme, while the Term + ** links and configures these data records and prepares them to instruct the Scheduler. + ** Through the activity::Term, relevant attachment points are exposed for configuration, + ** yet after posting the entrance point of an activity chain to the Scheduler, the term + ** is obsoleted and can be discarded without affecting the individual Activities awaiting + ** activation through the Scheduler. + ** + ** @see SchedulerActivity_test + ** @see activity-lang.hpp Entrance point to Activity definition + ** @see activity.hpp definition of verbs + ** + ** @todo WIP-WIP-WIP 8/2023 »Playback Vertical Slice« + ** + */ + + +#ifndef SRC_VAULT_GEAR_ACTIVITY_TERM_H_ +#define SRC_VAULT_GEAR_ACTIVITY_TERM_H_ + + +#include "vault/gear/activity.hpp" +#include "vault/gear/block-flow.hpp" +//#include "lib/symbol.hpp" +#include "lib/time/timevalue.hpp" +//#include "lib/util.hpp" + +//#include +#include + + +namespace vault{ +namespace gear { + + using lib::time::Time;////////////WIP +// using util::isnil; +// using std::string; + using std::move; + + using BlockFlowAlloc = BlockFlow; + + + namespace activity { + + /** + * A Term of the »Activity Language«, describing the steps necessary + * to perform the calculation of a single frame or similar tasks. + */ + class Term + { + + using AllocHandle = BlockFlowAlloc::AllocatorHandle; + + AllocHandle alloc_; + + public: + enum Template {CALC_JOB ///< scheme for a synchronous media calculation job + ,LOAD_JOB ///< scheme for an asynchronous data retrieval job + ,META_JOB ///< scheme for planning and organisational job + }; + + explicit + Term (AllocHandle&& allocHandle, Template kind, Time start, Time after) + : alloc_{move (allocHandle)} + { } + +// virtual std::string +// diagnostic() const +// { +// return "Activity::Hook"; +// } + +// operator std::string() const +// { +// return diagnostic(); +// } + }; + + + /** */ + + }//(End)namespace activity + + + +}} // namespace vault::gear +#endif /*SRC_VAULT_GEAR_ACTIVITY_TERM_H_*/ diff --git a/src/vault/gear/activity.hpp b/src/vault/gear/activity.hpp index b9e4f0558..ddf999063 100644 --- a/src/vault/gear/activity.hpp +++ b/src/vault/gear/activity.hpp @@ -204,7 +204,7 @@ namespace gear { /*********************************************//** - * Term to describe an Activity, + * Record to describe an Activity, * to happen within the Scheduler's control flow. * @note Activity is a »POD with constructor« * - trivially *destructible* diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index e85ba6026..0ca73a866 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -76660,6 +76660,13 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + + + + @@ -76990,7 +76997,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200

- ...uns anders wäre es sogar erst mal viel plausibler; ich selber habe lange Zeit anders gedancht, nämlich das die Channel hier den Medienkanälen entsprechen. Dann müßte man aber jedem CalcStream noch ein Channel-Mapping mitgeben, und auch für Prerequisites müßte eine Transformation für dieses Mapping mit angegeben werden. Daraus wird plausibel, warum ich diesen naiven Ansatz verworfen habe.... + ...uns anders wäre es sogar erst mal viel plausibler; ich selber habe lange Zeit anders gedacht, nämlich das die Channel hier den Medienkanälen entsprechen. Dann müßte man aber jedem CalcStream noch ein Channel-Mapping mitgeben, und auch für Prerequisites müßte eine Transformation für dieses Mapping mit angegeben werden. Daraus wird plausibel, warum ich diesen naiven Ansatz verworfen habe....

@@ -77117,6 +77124,12 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + + + @@ -77840,7 +77853,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + @@ -78146,7 +78159,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + + @@ -78263,14 +78277,14 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- +

- Das ergibt sich unmittelbar aus den Prinzipien dieses Designs: Job-Planung läuft auf das Erstellen von Activities hinaus, und dies bedingt Speicherverwaltung — welche der grundlegenden Entscheidung gemäß nur in einem Thread (unter GroomingToken) stattfinden darf + Das ergibt sich unmittelbar aus den Prinzipien dieses Designs: Job-Planung läuft auf das Erstellen von Activities hinaus, und dies bedingt Speicherverwaltung — welche der grundlegenden Entscheidung gemäß nur im Management-Modus (single-threaded, unter GroomingToken) stattfinden darf

@@ -78310,9 +78324,100 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ gib mir alle Ressourcen jetzt +

+ +
+
+ + + + +

+ gib mir anderweitig nicht benötigte freie Resourcen +

+ +
+
+
+ + + + + + +

+ zu knapp ⟹ Render korrumpiert +

+ +
+ + + +

+ Der implizite Kontrakt sowohl für »freewheeling render«, alsauch für »background render« ist, daß die Berechnungen vollständig sind — man hat ja genau dafür im Gegenzug auf die Deadline verzichtet... +

+ +
+
+ + + + +

+ Nach aktueller Einschätzung stellt dies kein echtes Problem dar, sondern ist nur unschön: exzessiv in die Zukunft gesetzte Deadlines bewirken das Belegen vieler dazwischen liegender Slots und belegen einen Teil des »Allokations-Stroms« mit längst schon obsoleten Activity-Daten; beide Effekte verlängern die Liste der aktiven Slots und erhöhen damit den wichtigsten Aufwands-Faktor für die Leistung des Allokators. Allerdings ist mein aktuelles Vor-Urteil, daß der Aufwand des Allokator (und des Schedulers) insgesamt vernachlässigbar bleibt im Verhältnis zu den aktuellen Medien-Berechnungen +

+ +
+
+
+ + + + +
@@ -78333,7 +78438,23 @@ Date:   Thu Apr 20 18:53:17 2023 +0200

+ + + + + + + +

+ nur Activities, die tatsächlich gescheduled werden müssen +

+ +
+ +
+ +
@@ -78714,7 +78835,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + @@ -78840,6 +78961,673 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + + + + + + + + + + + + + + + + + + + + + + +

+ stabile Benennung: this = ActivityDetector(ID) +

+ +
+
+ + + + + + + + + + +
+ + + + + + + + + + + +

+ wieder mal das lästige Problem mit den variadischen Templates: der Argument-Pack ist selber kein Typ, sondern man kann darauf nur matchen +

+ +
+ +
+ + + + + + + + + + + +
+ + + + + + +

+ ...auch wenn's bisher bloß der Test-Unterstützung dient, es ist in jedem Fall gerechtfertigt, einen generischen Erweiterungspunkt zu haben +

+ +
+ + + +
+ + + + +

+ geht leider nicht anders, weil ich mich für eine generische (concept-artige) Form des Execution-context entschieden habe; eine virtuelle Methode kann selber kein Template sein, und andererseits möchte ich den Activity-Record selber template-frei halten +

+ +
+ +
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ einfache Lösungen wie State-Flags oder Checksummen genügen nicht, denn es muß stets geprüft werden, daß mehrere Vorgänge insgesamt stattgefunden haben, und das in der richtigen Reihenfolge... +

+ +
+
+ + + + + + + +

+ analog zu dem Muster für das allgemeine EventLog.... +

+ +
+ + + + + + + + + + + + + +

+ ...das war vom Design her nicht vorgesehen, und wäre auch nicht ganz einfach zu realisieren; man müßte den EventMatch per CRTP definieren (und damit müßte er Header-only sein, mit den bekannten Folgen für die Größe des Debug-Build) +

+ +
+ +
+ + + + +

+ ...denn dies hier ist ein geschlossenes Ökosystem; daher ist sichergestellt, daß *this stets ein ActivityMatch ist +

+ +
+
+ + + + + + +
+ + + + + + +

+ CHECK (not ... ) führt zu irrelevanten Fehlermeldungen im Output +

+ +
+ + + +

+ ....weil ich seinerzeit Diagnose-Ausgaben per Seiteneffekt eingeführt habe — sowas ist unabdingbar zur Fehlersuche, aber lästig, wenn es aus einem negierten CHECK resultiert +

+ +
+
+ + + + +

+ ...allerdings liegt das an der Natur der logischen Negation selber, nicht an der unterstützung im Verifkations-Framework; ein Check ist eine Existenz-Aussage, und daher müßte zur Negation eine All-Aussage geprüft werden, durch eine erschöpfende Suche aller möglichen alternativen Prüf-Ketten. Anfangs habe ich das nicht gemacht, aber 9/2018 habe ich richtiges Backtracking eingebaut; damit sollte das nun korrekt funktionieren (was ich aber nie abschließend verifiziert habe, nur durch einzelne Testfälle geprüft) +

+ +
+
+ + + + +

+ das Schema dafür wurde im EventLog bereits geschaffen +

+ +
+
+
+
+ + + + + + + + + + + + + + +

+ ein Funktionsaufruf (typischwerweise von einem rigged-Functor) +

+ +
+ +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ Der Ansatz, alles ein einen Prüf-Aufruf zu packen, ist insgeseamt ungeschickt; genau deshalb wurde doch für das EventLog dieser komplizierte Builder / Verfeinerungs-Ansatz gemacht: darüber kann man ganz natürlich ausdrücken, wenn man etwas über die Argumente speziell geprüft haben möchte, oder eben nicht... +

+ +
+ +
+
+
+ + + + + + + + + +

+ detector.verifyInvocation ("funny").arg(-rnd) +

+ +
+
+ + + + +

+ Log-Ausgabe: FAILED to match-arguments(4294965953) +

+ +
+ +
+ + + +
+ + + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ (man kann per verifyInvocation prüfen) +

+ +
+
+
+ + + +
+ + + + + + + +

+ kann (optional) die Aktivierung an ein dekoriertes Subjekt weitergeben +

+ +
+ + + +

+ das heißt, die ActivityProbe wird dem zu beobachteten Activity-Record vorgeschaltet; man muß dann auch die Verdrahtung enstprechend anpassen, so daß die Aktivierung durch diesen Dekorator hindurch erfolgt +

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ es ist noch gar nicht klar, was für Verifikationen wirklich benötigt werden +

+ +
+ +
+ + + + +

+ möglicherweise geht es hier vornehmlich um die Aktiviertung  (den Fakt des Aufrufs) +

+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ passende ID hierfür vergeben: afterGATE +

+ +
+ +
+ + +
+
+
@@ -78880,6 +79668,14 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + + + + + @@ -78902,10 +79698,15 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + + + + + + @@ -78943,9 +79744,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - +

Beispiel: __throw_if_empty() @@ -78956,9 +79755,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - +

und sollte nur in Frage gestellt werden, sofern dafür explizit  ein unverhältnismäßiger Overhead nachweisbar ist... @@ -79009,9 +79806,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - +

ja — und zwar über den Scheduler selbst @@ -79054,9 +79849,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - +

die Ausführungs-Struktur liegt in den Termen (nicht in der Queue) @@ -79078,9 +79871,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - +

wichtig für die IO-Jobs @@ -79192,9 +79983,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - +

d.h. wird stehts von einem Worker ausgeführt, der aktuell das GroomingToken hält ⟹ Race zwischen Inkrementieren und Gate-Check ausgeschlossen @@ -79209,9 +79998,7 @@ 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) @@ -79561,12 +80348,12 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - + + - + @@ -79575,7 +80362,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200

- +
@@ -79640,7 +80427,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + + @@ -79695,9 +80483,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - +

Dieses Schema hat grundsätzlich die gleichen Charakteristiken wie ein flacher Kachel-Pool, aber die Cluster-Größe wirkt als Hebel:  zusammengehörige Elemente liegen im Cluster und sind damit cache-freundlicher. Fragementierung findet zwar statt, aber auf Cluster-Ebene; deshalb braucht man auch weiterhin eine Free-List, aber auch diese wird nur einmal pro Cluster aktualisiert. @@ -79707,9 +80493,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - +

Am Ende einer Kette von Activities muß eine Spezialbehandlung liegen, die die Länge der Kette weiß; zusätzlich kompliziert wird es, wenn diese Kette nicht in einen Cluster paßt (dann braucht es mehrere Notifications). Im Commutator ist spezielle Logik notwendig, die die Ausführung dieser Freigabe-Benachrichtigungen sicherstellt, damit diese dann ein gemeinsames Cluster-Gate dekrementieren, das in der ersten Allokation des Clusters liegt (und insofern Platz verschwendet) @@ -79725,9 +80509,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - +

Komplexe zeitliche Struktur, die auch zwingend zu einem gewissen Leerlauf führt, man braucht also reichlich Speicher. Außerdem ist nicht von Vornherein klar, wie viel Speicher bis zu einer Deadline noch gebraucht wird; man steht dadurch vor der Wahl, entweder Fragmentierungin Kauf zu nehmen, oder eben überschüssige Allokationen der nächsten Deadline zuzuschlagen, wodurch sie dann unnötig lange geblockt gehalten werden müssen @@ -79735,11 +80517,9 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + - - - +

Das führt zu einer Komplikation, da es solche Activities geben wird (Render-to-File, background activities); es muß dann eine pseudo-Deadline eingeführt werde, bei deren Überschreitung ein re-Scheduling in einen neuen Pool erfolgt. Ebenso stellen Deadlines weit in der Zukunft ein Problem dar @@ -79749,9 +80529,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - +

man muß für jeden Worker mitverfolgen, ob er die Epoche verlassen hat; das ist so nicht ohne Weiteres möglich, da es Activities geben könnte, die später gestartet werden aber doch eine knappere Deadline haben (und damit noch in eine frühere Epoche fallen würden) — man müßte also warten, bis die Startzeitpunkte hinter der Deadline der Epoche liegen @@ -79789,9 +80567,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - +

Allokationen erfolgen single-threaded, unter GroomingToken @@ -79811,9 +80587,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - +

ein externer Trigger kann einen »post« auslösen; da ein solcher Trigger auch noch verspätet auftreten kann (nach Überschreiten der Deadline), muß nochmal explizit geprüft werden, ob die Epoche „noch lebt“, bevor man in ihr eine Activity auslöst. Das bedingt aber zumindest noch einen beweglichen Parameter für einen generischen Funktor, der irgendwo gespeichert werden muß (und nicht in der Storage der Epoche selber liegen kann). @@ -79823,9 +80597,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - +

...vielmehr muß man den Callback selber „erwischen“ und unschädlich machen, bevor er bereits wiederverwendete Storage anspricht @@ -79860,9 +80632,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - +

da Jobs nach Zeit geordnet aktiviert werden, kann man für jeden Worker eine Markierung der aktuellen Epoche erzeugen; sie wäre jeweils zu aktualisieren, wenn ein Worker das GroomingToken abgibt... (und damit in einen Render-Job einsteigt) — mithin ließe sich feststellen, wenn alle Worker eine Epoche verlassen haben. @@ -79872,9 +80642,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - +

Es handelt sich hierbei um ein grundsätzliches Problem. Es liegt in der Natur von IO, daß eine solche Operation eine unbestimmte Zeit dauern kann; und diese Zeit kann ganz erheblich sein, wenn das IO-Subsystem überlastet wird. Es gibt keine Möglichkeit, eine IO-Operation abzubrechen; vielmehr kommen die Daten irgendwann an, und landen dann in dem dafür vorgesehenen Buffer. Und solange das nicht passiert ist, muß der Buffer und der Callback im Speicher bereitliegen. Ich sehe keine andere Möglichkeit, als für jede Epoche einen Zähler aller schwebenden IO-Operationen mitzuführen. Mithilfe der »post«, »notify« und »gate«-Activities ließe sich das jedoch single-threaded verwirklichen — Synchronisations-Effekte treten daher nur für Threads, die grade eine IO-Operation abgeschlossen haben, sowie den Thread, der das GroomingToken hält @@ -79901,9 +80669,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - +

ein Extent ist ein uninitialisierter Speicherblock @@ -79926,9 +80692,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - +

Begründung: @@ -79953,9 +80717,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - +

nested Typedef Payload @@ -79981,9 +80743,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - +

das heißt: es findet zwar eine default-Initialisierung statt, aber für einen Objekt-Typ mit implizitem default-ctor bedeutet das default-Initialisierung der Member. Nach meinem Verständnis hat std::array einen impliziten default-ctor und als einziges Member ein Array, und dafür wiederum erfolgt dann default-Initialisierung jedes einzelnen Elements. Und da das Element ein base-value (char) ist, erfolgt überhaupt keine Initialisierung. @@ -80017,9 +80777,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - +

genau für sowas war der gedacht ☻ @@ -80122,9 +80880,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - +

Damit vermeide ich, einen speziellen Marker-Wert zu verwenden; @@ -80162,9 +80918,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - +

...da wir den Platz im EpochGuard bereits anderweitig komplett ausschöpfen, muß die ExtentFamily auch beim Navigieren über die Sequenz der Epochen hinweg helfen. Und im Besonderen eine Navigation über das Ende hinaus muß nahtlos eine Erweiterung der Allokation  ermöglichen. Habe mich entschlossen, die Limitierung als Ausnahme/Exception zu definieren, so daß im Regelfall die ExtentFamily einfach immer weiter wachsen soll @@ -80185,9 +80939,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - +

...das heißt, es könnte kein »for each« mehr geben, weil die Iteration bis zum Out-of-Memory weiterliefe. Könnte man machen, sollte man aber nicht so machen @@ -80198,9 +80950,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - +

stattdessen Allokations-Erweiterung auf dem Iterator anbieten: expandAlloc() @@ -80236,9 +80986,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - +

...dieser tauscht per std::swap aus; und zwar rekursiv inkrementell: erst das Segment vom Ende an den Anfang und dann rekursiv wieder std::rotate für den Rest. Komplexität: linear @@ -80274,9 +81022,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - +

...selbst wenn es Zusammenhänge gibt — notfalls wird die Aktion in die nächst nachfolgende Epoche geschoben (welche stets länger lebt) @@ -80293,9 +81039,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - +

Entscheidung: Allokation entgleist nur ausnahmsweise @@ -80324,9 +81068,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - +

jede Deadline vor dieser Zeit ist damit grundsätzlich obsolet @@ -80642,9 +81384,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - +

...denn speziell das Count-down-Feld ist gradezu der springende Punkt beim EpochGate (damit lösen wir das Problem, daß IO-Operationen hängenbleiben können) @@ -81043,9 +81783,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - +

aber: BlockFlow macht schon verdammt viel für jede Allokation @@ -81158,9 +81896,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - +

muß die Dämpfung für extreme Zustände so einstellen, @@ -81184,9 +81920,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - +

Feinabstimmung: den Testfall rund laufen lasssen @@ -81196,9 +81930,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - +

Die Korrektur bei Overflows darf nur so stark sein, daß die Blöcke während der Vorlaufzeit etwa halbiert werden, aber nicht so stark, daß wir gegen das Limit laufen @@ -81208,9 +81940,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - +

  • @@ -81230,9 +81960,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
    - - - +

    man müßte ja den shared_ptr direkt in die Activity-Datenstruktur einbetten @@ -81287,9 +82015,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
    - - - +

    das heißt, bei jedem Overflow müssen wir doch einen Ticken stärker die Epochenlänge reduzieren... fragt sich nur, wie stark...? @@ -81336,9 +82062,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
    - - - +

    Auch ein Tiling-Pool-Allocator mit Freelist erziehlt die beobachtbare Leistuntssteigerung vor allem durch die Amortisierung über einen Skalenfaktor. Ich muß hier auf etwas ähnliches ziehlen: möglichst viele Allokationen aus einem bereits etablierten Block, und möglichst wenig Blöcke gleichzeitig @@ -81534,9 +82258,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
    - - - +

    bereits nach 5 sec im lock-step @@ -81546,9 +82268,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
    - - - +

    unter extremer Überlast gibt es einen ungünstigen Mitkopplungs-Effekt @@ -81561,9 +82281,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
    - - - +

    ... dann werden extrem viele neue Blöcke hinzugefügt @@ -81571,9 +82289,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
    - - - +

    In diesem extremen Overload gilt: jeder neue Block wandert die Kette entlang und wird „hinten abgeworfen“. Dort hinten ist dann zwar das Spacing bereits klein genug, um die Last aufzufangen — aber vorne besteht noch ein viel größeres Spacing. Konsequenz: während die Einfügeposition vorne immer noch die gleichen alten zu langen Epochen überfüllt, werden hinten permanent neue Mini-Epochen angehängt. Erst wenn auch die Einfüge-Position im Bereich der kleinen Blöcke angekommen ist, baut sich der Rückstau (ziemlich schnell) ab. @@ -81611,9 +82327,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
    - - - +

    nach weiteren 6 Sekunden ist die Regelung locked to target @@ -81651,9 +82365,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
    - - - +

    ein POST könnte geplant werden, @@ -81676,9 +82388,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
    - - - +

    Ich gehe davon aus, daß „dieser ganze Scheduler“ so dimensioniert ist und sich selber derart einregelt, daß er mit dem Flow der Berechnungen klarkommt. Aufgrund der dynamischen und offenen Natur dieser Konstruktion kann ich jedoch keine Garantien geben, daß diese Steuerung stets funktioniert. Die Activity-Language schafft ja grade die Möglichkeit, gegenwärtig noch gar nicht vorstellbare Steuerungs-Mechanismen später noch realisieren zu können, lediglich durch eine veränderte Parametrisierung. Aber zumindest ein Szenario des Scheiterns kann aus aktueller Sicht bereits konstruiert werden: und zwar wenn durch eine Überlastung des IO-Subsystems ältere Epochen noch nicht freigegeben werden können, da an ihnen noch Buffer für schwebende IO-Vorgänge hängen. Ein laufend fortschreitender BlockFlow würde dann sukzessive den verbleibenden Arbeitsspeicher belegen und blockieren. @@ -81688,9 +82398,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
    - - - +

    Ein im BlockFlow aktiv verwaltetes Limit für den Allokations-Pool stellt daher eine Sicherheitsbarriere dar, damit das System nicht insgesamt in einen degenerierten und unkontrollierbaren Betriebszustand gleitet (sog. „trashing“). Dem Zufolge sollte ein Auslösen dieser Sicherung nicht in Reparatur-Versuche münden, sondern schnellstmöglich zu einem Scheitern des Playback/Rendervorganges führen @@ -81713,9 +82421,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
    - - - +

    Es ist klar, wenn eine Epoche überläuft, aber in dem Moment ist noch nicht klar, welcher Prozentsatz des Platztes nun noch unterzubringen ist. Umgekehrt ist nicht klar, wann eine Epoche fertig besetzt ist; Hilfsweise könnte man beim Aufräumen prüfen, was aber erst deutlich später passiert — in beide Richtungen ist also die Rückkopplung verzögert und ungenau und kann daher zu Regelschwingungen führen. @@ -81731,9 +82437,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
    - - - +

    damit kann die Mittelung in beide Richtungen um den Optimalwert arbeiten @@ -81745,9 +82449,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
    - - - +

    • @@ -81810,674 +82512,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - - - - - - - - - - - - - - - - - - - - - - -

      - stabile Benennung: this = ActivityDetector(ID) -

      - -
      -
      - - - - - - - - - - -
      - - - - - - - - - - - -

      - wieder mal das lästige Problem mit den variadischen Templates: der Argument-Pack ist selber kein Typ, sondern man kann darauf nur matchen -

      - -
      - -
      - - - - - - - - - - - -
      - - - - - - -

      - ...auch wenn's bisher bloß der Test-Unterstützung dient, es ist in jedem Fall gerechtfertigt, einen generischen Erweiterungspunkt zu haben -

      - -
      - - - -
      - - - - -

      - geht leider nicht anders, weil ich mich für eine generische (concept-artige) Form des Execution-context entschieden habe; eine virtuelle Methode kann selber kein Template sein, und andererseits möchte ich den Activity-Record selber template-frei halten -

      - -
      - -
      - - - -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

      - einfache Lösungen wie State-Flags oder Checksummen genügen nicht, denn es muß stets geprüft werden, daß mehrere Vorgänge insgesamt stattgefunden haben, und das in der richtigen Reihenfolge... -

      - -
      -
      - - - - - - - -

      - analog zu dem Muster für das allgemeine EventLog.... -

      - -
      - - - - - - - - - - - - - -

      - ...das war vom Design her nicht vorgesehen, und wäre auch nicht ganz einfach zu realisieren; man müßte den EventMatch per CRTP definieren (und damit müßte er Header-only sein, mit den bekannten Folgen für die Größe des Debug-Build) -

      - -
      - -
      - - - - -

      - ...denn dies hier ist ein geschlossenes Ökosystem; daher ist sichergestellt, daß *this stets ein ActivityMatch ist -

      - -
      -
      - - - - - - -
      - - - - - - -

      - CHECK (not ... ) führt zu irrelevanten Fehlermeldungen im Output -

      - -
      - - - -

      - ....weil ich seinerzeit Diagnose-Ausgaben per Seiteneffekt eingeführt habe — sowas ist unabdingbar zur Fehlersuche, aber lästig, wenn es aus einem negierten CHECK resultiert -

      - -
      -
      - - - - -

      - ...allerdings liegt das an der Natur der logischen Negation selber, nicht an der unterstützung im Verifkations-Framework; ein Check ist eine Existenz-Aussage, und daher müßte zur Negation eine All-Aussage geprüft werden, durch eine erschöpfende Suche aller möglichen alternativen Prüf-Ketten. Anfangs habe ich das nicht gemacht, aber 9/2018 habe ich richtiges Backtracking eingebaut; damit sollte das nun korrekt funktionieren (was ich aber nie abschließend verifiziert habe, nur durch einzelne Testfälle geprüft) -

      - -
      -
      - - - - -

      - das Schema dafür wurde im EventLog bereits geschaffen -

      - -
      -
      -
      -
      - - - - - - - - - - - - - - -

      - ein Funktionsaufruf (typischwerweise von einem rigged-Functor) -

      - -
      - -
      -
      -
      -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

      - Der Ansatz, alles ein einen Prüf-Aufruf zu packen, ist insgeseamt ungeschickt; genau deshalb wurde doch für das EventLog dieser komplizierte Builder / Verfeinerungs-Ansatz gemacht: darüber kann man ganz natürlich ausdrücken, wenn man etwas über die Argumente speziell geprüft haben möchte, oder eben nicht... -

      - -
      - -
      -
      -
      - - - - - - - - - -

      - detector.verifyInvocation ("funny").arg(-rnd) -

      - -
      -
      - - - - -

      - Log-Ausgabe: FAILED to match-arguments(4294965953) -

      - -
      - -
      - - - -
      - - - - - - - - - -
      -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

      - (man kann per verifyInvocation prüfen) -

      - -
      -
      -
      - - - -
      - - - - - - - -

      - kann (optional) die Aktivierung an ein dekoriertes Subjekt weitergeben -

      - -
      - - - -

      - das heißt, die ActivityProbe wird dem zu beobachteten Activity-Record vorgeschaltet; man muß dann auch die Verdrahtung enstprechend anpassen, so daß die Aktivierung durch diesen Dekorator hindurch erfolgt -

      - -
      -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

      - es ist noch gar nicht klar, was für Verifikationen wirklich benötigt werden -

      - -
      - -
      - - - - -

      - möglicherweise geht es hier vornehmlich um die Aktiviertung  (den Fakt des Aufrufs) -

      - -
      - -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

      - passende ID hierfür vergeben: afterGATE -

      - -
      - -
      - - -
      -
      -
      -
      - + @@ -82486,6 +82521,11 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      + + + + +
      @@ -82559,9 +82599,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      Zunächst dachte ich, das ist nur ein Provisorium... @@ -82590,12 +82628,25 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      + + + + + + + + + + + + + @@ -82623,9 +82674,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      ...ein eigenartiger Widerspruch, den ich nicht auflösen kann... @@ -82639,9 +82688,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      »Deadline« ist immer in realTime @@ -82670,9 +82717,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      symbolische Repräsentation eines dynamisch laufenden Berechnungsprozesses @@ -82682,9 +82727,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      es enthält keine relevanten Informationen und dient auch nicht dem Tracking; vielmehr ist es ein Schlüssel, mit dessen Hilfe der PlayProcess später mit der Render-Engine reden kann @@ -82694,9 +82737,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      Es ist im Entwurf von 2011 noch nicht festgelegt, ob diese Implementierung konkret ist (d.h. direkt Elemente aus dem Play-Service verbindet), oder nur abstrakt, durch Aufruf der RenderEnvironmentClosure. Letzteres wäre adäquat im sinne von Inversion of Control @@ -82729,9 +82770,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      soll genau dann reproduzierbar sein, @@ -82759,9 +82798,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      Änderung auch nur eines Teils des Render-Graphen: Hash ändert sich ⟹ Cache invalidiert @@ -82802,9 +82839,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      hier ist mindestens eine Indirektion notwendig @@ -82812,9 +82847,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      aktuell passieren sogar zwei Indirektionen @@ -82832,9 +82865,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      wie generisch, ist eine offene Frage, die eing damit zusammenhängt, was tatsächlich durch die PriorityQueue läuft: Wenn nämlich auch schon der Job-Parameter in separater Storage liegt, dann könnte bereits dieser eine Vorstufe zum Funktor sein, und bsp. auch den Einsprung für die passende ProcNode transportieren; in diesem Fall gäbe es dann nur noch ganz wenige, prototypische Basis-Funktoren (Render aufrufen, Daten laden, Netzkommunikation, Verwaltungsaufgaben), und der konkrete Aufrufkontext würde im Parameter stecken — wir hätten dann wieder zwei Indirektionen (Job⟼Parameter und Parameter⟼Nutzfunktion) @@ -82846,9 +82877,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      welcher Teil muß wirklich flexibel sein? @@ -82863,9 +82892,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      ...denn von den grundsätzlichen Abhängigkeiten her weiß nicht einmal ein JobTicket, in welchem Segment es hängt; auch ProcNodes könnten theoretisch sogar in mehreren Segmenten hängen ⟹ es schreint mehr als fragwürdig, ob ein JobFunktor überhaupt im Stande ist, eine inhaltlich sinnvolle verifikation zu machen (über das Prüfen auf null-Pointer hinaus) @@ -82930,9 +82957,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      da Jobs massiv über mehrere Threads hinweg gereicht werden, könnte der bloße Umstand einer Datenaktualisierung bereits zu Cache-Coherency-Overheads führen @@ -82946,7 +82971,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - + @@ -82971,9 +82996,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      Zeitsteuerung funktioniert am Besten bei eigentlich entkoppelten Aktivitäten, welche ohne weitere Prüfungen und Synchronisationen starten und enden können @@ -82984,9 +83007,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      Event ⟶ push @@ -82999,9 +83020,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      weil außer dem zeitgetriggerten Start... @@ -83026,9 +83045,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      ...nämlich beim finalen Rendern! Lumiera ist darauf ausgelegt, und grade nicht als Aufführungs-System konzipiert. Und auf der anderen Seite, wenn es um zeitgebundene Wiedergabe geht, fordern wir ohnehin, den Aufwand so sehr zu reduzieren (Proxyies), daß das System weit von Vollauslastung entfernt läuft @@ -83040,9 +83057,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      Denn stabiler Playback erfordert zwingend zusätzliche Leistungspuffer (sofern auch nur ein kleiner Teil der Pipeline zufällig streut). Daher steht und fällt die Möglichkeit für flüssigen Playback damit, den Aufwand garantiert erheblich unter das Limit zu drücken. Unter diesen Umständen würde meist auch Batching plus Vorlauf mit Datenpuffer genügen @@ -83052,9 +83067,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      ...mehr noch, da letzten Endes die amortisierte Lade-Zeit pro Frame deutlich kleiner sein muß als die Framerate, brauchen wir ehr einen ausreichenden Vorlauf und einfache Datenpuffer — zumal flüssiger Playback ohnehin nur mit kleinen Frames funktioniert, denn die I/O-Bandbreite ist bei Weitem nicht so angewachsen, wie die Rechenleistung @@ -83064,9 +83077,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      In diesem Fall verschlechtert Zeitsteuerung eigentlich die benötigte Gesamtzeit; die optimale Lösung wäre hier, jeweils parallel mehrere I/O-Pipelines, und dann einige Worker nach best serve-Verteilung laufen zu lassen @@ -83077,9 +83088,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      praktisch alle Video-Verarbeitung involviert I/O in irgendeiner Form, und muß deshalb auf Events reagieren, dann aber einen nachfolgenden festen Arbeitsaufwand gleichmäßig disponieren @@ -83098,9 +83107,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      die wirklich recht komplexe Steuerung ist einzig und allein dadurch gerechtfertigt, daß so lange laufende und schwer vorhersehbare Sequenzen überlappend verschachtelt werden können, was bei einem strikten Pipelining oder rein Event-getriebener Verarbeitung nicht möglich wäre; letztere Ansätze funktionieren nur gut bei sehr kleinen Arbeitspaketen oder bei extremer horizontaler Skalierung @@ -83111,9 +83118,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      das heißt, die Priority-Queue ist das Entscheidende; das Ordnungsmaß darf gar nicht primär als ein Zeitplan verstanden werden, sondern als ein Maß an aktueller Dringlichkeit @@ -83124,9 +83129,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      Bei einem reinen Pipelining kann es zur Stau und Lastspitzen kommen, und genau dann auch zu Lock-contention. Wir sollten also die zur Integration der widersprüchlichen Anforderungen notwendigen Pufferzeiten als eine zufällige Streuung deuten, die Lastspitzen durch Verteilung entzerrt; sofern nicht in kurzer Zeit Aktionen an mehrere Threads zugleich  weitergegeben werden müssen, treten auch weniger Behinderungen durch Synchronisation auf @@ -83137,9 +83140,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      Die Implementierung sollte sich von den exakten Zeiten lösen — besser sollte stets mit reichlich Puffer gearbeitet werden, dafür aber auch eine Activity in einer gewissen Toleranzzone um den definierten Zeitpunkt herum gestartet werden können. Dafür sollte im Gegenzug die Menge der jeweils aus der Queue entommenen Activities dynamisch geregelt werden, und stets nur so viel wie gut möglich getan werden. Die concurrency-Struktur sollte zum Leitmaß erhoben werden; idealerweise sollte stets nur ein Thread abnehmen, und auch das nur so lange,  bis er wieder auf eine größere Aufgabe geschickt wird. @@ -83150,9 +83151,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      Keinesfalls sollte a priori eine bestimmte Thread-Struktur festgelegt werden! Im Besonderen auch nicht die Annahme, daß es einen »Scheduler-Thread« gibt, welcher Aufgaben verteilt. Denn letztlich hängen alle Leistungs-Eigenschaften an der Cache-Locality, und diese läßt sich nur empirisch optimieren, denn es ist klar, daß unser Daten-Durchsatz die Cache-Kapazität insgesamt übersteigt — inwiefern sich eine einzelne CPU für bestimmte Aufgaben überhaupt „warm laufen“ kann, muß sich in der Praxis zeigen; gut möglich, daß I/O-Limitierungen jedweden Cache-Efekt überdecken. Grundsätzlich sollte die Möglichkeit vorgesehen werden, daß jeder Thread die Queue bedienen kann — sowohl eingangsseitig alsauch ausgangsseitig. Natürlich darf es stets nur ein Thread sein, der die Queue bedient; andere untätige Threads legen sich schlafen. @@ -83166,9 +83165,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      Earliest deadline first (EDF) or least time to go is a dynamic priority scheduling algorithm used in real-time operating systems to place processes in a priority queue. Whenever a scheduling event occurs (task finishes, new task released, etc.) the queue will be searched for the process closest to its deadline. This process is the next to be scheduled for execution. @@ -83181,9 +83178,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      ...und würde dann strikt nach zeit-Ordnung zuerst bedient, und damit dem Realtime-Task die Ressourcen wegnehmen @@ -83199,9 +83194,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      zwei Queues @@ -83219,9 +83212,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      reguliert über ein konventionelles Lock, oder (besser) über ein Atomic-Token mit CaS @@ -83236,9 +83227,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      zu den Steuerungs-Aufgaben gehört gleichermaßen @@ -83256,9 +83245,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      Activities werden in/aus der Notification-Queue verschoben @@ -83271,9 +83258,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      is ja eine linked List @@ -83284,9 +83269,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      Die Koordination von Memory-Management ist ein gefährlicher Verzögerungs-Faktor (weil sie zu einem globalen flush der Cache-Hierarchie führen kann). @@ -83412,6 +83395,9 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      + + + @@ -83496,9 +83482,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      Die Methode steht und fällt damit, daß die Tangente näher zur Lösung zeigt, als der aktuelle (Start)Wert. Sonst kann die Iteration in weite Oszillationen münden und sich ggfs sogar in einem neben-Minimum festbeißen. Die Newton-Methode spielt daher ihr Potential einer senationell schnellen Konvergenz nur aus, wenn man anderweitig schon eine sehr gute Näherung als Startwert hat. @@ -83536,9 +83520,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      saugeil @@ -83576,9 +83558,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      das Konzept gibts nicht @@ -83589,9 +83569,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      GTK-Widget: hide() @@ -83606,9 +83584,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      GObject: unref() @@ -83624,9 +83600,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      ...in der Praxis aber entsteht indirekt eine Auswirkung, @@ -83676,9 +83650,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      Widget berechnet adjusted allocation @@ -83689,9 +83661,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      ...also abzüglich Dekoration und Margin @@ -83708,9 +83678,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      ...was der Fall sein kann in einer Box oder einem Grid, @@ -83764,9 +83732,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      "Widget is in a background toplevel window" @@ -83817,9 +83783,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      Adwaita ist leider direkt in GTK integriert und ist ein aufgeblähter Wust an SCSS-generierten Regeln, die dann aus »performance-Gründen« (d.h. aus Dummheit und Arroganz) binär compiliert und eingebettet werden müssen. @@ -83834,9 +83798,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      geläufiges
      Farbschema @@ -83844,9 +83806,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      Es war und ist immer noch üblich, daß jedes Theme einen Satz von Basis-Farben definiert. Auch Adwaita macht das aktuell so (wenngleich es den Gnome-Leuten lästig ist, und sie immer wieder darauf hinweisen, daß das alles "difficult" und "challenging" ist. Sprich, man will raus aus der Nummer, aber der Widerstand der Nutzer ist zu stark) @@ -83856,9 +83816,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      widget text/foreground color @@ -83868,9 +83826,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      text color for entries, views and content in general @@ -83880,9 +83836,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      widget base background color @@ -83892,9 +83846,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      text widgets and the like base background color @@ -83904,9 +83856,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      base background color of selections @@ -83916,9 +83866,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      text/foreground color of selections @@ -83928,9 +83876,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      base background color of insensitive widgets @@ -83940,9 +83886,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      text foreground color of insensitive widgets @@ -83952,9 +83896,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      insensitive text widgets and the like base background color @@ -83964,9 +83906,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      widget text/foreground color on backdrop windows @@ -83976,9 +83916,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      text color for entries, views and content in general on backdrop windows @@ -83988,9 +83926,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      widget base background color on backdrop windows @@ -84000,9 +83936,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      text widgets and the like base background color on backdrop windows @@ -84012,9 +83946,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      base background color of selections on backdrop windows @@ -84024,9 +83956,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      text/foreground color of selections on backdrop windows @@ -84036,9 +83966,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      insensitive color on backdrop windows @@ -84048,9 +83976,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      widgets main borders color @@ -84060,9 +83986,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      widgets main borders color on backdrop windows @@ -84078,9 +84002,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      these colors are exported for the window manager and shouldn't be used in applications, @@ -84129,9 +84051,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      Warum? @@ -84158,9 +84078,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      in den Fällen, die ich mir angeschaut habe, steht dieser String hart codiert in der XXXX_class_init()-Funktion @@ -84173,9 +84091,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      d.h. die angegebenen Abmessungen entsprechen der bounding box @@ -84185,9 +84101,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      es geht also nicht, daß man sagt @@ -84216,9 +84130,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      <offX> <offY> [<blur> [<spread>]] <colour> @@ -84249,9 +84161,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      d.h. wir haben Referenz-Semantik @@ -84271,9 +84181,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      ...die sich aus den CSS-Selektoren ergibt, gemäß dem StylePath für diesen StyleContext, @@ -84289,9 +84197,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      Bounding-Box meint ja, den effektiven äußeren Umfang. @@ -84329,9 +84235,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      @deprecated früher gab es die Stock-IDs @@ -84350,9 +84254,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      Glib::RefPtr<StyleContext> context = widget->get_style_context(); @@ -84399,9 +84301,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      this->set_name("my-widget") @@ -84411,9 +84311,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      (2019 / Debian-Stretch) @@ -84469,9 +84367,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      gtk_widget_class_set_css_name (GTK_WIDGET_GET_CLASS(gobj()), "body"); @@ -84495,9 +84391,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      aber der Tag-Name für den CSS-Selector wird dadurch nicht  geändert @@ -84545,9 +84439,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      8/2018: @@ -84575,9 +84467,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      gtk_widget_path () @@ -84655,9 +84545,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      d.h. nur ein Pointer auf ein GObj @@ -84676,9 +84564,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      As a consequence, the style will be regenerated to match the new given path. @@ -84696,9 +84582,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      ein Widget kann einem GDK-Window zugeordnet sein @@ -84737,9 +84621,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      ...nicht mehr das klassische gtk::Main @@ -84779,9 +84661,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      ...und erzeugt diesen on demand auch neu @@ -84812,9 +84692,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      warum? @@ -84856,9 +84734,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      ...allerdings eingepackt in eine vfunc, @@ -84882,9 +84758,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      ...nur wegen dem ganzen Registrierungs-Glump. @@ -84905,9 +84779,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      suche (case insensitive) nach application_activate @@ -84930,9 +84802,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      nicht durch gtk_main @@ -84940,9 +84810,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      wichtige Einsicht: @@ -84971,9 +84839,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      beachte: ruft nicht gtk_main sondern macht das Äquivalent @@ -85001,9 +84867,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      initialisiert das @@ -85024,9 +84888,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      gboolean @@ -85093,9 +84955,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      void Main::init_gtkmm_internals() @@ -85220,9 +85080,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      ...und das ist nicht gtk_main, @@ -85235,9 +85093,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      ...das heißt, es wurde "retrofitted". @@ -85268,9 +85124,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      der springende Punkt mit sigc::trackable ist, @@ -85293,9 +85147,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      alles was von sigc::trackable erbt @@ -85309,9 +85161,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      für alles aus GTKmm zu verwenden @@ -85319,9 +85169,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      ...gemeint ist: @@ -85380,9 +85228,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      @@ -85431,9 +85277,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - + The event mask determines which events a widget will receive. Keep in mind that different widgets have different default event masks, and by changing the event mask you may disrupt a widget’s functionality, so be careful. This function must be called while a widget is unrealized. Consider @@ -85449,9 +85293,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      Beispiel: @@ -85477,9 +85319,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      wenn ein Kind-Widget sein eigenes Fenster aufmacht, dann ist ein unsichtbares EventBox-GdkWindow nicht ein Parent-Window von dem Kind-Widget-Window. Das kann das Propagieren von Events verhindern @@ -85512,9 +85352,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      jedoch indirekt dann auch für darauf aufbauende Events, z.B. GTK-Events, weil eben nur noch das zum grabbed window gehörige Widgets diese Events überhaupt sieht @@ -85553,9 +85391,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      ....bin damals mit size_request eingestiegen — aber von dort bald auf gtk_widget_size_allocate_with_baseline gestoßen; letzteres ist die eigentliche zentrale Funktion @@ -85580,9 +85416,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      setzt bei Bedarf ein queue_resize ab @@ -85595,9 +85429,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      danach: priv->resize_needed = TRUE @@ -85621,9 +85453,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - +

      • @@ -85650,9 +85480,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

        Einstiegspunkt aus vielen Widgets @@ -85674,9 +85502,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

        gtk_widget_size_allocate_with_baseline @@ -85702,9 +85528,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

        aber: spezielle Widgets/Container @@ -85717,9 +85541,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

        gtk_widget_size_allocate_with_baseline @@ -85746,9 +85568,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

        Beachte: _GtkCssGadgetClass->allocate @@ -85758,9 +85578,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

        typischerweise(via GadgetClass): gtk_css_gadget_real_allocate @@ -85782,9 +85600,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

        und damit wieder von gtk_css_gadget_allocate @@ -85795,9 +85611,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

        allerdings dann vom umschließenden Widget @@ -85809,9 +85623,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

        Implementierung: gtk_frame_allocate @@ -85837,9 +85649,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

        dieses baut auf auf: gtk_css_gadget_allocate @@ -85853,9 +85663,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

        (konkret im Beispiel): gtk_frame_size_allocate @@ -85874,9 +85682,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

        ruft damit gtk_css_gadget_allocate @@ -85908,9 +85714,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

        alle Fäden laufen zusammen bei.... @@ -85928,9 +85732,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

        ...da Funktionen irgendwo dann an Funktionspointer zugewiesen werden für "virtuelle Funktionen" @@ -85983,9 +85785,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

        wird im class-init mit der jeweiligen konkreten Implementierung belegt, z.b. gtk_button_size_allocate @@ -86029,9 +85829,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

        das ist eine Flag in der privaten Widget-Struktur. Keine Ahnung was das bedeutet.
        Und übrigens: sichtbar muß das Widget auch noch sein... @@ -86046,9 +85844,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

         * Gets whether the widget prefers a height-for-width layout @@ -86087,9 +85883,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

        also stellt eigentlich grade nicht die versprochene Logik bereit @@ -86125,9 +85919,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

        danach noch die adjust_baseline_allocation @@ -86164,9 +85956,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

        also entweder in horizontaler, oder in vertikaler Richtung @@ -86208,9 +85998,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

        /* @@ -86305,9 +86093,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

        Gtk::Expander @@ -86326,9 +86112,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

        ...ob beim Expand/Collapse das umschließende Widget resized werden soll @@ -86338,9 +86122,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

        ob eingeklappt oder ausgeklappt @@ -86353,9 +86135,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

        ein Frame setzt beim Kind property_expand() = true, @@ -86371,9 +86151,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

        Gtk::Grid @@ -86402,9 +86180,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

        stets zwischen den Zeichen @@ -86414,9 +86190,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

        Danke! endlich bekommt das mal jemand korrekt hin @@ -86470,9 +86244,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

        This function is only used by Gtk::Container subclasses, to assign a size, position and (optionally) baseline to their child widgets. @@ -86492,9 +86264,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

        "Destroys the widget. @@ -86509,9 +86279,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

          //This has probably been called already from Gtk::Object::destroy_(), which is called from derived destructors. @@ -86565,9 +86333,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

        d.h. zerstört auch die Heap-Allokation, @@ -86580,9 +86346,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

        ein normaler Widget/Container tut das nicht @@ -86600,9 +86364,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

        ...führen automatisch dazu, daß das Widget @@ -86663,9 +86425,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

        ...können vom CSS-Stylesheet aus gesetzt werden. @@ -86685,9 +86445,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

        ist of einfacher und der bevorzugete Weg. @@ -86744,9 +86502,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

        Hier steckt die Implementierung, und zwar die Kernimplementierung der Platzzuteilungs-Logik von GTK @@ -86784,9 +86540,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

        min_size = get_number (style, GTK_CSS_PROPERTY_MIN_WIDTH); @@ -86800,9 +86554,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

        basierend auf der Widget-Struktur, welche in Widget-Paths übersetzt wurde @@ -86884,9 +86636,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

        Keine gute Idee: diese Funtktion wird verwendet, um die Dekoration zu entfernen, und Stil-Anpassungen zu machen; sie sollte daher besser als pure function betrachtet werden @@ -86913,9 +86663,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

        in dem Widget, das diesen Aufruf empfängt, wird der Margin abgezogen, und nur dieser reduzierte Wert wird im Widget selber als Allocation gespeichert @@ -86930,9 +86678,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

        ...per Design von GTK sind nur wenig Eingriffsmöglichkeiten vorgesehen; stattdessen soll man die Layout-Manager nutzen, die das Layout-reflow automatisch erledigen. Was man definitiv tun kann ist, aus den get_preferred_*()-VFunks dynamisch angepaßte Werte zu liefern @@ -86942,9 +86688,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

        man kann sich nur dazwischen schalten und auf Stabilisierung hoffen @@ -86952,9 +86696,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

        ...wenn man in der Phase der Layout-Steuerung eingreift, und einzelne Elemente verändert, muß man durch "invalidation" dafür sorgen, daß GTK die Layout-Berechnung später nochmal macht, und dann hoffen, daß sich in diesem zweiten (oder N-ten) Durchgang keine Änderung mehr ergibt. @@ -86964,9 +86706,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

        sofern in dieser Phase ein Widget visible ist, stimmen auch seine Layout-Antworten @@ -87004,9 +86744,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

        ....how does the event dispatching deal with partially covered widgets @@ -87016,9 +86754,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

        ...for embedded widgets @@ -87059,9 +86795,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

        ...meaning, "this event is not yet fully processed", @@ -87077,9 +86811,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

        Warning: allocation is the visible area @@ -87093,9 +86825,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

        asked on stackoverflow... @@ -87109,9 +86839,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

        ...as can be observed @@ -87128,9 +86856,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

        ...otherwise adjustment values will cummulate, @@ -87170,9 +86896,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

        ...die anderen, die noch in Frage kommen würden, @@ -87188,9 +86912,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

        on_check_resize() wird nicht aufgerufen @@ -87258,9 +86980,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

        ...keine Ahnung, was ich beim ersten Mal falsch gemacht habe. @@ -87333,9 +87053,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

        in der Implementierung, mywidget.cc @@ -87356,9 +87074,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

        Beispiel im Guide @@ -87376,9 +87092,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
        - - - +

        • @@ -87397,9 +87111,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
          - - - +

          Multithreded-Beispiel @@ -87469,9 +87181,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
          - - - +

          A dock item is a container widget that can be docked at different place. @@ -87523,9 +87233,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
          - - - +

          der Druck-Metapher gemäß ist das die „Farbwalze“ oder das „Stempelkissen“ @@ -87539,9 +87247,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
          - - - +

          wird mit jeder stroke() oder fill()-Operation geleert. Ist Teil des Context, und weitere Zeichen-Operationen fügen zu dem Pfad hinzu @@ -87558,9 +87264,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
          - - - +

          die Source wird durch die Mask hindurch „gestempelt“ @@ -87572,9 +87276,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
          - - - +

          • @@ -87620,9 +87322,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
            - - - +

            current transformation matrix (CTM) : User-Space ⟼ Device-Space @@ -87635,9 +87335,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
            - - - +

            Transformations-Definition wird eingangsseitig vor die aktuelle CTM vorgeschaltet @@ -87650,9 +87348,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
            - - - +

            Beispiel: @@ -87673,9 +87369,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
            - - - +

            ...die aktuellen Transformations-Einstellungen (current transformation matrix CTM) @@ -87715,9 +87409,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
            - - - +

            anscheinend gibt es eine Konvention, welche die im UI sichtbaren Koordinaten in vertikaler Richtung spiegelt; auch ist der auf dem Lineal angezeigte Ursprung unten links @@ -87731,9 +87423,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
            - - - +

            Koordinaten »versäubern« @@ -87776,9 +87466,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
            - - - +

            ...und Inkscape wird das erhalten, solange man die betr. Features nicht wieder aktiviert. Im Besonderen kann man @@ -87802,9 +87490,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
            - - - +

            style="fill:black;fill-opacity:0.5;stroke:#5a8fb2;stroke-opacity:1;stroke-width:0.1" @@ -87814,9 +87500,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
            - - - +

            style="fill:#ffffff;fill-opacity:0.75;stroke:none;stroke-width:0.05" @@ -87827,9 +87511,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
            - - - +

            aber leider nur als globales Verhalten der Inkscape-Installation @@ -87842,9 +87524,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
            - - - +

            Behaviour > Transforms > store optimised @@ -87872,9 +87552,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
            - - - +

            wenn ein Member eine nichttriviale Funktion hat, @@ -87906,9 +87584,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
            - - - +

            im Zweifelsfall: std::is_pod<TY>() fragen @@ -88201,18 +87877,37 @@ class Something - - - - - + +

            - Eine Störstelle in der Heap-Struktur wird durch „lokales bouble“ korrigiert. Ein am Ende hinzugefügtes Element boubled hoch, bis es größer ist als beide Kinder. Für ein entferntes größtes Element rutscht das größere Kind hoch. Für ein entferntes inneres Element wird zunächst das letzte Element an diese Stelle gesetzt  (weil dadurch dann die letzte Position frei wird); die dadurch entstehende Störstelle wird dann nach oben/unten korrigiert: ist das Element größer als der Vater, tauscht es mit diesem, ist es kleiner als das größere seiner Kinder, tauscht es mit diesem. + verblüffenderweise ist das im Schnitt die effizienteste Lösung, aufgrund der guten Cache-Lokalität des Vektors +

            +
              +
            • + da die Heap-Algorithmen stets die Elemente paarweise vertauschen, werden niemals Einfüge/Löschoperationen des unterliegenden Containers benötigt +
            • +
            • + da der Heap eine raum-organisierende Datenstruktur ist, werden niemals direkte Zeiger auf andere Elemente benötigt, sonder der Zugriff erfolgt stets per (logarithmisch) errechnetem Index +
            • +
            + +
            +
            + + + + + + + + +

            + Eine Störstelle in der Heap-Struktur wird durch „lokales bubble“ korrigiert. Ein am Ende hinzugefügtes Element bubbled hoch, bis es größer ist als beide Kinder. Für ein entferntes größtes Element rutscht das größere Kind hoch. Für ein entferntes inneres Element wird zunächst das letzte Element an diese Stelle gesetzt  (weil dadurch dann die letzte Position frei wird); die dadurch entstehende Störstelle wird dann nach oben/unten korrigiert: ist das Element größer als der Vater, tauscht es mit diesem, ist es kleiner als das größere seiner Kinder, tauscht es mit diesem.