From 72543a8b34747242b894865851e9bf1c02fec4db Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Mon, 3 Feb 2025 22:10:10 +0100 Subject: [PATCH] Invocation: investigate kind of data to be represented in ProcID ...especially the extended attributes remain somewhat nebulous, since non of the prospective usages are close to being implemented right now. It seems, we'll get two distinct sources at construction time of the Node * additional qualifiers from the Library plug-in * internal flags or qualifiers provided by the `NodeBuilder` Another related concern seems to be generation of cache-keys, which however will ''consume'' the proc-hash generated by the ProcID, but not change the ID itself; cache-key generation is a tricky subject and was somewhat overlooked regarding the connection to the `BufferProvider`. Opened a new ticket #1292 as reminder for this issue. --- src/steam/engine/buffer-provider.cpp | 1 + src/steam/engine/feed-manifold.hpp | 2 +- src/steam/engine/proc-id.hpp | 9 +- src/steam/engine/proc-node.cpp | 34 +++++-- src/steam/engine/turnout.hpp | 2 + wiki/thinkPad.ichthyo.mm | 144 ++++++++++++++++++++++++--- 6 files changed, 166 insertions(+), 26 deletions(-) diff --git a/src/steam/engine/buffer-provider.cpp b/src/steam/engine/buffer-provider.cpp index 711854b00..8b057a7e9 100644 --- a/src/steam/engine/buffer-provider.cpp +++ b/src/steam/engine/buffer-provider.cpp @@ -136,6 +136,7 @@ namespace engine { * @note this function may be used right away, without prior announcing, but then * the client should be prepared for exceptions. The #announce operation allows * to establish a reliably available baseline. + * @todo 2/2025 might need to accept a cache key as additional parameter //////////////////////////////////TICKET #1392 : get cache key from computation to the cache backend */ BuffHandle BufferProvider::lockBuffer (BuffDescr const& type) diff --git a/src/steam/engine/feed-manifold.hpp b/src/steam/engine/feed-manifold.hpp index a1a2904e8..5e0751caa 100644 --- a/src/steam/engine/feed-manifold.hpp +++ b/src/steam/engine/feed-manifold.hpp @@ -345,7 +345,7 @@ namespace engine { template ParamStorage (INIT&& ...paramInit) : param{forward (paramInit)...} - { } + { } /////////////////////////////TICKET #1392 : pick up actual param and compute cache key }; /** FeedManifold building block: hold input buffer pointers */ diff --git a/src/steam/engine/proc-id.hpp b/src/steam/engine/proc-id.hpp index f68ea9cf5..5be74e96e 100644 --- a/src/steam/engine/proc-id.hpp +++ b/src/steam/engine/proc-id.hpp @@ -111,22 +111,25 @@ namespace engine { /** * Metadata to qualify a Port (and implicitly the enclosing Node). + * @note must be essentially immutable; should ensure that implementation + * never changes anything constituent for the \ref hash_value(), + * due to de-duplication into a hashtable (see proc-node.cpp). */ class ProcID { StrView nodeName_; StrView portQual_; StrView argLists_; - ProcAttrib attrib_{}; + ProcAttrib attrib_; - ProcID (StrView nodeSymb, StrView portQual, StrView argLists); + ProcID (StrView nodeSymb, StrView portQual, StrView argLists, ProcAttrib); using ProcNodeRef = std::reference_wrapper; using Leads = lib::Several; public: /** build and register a processing ID descriptor */ - static ProcID& describe (StrView nodeSymb, StrView portSpec); + static ProcID& describe (StrView nodeSymb, StrView portSpec, ProcAttrib extAttrib =ProcAttrib{}); /* === symbolic descriptors === */ diff --git a/src/steam/engine/proc-node.cpp b/src/steam/engine/proc-node.cpp index 8215eb84b..96021386f 100644 --- a/src/steam/engine/proc-node.cpp +++ b/src/steam/engine/proc-node.cpp @@ -183,9 +183,11 @@ namespace engine { * @remark this is the only public access point to ProcID entries, * which are automatically deduplicated and managed in a common registry * and retained until end of the Lumiera process (never deleted). + * @todo isn't returning a non-const reference dangerous? someone might add + * mutable state then, thereby undercutting de-duplication into a hashtable. */ ProcID& - ProcID::describe (StrView nodeSymb, StrView portSpec) + ProcID::describe (StrView nodeSymb, StrView portSpec, ProcAttrib extAttrib) { REQUIRE (not isnil (nodeSymb)); REQUIRE (not isnil (portSpec)); @@ -196,7 +198,7 @@ namespace engine { "Node:%s Spec:%s"} % nodeSymb % portSpec }; - auto res = procRegistry.insert (ProcID{nodeSymb, portSpec.substr(0,p), portSpec.substr(p)}); + auto res = procRegistry.insert (ProcID{nodeSymb, portSpec.substr(0,p), portSpec.substr(p), extAttrib}); ProcID& entry{unConst (*res.first)}; if (res.second) {// new record placed into the registry @@ -209,10 +211,11 @@ namespace engine { } /** @internal */ - ProcID::ProcID (StrView nodeSymb, StrView portQual, StrView argLists) + ProcID::ProcID (StrView nodeSymb, StrView portQual, StrView argLists, ProcAttrib extAttrib) : nodeName_{nodeSymb} , portQual_{portQual} , argLists_{argLists} + , attrib_{extAttrib} { } /** @@ -386,6 +389,7 @@ namespace engine { } + namespace {// create a »backdoor access« into actual weaving-pattern instances using _DummyProc = void(&)(NullType*); @@ -393,12 +397,25 @@ namespace engine { using _DummyMediaWeaving = MediaWeavingPattern<_DummyProto>; using _RecastMediaWeaving = _TurnoutDiagnostic<_DummyMediaWeaving>; + using _EmptySpec = decltype(buildParamSpec()); + using _DummyParamWeaving = ParamWeavingPattern<_EmptySpec>; + using _RecastParamWeaving = _TurnoutDiagnostic<_DummyParamWeaving>; + lib::Several EMPTY_PRECURSORS; } - /** - * Intrude into the Turnout and find out about source connectivity + * Intrude into the Turnout and find out about source connectivity. + * At interface level, this information about predecessor ports is not retained, + * but for the most common weaving patterns (Port implementations) there is a way + * to access implementation internals, bypassing the \ref Port interface; otherwise + * a reference to an empty port collection is returned. + * @warning this is a possibly dangerous low-level access, bypassing type safety. + * It relies on flags in the ProcID attributes to be set properly by the builder, + * and it relies on a common shared prefix in the memory layout of weaving patterns. + * @remark the \ref Port interface is kept minimal, since a very large number of + * implementations and template instantiations can be expected, so that any further + * function would cause a lot of additional and mostly redundant code generation. */ lib::Several const& PortDiagnostic::srcPorts() @@ -408,7 +425,12 @@ namespace engine { auto [leads,types] = _RecastMediaWeaving::accessInternal (p_); return leads; } -/////////////////////////////////////////////////OOO add branch here to support Proxy-patterns + else + if (p_.procID.hasProxyPatt()) + { + Port& delegate = std::get<0>(_RecastParamWeaving::accessInternal (p_)); + return watch(delegate).srcPorts(); + } // recursive invocation on delegate of proxy else return EMPTY_PRECURSORS; } diff --git a/src/steam/engine/turnout.hpp b/src/steam/engine/turnout.hpp index 33495b7ae..2dceaff85 100644 --- a/src/steam/engine/turnout.hpp +++ b/src/steam/engine/turnout.hpp @@ -144,6 +144,8 @@ namespace engine { + + /** * @internal »Backdoor« for diagnostic * @warning must be kept **layout compatible** with Turnout diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 9c7237e5b..ff751b733 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -94909,6 +94909,12 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + + + @@ -94943,6 +94949,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+
@@ -102842,7 +102849,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + @@ -102851,6 +102858,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)

