From 72703f70c96e741b28bcf0e6ba4a30e103e37a4b Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Fri, 20 Dec 2024 07:05:43 +0100 Subject: [PATCH] Invocation: integrate active ''parameter functor'' While basically the `FeedPrototype` could be created directly, passing both the processing- and the parameter-functor, in practice a two-step configuration can be expected, since the processing-functor is built by the Library-Plug-in, while the parameter-functor is then later added as decoration by the builder. Thus we need the ability to ''collect configuration'' within the Level-2 builder, which can be achieved by a ''cross-builder'' mechanic, where we create an adapted builder from the augmented configuration. A similar approach is also used to add the configuration of the custom allocator. Added an extensive demo in the test, playing with several instances to highlight the point where the parameter-functor is actually invoked. --- src/steam/engine/feed-manifold.hpp | 27 ++- tests/core/steam/engine/node-base-test.cpp | 59 +++++- wiki/thinkPad.ichthyo.mm | 212 +++++++++++++-------- 3 files changed, 210 insertions(+), 88 deletions(-) diff --git a/src/steam/engine/feed-manifold.hpp b/src/steam/engine/feed-manifold.hpp index aef6200ba..40a4f5a9b 100644 --- a/src/steam/engine/feed-manifold.hpp +++ b/src/steam/engine/feed-manifold.hpp @@ -263,7 +263,7 @@ namespace engine { static constexpr bool hasParam() { return _Proc::hasParam(); } - using Param = std::conditional_t>; + using Param = std::conditional_t>; template using Res = typename _Fun::Ret; @@ -569,7 +569,7 @@ namespace engine { , paramFun_{move (par)} { } // default move acceptable : pass pre-established setup - + static constexpr bool hasParam() { return _Trait::hasParam(); } static constexpr bool hasParamFun() { return _Trait::template isParamFun(); } static constexpr bool canActivate() { return _Trait::template canActivate(); } @@ -582,9 +582,30 @@ namespace engine { { if constexpr (hasParamFun()) if (_Trait::isActivated(paramFun_)) - return Feed{paramFun_(turnoutSys), procFun_}; + return Feed(paramFun_(turnoutSys), procFun_); return Feed{procFun_}; } + + + template + using Adapted = FeedPrototype; + + /** + * Cross-Builder to add configuration with a given parameter-functor. + * @return new FeedPrototype instance outfitted with the current + * processing-functor and the given other param-functor + * @warning the current instance is likely **defunct** after this call, + * and should not be used any more, due to the move-construct. + * @remark together with the move-ctor of FeedPrototype this helper + * can be used to configure a Prototype in several steps. + */ + template + auto + moveAdapted (PFX otherParamFun) + { + using OtherParamFun = std::decay_t; + return Adapted{move(procFun_), move(otherParamFun)}; + } }; diff --git a/tests/core/steam/engine/node-base-test.cpp b/tests/core/steam/engine/node-base-test.cpp index 7ac87019d..36e200ae0 100644 --- a/tests/core/steam/engine/node-base-test.cpp +++ b/tests/core/steam/engine/node-base-test.cpp @@ -328,7 +328,6 @@ namespace test { verify_FeedPrototype() { // Prepare setup to build a suitable FeedManifold... - long r1 = rani(100); using Buffer = long; BufferProvider& provider = DiagnosticBufferProvider::build(); BuffHandle buff = provider.lockBufferFor (-55); @@ -336,24 +335,66 @@ namespace test { auto fun_singleParamOut = [](short param, Buffer* buff) { *buff = param-1; }; using M1 = FeedManifold; using P1 = M1::Prototype; - CHECK ( P1::hasParam()); - CHECK (not P1::hasParamFun()); + CHECK ( P1::hasParam()); // checks that the processing-function accepts a parameter + CHECK (not P1::hasParamFun()); // while this prototype has no active param-functor CHECK (not P1::canActivate()); - P1 p1{move (fun_singleParamOut)}; + P1 p1{move (fun_singleParamOut)}; // create the instance of the prototype, moving the functor in CHECK (sizeof(p1) <= sizeof(void*)); - TurnoutSystem turSys{Time::NEVER}; + TurnoutSystem turSys{Time::NEVER}; // Each Node invocation uses a TurnoutSystem instance.... - M1 m1 = p1.createFeed(turSys); - CHECK (m1.param == short{}); - m1.outBuff.createAt(0, buff); + M1 m1 = p1.createFeed(turSys); //... and also will create a new FeedManifold from the prototype + CHECK (m1.param == short{}); // In this case here, the param value is default constructed. + m1.outBuff.createAt(0, buff); // Perform the usual steps for an invocation.... CHECK (buff.accessAs() == -55); m1.connect(); CHECK (*m1.outArgs == -55); m1.invoke(); - CHECK (*m1.outArgs == 0 - 1); + CHECK (*m1.outArgs == 0 - 1); // fun_singleParamOut() -> param - 1 and param ≡ 0 CHECK (buff.accessAs() == 0 - 1); + long& calcResult = buff.accessAs(); // for convenience use a reference into the result buffer + + + + //_____________________________________ + // Reconfigure to attach a param-functor + long rr{11}; // ▽▽▽▽ Note: side-effect + auto fun_paramSimple = [&](TurnoutSystem&){ return rr += 1+rani(100); }; + using P1x = P1::Adapted; + CHECK ( P1x::hasParam()); + CHECK ( P1x::hasParamFun()); + CHECK (not P1x::canActivate()); + + P1x p1x = p1.moveAdapted (move(fun_paramSimple)); + M1 m1x = p1x.createFeed(turSys); // ◁————————— param-functor invoked here + CHECK (rr == m1x.param); // ...as indicated by the side-effect + short r1 = m1x.param; + + // the rest works as always with FeedManifold (which as such is agnostic of the param-functor!) + m1x.outBuff.createAt(0, buff); + m1x.connect(); + m1x.invoke(); // Invoke the processing functor + CHECK (calcResult == r1 - 1); // ...which computes fun_singleParamOut() -> param-1 + + // but let's play with the various instances... + m1.invoke(); // the previous FeedManifold is sill valid and connected + CHECK (calcResult == 0 - 1); // and uses its baked in parameter value (0) + m1x.invoke(); + CHECK (calcResult == r1 - 1); // as does m1x, without invoking the param-functor + + // create yet another instance from the prototype... + M1 m1y = p1x.createFeed(turSys); // ◁————————— param-functor invoked here + CHECK (rr == m1y.param); + CHECK (r1 < m1y.param); // ...note again the side-effect + m1y.outBuff.createAt(0, buff); + m1y.connect(); + m1y.invoke(); // ...and so this third FeedManifold instance... + CHECK (calcResult == rr - 1); // uses yet another baked-in param value; + m1x.invoke(); // recall that each Node invocation creates a new + CHECK (calcResult == r1 - 1); // FeedManifold on the stack, since invocations are + m1.invoke(); // performed concurrently, each with its own set of + CHECK (calcResult == 0 - 1); // buffers and parameters. } }; diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 48c107c6b..433b51247 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -26939,9 +26939,7 @@ - - - +

b = 0.6180339887498948482 @@ -27630,9 +27628,7 @@ - - - +

  • @@ -28112,9 +28108,7 @@ - - - + The device-space coordinate system is tied to the surface, and cannot change. The user-space coordinate system @@ -28873,9 +28867,7 @@ - - - +

    Beispiel: Wenn der Typ selber keinen Support anbietet, @@ -28908,9 +28900,7 @@ - - - +

    ...denn diese Duck-Detector-Metafunktion bildet den Typ eines Member-Pointers, @@ -30202,9 +30192,7 @@ - - - +

    Anmerkung 1/2023: seinerzeit habe ich die Mechanik der Layout-Zuteilung noch nicht wirklich verstanden @@ -31593,9 +31581,7 @@ - - - +

    spezielle Regel gesetzt auf: .timeline-page > .timeline-body fork.timeline @@ -32945,9 +32931,7 @@ - - - +

    d.h. wir müssen... @@ -33686,9 +33670,7 @@ - - - +

    ...darüber bin ich auch beim Zeichnen der Connector im StaveBracket gestolpert @@ -33876,9 +33858,7 @@ - - - +

    • @@ -34580,9 +34560,7 @@ - - - +

      ...diese erstreckt sich typischerweise über die gesamte Länge des umschließenden Containers, und paßt sich dieser ohne weiteres dynamisch an @@ -34960,9 +34938,7 @@ - - - +

      ...habe ich aber noch nie getestet... @@ -88756,8 +88732,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      auch Implementierung von all_buffers_released() fehlt

      - -
      + @@ -88765,8 +88740,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      Glorreich — testgetriebene Entwicklung und dann den wichtigen zentralen Test >10 Jahre lang auskommentiert rumstehen lassen

      - -
      +
      @@ -88792,8 +88766,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      also muß ich im BlockPool alles als released markieren

      - - +
      @@ -88837,6 +88810,9 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      + + +
      @@ -91653,8 +91629,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - + + @@ -91695,17 +91671,19 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - + + - - + + - + + + @@ -91811,6 +91789,13 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      + + + + + + +
      @@ -91872,7 +91857,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - + + @@ -91902,14 +91888,15 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - + - - + + + - + @@ -91984,7 +91971,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - + @@ -92104,7 +92091,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - + @@ -92112,9 +92099,9 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - + - + @@ -92129,6 +92116,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      + @@ -92222,24 +92210,29 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - - - + + + + + - - + + + + + + @@ -92459,6 +92452,18 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      + + + + + + + + + + + + @@ -92490,24 +92495,52 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - - + + + + - - + + + + + + + + + + +

      + Name: prototype.moveAdapted (paramFun) +

      + + +
      + + + + + + + +
      - - + + + - - + - + + + + + @@ -92520,6 +92553,32 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      @@ -92844,6 +92903,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      + @@ -92919,7 +92979,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - +
      @@ -99108,8 +99168,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
      - + @@ -150185,7 +150245,7 @@ unsigned int ThreadIdAsInt = *static_cast<unsigned int*>(static_cast<vo sieht aber soweit sauber aus...

      - Wenngleich auch ziemlich elaboriert; all diese Tracking-Funktionalität war seinerzeit angelegt worden, aber nur oberflächlich getestet, weil der Render-Engine-Entwurf von 2012 letztlich steckengeblieben ist. Jetzt, 2024 beginne ich, den TrackingHeapBlockProvider zu für Tests zu nutzen, einfach weil er da ist — und stelle fest, daß einige Details unfertig und etwas unausgereift wirken.... + Wenngleich auch ziemlich elaboriert; all diese Tracking-Funktionalität war seinerzeit angelegt worden, aber nur oberflächlich getestet, weil der Render-Engine-Entwurf von 2012 letztlich steckengeblieben ist. Jetzt, 2024 beginne ich, den TrackingHeapBlockProvider zu für Tests zu nutzen, einfach weil er da ist — und stelle fest, daß einige Details unfertig und etwas unausgereift wirken....