Invocation: now able to pass parameter tuples

This basically completes the reworked implementation of the `FeedManifold`
An important aspect however is now separated out and still remains to be solved:
''how to configure and invoke a Parameter-Functor?''
This commit is contained in:
Fischlurch 2024-12-19 19:44:21 +01:00
parent 3a3b7e4dd7
commit 07410e14f1
3 changed files with 286 additions and 95 deletions

View file

@ -25,7 +25,7 @@
** the aforementioned »network of Render Nodes.« At this point, external functionality must actually
** be connected to internal structures: this purpose is served by the FeedManifold.
**
** This amounts to an tow-stage adaptation process. Firstly, the plug-in for an external library
** This amounts to an two-stage adaptation process. Firstly, the plug-in for an external library
** has to wrap-up and package the library functions into an _invocation functor_ which thereby
** creates a _low-level Specification_ of the functionality to invoke. This functor is picked up
** and stored as a prototype within the associated render node. More specifically, each node can
@ -46,7 +46,7 @@
** might have to create a wrapper type in cases where the external library requires to use a
** specific constructor function for buffers (if this requirement turns out as problematic,
** there is leeway to pass constructor arguments to such a wrapper yet Lumiera will insist
** on managing the memory, so frameworks insisting on their own memory management will have
** on managing the memory, so frameworks enforcing their own memory management will have
** to be broken up and side-stepped, in order to be usable with Lumiera).
** - when several and even mixed types of a kind must be given, e.g. several buffers or
** several parameters, then the processing functor should be written such as to
@ -56,12 +56,12 @@
** A suitable storage layout is chosen at compile type, based on the given functor type.
** - essentially, FeedManifold is structured storage with some default-wiring.
** - the trait functions #hasInput() and #hasParam() should be used by downstream code
** to find out if some part of the storage is present and branch accordingly
** to find out if some part of the storage is present and branch accordingly...
** @todo 12/2024 figure out how constructor-arguments can be passed flexibly
** @remark in the first draft version of the Render Engine from 2009/2012, there was an entity
** called `BuffTable`, which however provided additional buffer-management functionality.
** called `BuffTable`, which however provided additional buffer-management capabilities.
** This name describes well the basic functionality, which can be hard to see with all
** this additional meta-programming related to the flexible functor signature. When it
** the additional meta-programming related to the flexible functor signature. When it
** comes to actual invocation, we collect input buffers from predecessor nodes and
** we prepare output buffers, and then we pass both to a processing function.
**
@ -70,6 +70,7 @@
** We have still to reach the point were the engine becomes operational!!!
** @see NodeBase_test
** @see weaving-pattern-builder.hpp
** @see lib::meta::ElmTypes in variadic-helper.hpp : uniform processing of »tuple-like« data
*/
@ -158,6 +159,7 @@ namespace engine {
* which all may be simple types, tuples or arrays.
* @note »Buffers« are always accepted by pointer, which allows
* to distinguish parameter and data «slots«
* @see VariadicHelper_test::rebuild_variadic()
*/
template<class FUN>
struct _ProcFun
@ -247,33 +249,46 @@ namespace engine {
/**
* Configuration context for a FeedManifold.
* This type-rebinding helper provides a storage configuration
* specifically tailored to serve the invocation of \a FUN
* @note storage segments for input and parameters are only present
* when the given function is classified by _ProcFun<FUN>
* as handling input and / or parameters.
* @remark since BuffHandle is not default-constructible, but must be
* retrieved from a BufferProvider rather, a chunk of uninitialised
* storage is used to accept the `BuffHandle`s allocated and populated
* with results from preceding Nodes.
*/
template<class FUN>
struct _StorageSetup
{
using _Trait = _ProcFun<FUN>;
enum{ FAN_I = _Trait::FAN_I
, FAN_O = _Trait::FAN_O
};
static constexpr bool hasInput() { return _Trait::hasInput(); }
static constexpr bool hasParam() { return _Trait::hasParam(); }
using ParSig = typename _Trait::SigP;
enum{ FAN_P = hasParam()? _Trait::FAN_P : 0
, FAN_I = hasInput()? _Trait::FAN_I : 0
, FAN_O = _Trait::FAN_O
};
template<size_t fan>
using BuffS = lib::UninitialisedStorage<BuffHandle, fan>;
// ^^^ can not be default-constructed
using BuffI = BuffS<FAN_I>;
using BuffO = BuffS<FAN_O>;
using ArgI = typename _Trait::SigI;
using Param = std::conditional_t<hasParam(), typename _Trait::SigP, std::tuple<>>;
using ArgI = std::conditional_t<hasInput(), typename _Trait::SigI, std::tuple<>>;
using ArgO = typename _Trait::SigO;
/** FeedManifold building block: hold parameter data */
struct ParamStorage
{
ParSig param;
Param param;
ParamStorage() = default;
@ -283,12 +298,14 @@ namespace engine {
{ }
};
/** FeedManifold building block: hold input buffer pointers */
struct BufferSlot_Input
{
BuffI inBuff;
ArgI inArgs{};
};
/** FeedManifold building block: hold output buffer pointers */
struct BufferSlot_Output
{
BuffO outBuff;
@ -296,7 +313,7 @@ namespace engine {
};
template<typename F>
using enable_if_hasParam = typename lib::meta::enable_if_c<_ProcFun<std::decay_t<F>>::hasParam()>::Type;
using enable_if_hasParam = typename lib::meta::enable_if_c<_ProcFun<F>::hasParam()>::type;
template<class X>
using NotProvided = Tagged<lib::meta::NullType, X>;
@ -311,6 +328,7 @@ namespace engine {
/**
* Data Storage block for the FeedManifold
* Flexibly configured based on the processing function.
* @remark mixed-in as base-class
*/
struct Storage
: util::NonCopyable
@ -325,10 +343,9 @@ namespace engine {
: process{forward<F> (fun)}
{ }
template<typename F, typename...INIT, typename =disable_if_self<Storage,F>
, typename =enable_if_hasParam<F>>
Storage (F&& fun, INIT&& ...paramInit)
: FeedParam{forward<INIT> (paramInit)...}
template<typename F, typename =enable_if_hasParam<F>>
Storage (Param p, F&& fun)
: FeedParam{move (p)}
, process{forward<F> (fun)}
{ }
};
@ -339,10 +356,33 @@ namespace engine {
* Adapter to connect input/output buffers to a processing functor backed by an external library.
* Essentially, this is structured storage tailored specifically to a given functor signature.
* Tables of buffer handles are provided for the downstream code to store results received from
* preceding odes or to pick up calculated data after the invocation. From these BuffHandle entries,
* preceding nodes or to pick up calculated data after invocation. From these BuffHandle entries,
* buffer pointers are retrieved and packaged suitably for use by the wrapped invocation functor.
* This setup is used by a »weaving pattern« within the invocation of a processing node for the
* purpose of media processing or data calculation.
* This setup is intended for use by a »weaving pattern« within the invocation of a processing node
* for the purpose of media processing or data calculation.
*
* # Interface exposed to down-stream code
* Data fields are typed to suit the given functor \a FUN, and are present only when needed
* - `param` holds a parameter value or tuple of values, as passed to the constructor
* - `inBuff` and `outBuff` are chunks of \ref UninitialisedStorage with suitable dimension
* to hold an array of \ref BuffHandle to organise input- and output-buffers
* - the constants `FAN_P`, `FAN_I` and `FAN_O` reflect the number of individual elements
* connected for parameters, inputs and outputs respectively.
* - `inBuff.array()` and `outBuff.array()` expose the storage for handles as std::array,
* with suitable dimension, subscript-operator and iteration. Note however that the
* storage itself is _uninitialised_ and existing handles must be _emplaced_ by
* invoking copy-construction e.g. `outBuff.createAt (idx, givenHandle)`
* - after completely populating all BuffHandle slots this way, FeedManifold::connect()
* will pick up buffer pointers and transfer them into the associated locations in
* the input and output arguments `inArgs` and `outArgs`
* - finally, FeedManifold::invoke() will trigger the stored processing functor,
* passing `param`, `inArgs` and `outArgs` as appropriate.
* The `constexpr` functions #hasInput() and #hasParam() can be used to find out
* if the functor was classified to take inputs and / or parameters.
* @note destructors of parameter values will be invoked, but nothing will be done
* for the BuffHandle elements; the caller is responsible to perform the
* buffer management protocol, i.e. invoke BuffHandle::emit()
* and BuffHandle::release()
*
* @todo WIP-WIP 12/24 now adding support for arbitrary parameters /////////////////////////////////////TICKET #1386
*/
@ -369,8 +409,10 @@ namespace engine {
using ArgI = typename _S::ArgI;
using ArgO = typename _S::ArgO;
using Param = typename _S::Param;
enum{ FAN_I = _S::FAN_I
, FAN_O = _S::FAN_O
, FAN_P = _S::FAN_P
};
static constexpr bool hasInput() { return _S::hasInput(); }
@ -415,6 +457,12 @@ namespace engine {
void
invoke()
{
if constexpr (hasParam())
if constexpr (hasInput())
_F::process (_F::param, _F::inArgs, _F::outArgs);
else
_F::process (_F::param, _F::outArgs);
else
if constexpr (hasInput())
_F::process (_F::inArgs, _F::outArgs);
else

View file

@ -37,6 +37,7 @@ using std::tuple;
using std::array;
using util::isSameAdr;
using lib::test::showType;
using lib::izip;
namespace steam {
@ -75,6 +76,23 @@ namespace test {
/** @test the FeedManifold as adapter between Engine and processing library
* - bind local λ with various admissible signatures
* - construct specifically tailored FeedManifold types
* - use the DiagnosticBufferProvider for test buffers
* - create FeedManifold instance, passing the λ and additional parameters
* - connect BuffHandle for these buffers into the FeedManifold instance
* - trigger invocation of the function
* - look into the buffers and verify effect
* @remark within each Render Node, a FeedManifold is used as junction
* to tap into processing functionality provided by external libraries.
* Those will be adapted by a Plug-in, to be loaded by the Lumiera core
* application. The _signature of a functor_ linked to the FeedManifold
* is used as kind of a _low-level-specification_ how to invoke external
* processing functions. Obviously this must be complemented by a more
* high-level descriptor, which is interpreted by the Builder to connect
* a suitable structure of Render Nodes.
* @see feed-manifold.h
* @see NodeLinkage_test
*/
void
verify_FeedManifold()
@ -84,11 +102,15 @@ namespace test {
using Buffer = long;
//______________________________________________________________
// Example-1: a FeedManifold to adapt a simple generator function
auto fun_singleOut = [&](Buffer* buff) { *buff = r1; };
using M1 = FeedManifold<decltype(fun_singleOut)>;
CHECK (not M1::hasInput());
CHECK (not M1::hasParam());
CHECK (0 == M1::FAN_P);
CHECK (0 == M1::FAN_I);
CHECK (1 == M1::FAN_O);
// instantiate...
M1 m1{fun_singleOut};
CHECK (1 == m1.outBuff.array().size());
@ -113,6 +135,7 @@ namespace test {
CHECK (buff.accessAs<long>() == r1); // result: the random number r1 was written into the buffer.
//_____________________________________________________________
// Example-2: adapt a function to process input -> output buffer
auto fun_singleInOut = [](Buffer* in, Buffer* out) { *out = *in + 1; };
using M2 = FeedManifold<decltype(fun_singleInOut)>;
@ -151,6 +174,7 @@ namespace test {
CHECK (buffOut.accessAs<long>() == r1+1);
//______________________________________
// Example-3: accept complex buffer setup
using Sequence = array<Buffer,3>;
using Channels = array<Buffer*,3>;
@ -158,7 +182,7 @@ namespace test {
auto fun_complexInOut = [](Channels in, Compound out)
{
auto [seq,extra] = out;
for (auto [i,b] : lib::izip(in))
for (auto [i,b] : izip(in))
{
(*seq)[i] = *b + 1;
*extra += *b;
@ -216,6 +240,76 @@ namespace test {
CHECK ( o01 == *ia1+1);
CHECK ( o02 == *ia2+1);
CHECK (*oa1 == -55 + *ia0+*ia1+*ia2); ///////////////////////////////////////////OOO should be -33
//_________________________________
// Example-4: pass a parameter tuple
using Params = tuple<short,long>;
// Note: demonstrates mix of complex params, an array for input, but just a simple output buffer
auto fun_ParamInOut = [](Params param, Channels in, Buffer* out)
{
auto [s,l] = param;
*out = 0;
for (Buffer* b : in)
*out += (s+l) * (*b);
};
using M4 = FeedManifold<decltype(fun_ParamInOut)>;
CHECK (M4::hasInput());
CHECK (M4::hasParam());
CHECK (2 == M4::FAN_P);
CHECK (3 == M4::FAN_I);
CHECK (1 == M4::FAN_O);
CHECK (showType<M4::ArgI>() == "array<long*, 3ul>"_expect);
CHECK (showType<M4::ArgO>() == "long *"_expect);
CHECK (showType<M4::Param>() == "tuple<short, long>"_expect);
// Note: instantiate passing param values as extra arguments
short r2 = 1+rani(10);
long r3 = rani(1000);
M4 m4{Params{r2,r3}, fun_ParamInOut}; // parameters directly given by-value
auto& [p0,p1] = m4.param;
CHECK (p0 == r2); // parameter values exposed through manifold
CHECK (p1 == r3);
// wire-in existing buffers for this example
m4.inBuff.createAt (0, buffI0);
m4.inBuff.createAt (1, buffI1);
m4.inBuff.createAt (2, buffI2);
m4.outBuff.createAt(0, buffO1);
CHECK (*ia0 == r1 ); // existing values in the buffers....
CHECK (*ia1 == r1+1);
CHECK (*ia2 == -55 ); /////////////////////////////////////////////////////OOO should be -22
CHECK (*oa1 == -55 + *ia0+*ia1+*ia2); ///////////////////////////////////////////OOO should be -33
m4.connect();
m4.invoke(); // processing combines input buffers with parameters
CHECK (*oa1 == (r2+r3) * (r1 + r1+1 -55)); /////////////////////////////////////OOO should be -22
//______________________________________
// Example-5: simple parameter and output
auto fun_singleParamOut = [&](short param, Buffer* buff) { *buff = param-1; };
using M5 = FeedManifold<decltype(fun_singleParamOut)>;
CHECK (not M5::hasInput());
CHECK ( M5::hasParam());
CHECK (1 == M5::FAN_P);
CHECK (0 == M5::FAN_I);
CHECK (1 == M5::FAN_O);
CHECK (showType<M5::ArgI>() == "tuple<>"_expect);
CHECK (showType<M5::ArgO>() == "long *"_expect);
CHECK (showType<M5::Param>() == "short"_expect);
// instantiate, directly passing param value
M5 m5{r2, fun_singleParamOut};
// wire with one output buffer
m5.outBuff.createAt(0, buffO1);
m5.connect();
CHECK (m5.param == r2); // the parameter value passed to the ctor
// CHECK (m5.inArgs ); // does not compile because storage field is not provided
CHECK (*m5.outArgs == *oa1); // still previous value sitting in the buffer...
m5.invoke();
CHECK (*oa1 == r2 - 1); // processing has placed result based on param into output buffer
}
};

View file

@ -26196,9 +26196,7 @@
</node>
<node CREATED="1576757228532" ID="ID_292264284" MODIFIED="1576757344691" TEXT="es ist eine direkte Konsequenz der Abstraktion">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
und zwar, genauer gesagt, eine Konsequenz der Entscheidung, nicht nur einen ViewHook, sondern ein ViewHooked zu machen. Ich hab die Beziehung in's Strukturelle hinen genommen. Damit mu&#223; auch die Wurzel diese Struktur unterst&#252;tzen, und damit wird an dieser Stelle die Abstraktion undicht.
@ -26850,9 +26848,7 @@
</body>
</html></richcontent>
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
Ich habe beim Upgrade auf Debian-Stretch mal nachgemessen: tats&#228;chlich hat mein Display 94dpi. Demnach w&#228;re der andere weithin &#252;bliche Wert von 96dpi pr&#228;ziser. Jedoch bin ich nach mehreren Experimenten bei 90dpi geblieben, da f&#252;r mich so die Schriftarten die &#8222;richtige Gr&#246;&#223;e&#8220; haben &#8212; das mag auch daran liegen, da&#223; ich leicht kurzsichtig bin und typischeweise etwas n&#228;her am Bildschirm sitze.
@ -27481,9 +27477,7 @@
<icon BUILTIN="button_ok"/>
<node COLOR="#435e98" CREATED="1677718715763" FOLDED="true" ID="ID_354383908" MODIFIED="1677775372224" TEXT="Balken ist unten zu kurz">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
...aber der Code schaut <i>komplett richtig</i>&#160;aus; man mu&#223; ja die Differenz zwischen oberem und unterem Anker als H&#246;he ansetzen, und man mu&#223; dabei bedenken, da&#223; die Zeichnung des Balkens dann skaliert wird, jedoch <i>nach Skalierung</i>&#160;genau bis zum unteren Anker reichen soll (und eben dieses funktioniert nicht)
@ -28069,9 +28063,7 @@
<node CREATED="1677626560803" ID="ID_1545300397" MODIFIED="1677626590307" TEXT="DPI &#x27fc; Anzahl Pixel per inch"/>
<node CREATED="1677626435688" ID="ID_1985359358" MODIFIED="1677626725417">
<richcontent TYPE="NODE"><html>
<head>
</head>
<head/>
<body>
<p>
daraus absolute Font-Size und weiter wie&#160;<font color="#8323d6">[Fall-1]</font>
@ -29182,9 +29174,7 @@
<icon BUILTIN="button_ok"/>
<node CREATED="1555808300703" ID="ID_621465643" MODIFIED="1576282358063" TEXT="kann/sollte die L&#xf6;song mehr integriert sein?">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
sollten z.B. die Konstruktor-Funktionen nicht unmittelbar mit definiert werden?
@ -30387,9 +30377,7 @@
</node>
<node CREATED="1672847699754" ID="ID_921332802" MODIFIED="1672867412724" TEXT="Feststellung: Gr&#xf6;&#xdf;e &quot;st&#xf6;&#xdf;t an&quot; an gesetzter Canvas-Gr&#xf6;&#xdf;e">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
Beispiel:
@ -31389,9 +31377,7 @@
<node CREATED="1562854835241" ID="ID_766058517" MODIFIED="1562854840584" TEXT="mit geeignetem Refcounting">
<node CREATED="1562854871923" ID="ID_332819323" MODIFIED="1562854888696" TEXT="~WidgetPath()">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
WidgetPath::~WidgetPath() noexcept
@ -32585,9 +32571,7 @@
<node CREATED="1564500576627" ID="ID_979278974" MODIFIED="1564500613622" TEXT="weil das Hinzuf&#xfc;gen von Klassen eine vorgesehene Operation ist"/>
<node CREATED="1564500614693" ID="ID_178343581" MODIFIED="1564500683747" TEXT="Hinzuf&#xfc;gen eines CssProvider ist eine aufwendige Sache">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
da wird ggfs eine neue CSS-Kaskade erstellt, oder die bestehende Kaskade erweitert.
@ -34027,9 +34011,7 @@
</node>
<node CREATED="1584202974665" ID="ID_920397941" MODIFIED="1584203052619" TEXT="eigentlich ehr vom Anzeigestil abh&#xe4;ngig">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
oder umgekeht....
@ -34939,9 +34921,7 @@
<node CREATED="1666451404745" ID="ID_1685238185" MODIFIED="1666451415979" TEXT="Clip mu&#xdf; seine eigene Ausdehnung festsetzen k&#xf6;nnen"/>
<node CREATED="1666451422758" ID="ID_1448482248" MODIFIED="1666451488041">
<richcontent TYPE="NODE"><html>
<head>
</head>
<head/>
<body>
<p>
<u>L&#246;sung</u>: Interface <font face="Monospaced"><b>DisplayMetric</b></font>&#160;im <font face="Monospaced" color="#1e128f">CanvasHook</font>
@ -35300,9 +35280,7 @@
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1675384884653" ID="ID_1042919827" MODIFIED="1675385087573" TEXT="Lifecycle f&#xfc;r Content-Renderer potentiell problematisch">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
...da das ElementBoxWidget nicht die ownership f&#252;r sein Kind-Widget (den ContentRenderer) &#252;bernimmt; daher mu&#223; das Kind l&#228;nger leben als das ElementBoxWidget, aber genau das ist <b>nicht gew&#228;hrleistet</b>, wenn das Clip-Delegate von ElementBoxWidget <b>erbt</b>.
@ -36009,9 +35987,7 @@
<icon BUILTIN="button_ok"/>
<node COLOR="#435e98" CREATED="1532788681197" FOLDED="true" HGAP="336" ID="ID_32192034" MODIFIED="1576282358033" TEXT="bei GTK selber abschauen" VSHIFT="-52">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
erinnere mich, diverse Mechanismen gesehen zu haben,
@ -88412,10 +88388,10 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1734310118603" ID="ID_1954508996" MODIFIED="1734310510263" TEXT="Feed-Manifold: Eigenschaften demonstrieren">
<node COLOR="#338800" CREATED="1734310118603" ID="ID_1954508996" MODIFIED="1734631398113" TEXT="Feed-Manifold: Eigenschaften demonstrieren">
<linktarget COLOR="#406cd3" DESTINATION="ID_1954508996" ENDARROW="Default" ENDINCLINATION="-484;30;" ID="Arrow_ID_640616380" SOURCE="ID_1710382999" STARTARROW="None" STARTINCLINATION="-2974;268;"/>
<icon BUILTIN="pencil"/>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1734310213994" ID="ID_691754137" MODIFIED="1734556323351" TEXT="mehrere Varianten von Funktions-Signaturen vorstellen">
<icon BUILTIN="button_ok"/>
<node COLOR="#338800" CREATED="1734310213994" ID="ID_691754137" MODIFIED="1734631391185" TEXT="mehrere Varianten von Funktions-Signaturen vorstellen">
<icon BUILTIN="yes"/>
<node COLOR="#338800" CREATED="1734310245306" ID="ID_1881940952" MODIFIED="1734535951144" TEXT="reiner Output mit einem Buffer">
<icon BUILTIN="button_ok"/>
@ -88428,8 +88404,12 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<node COLOR="#338800" CREATED="1734552381857" ID="ID_1059351113" LINK="#ID_1910303400" MODIFIED="1734556282597" TEXT="Input &#x27fc; Output mit komplexen Typen">
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1734310306689" ID="ID_246862993" MODIFIED="1734310327544" TEXT="Input &#x27fc; Output mit einem Buffer mit einem Parameter">
<icon BUILTIN="flag-yellow"/>
<node COLOR="#338800" CREATED="1734625697475" ID="ID_215671450" MODIFIED="1734631607257" TEXT="Input &#x27fc; Output mit komplexem Mix + Parameter-Tupel">
<linktarget COLOR="#4dcd43" DESTINATION="ID_215671450" ENDARROW="Default" ENDINCLINATION="747;40;" ID="Arrow_ID_869346495" SOURCE="ID_641534673" STARTARROW="None" STARTINCLINATION="-627;30;"/>
<icon BUILTIN="button_ok"/>
</node>
<node COLOR="#338800" CREATED="1734310306689" ID="ID_246862993" MODIFIED="1734631358343" TEXT="einfacher Output mit einem Buffer mit einem Parameter-Wert">
<icon BUILTIN="button_ok"/>
</node>
</node>
<node COLOR="#338800" CREATED="1734310333302" ID="ID_1944960168" MODIFIED="1734391162068" TEXT="jeweils eine Manifold erstellen">
@ -88796,6 +88776,10 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<icon BUILTIN="button_ok"/>
</node>
</node>
<node COLOR="#338800" CREATED="1734631471232" ID="ID_1048829589" MODIFIED="1734631527235" TEXT="Feed-Prototype: Parameter-Behandlung zeigen">
<linktarget DESTINATION="ID_1048829589" ENDARROW="Default" ID="Arrow_ID_58841322" SOURCE="ID_1416331336" STARTARROW="None" STARTINCLINATION="-90;-5;" COLOR="#406cd3" ENDINCLINATION="-484;30;"/>
<icon BUILTIN="button_ok"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1733525831136" ID="ID_1553180375" MODIFIED="1733527489987" TEXT="NodeBuilder_test">
<icon BUILTIN="flag-yellow"/>
@ -92097,16 +92081,16 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
...und die neueren Compiler k&#246;nnen sich auch nicht beschweren, da&#223; wir anonyme Typen in die Storage binden, und obendrein sind so die ganzen Meta-Definitionen wirklich downstream nicht mehr sichtbar
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node CREATED="1734583328473" ID="ID_1649151484" MODIFIED="1734583342689" TEXT="dann gibt man den Basis-Storage-Modulen explizit Namen"/>
<node CREATED="1734583343988" ID="ID_430940225" MODIFIED="1734583360386" TEXT="und definiert dann erst die nested struct Storage"/>
<node CREATED="1734583361711" ID="ID_568129151" MODIFIED="1734583372909" TEXT="FeedManifold erbt dann von dieser"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1734583395510" ID="ID_1700565848" MODIFIED="1734583633132" TEXT="mu&#xdf; dann einen weiteren Ctor auf dieser Basisklasse conditional sichtbar machen">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#fafe99" COLOR="#fa002a" CREATED="1734583422523" ID="ID_907955668" MODIFIED="1734583446849" TEXT="puh .... FEHLER FEHLER FEHLER FEHLER">
<node COLOR="#338800" CREATED="1734583395510" ID="ID_1700565848" MODIFIED="1734625568156" TEXT="mu&#xdf; dann einen weiteren Ctor auf dieser Basisklasse conditional sichtbar machen">
<icon BUILTIN="button_ok"/>
<node BACKGROUND_COLOR="#e8d88a" COLOR="#d5017d" CREATED="1734583422523" ID="ID_907955668" MODIFIED="1734625367025" TEXT="puh .... FEHLER FEHLER FEHLER FEHLER">
<arrowlink COLOR="#fee7c1" DESTINATION="ID_1031755621" ENDARROW="Default" ENDINCLINATION="367;-22;" ID="Arrow_ID_988126033" STARTARROW="None" STARTINCLINATION="377;26;"/>
<icon BUILTIN="broken-line"/>
</node>
<node CREATED="1734583449376" ID="ID_1289337298" MODIFIED="1734583476552" TEXT="der Compiler pr&#xfc;ft Copy-Konstruktoren"/>
@ -92121,10 +92105,64 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</html></richcontent>
</node>
<node CREATED="1734583588029" ID="ID_442569333" MODIFIED="1734583600327" TEXT="mu&#xdf; disable_if_self&lt;Storage,F&gt; vorschalten"/>
</node>
<node COLOR="#338800" CREATED="1734583606218" ID="ID_1419317245" MODIFIED="1734583618846" TEXT="compiliert wieder und bestehende Tests laufen....">
<node COLOR="#338800" CREATED="1734583606218" ID="ID_1419317245" MODIFIED="1734623582486" TEXT="compiliert wieder und bestehende Tests laufen....">
<icon BUILTIN="button_ok"/>
</node>
<node COLOR="#435e98" CREATED="1734623550923" ID="ID_1042555078" MODIFIED="1734625141081" TEXT="funktioniert aber noch nicht">
<icon BUILTIN="broken-line"/>
<node COLOR="#c9018d" CREATED="1734624810569" ID="ID_725229821" MODIFIED="1734625028735" TEXT="&#xd83d;&#xdca3; &#xd83d;&#xdc7b; Panik...">
<icon BUILTIN="smiley-angry"/>
</node>
<node COLOR="#435e98" CREATED="1734624864987" ID="ID_817704364" MODIFIED="1734625134765" TEXT="Analyse...">
<icon BUILTIN="yes"/>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1734624903372" ID="ID_951655525" MODIFIED="1734624977374">
<richcontent TYPE="NODE"><html>
<head/>
<body>
<p>
enable_if_hasParam : verwendet&#160;statt <font face="Monospaced" color="#ac0909">Type</font>&#160;statt <font face="Monospaced" color="#ac0909">type</font>
</p>
</body>
</html>
</richcontent>
<icon BUILTIN="broken-line"/>
</node>
<node COLOR="#ff00ca" CREATED="1734624978674" ID="ID_514782434" MODIFIED="1734625013697" TEXT="ja dann KANNs ja gar nicht funktionieren...">
<icon BUILTIN="ksmiletris"/>
</node>
<node BACKGROUND_COLOR="#db96af" COLOR="#fa002a" CREATED="1734625072838" ID="ID_1031755621" MODIFIED="1734625330133" TEXT="die L&#xf6;sung ist gef&#xe4;hrlich komplex">
<linktarget COLOR="#fee7c1" DESTINATION="ID_1031755621" ENDARROW="Default" ENDINCLINATION="367;-22;" ID="Arrow_ID_988126033" SOURCE="ID_907955668" STARTARROW="None" STARTINCLINATION="377;26;"/>
<font ITALIC="true" NAME="SansSerif" SIZE="12"/>
<icon BUILTIN="clanbomber"/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#c8c0b6" COLOR="#435e98" CREATED="1734625145459" ID="ID_1322521981" MODIFIED="1734625173692" TEXT="bessere L&#xf6;sung: klare Argument-Ordnung">
<icon BUILTIN="idea"/>
<node CREATED="1734625178200" ID="ID_1065935269" MODIFIED="1734625203129" TEXT="kann davon ausgehen da&#xdf; ohnehin das Parameter-Tuple als Wert vorliegt">
<icon BUILTIN="yes"/>
</node>
<node CREATED="1734625205276" ID="ID_518154967" MODIFIED="1734625259337" TEXT="setzte dies an 1.Stelle &#x27f9; schlie&#xdf;t dann auch copy-ctor aus">
<icon BUILTIN="idea"/>
</node>
<node CREATED="1734625269435" ID="ID_1585355729" MODIFIED="1734625307890" TEXT="sollte trotzdem die enable_if_hasParam beibehalten &#x27f6; bessere Fehlermeldung"/>
</node>
<node COLOR="#338800" CREATED="1734625381943" ID="ID_755107673" MODIFIED="1734625507411" TEXT="im Test best&#xe4;tigt: funktioniert">
<icon BUILTIN="button_ok"/>
</node>
<node COLOR="#436e98" CREATED="1734625522105" ID="ID_777408007" MODIFIED="1734625555155" TEXT="pfffffft........">
<font ITALIC="true" NAME="SansSerif" SIZE="10"/>
<icon BUILTIN="smiley-neutral"/>
</node>
</node>
<node COLOR="#338800" CREATED="1734625584442" ID="ID_641534673" MODIFIED="1734631614375" TEXT="komplexer gemischter Aufruf im Unit-Test durchgespielt....">
<arrowlink COLOR="#4dcd43" DESTINATION="ID_215671450" ENDARROW="Default" ENDINCLINATION="747;40;" ID="Arrow_ID_869346495" STARTARROW="None" STARTINCLINATION="-627;30;"/>
<icon BUILTIN="button_ok"/>
<node COLOR="#435e98" CREATED="1734631621660" ID="ID_893434622" MODIFIED="1734631703465" TEXT="verwende ein Tupel von Parameter-Werten"/>
<node COLOR="#435e98" CREATED="1734631632906" ID="ID_1352652969" MODIFIED="1734631703467" TEXT="verwende ein Array f&#xfc;r Eingabe-Puffer"/>
<node COLOR="#435e98" CREATED="1734631646081" ID="ID_1254772125" MODIFIED="1734631703467" TEXT="verwende aber direkten Pointer zur Ausgabe"/>
<node COLOR="#435e98" CREATED="1734631663263" ID="ID_1915555663" MODIFIED="1734631703467" TEXT="demonstriere auch reinen Output mit Parameter"/>
</node>
</node>
<node CREATED="1734226618888" ID="ID_758716189" MODIFIED="1734226624083" TEXT="Operationen">
<node CREATED="1734226624933" ID="ID_1270095402" MODIFIED="1734282238319" TEXT="buildFeed(TurnoutSystem&amp;) &#x2014; statisch"/>
@ -92187,8 +92225,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<i>beide Funktoren</i>&#160;m&#252;ssen in den Typ eingehen
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node CREATED="1734565258271" ID="ID_963615663" MODIFIED="1734565519358" TEXT="das Weaving-Pattern ist tats&#xe4;chlich mit dem Prototyp parametrisiert">
<linktarget COLOR="#fdf5ca" DESTINATION="ID_963615663" ENDARROW="Default" ENDINCLINATION="-108;-6;" ID="Arrow_ID_47883929" SOURCE="ID_681345521" STARTARROW="None" STARTINCLINATION="-48;3;"/>
@ -92212,8 +92249,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
wenngleich auch lediglich indirekt, denn der sichtbare Parameter ist FUN, der Typ der Processing-Function
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node CREATED="1734569012990" ID="ID_1162717655" MODIFIED="1734569034684" TEXT="ben&#xf6;tigt wird er allerdings erst im terminalen WeavingBuilder::build()"/>
<node CREATED="1734569036235" ID="ID_356055578" MODIFIED="1734569057978" TEXT="eine Quer-Bewegung zu einem anders parametrisierten WeavingBuilder ist denkbar">
@ -92229,8 +92265,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
neuer Name: <b>FeedPrototype</b>
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node CREATED="1734569182079" ID="ID_716530363" MODIFIED="1734572949166" TEXT="Konfiguration des Parameter-Funktors &#x27f9; Anpassung des FeedPrototype">
<linktarget COLOR="#7389a1" DESTINATION="ID_716530363" ENDARROW="Default" ENDINCLINATION="203;250;" ID="Arrow_ID_1856006217" SOURCE="ID_1285997694" STARTARROW="None" STARTINCLINATION="611;31;"/>
@ -92245,8 +92280,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
Wenn es also ein Param-Tupel gibt, entscheidet es sich im Aufruf-Kontext, ob daf&#252;r ein Init-Wert geliefert wird. Wenn nicht, dann findet Default-Initialisierung statt. Ganz einfach
</p>
</body>
</html>
</richcontent>
</html></richcontent>
<linktarget COLOR="#d8e6f7" DESTINATION="ID_1722557648" ENDARROW="Default" ENDINCLINATION="-31;231;" ID="Arrow_ID_1230712950" SOURCE="ID_317086869" STARTARROW="None" STARTINCLINATION="584;41;"/>
</node>
</node>
@ -92352,8 +92386,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
&#10233; geht in eine <u>Builder-Klasse</u>&#160;<font color="#392ebf" face="Monospaced"><b>FeedPrototype</b></font><font color="#8a7979" face="Monospaced">&lt;</font><font color="#ab020a" face="Monospaced">FUN</font><font color="#8a7979" face="Monospaced">,</font><font color="#ba3b76" face="Monospaced">PAM</font><font color="#8a7979" face="Monospaced">&gt;</font>
</p>
</body>
</html>
</richcontent>
</html></richcontent>
<arrowlink COLOR="#7389a1" DESTINATION="ID_716530363" ENDARROW="Default" ENDINCLINATION="203;250;" ID="Arrow_ID_1856006217" STARTARROW="None" STARTINCLINATION="611;31;"/>
</node>
</node>
@ -92722,8 +92755,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
in den Turnout wird ein <b>Prototyp</b> der FeedManifold eingebettet
</p>
</body>
</html>
</richcontent>
</html></richcontent>
<node CREATED="1734562117362" ID="ID_462941923" MODIFIED="1734562132362" TEXT="die gebundene Adapter/Processing-Function steckt hier"/>
<node CREATED="1734562133675" ID="ID_332757580" MODIFIED="1734562147837" TEXT="das kann auch versteckte Binding-Daten mit beinhalten"/>
</node>
@ -92737,8 +92769,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
das hei&#223;t, idealerweise ist dieses ganze komplexe Konfigurations-Thema optional und transparent
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
</node>
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1734388801494" ID="ID_1469272212" MODIFIED="1734389073266" TEXT="Hier k&#xf6;nnte ein Buffer-Typ-Konstruktor mit eingebunden werden">
@ -92794,8 +92825,8 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1734573119398" ID="ID_112390056" MODIFIED="1734573353430" TEXT="wird erst zur Laufzeit von einem FeedPrototype(Builder) erzeugt">
<arrowlink COLOR="#35a1d3" DESTINATION="ID_1416331336" ENDARROW="Default" ENDINCLINATION="420;24;" ID="Arrow_ID_1552949599" STARTARROW="None" STARTINCLINATION="245;11;"/>
<arrowlink COLOR="#d35582" DESTINATION="ID_955026014" ENDARROW="Default" ENDINCLINATION="-620;38;" ID="Arrow_ID_278216824" STARTARROW="None" STARTINCLINATION="1203;53;"/>
<arrowlink COLOR="#35a1d3" DESTINATION="ID_1416331336" ENDARROW="Default" ENDINCLINATION="420;24;" ID="Arrow_ID_1552949599" STARTARROW="None" STARTINCLINATION="245;11;"/>
<icon BUILTIN="flag-yellow"/>
</node>
<node CREATED="1734573135923" ID="ID_1817637241" LINK="#ID_1722557648" MODIFIED="1734573174846">
@ -92806,8 +92837,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
bekommt ggfs. ein zus&#228;tzliches Parameter-Tupel <i>als ctor-Wert</i>
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1734582923838" ID="ID_1465521206" MODIFIED="1734583016228" TEXT="mu&#xdf; daf&#xfc;r nochmal Definitions-Struktur umkrempeln">
<arrowlink COLOR="#c1428c" DESTINATION="ID_1616386454" ENDARROW="Default" ENDINCLINATION="-1351;60;" ID="Arrow_ID_676623897" STARTARROW="None" STARTINCLINATION="-527;29;"/>
@ -92827,16 +92857,30 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</html></richcontent>
<icon BUILTIN="button_cancel"/>
</node>
<node CREATED="1734309990069" ID="ID_1710382999" MODIFIED="1734310510263" TEXT="angesiedelt in NodeBase_test">
<node CREATED="1734309990069" ID="ID_1710382999" MODIFIED="1734633414037" TEXT="angesiedelt in NodeBase_test">
<arrowlink COLOR="#406cd3" DESTINATION="ID_1954508996" ENDARROW="Default" ENDINCLINATION="-484;30;" ID="Arrow_ID_640616380" STARTARROW="None" STARTINCLINATION="-2974;268;"/>
<linktarget COLOR="#16a2aa" DESTINATION="ID_1710382999" ENDARROW="Default" ENDINCLINATION="539;-32;" ID="Arrow_ID_129574515" SOURCE="ID_1348489291" STARTARROW="None" STARTINCLINATION="183;11;"/>
<linktarget COLOR="#467fbe" DESTINATION="ID_1710382999" ENDARROW="Default" ENDINCLINATION="73;6;" ID="Arrow_ID_1026737432" SOURCE="ID_1795683894" STARTARROW="None" STARTINCLINATION="97;6;"/>
<icon BUILTIN="info"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1734573209952" ID="ID_1416331336" MODIFIED="1734573261692" TEXT="FeedPrototype in separatem Testfall abhandeln">
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1734573209952" ID="ID_1416331336" MODIFIED="1734631527235" TEXT="FeedPrototype in separatem Testfall abhandeln">
<arrowlink DESTINATION="ID_1048829589" ENDARROW="Default" ID="Arrow_ID_58841322" STARTARROW="None" STARTINCLINATION="-90;-5;" COLOR="#406cd3" ENDINCLINATION="-484;30;"/>
<linktarget COLOR="#35a1d3" DESTINATION="ID_1416331336" ENDARROW="Default" ENDINCLINATION="420;24;" ID="Arrow_ID_1552949599" SOURCE="ID_112390056" STARTARROW="None" STARTINCLINATION="245;11;"/>
<icon BUILTIN="flag-yellow"/>
</node>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1734633240020" ID="ID_1833389965" MODIFIED="1734633492466" TEXT="Dokumentation FeedManifold">
<linktarget COLOR="#82878e" DESTINATION="ID_1833389965" ENDARROW="Default" ENDINCLINATION="-1293;117;" ID="Arrow_ID_1228391309" SOURCE="ID_1954201095" STARTARROW="None" STARTINCLINATION="1447;0;"/>
<icon BUILTIN="pencil"/>
<node COLOR="#435e98" CREATED="1734633366137" ID="ID_1795683894" MODIFIED="1734633419361" TEXT="beispielhafte Demonstration im NodeBase_test">
<arrowlink COLOR="#467fbe" DESTINATION="ID_1710382999" ENDARROW="Default" ENDINCLINATION="73;6;" ID="Arrow_ID_1026737432" STARTARROW="None" STARTINCLINATION="97;6;"/>
</node>
<node COLOR="#435e98" CREATED="1734633423725" ID="ID_1203638933" MODIFIED="1734633440575" TEXT="feed-manifold.hpp : Konzept erl&#xe4;utert"/>
<node COLOR="#435e98" CREATED="1734633464974" ID="ID_1798872805" MODIFIED="1734633498599" TEXT="struct FeedManifold : Interface f&#xfc;r downstream-Code"/>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1734633505472" ID="ID_1970366380" MODIFIED="1734633532457" TEXT="Fehlt noch: Gesamt-Ablauf im TiddlyWiki">
<icon BUILTIN="bell"/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1734133441531" ID="ID_109108903" MODIFIED="1734133509736" TEXT="Turnout-System mit Storage implementieren">
<icon BUILTIN="flag-yellow"/>
@ -137811,7 +137855,12 @@ std::cout &lt;&lt; tmpl.render({&quot;what&quot;, &quot;World&quot;}) &lt;&lt; s
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1702415671495" ID="ID_690521198" MODIFIED="1702416445460" TEXT="Doxygen">
<icon BUILTIN="prepare"/>
<node CREATED="1702416632230" ID="ID_842762054" MODIFIED="1702416637945" TEXT="zentrale Technologien"/>
<node CREATED="1702416632230" ID="ID_842762054" MODIFIED="1702416637945" TEXT="zentrale Technologien">
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1734633109131" ID="ID_1954201095" MODIFIED="1734633492466" TEXT="FeedManifold">
<arrowlink COLOR="#82878e" DESTINATION="ID_1833389965" ENDARROW="Default" ENDINCLINATION="-1293;117;" ID="Arrow_ID_1228391309" STARTARROW="None" STARTINCLINATION="1447;0;"/>
<icon BUILTIN="pencil"/>
</node>
</node>
<node CREATED="1702416647540" ID="ID_1689012176" MODIFIED="1702416651071" TEXT="&#xdc;bersichts-Seiten"/>
</node>
<node CREATED="1702417147449" ID="ID_127149039" MODIFIED="1702417598605" TEXT="Tickets">