diff --git a/src/lib/hetero-data.hpp b/src/lib/hetero-data.hpp index 986360251..8aacc375a 100644 --- a/src/lib/hetero-data.hpp +++ b/src/lib/hetero-data.hpp @@ -110,6 +110,8 @@ namespace lib { template void linkInto (HeteroData&); + template + void detachFrom (HeteroData&); template auto& get() noexcept { return std::get(*this); } template auto& get() noexcept { return std::get(*this); } @@ -143,7 +145,8 @@ namespace lib { _Tail& accessTail() { - REQUIRE (Frame::next, "HeteroData storage logic broken: follow-up extent not yet allocated"); + if (Frame::next == nullptr) // Halt system by breaking noexcept + throw lumiera::error::Fatal{"HeteroData storage logic broken: follow-up extent not(yet) allocated"}; return * reinterpret_cast<_Tail*> (Frame::next); } @@ -341,6 +344,32 @@ namespace lib { , segments); return last->next; } + + /** + * @internal detach the HeteroData-chain at the link to the given chainBlock. + * This enables some additional data sanity, because the internal chain can + * thus be severed when an extension data block is known to go out of scope. + * If somehow a store accessor is used after that point, the system will + * be halted when attempting to navigate to the (now defunct) data block. + */ + inline void + checkedDetach (size_t segments, StorageLoc* seg, void* chainBlock) + { + REQUIRE(seg); + while (segments and seg->next) + if (segments == 1 and seg->next == chainBlock) + { + seg->next = nullptr; + return; + } + else + { + seg = seg->next; + --segments; + } + NOTREACHED ("Failure to detach a data segment from HeteroData: " + "assumed type structure does not match real connectivity"); + } }//(End)helper @@ -369,6 +398,16 @@ namespace lib { ENSURE (lastLink == nullptr); lastLink = this; } + + /** cleanly detach this storage frame from the HeteroData prefix-chain. */ + template + template + inline void + StorageFrame::detachFrom (HeteroData& prefixChain) + { + StorageLoc* firstSeg = reinterpret_cast (&prefixChain); + checkedDetach (seg, firstSeg, this); + } }// namespace lib diff --git a/src/steam/engine/turnout-system.hpp b/src/steam/engine/turnout-system.hpp index 0538de8da..13e3b1ade 100644 --- a/src/steam/engine/turnout-system.hpp +++ b/src/steam/engine/turnout-system.hpp @@ -67,10 +67,6 @@ namespace engine { }; private: - template - using Accessor = typename lib::HeteroData::template Accessor; - - FrontBlock invoParam_; public: @@ -90,19 +86,31 @@ namespace engine { return invoParam_.get(); } - template + template auto& - get (Accessor const& getter) + get (ACC const& getter) { return getter.get (invoParam_); } + /** attach an extension block with further parameters + * as HeteroData-chain to the embedded FrontBlock + * @note structural properties must match, which + * is ensured when using a ParamBuildSpec. + */ template void attachChainBlock (CHAIN& chainBlock) { chainBlock.linkInto (invoParam_); } + + template + void + detachChainBlock (CHAIN& chainBlock) + { + chainBlock.detachFrom (invoParam_); + } }; diff --git a/tests/core/steam/engine/node-feed-test.cpp b/tests/core/steam/engine/node-feed-test.cpp index 0c964c1f2..ac62b226b 100644 --- a/tests/core/steam/engine/node-feed-test.cpp +++ b/tests/core/steam/engine/node-feed-test.cpp @@ -27,6 +27,7 @@ #include "steam/asset/meta/time-grid.hpp" #include "lib/several-builder.hpp" #include "lib/time/timecode.hpp" +#include "lib/test/test-helper.hpp" #include "lib/test/diagnostic-output.hpp"/////////////////////TODO //#include "lib/util.hpp" @@ -36,6 +37,8 @@ using lib::Several; using lib::makeSeveral; using lib::time::Time; using lib::time::FSecs; +using lib::time::FrameNr; +using lib::test::showType; namespace steam { @@ -44,7 +47,6 @@ namespace test { - /************************************************************************//** * @test demonstrate how to feed data into, through and out of render nodes. */ @@ -53,6 +55,7 @@ namespace test { virtual void run (Arg) { + seedRand(); feedParam(); feedParamNode(); UNIMPLEMENTED ("render node pulling source data from vault"); @@ -105,36 +108,73 @@ namespace test { result.release(); } - /** @test create extended parameter data for use in recursive Node invocation */ + + /** @test create extended parameter data for use in recursive Node invocation. + * - demonstrate the mechanism of param-functor invocation, + * and how a Param-Spec is built to create and hold those functors + * - then instantiate an actual TurnoutSystem, as is done for a Node invocation, + * with an embedded »absolute nominal time« parameter value + * - can then invoke the param-functors and materialise results into a Param-Data-Block + * - which then can be linked internally to be reachable through the TurnoutSystem + * - other code further down the call-stack can thus access those parameter values. + * - The second part of the test uses the same scheme embedded into a Param(Agent)Node + */ void feedParamNode() { steam::asset::meta::TimeGrid::build("grid_sec", 1); + // Parameter-functor based on time-quantisation into a 1-seconds-grid auto fun1 = [](TurnoutSystem& turSys) { - return lib::time::FrameNr::quant (turSys.getNomTime(), "grid_sec"); + return FrameNr::quant (turSys.getNomTime(), "grid_sec"); }; + // The Param-Spec is used to coordinate type-safe access + // and also is used as a blueprint for building a Param(Agent)Node auto spec = buildParamSpec() .addValSlot (LIFE_AND_UNIVERSE_4EVER) .addSlot (move (fun1)) ; - using Spec = decltype(spec); -SHOW_TYPE(Spec) -SHOW_TYPE(Spec::ParamTup) - TurnoutSystem turnoutSys{Time{FSecs(5,2)}}; + // The implied type of the parameter-tuple to generate + using ParamTup = decltype(spec)::ParamTup; + CHECK (showType() == "tuple"_expect); + + // can now store accessor-functors for later use.... + auto acc0 = spec.slot<0>().makeAccessor(); + auto acc1 = spec.slot<1>().makeAccessor(); + + // drive test with a random »nominal Time« <10s with ms granularity + Time nomTime{rani(10'000),0}; + TurnoutSystem turnoutSys{nomTime}; + // can now immediately invoke the embedded parameter-functors auto v0 = spec.slot<0>().invokeParamFun (turnoutSys); auto v1 = spec.slot<1>().invokeParamFun (turnoutSys); -SHOW_EXPR(v0) -SHOW_EXPR(v1) + CHECK (v0 == LIFE_AND_UNIVERSE_4EVER); // ◁————————— the first paramFun yields the configured fixed value + CHECK (v1 == FrameNr::quant (nomTime, "grid_sec")); // ◁————————— the second paramFun accesses the time in TurnoutSystem + + { // Now build an actual storage block in local scope, + // thereby invoking the embedded parameter-functors... + auto paramBlock = spec.buildParamDataBlock (turnoutSys); + // Values are now materialised into paramBlock + CHECK (v0 == paramBlock.get<0>()); + CHECK (v1 == paramBlock.get<1>()); + + // link this extension block into the parameter-chain in TurnoutSystem + turnoutSys.attachChainBlock(paramBlock); + + // can now access the parameter values through the TurnoutSystem as front-End + CHECK (v0 == spec.slot<0>().getParamVal (turnoutSys)); + CHECK (v1 == spec.slot<1>().getParamVal (turnoutSys)); + // and can also use the accessor-functors stored above + CHECK (v0 == turnoutSys.get(acc0)); + CHECK (v1 == turnoutSys.get(acc1)); + + // should detach extension block before leaving scope + turnoutSys.detachChainBlock(paramBlock); + } - auto paramBlock = spec.buildParamDataBlock (turnoutSys); -SHOW_EXPR(paramBlock) -SHOW_EXPR(paramBlock.get<0>()) -SHOW_EXPR(paramBlock.get<1>()) - TODO ("implement a simple Builder for ParamAgent-Node"); TODO ("then use both together to demonstrate a param data feed here"); } diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index bc9c9745a..9f5bfc44e 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -82336,8 +82336,19 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - + + + + + + + +

+ Das heißt, hier haben wir immer einen festen Satz an Parametern, die stets im TurnoutSystem eingebettet vorliegen; diese können aber als HeteroData-Chain erweitert werden um die Blöcke, die wir über eine (oder eine Kette von) ParamBuildSpec erzeugen +

+ + +
@@ -94180,8 +94191,9 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + + @@ -94235,8 +94247,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - + + @@ -94298,8 +94310,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - + + @@ -94311,13 +94323,13 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - + + - - + +