Invocation: demonstrate complete usage cycle of extension block
In `NodeFeed_test`... Demonstrate the base mechanism of creating a ''Param Spec'' with a functor-definition for each parameter. This can then later be used to invoke those functors and materialise the results into a data tuple, and this data tuple can be linked into the TurnoutSystem, so that the parameter values can be accessed type-safe with getter-functors.
This commit is contained in:
parent
107d03f6ef
commit
fe75bed227
4 changed files with 131 additions and 32 deletions
|
|
@ -110,6 +110,8 @@ namespace lib {
|
|||
|
||||
template<typename SPEC>
|
||||
void linkInto (HeteroData<SPEC>&);
|
||||
template<typename SPEC>
|
||||
void detachFrom (HeteroData<SPEC>&);
|
||||
|
||||
template<size_t slot> auto& get() noexcept { return std::get<slot>(*this); }
|
||||
template<typename X> auto& get() noexcept { return std::get<X>(*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<size_t seg, typename...DATA>
|
||||
template<typename SPEC>
|
||||
inline void
|
||||
StorageFrame<seg,DATA...>::detachFrom (HeteroData<SPEC>& prefixChain)
|
||||
{
|
||||
StorageLoc* firstSeg = reinterpret_cast<StorageLoc*> (&prefixChain);
|
||||
checkedDetach (seg, firstSeg, this);
|
||||
}
|
||||
}// namespace lib
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -67,10 +67,6 @@ namespace engine {
|
|||
};
|
||||
|
||||
private:
|
||||
template<class SPEC, size_t idx>
|
||||
using Accessor = typename lib::HeteroData<SPEC>::template Accessor<idx>;
|
||||
|
||||
|
||||
FrontBlock invoParam_;
|
||||
|
||||
public:
|
||||
|
|
@ -90,19 +86,31 @@ namespace engine {
|
|||
return invoParam_.get<SLOT_KEY>();
|
||||
}
|
||||
|
||||
template<class SPEC, size_t idx>
|
||||
template<class ACC>
|
||||
auto&
|
||||
get (Accessor<SPEC,idx> 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<class CHAIN>
|
||||
void
|
||||
attachChainBlock (CHAIN& chainBlock)
|
||||
{
|
||||
chainBlock.linkInto (invoParam_);
|
||||
}
|
||||
|
||||
template<class CHAIN>
|
||||
void
|
||||
detachChainBlock (CHAIN& chainBlock)
|
||||
{
|
||||
chainBlock.detachFrom (invoParam_);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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,35 +108,72 @@ 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<ParamTup>() == "tuple<uint, long>"_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
|
||||
|
||||
auto paramBlock = spec.buildParamDataBlock (turnoutSys);
|
||||
SHOW_EXPR(paramBlock)
|
||||
SHOW_EXPR(paramBlock.get<0>())
|
||||
SHOW_EXPR(paramBlock.get<1>())
|
||||
{ // 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);
|
||||
}
|
||||
|
||||
TODO ("implement a simple Builder for ParamAgent-Node");
|
||||
TODO ("then use both together to demonstrate a param data feed here");
|
||||
|
|
|
|||
|
|
@ -82336,8 +82336,19 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
<node CREATED="1735353775789" ID="ID_1394846816" MODIFIED="1735353797045" TEXT="dazu ist ein Funktor-Typ definiert"/>
|
||||
<node CREATED="1735353798274" ID="ID_1422658744" MODIFIED="1735353856467" TEXT="und ein Accessor-Typ">
|
||||
<node CREATED="1735353948999" ID="ID_1107757772" MODIFIED="1735353956728" TEXT="dieser findet zum Slot zurück"/>
|
||||
<node CREATED="1735353970175" ID="ID_542964897" MODIFIED="1735353992387" TEXT="und ist eine Erweiterung der HeteroData-Accessoren">
|
||||
<node CREATED="1735353994703" ID="ID_755528962" MODIFIED="1735354004015" TEXT="vielleicht gar keine Erweiterung?"/>
|
||||
<node CREATED="1735353970175" ID="ID_542964897" MODIFIED="1735519560792" TEXT="und ist ein HeteroData-Accessor"/>
|
||||
<node CREATED="1735519565352" ID="ID_646241396" MODIFIED="1735519667848" TEXT="mit dem TurnoutSystem als Front-Block">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
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
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
|
|
@ -94180,8 +94191,9 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
<linktarget COLOR="#4033e3" DESTINATION="ID_348960119" ENDARROW="Default" ENDINCLINATION="-2228;-103;" ID="Arrow_ID_1086551966" SOURCE="ID_1769136387" STARTARROW="None" STARTINCLINATION="1977;97;"/>
|
||||
<linktarget COLOR="#ff6936" DESTINATION="ID_348960119" ENDARROW="Default" ENDINCLINATION="-641;1944;" ID="Arrow_ID_1163958018" SOURCE="ID_311704401" STARTARROW="None" STARTINCLINATION="1383;132;"/>
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node CREATED="1735416170297" ID="ID_736958022" MODIFIED="1735416236279" TEXT="brauche ParamBuildSpec">
|
||||
<node BACKGROUND_COLOR="#c8c0b6" COLOR="#435e98" CREATED="1735416170297" ID="ID_736958022" MODIFIED="1735519479807" TEXT="brauche ParamBuildSpec">
|
||||
<linktarget COLOR="#bb1f2e" DESTINATION="ID_736958022" ENDARROW="Default" ENDINCLINATION="-25;-162;" ID="Arrow_ID_44922252" SOURCE="ID_1577179744" STARTARROW="None" STARTINCLINATION="32;153;"/>
|
||||
<icon BUILTIN="yes"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1735422554816" ID="ID_197118422" MODIFIED="1735438575232" TEXT="Aufgabe: schrittweise aufbaubar">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node CREATED="1735422591091" ID="ID_1649575055" MODIFIED="1735422735480" TEXT="Diskrepanz zu den HeteroData Chain-Blocks">
|
||||
|
|
@ -94235,8 +94247,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
<node CREATED="1735486938666" ID="ID_1675979650" MODIFIED="1735487816128" TEXT="also direkt anwendbar auf's Turnout-System"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1735427341106" ID="ID_29906476" MODIFIED="1735427368610" TEXT="Lösung aufbauen...">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node COLOR="#338800" CREATED="1735427341106" ID="ID_29906476" MODIFIED="1735519449554" TEXT="Lösung aufbauen...">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node CREATED="1735427377686" ID="ID_1047293090" MODIFIED="1735427389228" TEXT="Typisierung">
|
||||
<node CREATED="1735427448052" ID="ID_1835841396" MODIFIED="1735427511976" TEXT="muß komplett explizit sein">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
|
|
@ -94298,8 +94310,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
<linktarget COLOR="#637488" DESTINATION="ID_870944737" ENDARROW="Default" ENDINCLINATION="310;0;" ID="Arrow_ID_1871378220" SOURCE="ID_1331974543" STARTARROW="None" STARTINCLINATION="145;9;"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1735438595508" ID="ID_696254160" MODIFIED="1735438784764" TEXT="Implementierung">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node COLOR="#338800" CREATED="1735438595508" ID="ID_696254160" MODIFIED="1735519446480" TEXT="Implementierung">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node COLOR="#338800" CREATED="1735438607044" ID="ID_1948837984" MODIFIED="1735438628651" TEXT="Builder-Anker: buildParamSpec()">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
|
|
@ -94311,13 +94323,13 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
<node CREATED="1735438678865" ID="ID_548533062" MODIFIED="1735438686677" TEXT="ähnlich wie für die FeedManifold"/>
|
||||
<node CREATED="1735438687997" ID="ID_283878162" MODIFIED="1735438699784" TEXT="verwendet lib::meta::ElmTypes :: Apply"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1735438707680" ID="ID_1085577180" MODIFIED="1735438715228" TEXT="Zugriffs-Slot">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node COLOR="#338800" CREATED="1735438707680" ID="ID_1085577180" MODIFIED="1735519443885" TEXT="Zugriffs-Slot">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node COLOR="#338800" CREATED="1735438717070" ID="ID_1429780349" MODIFIED="1735438724209" TEXT="jeweiligen Funktor aufrufen">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1735438726120" ID="ID_1670785950" MODIFIED="1735438739642" TEXT="Daten-Accessor konstruieren">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node COLOR="#338800" CREATED="1735438726120" ID="ID_1670785950" MODIFIED="1735519440292" TEXT="Daten-Accessor konstruieren">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node CREATED="1735487309329" ID="ID_1516453754" MODIFIED="1735487326656" TEXT="Bassis sind Accessoren auf HeteroData"/>
|
||||
<node CREATED="1735489834862" ID="ID_1311598461" MODIFIED="1735489845645" TEXT="muß dazu den Chain-Block-Typ konstruieren">
|
||||
<node CREATED="1735489850973" ID="ID_1621449411" MODIFIED="1735489863415" TEXT="aus dem Anker-Typ :: Chain"/>
|
||||
|
|
|
|||
Loading…
Reference in a new issue