+ @@ -103260,7 +103268,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + @@ -103274,6 +103282,15 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) + + + + + + + + + @@ -104890,6 +104907,11 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) + + + + + @@ -105078,6 +105100,26 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) + + + + + + + + + + +

+ ...braucht einen aktuellen Port-Hash, berechnet aber auf dieser Basis direkt den Beitrag der aktuell erzeugten Parameter-Werte +

+ + +
+
+
+ + @@ -105141,6 +105183,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) +
@@ -106235,30 +106278,66 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
- + - + - - - +

MediaWeavingPattern ⟵  Dummy-Funktion void(&)(NullType*)

- -
+
+ + + + +

+ ParamWeavingPattern ⟵  empty Spec buildParamSpec() +

+ +
+ +
+ + + + +

+ ....da ich im Moment nur spekuliere, und ein konkreter Bezugspunkt noch in weiter Ferne liegt; wegen der de-Duplikation sollten alle Quellen bereits in den statischen Factory-Aufruf gehen; man könnte natürlich eine Builder-DSL davor setzen (nicht daß wir schon genug Builder in dem Bereich hätten....) +

+ +
+
- + + + + + + + + + + + + + + + + + + + @@ -106280,18 +106359,33 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + - - + + - - + + + + + + + + + + +

+ Da Fall-1 am Wichtigsten ist, orientiert sich das Interface daran und reicht einfach die Collection der Vorgänger-Ports per Referenz heraus. Leider haben wir aber im Fall de ParamWeavingPattern gar keine Collection der Vorgänger-Ports, sondern nur eine direkte Referenz auf den Delegate des Proxy; und da es sich um einen einfachen Funktionsaufruf handelt, haben wir keinen Ort, an dem eine solche Collection hilfsweise konstruiert und abgelegt werden könnte. Deshalb bleibt nur, entweder in dem Fall gar nichts zu liefern, d.h. zwei verschiedene Methoden zu bieten, oder eben die Rekursion auf das Delegate (das dann hoffentlich ein Manifold-Pattern ist und deshalb eine solche Collection hat) +

+ +
+ +
@@ -106300,6 +106394,19 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
+ + + + +

+ ...entweder, indem es direkt im Turnout eine Querverbindung gibt, oder duch einen low-Level-Zugangsweg analog zu den Source-Ports +

+ +
+ + + +
@@ -107366,7 +107473,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + @@ -148253,6 +148360,11 @@ std::cout << tmpl.render({"what", "World"}) << s + + + + +