diff --git a/src/steam/engine/feed-manifold-obsolete.hpp b/src/steam/engine/feed-manifold-obsolete.hpp index 376880253..ad5296d99 100644 --- a/src/steam/engine/feed-manifold-obsolete.hpp +++ b/src/steam/engine/feed-manifold-obsolete.hpp @@ -57,7 +57,7 @@ namespace engine { * to use a single contiguous memory area and just layer the object structure on top * (by using placement new). Yet the idea of an stack-like organisation should be retained */ - struct FeedManifold ///////////////////////////////////OOO rename into FeedManifold + struct FeedManifold_BuffTable_OBSOLETE ///////////////////////////////////OOO this is obliterated by the new implementation of FeedManifold_BuffTable_OBSOLETE { typedef BuffHandle * PHa; typedef BuffHandle::PBuff * PBu; @@ -109,7 +109,7 @@ namespace engine { * starting at current level to be used * by the newly created BuffTableChunk */ - FeedManifold::Chunk + FeedManifold_BuffTable_OBSOLETE::Chunk claim (uint slots) { ASSERT (pTab_.size() == hTab_.size()); @@ -132,7 +132,7 @@ namespace engine { } bool - level_check (FeedManifold::Chunk& prev_level) + level_check (FeedManifold_BuffTable_OBSOLETE::Chunk& prev_level) { return prev_level.first == &hTab_[level_] && prev_level.second == &pTab_[level_]; @@ -148,11 +148,11 @@ namespace engine { * object's lifecycle. */ class BuffTableChunk - : public FeedManifold, + : public FeedManifold_BuffTable_OBSOLETE, util::NonCopyable { const uint siz_; - FeedManifold::Chunk tab_; + FeedManifold_BuffTable_OBSOLETE::Chunk tab_; BuffTableStorage& sto_; public: diff --git a/src/steam/engine/feed-manifold.hpp b/src/steam/engine/feed-manifold.hpp index a6176feca..307d6d509 100644 --- a/src/steam/engine/feed-manifold.hpp +++ b/src/steam/engine/feed-manifold.hpp @@ -14,9 +14,54 @@ /** @file feed-manifold.hpp + ** Adapter to connect parameters and data buffers to an external processing function. + ** The Lumiera Render Engine relies on a »working substrate« of _Render Nodes,_ interconnected + ** in accordance to the structure of foreseeable computations. Yet the actual media processing + ** functionality is provided by external libraries — while the engine is arranged in a way to + ** remain _agnostic_ regarding any details of actual computation. Those external libraries are + ** attached into the system by means of a _library plugin,_ which cares to translate the external + ** capabilities into a representation as _Processing Assets._ These can be picked up and used in + ** the Session, and will eventually be visited by the _Builder_ as part of the effort to establish + ** 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 + ** 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 + ** offer several [ports for computation](\ref steam::engine::Port). This interface is typically + ** implemented by a [Turnout](\ref turnout.hpp), which in turn is based on some »weaving pattern« + ** performed around and on top of a FeedManifold instance, which is created anew on the stack for + ** each invocation. This invocation scheme implies that the FeedManifold is tailored specifically + ** for a given functor, matching the expectations indicated by the invocation functor's signature: + ** - A proper invocation functor may accept _one to three arguments;_ + ** - in _must accept_ one or several **output** buffers, + ** - optionally it _can accept_ one or several **input** buffers, + ** - optionally it _can accept_ also one or several **parameters** to control specifics. + ** - the order of these arguments is fixed to the sequence: _parameters, inputs, outputs._ + ** - Parameters are assumed to have _value semantics._ They must be copyable and default-constructible. + ** - Buffers are always passed _by pointer._ The type of the pointee is picked up and passed-through. + ** - such a pointee or buffer-type is assumed to be default constructible, since the engine will have + ** to construct result buffers within its internal memory management scheme. The library-plugin + ** 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 + ** 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 + ** accept a std::tuple or a std::array. + ** + ** \par Implementation remarks + ** 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 + ** @todo 12/2024 figure out how constructor-arguments can be passed flexibly ** @todo staled since 2009, picked up in 2024 in an attempt to finish the node invocation. ** @todo WIP-WIP 2024 rename and re-interpret as a connection system - ** @see nodeinvocation.hpp + ** @see NodeBase_test + ** @see weaving-pattern-builder.hpp */ @@ -29,6 +74,7 @@ //#include "steam/engine/proc-node.hpp" #include "steam/engine/buffhandle.hpp" #include "lib/uninitialised-storage.hpp" +#include "lib/meta/function.hpp" //#include "lib/several.hpp" //#include @@ -43,25 +89,83 @@ namespace engine { // using std::pair; // using std::vector; + namespace {// Introspection helpers.... + + using lib::meta::_Fun; + using lib::meta::is_BinaryFun; + using std::remove_reference_t; + + /** Helper to pick up the parameter dimensions from the processing function + * @remark this is the rather simple yet common case that media processing + * is done by a function, which takes an array of input and output + * buffer pointers with a common type; this simple case is used + * 7/2024 for prototyping and validate the design. + * @tparam FUN a _function-like_ object, expected to accept two arguments, + * which both are arrays of buffer pointers (input, output). + */ + template + struct _ProcFun + { + static_assert(_Fun() , "something funktion-like required"); + static_assert(is_BinaryFun() , "function with two arguments expected"); + + using Sig = typename _Fun::Sig; + + template + struct MatchBuffArray + { + static_assert(not sizeof(ARG), "processing function expected to take array-of-buffer-pointers"); + }; + template + struct MatchBuffArray> + { + using Buff = BUF; + enum{ SIZ = N }; + }; + + using SigI = remove_reference_t::Args::List::Head>; + using SigO = remove_reference_t::Args::List::Tail::Head>; + + using BuffI = typename MatchBuffArray::Buff; + using BuffO = typename MatchBuffArray::Buff; + + enum{ FAN_I = MatchBuffArray::SIZ + , FAN_O = MatchBuffArray::SIZ + , SLOT_I = 0 + , SLOT_O = 1 + , MAXSZ = std::max (uint(FAN_I), uint(FAN_O)) /////////////////////OOO required temporarily until the switch to tuples + }; + + static constexpr bool hasInput() { return SLOT_I != SLOT_O; } + static constexpr bool hasParam() { return 0 < SLOT_I; } + }; + + }//(End)Introspection helpers. + + template + struct FeedManifold_StorageSetup + : util::NonCopyable + { + + }; /** - * Obsolete, to be rewritten /////TICKET #826 - * - * Tables of buffer handles and corresponding dereferenced buffer pointers. - * Used within the invocation of a processing node to calculate data. - * The tables are further differentiated into input data buffers and output - * data buffers. The tables are supposed to be implemented as bare "C" arrays, - * thus the array of real buffer pointers can be fed directly to the - * processing function of the respective node. + * 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, + * 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. * * @todo WIP-WIP-WIP 7/24 now reworking the old design in the light of actual render engine requirements... */ - template + template struct FeedManifold - : util::NonCopyable + : FeedManifold_StorageSetup { - using BuffS = lib::UninitialisedStorage; - enum{ STORAGE_SIZ = N }; + enum{ STORAGE_SIZ = _ProcFun::MAXSZ }; + using BuffS = lib::UninitialisedStorage; BuffS inBuff; BuffS outBuff; @@ -69,6 +173,63 @@ namespace engine { + /** + * Adapter to handle a simple yet common setup for media processing + * - somehow we can invoke processing as a simple function + * - this function takes two arrays: the input- and output buffers + * @remark this setup is useful for testing, and as documentation example; + * actually the FeedManifold is mixed in as baseclass, and the + * buffer pointers are retrieved from the BuffHandles. + * @tparam MAN a FeedManifold, providing arrays of BuffHandles + * @tparam FUN the processing function + */ + template + struct SimpleFunctionInvocationAdapter + : MAN + { + using BuffI = typename _ProcFun::BuffI; + using BuffO = typename _ProcFun::BuffO; + + enum{ N = MAN::STORAGE_SIZ + , FAN_I = _ProcFun::FAN_I + , FAN_O = _ProcFun::FAN_O + }; + + static_assert(FAN_I <= N and FAN_O <= N); + + using ArrayI = typename _ProcFun::SigI; + using ArrayO = typename _ProcFun::SigO; + + + FUN process; + + ArrayI inParam; + ArrayO outParam; + + template + SimpleFunctionInvocationAdapter (INIT&& ...funSetup) + : process{forward (funSetup)...} + { } + + + void + connect (uint fanIn, uint fanOut) + { + REQUIRE (fanIn == FAN_I and fanOut == FAN_O); //////////////////////////OOO this distinction is a left-over from the idea of fixed block sizes + for (uint i=0; i(); + for (uint i=0; i(); + } + + void + invoke() + { + process (inParam, outParam); + } + }; + + }} // namespace steam::engine #endif /*ENGINE_FEED_MANIFOLD_H*/ diff --git a/src/steam/engine/nodeinvocation-obsolete.hpp b/src/steam/engine/nodeinvocation-obsolete.hpp index 7c389fffe..630b61caf 100644 --- a/src/steam/engine/nodeinvocation-obsolete.hpp +++ b/src/steam/engine/nodeinvocation-obsolete.hpp @@ -39,7 +39,7 @@ ** @todo relies still on an [obsoleted implementation draft](\ref bufftable-obsolete.hpp) ** @see engine::ProcNode ** @see engine::StateProxy - ** @see engine::FeedManifold + ** @see engine::FeedManifold_BuffTable_OBSOLETE ** @see nodewiring.hpp interface for building/wiring the nodes ** */ @@ -110,7 +110,7 @@ namespace engine { * access the context via the references in this struct, while also using the inherited * public State interface. The object instance actually used as Invocation is created * on the stack and parametrised according to the necessities of the invocation sequence - * actually configured. Initially, this real instance is configured without FeedManifold, + * actually configured. Initially, this real instance is configured without FeedManifold_BuffTable_OBSOLETE, * because the invocation may be short-circuited due to Cache hit. Otherwise, when * the invocation sequence actually prepares to call the process function of this * ProcNode, a buffer table chunk is allocated by the StateProxy and wired in. @@ -121,10 +121,10 @@ namespace engine { Connectivity const& wiring; const uint outNr; - FeedManifold* feedManifold; + FeedManifold_BuffTable_OBSOLETE* feedManifold; protected: - /** creates a new invocation context state, without FeedManifold */ + /** creates a new invocation context state, without FeedManifold_BuffTable_OBSOLETE */ Invocation (StateClosure_OBSOLETE& callingProcess, Connectivity const& w, uint o) : StateAdapter(callingProcess), wiring(w), outNr(o), @@ -137,7 +137,7 @@ namespace engine { uint buffTabSize() const { return nrO()+nrI(); } /** setup the link to an externally allocated buffer table */ - void setBuffTab (FeedManifold* b) { this->feedManifold = b; } + void setBuffTab (FeedManifold_BuffTable_OBSOLETE* b) { this->feedManifold = b; } bool buffTab_isConsistent () diff --git a/src/steam/engine/weaving-pattern-builder.hpp b/src/steam/engine/weaving-pattern-builder.hpp index 55e14cc06..37b76b42d 100644 --- a/src/steam/engine/weaving-pattern-builder.hpp +++ b/src/steam/engine/weaving-pattern-builder.hpp @@ -122,114 +122,13 @@ namespace engine { using StrView = std::string_view; using std::forward; - using lib::Literal; +// using lib::Literal; using lib::Several; using lib::Depend; using util::_Fmt; using util::max; - namespace {// Introspection helpers.... - - using lib::meta::_Fun; - using lib::meta::is_BinaryFun; - using std::remove_reference_t; - - /** Helper to pick up the parameter dimensions from the processing function - * @remark this is the rather simple yet common case that media processing - * is done by a function, which takes an array of input and output - * buffer pointers with a common type; this simple case is used - * 7/2024 for prototyping and validate the design. - * @tparam FUN a _function-like_ object, expected to accept two arguments, - * which both are arrays of buffer pointers (input, output). - */ - template - struct _ProcFun - { - static_assert(_Fun() , "something funktion-like required"); - static_assert(is_BinaryFun() , "function with two arguments expected"); - - using SigI = remove_reference_t::Args::List::Head>; - using SigO = remove_reference_t::Args::List::Tail::Head>; - - template - struct MatchBuffArray - { - static_assert(not sizeof(ARG), "processing function expected to take array-of-buffer-pointers"); - }; - template - struct MatchBuffArray> - { - using Buff = BUF; - enum{ SIZ = N }; - }; - - using BuffI = typename MatchBuffArray::Buff; - using BuffO = typename MatchBuffArray::Buff; - - enum{ FAN_I = MatchBuffArray::SIZ - , FAN_O = MatchBuffArray::SIZ - , MAXSZ = std::max (uint(FAN_I), uint(FAN_O)) /////////////////////OOO required temporarily until the switch to tuples - }; - }; - }//(End)Introspection helpers. - - - /** - * Adapter to handle a simple yet common setup for media processing - * - somehow we can invoke processing as a simple function - * - this function takes two arrays: the input- and output buffers - * @remark this setup is useful for testing, and as documentation example; - * actually the FeedManifold is mixed in as baseclass, and the - * buffer pointers are retrieved from the BuffHandles. - * @tparam MAN a FeedManifold, providing arrays of BuffHandles - * @tparam FUN the processing function - */ - template - struct SimpleFunctionInvocationAdapter - : MAN - { - using BuffI = typename _ProcFun::BuffI; - using BuffO = typename _ProcFun::BuffO; - - enum{ N = MAN::STORAGE_SIZ - , FAN_I = _ProcFun::FAN_I - , FAN_O = _ProcFun::FAN_O - }; - - static_assert(FAN_I <= N and FAN_O <= N); - - using ArrayI = typename _ProcFun::SigI; - using ArrayO = typename _ProcFun::SigO; - - - FUN process; - - ArrayI inParam; - ArrayO outParam; - - template - SimpleFunctionInvocationAdapter (INIT&& ...funSetup) - : process{forward (funSetup)...} - { } - - - void - connect (uint fanIn, uint fanOut) - { - REQUIRE (fanIn == FAN_I and fanOut == FAN_O); //////////////////////////OOO this distinction is a left-over from the idea of fixed block sizes - for (uint i=0; i(); - for (uint i=0; i(); - } - - void - invoke() - { - process (inParam, outParam); - } - }; /** * Typical base configuration for a Weaving-Pattern chain: @@ -246,7 +145,7 @@ namespace engine { : util::MoveOnly { enum{ MAX_SIZ = _ProcFun::MAXSZ }; - using Manifold = FeedManifold; + using Manifold = FeedManifold; using Feed = SimpleFunctionInvocationAdapter; std::function buildFeed; @@ -279,7 +178,7 @@ namespace engine { * for each port, as specified by preceding builder-API invocations. * @tparam PAR recursive layering for preceding entries * @tparam BUILD a builder functor to emplace one Turnout instance, - * opaquely embedding all specific data typing. + * thereby opaquely embedding all specific data typing. * @tparam siz storage in bytes to hold data produced by \a BUILD */ template diff --git a/tests/47engine.tests b/tests/47engine.tests index eb56df7f0..58420ba1b 100644 --- a/tests/47engine.tests +++ b/tests/47engine.tests @@ -27,11 +27,6 @@ return: 0 END -PLANNED "feed manifold" FeedManifold_test < - -  **Lumiera** 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. See the file COPYING for further details. - -* *****************************************************************/ - -/** @file feed-manifold-test.cpp - ** unit test \ref FeedManifold_test - */ - - -#include "lib/test/run.hpp" -#include "lib/error.hpp" - -#include "steam/engine/proc-node.hpp" -#include "steam/engine/feed-manifold.hpp" -#include "lib/format-cout.hpp" ////////////////TODO - -#include - -using test::Test; - - -namespace steam { -namespace engine{ -namespace test { - - namespace { // used internally - - const uint TABLE_SIZ = 100000; - const uint CHUNK_MAX = 8000; - const uint WIDTH_MAX = 3; - - -#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1367 : Rebuild the Node Invocation - /** just some crap to pass in as ctor argument... */ - template - struct DummyArray : lib::RefArray - { - E decoy; - E const& operator[] (size_t) const { return decoy; } - size_t size() const { return CHUNK_MAX;} - }; - DummyArray dummy1; - DummyArray dummy2; - - - /** a "hijacked" Connectivity descriptor requesting - * a random number of inputs and outputs */ - struct MockSizeRequest - : Connectivity - { - uint ii,oo; - - MockSizeRequest() - : Connectivity(dummy1,dummy2,0,NodeID()), - ii(rani (CHUNK_MAX)), - oo(rani (CHUNK_MAX)) - { } - - virtual uint getNrI() const { return ii; } - virtual uint getNrO() const { return oo; } - - virtual BuffHandle callDown (StateClosure_OBSOLETE&, uint) const - { throw lumiera::Error("not intended to be called"); } - }; -#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1367 : Rebuild the Node Invocation - - - -#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #852 - void* - detect_start_level (BuffTableStorage& sto) - { - return BuffTableChunk(MockSizeRequest(), sto ).outHandle; - } // address of first available storage element - - - inline void* - first_behind (BuffTable const& thisChunk, const uint nrI) - { - return &thisChunk.inHandle[nrI]; - } - - - inline bool - not_within(void* candidate, void* lower, void* upper) - { - return (candidate < lower) || (upper <= candidate); - } - - - bool - consistencyCheck (BuffTable const& b, Connectivity const& num, void* lastLevel) - { - return (b.outHandle == lastLevel ) // storage is allocated continuously - && (b.outBuff <= b.inBuff ) // input slots are behind the output slots - && (b.outHandle <= b.inHandle) - && (b.inBuff == &b.outBuff [num.nrO]) - && (b.inHandle == &b.outHandle[num.nrO]) - && (not_within(b.outBuff, b.outHandle, &b.inHandle[num.nrO])) // storage doesn't overlap - && (not_within(b.inBuff, b.outHandle, &b.inHandle[num.nrO])) - && (not_within(b.outHandle, b.outBuff, &b.inBuff[num.nrO])) - && (not_within(b.inHandle, b.outBuff, &b.inBuff[num.nrO])) - ; - } -#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #852 - } // (End) internal defs - - - - /***************************************************************//** - * @test create a random pattern of recursive invocations, each - * allocating a chunk out of a global buffer table storage. - * After returning, each allocation should be cleanly - * deallocated and the internal level in the storage vector - * should have doped to zero again. - */ - class FeedManifold_test : public Test - { -#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #852 - using PSto = std::unique_ptr; - - PSto pStorage; -#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #852 - ulong counter; - - void - run(Arg) override - { - seedRand(); ////////////////TODO RLY? - counter = 0; - -#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #852 - // allocate storage block to be used chunk wise - pStorage.reset (new BuffTableStorage (TABLE_SIZ)); - - invocation (0, detect_start_level(*pStorage)); - - pStorage.reset(0); // dtor throws assertion error if corrupted - - cout << "BuffTable chunks allocated: "< - - - +

Name: ZoomMetric @@ -24135,9 +24133,7 @@ - - - +

dieses speichern als TrackBody::contentHeight_ @@ -24689,9 +24685,7 @@ - - - +

...und damit eine Rekursion triggert @@ -25577,9 +25571,7 @@ - - - +

der ctor des DisplayFrame nimmt einen generischen Typ (Template), @@ -26914,9 +26906,7 @@ - - - +

mein Display: 90dpi @@ -28693,9 +28683,7 @@ - - - +

  • @@ -30114,9 +30102,7 @@ - - - +

    dann ist nämlich die startLine = 0; @@ -32476,9 +32462,7 @@ - - - +

    frame > border, @@ -34129,9 +34113,7 @@ - - - +

    *) die Referenz steckt nämlich schon im ViewHookable @@ -36303,9 +36285,7 @@ - - - +

      //We cannot add and show the window until the GApplication::activate signal @@ -37431,9 +37411,7 @@ - - - +

    ...sonst bleibt ein inkonsistender Zustand irgendwo "hängen".
    Leider ist das nun das bekanntermaßen unlösbare Problem eines sicheren Verbindungsabbaus, und wir müssen uns deshalb mit einem Timeout, oder re-check-Mechanismus behelfen @@ -38031,9 +38009,7 @@ - - - +

    Wenig problematisch ist dieser Fall, wenn der Button gedrückt bleibt und wir irgendwann zurückkommen; dann setzt sich das Dragging eben an der Stelle fort. Wenn dagegen der Button außerhalb released wurde, handelt es sich tatsächlich um den 3.Fall ― wenn aber eine normale Maus-Bewegung später wieder über das Widget fährt, wird das Dragging fortgesetzt, fälschlicherweise. @@ -38760,9 +38736,7 @@ - - - +

    ...sobald irgendwo eine Abstraktionsbarriere errichtet wird, muß mindestens ein Call indirekt oder virtuell sein.... @@ -38944,9 +38918,7 @@ - - - +

    Name: GestureObserver @@ -87558,7 +87530,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
    - + + @@ -91402,15 +91375,14 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
    ...weil wir SLOT_I ≔ SLOT_O setzen (wichtig!), wenn es keinen Input gibt; es gibt nur zwei Fälle ohne Parameter, und die lsassen sich damit in diesen Test zusammenfassen

    - -
    +
    - + @@ -91419,13 +91391,15 @@ Date:   Thu Apr 20 18:53:17 2023 +0200

    +
    - + + @@ -91444,8 +91418,11 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
    + + + + - @@ -91489,8 +91466,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
    Jede mögliche Funktions-Signatur erzeugt eine separate Turnout-Instanz

    - - + @@ -91500,8 +91476,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
    das Media-Lib-Plugin is Problemzone und Ansatzpunkt bzgl Template-Bloat

    - -
    + @@ -91524,6 +91499,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
    + @@ -91554,8 +91530,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
    ...denn exakt an dieser Stelle ist das Prototyping bis jetzt gescheitert ... wir konnten bisher nur eine „dämliche“ Dummy-Funktion binden; sobald eine echte Dummy-Funktion eingebunden werden sollte, bin ich darauf aufmerksam geworden, das eine solche Funktion zwangsläufig auch weitere Parameter brauchen wird, und nach einer weiteren, langen „Denk-Schleife“ bin ich hier wo ich grad bin

    - - +
    @@ -91577,13 +91552,149 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
    + + + + + + + + - + + + + + + + + + + + + + + + + + + + +

    + Der Name und die Vorstellung hat nun mehrfach gewechselt, aber es ging doch letztlich immer darum, eine unbekannte Library-Funktion so aufzurüsten, daß man sie mit einem generischen Schema zu fassen bekommt. Auch die Idee, die Buffer-Pointer in ein Array zu packen, gehört letztlich zu diesem Ansatz. Der darüber hinausgehende Teil der ursprünglichen Idee, dieses Strukur auch zu »bespielen« ist jetzt in der »weaving«-Metapher aufgegangen — und dieses fortschreitende Wechselspiel in der Speicherbelegung findet darüber ja nun tatsächlich statt. +

    + + +
    +
    + + + + + + +

    + beispielsweise könnte man den Parameter-Funktor im allgemeinen Funktor verstecken, und dann auch gleich noch den Scope, in dem der eigentliche Aufruf-Adapter gebaut wird. Man würde sich damit ein paar Bytes pro Node-Level sparen, um den Preis eines trickreichen Konstrukts ineinander geschachtelter Funktoren. Da gefällt es mir doch besser, die Funktoren und die Storage in einem Objekt nebeneinander abzulegen, zusammen mit Methoden, die von einem jeweiligen Weaving-Pattern genutzt werden könnten +

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

    + hier zeigt sich immer wieder der gleiche Trade-off: zusätzliche Indirektion vs. Template-Bloat +

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

    + Dahinter verbirgt sich ein architektonisches Problem: die FeedManifold ist ein Bindeglied, und daher bewirkt jeder Konstruktor-Parameter eine Einbindung in Detail-Strukturen — problematisch dabei bleibt, daß die Einbindung nach beiden Seiten erfolgen kann. Konkret bedeutet dies.... +

    +
      +
    • + von der usage-site her, also dem WeavingPattern muß die FeedManifold mit einer TurnoutSystem& versorgt werden +
    • +
    • + wohingegen von der Definitions-Seite her ggfs. Funktor-Objekte mit eingepackten Detail-Bindings übernommen werden müssen +
    • +
    • + und hier ist auch noch Variabilität gegeben: ein Funktor für Parameter ist optional, aber wenn er gegeben ist, dann kann (nicht muß) es sein, daß er ebenfalls Init-Argumente braucht, die dann aber ziemlich sicher aus einem anderen Struktur-Kontext stammen, nämlich aus der internen Logik des Builders, nicht aus dem Library-Plug-in +
    • +
    + + +
    + +
    @@ -91602,8 +91713,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
    ...insofern dann alle Fälle mit gleicher Signatur zusammenfallen; für die häufigsten Fälle (wie z.B. ein einziger int-Parameter) erwarte ich einen starken Hebel

    - - +
    @@ -94563,7 +94673,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
    - + + @@ -96035,9 +96146,10 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
    - + + @@ -96054,6 +96166,9 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
    + + +