diff --git a/src/steam/engine/node-builder.hpp b/src/steam/engine/node-builder.hpp index ce60a0252..783cf9d65 100644 --- a/src/steam/engine/node-builder.hpp +++ b/src/steam/engine/node-builder.hpp @@ -353,6 +353,9 @@ namespace engine { /*************************************************************//** * Terminal: complete the Port wiring and return to the node level. + * @remark this prepares a suitable Turnout instance for a port; + * but due to constraints with memory allocation, actual build + * is delayed and packaged as functor into a PatternData instance. */ auto completePort() @@ -369,9 +372,20 @@ namespace engine { : _Par{move(base)} , weavingBuilder_{forward (fun), _Par::symbol_, portSpec, _Par::leads_.policyConnect()} , defaultPort_{_Par::patternData_.size()} - { } + { } // ^^^ by default use next free port friend class PortBuilderRoot; + + /** cross-builder to adapt embedded WeavingBuilder type */ + template + PortBuilder (PortBuilder&& prevBuilder, WAB&& adaptedWeavingBuilder) + : _Par{move(prevBuilder)} + , weavingBuilder_{move (adaptedWeavingBuilder)} + , defaultPort_{prevBuilder.defaultPort_} + { } + + template + friend class PortBuilder; }; @@ -401,7 +415,8 @@ namespace engine { auto PortBuilderRoot::invoke (StrView portSpec, FUN fun) { - using WeavingBuilder_FUN = WeavingBuilder; + using Prototype = typename FeedManifold::Prototype; + using WeavingBuilder_FUN = WeavingBuilder; return PortBuilder{move(*this), move(fun), portSpec}; } /* diff --git a/src/steam/engine/weaving-pattern-builder.hpp b/src/steam/engine/weaving-pattern-builder.hpp index 016900313..383bd225e 100644 --- a/src/steam/engine/weaving-pattern-builder.hpp +++ b/src/steam/engine/weaving-pattern-builder.hpp @@ -235,18 +235,19 @@ namespace engine { * actual NodeBuilder and PortBuilder allows to introduce extension points * and helps to abstract away internal technical details of the invocation. * @tparam POL allocation and context configuration policy - * @tparam FUN function or invocation adapter to invoke + * @tparam PROT Prototype to generate a Feed or invocation adapter to invoke + * @remark in the standard case, PROT is a FeedManifold::Prototype and + * thus embeds the processing-functor and possibly a parameter-functor */ - template + template struct WeavingBuilder : util::MoveOnly { - using Prototype = typename FeedManifold::Prototype; - using WeavingPattern = MediaWeavingPattern; + using WeavingPattern = MediaWeavingPattern; using TurnoutWeaving = Turnout; static constexpr SizMark sizMark{}; - static constexpr uint FAN_I = Prototype::FAN_I; - static constexpr uint FAN_O = Prototype::FAN_O; + static constexpr uint FAN_I = PROT::FAN_I; + static constexpr uint FAN_O = PROT::FAN_O; using TypeMarker = std::function; @@ -262,15 +263,27 @@ namespace engine { StrView nodeSymb_; StrView portSpec_; - FUN fun_; + PROT prototype_; template - WeavingBuilder(FUN&& init, StrView nodeSymb, StrView portSpec, INIT&& ...alloInit) + WeavingBuilder (PROT&& prototype, StrView nodeSymb, StrView portSpec, INIT&& ...alloInit) : leadPorts{forward (alloInit)...} , buffTypes{fillDefaultBufferTypes()} , nodeSymb_{nodeSymb} , portSpec_{portSpec} - , fun_{move(init)} + , prototype_{move(prototype)} + { } + + /** cross-ctor to switch to another prototype */ + template + WeavingBuilder (WeavingBuilder&& prevBuilder, PROT&& adaptedPrototype) + : leadPorts {move (prevBuilder.leadPorts)} + , buffTypes {move (prevBuilder.buffTypes)} + , providers {move (prevBuilder.providers)} + , resultSlot{move (prevBuilder.resultSlot)} + , nodeSymb_ {move (prevBuilder.nodeSymb_)} + , portSpec_ {move (prevBuilder.portSpec_)} + , prototype_{move (adaptedPrototype)} { } WeavingBuilder&& @@ -333,7 +346,7 @@ namespace engine { // provide a free-standing functor to build a suitable Port impl (≙Turnout) return [leads = move(leadPorts.build()) ,types = move(outTypes.build()) - ,procFun = move(fun_) + ,prototype = move(prototype_) ,resultIdx = resultSlot ,procID = ProcID::describe (nodeSymb_,portSpec_) ] @@ -343,7 +356,7 @@ namespace engine { ,move(leads) ,move(types) ,resultIdx - ,move(procFun) + ,move(prototype) ); }; } @@ -382,7 +395,7 @@ namespace engine { } }; - using OutTypesDescriptors = typename Prototype::template OutTypesApply; + using OutTypesDescriptors = typename PROT::template OutTypesApply; using OutDescriptorTup = lib::meta::Tuple; /** A tuple of BufferDescriptor instances for all output buffer types */ diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 97b7a33c3..969232f0f 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -28727,9 +28727,7 @@ - - - +

...sichtbar wenn man ein Trackr-Objekt @@ -29228,9 +29226,7 @@ - - - +

vorher war nämlich das Profil im Canvas selber. @@ -29941,9 +29937,7 @@ - - - +

nested enthält Näherung für slope-up @@ -30587,9 +30581,7 @@ - - - +

Abstraktion: ViewHook (->Canvas) @@ -31504,9 +31496,7 @@ - - - +

damit kann man zwar einen Klassennamen für ein Custom-Widget setzen, also z.B.  'gtkmm__CustomObject_xyz' (wobei man xyz an den ctor übergeben hat). Aber das hat keinen Einfluß auf den Tag-Namen, wie er für den CSS-Selector relevant ist @@ -31627,9 +31617,7 @@ - - - +

...anstatt für jeden schließenden nested scope noch ein weiteres Verb hinzuzufügen. @@ -32143,9 +32131,7 @@ - - - +

den Zeichenvorgang für ein normales Frame-Widget analysieren @@ -32696,9 +32682,7 @@ - - - +

weil die CSS-box-shadow-Effekte zum Zeichnen komplexerer Strukturen nur bedingt nützlich sind. @@ -82215,8 +82199,9 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - + + + @@ -82226,8 +82211,89 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + + + +

+ ...also vor allem die Frage: wirft das jetzt alles über den Haufen, kann man es außen anbauen, oder gar in bestehende Strukturen lediglich hinein-codieren? +

+ + +
- + + + + +

+ ...da ich (wie so oft) mich bereits viel zu tief ins »wie« verstrickt habe... +

+ +
+
+ + + + +

+ ...wobei es darum geht, wie die (bisher rein intuitive) Vorstellung vom Turnout-System in tatsächliche Strukturen übersetzt werden kann, und auf welcher Ebene dabei die Parameter-Verarbeitung sinnvollerweise anzusiedeln ist +

+ +
+
+ + + + +

+ ...denn bereits für die Umsetzung der verknüpften, kaskadierenden Storage für das Turnout-System mußte ich massiv in die Meta-Programmierung einsteigen und mir das Instrumentarium für den Umgang mit beliebigen Datentupeln bereitlegen ... und so fühlte ich mich gerüstet, diese Art Datenhaltung direkt in die Kernverarbeitung hineinzunehmen, die dadurch (abzüglich der Metaprogrammierung) „eigentlich einfach“ wird... +

+ +
+
+
+ + + + +

+ Das bedeutet zweierlei +

+
    +
  • + die Daten in der Invocation werden breiter und weisen Parameter-Werte direkt sichtbar aus +
  • +
  • + die Parameter-Verarbeitung aber wandert von der Oberfläche tief in die Weaving-Patterns hinein und wird beim Aufruf implizit mit angetriggert. +
  • +
+

+ Der Ankerpunkt der normalen Verarbeitung sitzt nun im FeedPrototype, wird also sofort im ersten mount()-Schritt der Webe-Sequenz aufgerufen +

+ +
+
+ + + + + + + +

+ denn nun wird in der Regel erst mal aus dem PortBuilderRoot das Binding für die Processing-Function angelegt ⟹ PortBuilder — und erst von dort gibt man dann Parameter an ⟹ modifizierter PortBuilder +

+ + +
+
+ + +
+ @@ -82271,7 +82337,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + @@ -82287,6 +82353,10 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + @@ -82378,7 +82448,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + @@ -93575,7 +93645,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + @@ -96770,6 +96840,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ @@ -96866,6 +96937,424 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + + + + + + + + + +

+ ⟹ also muß der WeavingBuilder seine Typ-Parameter schwenken können +

+ + +
+
+ + + + +

+ ⟹ und der ihn umschließende PortBuilder muß diesen Schwenk mitgehen +

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

+ schon das Ding mit PatternData ist grauenhaft — und s'werd ois no fui schmlimma +

+ + +
+ +
+ + + + +

+ letztlich auch keine Katastrophe mehr. Da die darüber liegenden Ebenen eigentlich nichts mit der Funktion zu tun haben, läuft es darauf hinaus, zwei dämliche cross-build-Konstruktoren zu coden. Das ist lediglich lästig, weil man alle Datenfelder einzeln aufführen muß. Die sonstige Verwendung im Code wäre durchaus elegant: der äußere Port-Builder ist für das Große Ganze zuständig, und der WeavingBuilder bekommt nur noch einen vorkonfigurierten Parameter-Funktor und adressiert damit das cross-Builder-API des FeedPrototype.... +

+

+ +

+

+ Tja ... was mir daran definitiv nicht gefällt, ist die Vorstellung, mich in 5 Monaten in diese ganze Struktur von oben bis unten wieder hineindenken zu müssen, denn hier gibt es nichts, an dem man sich entlanghangeln könnte, sondern man sieht nur einzelne cross-Builder mit WTF-Faktor +

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

+ das ist dann schon Arbeits-Aufwand, und auch jeweils eine Code-Duplikation +

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

+ Denn das ist die zentrale Eigenschaft des lib::Several, die sich immer mehr als Glücksgriff herausstellt: man kann Detail-Typen unterbringen und sofort auf das Interface löschen +

+ +
+
+ + + + +

+ insofern ist PatternData tatsächlich eine Funktionale Datenstruktur +

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

+ dagegen spricht daß es die schlimmste Stelle noch komplexer  macht +

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

+ template<class RES> +

+

+ using Builder = function<pair<RES, Ctx>(Ctx)>; +

+ +
+
+
+ + + + + +
template<class RES>
+pair<RES, Ctx>
+runBuild(Builder<RES> buildr, Ctx c)
+{
+    return buildr(c);
+}
+ +
+
+
+ + + + +

+ eine Anpassung macht aus einem Resultat +

+

+ einen weiteren Kontext-abhängigen Builder +

+ +
+ + + + +

+ template<class R1, class R2> +

+

+ Extension = function<Builder<R2>(R1)> +

+ +
+
+
+ + + + + +
template<class R1, class R2>
+auto
+StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
+{
+    return [b1, ext](Ctx c) {
+        pair<R1, Ctx> inter = runBuild(b1, c);
+        Builder<R1> extBuilder = extension(inter.val);
+        return runBuild(extBuilder, inter.ctx);
+    };
+}
+ +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ aber das wäre das eigentliche Problem +

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

+ insofern hier nämlich bereits akzidentelle Komplexität generiert wird +

+ + +
+
+ + + + +

+ Man kann die Struktur zwar extrahieren, aber die extrahierte Version läßt sich nicht sinnvoll in einfachereren Begriffen darstellen +

+ + +
+
+ + + + +

+ ...insofern hier Komplexität nicht durch eine Abstraktion reduziert wurde, sondern nur durch Modularisierbarkeit und Zwischenschritte beherrschbarer gemacht wird; aber dies wird durch Generieren zusätzlicher Komplexität erkauft, was den Ansatz insgesamt in Frage stellt +

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

+ Fazit: bite the bullet... +

+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
@@ -96873,7 +97362,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + @@ -96882,6 +97371,17 @@ Date:   Thu Apr 20 18:53:17 2023 +0200

+ + + + +

+ Das Pattern heißt jetzt auch MediaWeavingPattern und ist zum Standard geworden; der Build-Mechanismus im Port-Builder könnte jedes dazu kompatible Pattern  ebenfalls handhaben +

+ + +
+
@@ -97804,14 +98304,14 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- +
- + @@ -97821,8 +98321,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - + +
@@ -97857,8 +98357,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - + + @@ -99176,8 +99676,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - + +