Invocation: implement the chaining and linking functionality

This basically solves this implementation challenge:
It was possible to construct a ''compile-time type-safe'' overlay,
while using force-casts ''without any metadata'' at runtime.

Obviously this is a dangerous setup, but ''should be resonably safe'' when used within the defined scheme...
This commit is contained in:
Fischlurch 2024-12-11 02:36:17 +01:00
parent eed0f55f83
commit 22f4b9dd7e
3 changed files with 309 additions and 97 deletions

View file

@ -30,7 +30,7 @@
** cache locality of recently used stack frames, thereby avoiding heap allocations altogether.
**
** @todo WIP-WIP this is the draft of a design sketch regarding the render node network,
** which seems to be still pretty much in flux as of 12/2024
** which seems to be still pretty much in flux as of 12/2024
** @see HeteroData_test
** @see steam::engine::TurnoutSystem (use case)
**
@ -48,6 +48,7 @@
//#include "lib/linked-elements.hpp"
#include "lib/meta/typelist.hpp"
#include "lib/meta/typelist-manip.hpp"
//#include "lib/meta/typelist-util.hpp"
#include "lib/meta/typeseq-util.hpp"
#include "lib/test/test-helper.hpp"
@ -59,39 +60,48 @@
namespace lib {
/**
*/
template<typename...DATA>
class HeteroData;
struct StorageLoc
: util::NonCopyable
{
StorageLoc* next{nullptr};
};
template<typename...DATA>
template<size_t seg, typename...DATA>
struct StorageFrame
: protected StorageLoc
, std::tuple<DATA...>
{
using std::tuple<DATA...>::tuple;
template<typename SPEC>
void linkInto (HeteroData<SPEC>&);
};
/**
*/
template<typename...DATA>
class HeteroData;
template<class TAIL, typename...DATA>
class HeteroData<meta::Node<StorageFrame<DATA...>,TAIL>>
: StorageFrame<DATA...>
template<size_t seg, typename...DATA, class TAIL>
class HeteroData<meta::Node<StorageFrame<seg, DATA...>,TAIL>>
: StorageFrame<seg, DATA...>
{
using _Self = HeteroData;
using _Tail = HeteroData<TAIL>;
using Tuple = std::tuple<DATA...>;
using Frame = StorageFrame<DATA...>;
using Frame = StorageFrame<seg, DATA...>;
static constexpr size_t localSiz = sizeof...(DATA);
template<size_t slot>
static constexpr bool isLocal = slot < localSiz;
template<size_t slot>
using PickType = std::conditional_t<isLocal<slot>, std::tuple_element<slot,Tuple>
, typename _Tail::template PickType<slot-localSiz>>;
_Tail&
accessTail()
{
@ -114,8 +124,8 @@ namespace lib {
}
template<size_t slot>
using Elm_t = std::conditional_t<isLocal<slot>, std::tuple_element_t<slot,Tuple>
, typename _Tail::template Elm_t<slot-localSiz>>;
using Elm_t = typename PickType<slot>::type;
template<size_t slot>
Elm_t<slot>&
@ -143,10 +153,10 @@ namespace lib {
};
template<typename...VALS>
struct Constructor
struct Chain
{
using NewFrame = StorageFrame<VALS...>;
using ChainType = meta::Append<meta::Node<Frame,TAIL>,NewFrame>;
using NewFrame = StorageFrame<seg+1, VALS...>;
using ChainType = HeteroData<typename meta::Append<meta::Node<Frame,TAIL>,NewFrame>::List>;
template<typename...INIT>
static NewFrame
@ -156,7 +166,7 @@ namespace lib {
}
template<typename...XVALS>
using ChainConstructor = typename ChainType::template Constructor<XVALS...>;
using ChainExtension = typename ChainType::template Chain<XVALS...>;
template<size_t slot>
using Accessor = typename ChainType::template Accessor<_Self::size()+slot>;
@ -174,13 +184,15 @@ namespace lib {
template<size_t>
using Elm_t = void;
template<size_t>
using PickType = void;
};
template<typename...DATA>
class HeteroData
: public HeteroData<meta::Node<StorageFrame<DATA...>, meta::NullType>>
: public HeteroData<meta::Node<StorageFrame<0, DATA...>, meta::NullType>>
{
using _Front = HeteroData<meta::Node<StorageFrame<DATA...>, meta::NullType>>;
using _Front = HeteroData<meta::Node<StorageFrame<0, DATA...>, meta::NullType>>;
public:
using NewFrame = typename _Front::Frame;
@ -195,5 +207,48 @@ namespace lib {
};
namespace {
/**
* @internal helper for safety-check when attaching segments.
* New segments are created by a constructor functor, guided by a
* type signature describing the complete chain. When attaching new
* segments, we can not verify that the base chain to extend does really
* match the presumed chain structure as encoded into the type (since this
* base chain does not store any meta data). But at least we can verify
* that the number of real segment-links matches the assumed structure.
* Notably it does not really matter what is stored in the base chain,
* as long as this segment count matches, because accessor functors
* generated by a `HeteroData::Chain` constructor will always address
* only their own (newly added) segment.
*/
inline StorageLoc*&
checkedTraversal (size_t segments, StorageLoc* last)
{
REQUIRE(last);
while (segments and last->next)
{
last = last->next;
--segments;
}
ASSERT (last->next == nullptr and segments == 1
,"Failure to attach new data segment to HeteroData: "
"assumed type structure does not match real connectivity, "
"end-of-chain encountered with %d type segment(s) remaining"
, segments);
return last->next;
}
}
template<size_t seg, typename...DATA>
template<typename SPEC>
inline void
StorageFrame<seg,DATA...>::linkInto (HeteroData<SPEC>& prefixChain)
{
StorageLoc* firstSeg = reinterpret_cast<StorageLoc*> (&prefixChain);
StorageLoc*& lastLink = checkedTraversal (seg, firstSeg);
ENSURE (lastLink == nullptr);
lastLink = this;
}
} // namespace lib
#endif /*LIB_HETERO_DATA_H*/

View file

@ -20,19 +20,18 @@
#include "lib/hetero-data.hpp"
#include "lib/meta/trait.hpp"
#include "lib/test/diagnostic-output.hpp"/////////////////TODO
#include "lib/util.hpp"
#include <string>
namespace lib {
namespace test{
using std::string;
using meta::is_Subclass;
using util::isSameObject;
namespace { // probe victims
}//(End) test data
#define TYPE(_EXPR_) showType<decltype(_EXPR_)>()
@ -54,11 +53,13 @@ namespace test{
// checksum = 0;
verify_FrontBlock();
verify_ChainBlock();
}
/** @test build a free standing data tuple block to start a chain */
void
verify_FrontBlock ()
verify_FrontBlock()
{
using Block1 = HeteroData<uint,double>;
CHECK ((is_Subclass<Block1::NewFrame, std::tuple<uint,double>>()));
@ -74,6 +75,41 @@ namespace test{
b2.get<1>() = 3.14;
CHECK (3.14 == b2.get<1>());
}
/** @test construct a follow-up data tuple block and hook it into the chain */
void
verify_ChainBlock()
{
using Block1 = HeteroData<uint>;
CHECK ((is_Subclass<Block1::NewFrame, std::tuple<uint>>()));
using Constructor = Block1::Chain<double,string>;
using Block2 = Constructor::NewFrame;
CHECK ((is_Subclass<Block2, std::tuple<double, string>>()));
auto b1 = Block1::build (41);
auto b2 = Constructor::build (1.61, "Φ");
b2.linkInto(b1);
auto& chain2 = reinterpret_cast<Constructor::ChainType&> (b1);
CHECK (b1.size() == 1);
CHECK (chain2.size() == 3);
CHECK (41 == chain2.get<0>());
CHECK (1.61 == chain2.get<1>());
CHECK ("Φ" == chain2.get<2>());
chain2.get<0>()++;
chain2.get<1>() = (1 + sqrt(5)) / 2;
CHECK (b1.get<0>() == 42);
CHECK (chain2.get<0>() == 42);
CHECK (std::get<0> (b2) == "1.618034"_expect);
CHECK (isSameObject (chain2.get<0>() ,b1.get<0>()));
CHECK (isSameObject (chain2.get<2>() ,std::get<1>(b2)));
}
};

View file

@ -22038,9 +22038,7 @@
</node>
<node CREATED="1582832796288" ID="ID_1100021505" MODIFIED="1582833171700" TEXT="praktisch wird es nie gebraucht">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
...praktisch k&#246;nnte es zwar sein, da&#223; wir darauf angewiesen sind, das Widget schon zu kennen. Konkret ist das aber im Moment nicht der Fall, und ich sollte mir dar&#252;ber jetzt auch keine Gedanken machen; das Design mu&#223; ohnehin sp&#228;ter nochmal &#252;berarbeitet werden...
@ -22719,9 +22717,7 @@
<node CREATED="1480694571310" ID="ID_1188786444" MODIFIED="1557498707226" TEXT="aber Controller wird Chef"/>
<node CREATED="1480725633399" FOLDED="true" ID="ID_1475661668" MODIFIED="1576282358082" TEXT="mu&#xdf; erst mal Controller implementieren">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
...abstraktes Interface
@ -23041,9 +23037,7 @@
</node>
<node CREATED="1480780538975" ID="ID_1139883143" MODIFIED="1539382659232" TEXT="nur die &quot;pa&#xdf;t schon&quot;-L&#xf6;sung ist vern&#xfc;nftig">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
...nach allen g&#228;ngigen Prinzipien der instrumentellen Vernunft.
@ -23532,9 +23526,7 @@
<node CREATED="1672706902644" ID="ID_429923017" MODIFIED="1672706904037" TEXT="using SignalStructureChange = sigc::signal&lt;void&gt;;"/>
<node CREATED="1672706906238" ID="ID_1588783616" MODIFIED="1672706918219">
<richcontent TYPE="NODE"><html>
<head>
</head>
<head/>
<body>
<p>
sollte <i>callable</i>&#160;sein
@ -24698,9 +24690,7 @@
</node>
<node CREATED="1612646254925" ID="ID_910305950" MODIFIED="1612646291779">
<richcontent TYPE="NODE"><html>
<head>
</head>
<head/>
<body>
<p>
Invariante gilt <i>auf einem</i>&#160;Fork
@ -26795,9 +26785,7 @@
<icon BUILTIN="button_ok"/>
<node COLOR="#435e98" CREATED="1674170380401" HGAP="36" ID="ID_600466568" MODIFIED="1674170473951" TEXT="sollte dann doch besser in eine eigene Zeile" VSHIFT="-3">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
wozu haben wir das Gtk::Grid
@ -29747,9 +29735,7 @@
<node CREATED="1561150688515" ID="ID_1217282542" MODIFIED="1561150695224" TEXT="stateful counting Filter geht doch..."/>
<node CREATED="1561150696094" ID="ID_1756846313" MODIFIED="1561150726654" TEXT="sollte am Ende genauso effizient sein">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
als ob es darauf ank&#228;me...
@ -32191,9 +32177,7 @@
<linktarget COLOR="#4587d6" DESTINATION="ID_1263142656" ENDARROW="Default" ENDINCLINATION="-80;5;" ID="Arrow_ID_1541352493" SOURCE="ID_1417021403" STARTARROW="None" STARTINCLINATION="-203;0;"/>
<node CREATED="1561734458294" ID="ID_73927449" MODIFIED="1562843967076">
<richcontent TYPE="NODE"><html>
<head>
</head>
<head/>
<body>
<p>
man sollte den <b>GtkStyleContext</b>&#160;nutzen
@ -36283,9 +36267,7 @@
</node>
<node CREATED="1582443855728" ID="ID_1789967574" MODIFIED="1582443913545" TEXT="cmd::test_meta_activateContentDiff">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<ul>
<li>
@ -38332,9 +38314,7 @@
<node CREATED="1618504487367" ID="ID_1202198317" MODIFIED="1618504512315" TEXT="Clip und Sequenz k&#xf6;nnen fixiert sein"/>
<node CREATED="1618504518013" ID="ID_1762835695" MODIFIED="1618504554622" TEXT="es ist besser, dies unmittelbar im UI erfahrbar zu machen">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
...anstatt blo&#223; die Ausf&#252;hrung entsprechender Commands zur&#252;ckzuweisen
@ -39362,9 +39342,7 @@
<node CREATED="1624112346753" ID="ID_1577761232" MODIFIED="1624112350129" TEXT="Beobachtungen">
<node CREATED="1624112351401" ID="ID_1554867729" MODIFIED="1624112475687" TEXT="h&#xe4;ngt ab vom Test-zeichen-Code in TimelineCanvas::drawOverlays(cox)">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
...dieser zeichnet die Kreise mit Ausdehnung der Allocation, und auch genau mit dieser Farbe und Linienbreite
@ -39727,9 +39705,7 @@
<node CREATED="1541859805246" ID="ID_1619845581" MODIFIED="1557498707233" TEXT="temporal extension of one unit"/>
<node CREATED="1542384386446" ID="ID_1472241358" MODIFIED="1576282358022" TEXT="minval / maxval or unlimited?">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
Beachte: nicht verwechseln mit absoluten Angaben.
@ -40229,9 +40205,7 @@
</node>
<node CREATED="1666966186762" ID="ID_1824326405" MODIFIED="1666966230396" TEXT="Nutzer wollen oft speziellere Dinge tun">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
m&#252;&#223;ten also dann jeweils selber dies in die Kenn-Parameter &#252;bersetzen &#10233; Gefahr von Code-Duplikation und inkonsistentem Verhalten
@ -40425,9 +40399,7 @@
<node CREATED="1667350440373" ID="ID_1896628944" MODIFIED="1667350460022" TEXT="Vorsicht... Minimum w&#xe4;re dann 1&#xb5;T/px"/>
<node CREATED="1667350475136" ID="ID_1672716361" MODIFIED="1667350817413" TEXT="&#x27f9; Sound-Samples lassen sich nicht sauber darstellen">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
alle 20 Schritte ein Sprung, bzw. sogar nur alle 10 Schritte bei 96kHz, denn 1/96000 = 10.41666666 &#181;Tick
@ -87758,7 +87730,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<node COLOR="#338800" CREATED="1733767199547" ID="ID_22701741" MODIFIED="1733868478977" TEXT="Template HeteroData">
<icon BUILTIN="button_ok"/>
</node>
<node COLOR="#338800" CREATED="1733767218786" ID="ID_121902085" MODIFIED="1733868478977" TEXT="HeteroData_test">
<node COLOR="#338800" CREATED="1733767218786" ID="ID_121902085" LINK="#ID_155186903" MODIFIED="1733883512764" TEXT="HeteroData_test">
<icon BUILTIN="button_ok"/>
</node>
</node>
@ -87791,14 +87763,59 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1733799750738" ID="ID_532258033" MODIFIED="1733799768652" TEXT="Implementierung ausarbeiten">
<icon BUILTIN="pencil"/>
<node CREATED="1733804423613" ID="ID_1306152229" MODIFIED="1733804462327" TEXT="Zugriff">
<node COLOR="#338800" CREATED="1733804423613" ID="ID_1306152229" MODIFIED="1733882827467" TEXT="Zugriff">
<icon BUILTIN="button_ok"/>
<node COLOR="#338800" CREATED="1733804463800" ID="ID_1686530886" MODIFIED="1733804491599" TEXT="definiere den Datentyp rekursiv">
<icon BUILTIN="button_ok"/>
</node>
<node CREATED="1733804471735" ID="ID_217423476" MODIFIED="1733804494202" TEXT="per Spezialisierung &#xfc;ber eine Loki-Typliste">
<node BACKGROUND_COLOR="#c8c0b6" COLOR="#435e98" CREATED="1733804471735" ID="ID_217423476" MODIFIED="1733882831311" TEXT="per Spezialisierung &#xfc;ber eine Loki-Typliste">
<icon BUILTIN="idea"/>
<node COLOR="#255579" CREATED="1733882844030" ID="ID_1418616342" MODIFIED="1733882911383" TEXT="Tip: size() einer Loki-Typliste &#x27f6; template count in &quot;typelist-util.hpp&quot;">
<font NAME="SansSerif" SIZE="11"/>
<icon BUILTIN="idea"/>
</node>
<node CREATED="1733804500755" ID="ID_1984459330" MODIFIED="1733804525607" TEXT="damit alle Zugriffe auf Index-Bedingung zur&#xfc;ckgef&#xfc;hrt"/>
</node>
<node CREATED="1733804500755" ID="ID_1984459330" MODIFIED="1733804525607" TEXT="damit alle Zugriffe auf Index-Bedingung zur&#xfc;ckgef&#xfc;hrt">
<node COLOR="#435e98" CREATED="1733881866474" ID="ID_1844233096" MODIFIED="1733881897434" TEXT="Problem: std::conditional wertet nicht lazy aus (kein short-circuit)">
<icon BUILTIN="broken-line"/>
<node BACKGROUND_COLOR="#c8c0b6" COLOR="#435e98" CREATED="1733881900018" ID="ID_974516263" LINK="https://stackoverflow.com/q/28432977/444796" MODIFIED="1733882181104" TEXT="Stackoverflow">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
kurz gesagt:&#160; <font face="Monospaced" color="#2a1864">std::conditional </font>soll zwischen zwei wohldefinierten Typen ausw&#228;hlen; es ist eigentlich nicht f&#252;r Metaprogrammierung gedacht
</p>
</body>
</html></richcontent>
<icon BUILTIN="info"/>
</node>
<node COLOR="#7c4e51" CREATED="1733881928049" ID="ID_921602357" MODIFIED="1733881969522" TEXT="schade aber auch ... es war so elegant">
<icon BUILTIN="smily_bad"/>
</node>
<node COLOR="#338800" CREATED="1733881980690" ID="ID_941924690" MODIFIED="1733882578394" TEXT="der Trick mit dem Traits-Template aus der einen Stackoverflow-Antwort k&#xf6;nnte gehen....">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
Ein Traits-Template hat eingeschachtelte Typen, mit denen sich weitere Eigenschaften abgreifen lassen. Das Traits-Template ist wohldefiniert, wenn es mit den gegebenen Typ-Parametern instantiiert werden kann. Das hei&#223;t, eingeschachtelte Definitionen m&#252;ssen syntaktisch korrekt sein, werden aber nur weiter ausgewertet, wenn man diese Definitionen dann tats&#228;chlich verwendet. Das ist ein grundlegendes Verhalten des Instantiierungs-Modells von C++, das u.A. auch Forward-Deklarationen m&#246;glich macht. Das kann man sich hier zunutze machen ... allerdings mu&#223; ich nun daf&#252;r ein Helper-Template anlegen, damit auf beiden Zweigen so etwas wie ein Traits-Template ausgew&#228;hlt werden kann. Ich f&#252;hre also eine private Def ein: PickType&lt;slot&gt;. Dann ist das Elm_t&lt;slot&gt; wie &#252;blich nur noch eine getemplatete Abk&#252;rzung, aber <i>erst diese greift auf die nested types tats&#228;chlich zu</i>
</p>
</body>
</html></richcontent>
<icon BUILTIN="button_ok"/>
</node>
</node>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1733882622244" ID="ID_934029936" MODIFIED="1733882821134" TEXT="Inh&#xe4;rente Einschr&#xe4;nkung: size() und alle Zugriffe beruhen auf dem Typ (nicht den Daten)">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
Das ist aber der Knackpunkt bei diesem Design &#8212; ich mache den ganzen komplexen Typ-Overlay nur, damit ich zur Laufzeit keinerlei Metadaten speichern mu&#223;; Zugriff erfolgt &#252;ber Accessoren, die sozusagen &#8222;eingebaute Leitplanken&#8220; haben, dann aber einfach einen force-Cast machen. Pro Level m&#246;chte ich eigentlich nur eine einzige Indirektion haben
</p>
</body>
</html></richcontent>
<icon BUILTIN="messagebox_warning"/>
</node>
</node>
<node COLOR="#338800" CREATED="1733804529591" ID="ID_811390325" MODIFIED="1733804573211" TEXT="Accessor als nested Template &#x27f9; enth&#xe4;lt implizit den Typ der gesamten Chain">
<icon BUILTIN="button_ok"/>
</node>
@ -87815,6 +87832,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</html></richcontent>
</node>
<node COLOR="#338800" CREATED="1733851547437" ID="ID_1704921041" MODIFIED="1733851566531" TEXT="man k&#xf6;nnte Variante bieten, den den Index per Typ findet">
<arrowlink COLOR="#678f9e" DESTINATION="ID_745130175" ENDARROW="Default" ENDINCLINATION="1747;-43;" ID="Arrow_ID_1832059516" STARTARROW="None" STARTINCLINATION="55;794;"/>
<icon BUILTIN="button_ok"/>
<node CREATED="1733851568306" ID="ID_1935766805" LINK="https://stackoverflow.com/q/18063451/444796" MODIFIED="1733851613554" TEXT="Stackoverflow">
<icon BUILTIN="idea"/>
@ -87897,18 +87915,21 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</body>
</html></richcontent>
</node>
<node BACKGROUND_COLOR="#fafe99" COLOR="#fa002a" CREATED="1733804917746" ID="ID_1185565269" MODIFIED="1733835639063" TEXT="??? wie schaffe ich das nur ???">
<node BACKGROUND_COLOR="#cab350" COLOR="#5f336d" CREATED="1733804917746" ID="ID_1185565269" MODIFIED="1733882944886" TEXT="??? wie schaffe ich das nur ???">
<arrowlink COLOR="#fffde1" DESTINATION="ID_1456102629" ENDARROW="Default" ENDINCLINATION="-241;13;" ID="Arrow_ID_1934239160" STARTARROW="None" STARTINCLINATION="-98;366;"/>
<icon BUILTIN="smily_bad"/>
<node CREATED="1733804944471" ID="ID_1490645699" MODIFIED="1733804971335" TEXT="Idee-1 : Storage-Frame bekommt zus&#xe4;tzlichen pointer-Parameter"/>
<node CREATED="1733804972427" ID="ID_1289574080" MODIFIED="1733804987877" TEXT="Idee-2 : etwas mit Lambdas zaubern....?">
<node COLOR="#5b280f" CREATED="1733804944471" ID="ID_1490645699" MODIFIED="1733882988723" TEXT="Idee-1 : Storage-Frame bekommt zus&#xe4;tzlichen pointer-Parameter">
<icon BUILTIN="button_cancel"/>
</node>
<node COLOR="#5b280f" CREATED="1733804972427" ID="ID_1289574080" MODIFIED="1733882988723" TEXT="Idee-2 : etwas mit Lambdas zaubern....?">
<icon BUILTIN="button_cancel"/>
<node CREATED="1733805043593" ID="ID_1213049717" MODIFIED="1733805053163" TEXT="Funktions-Verkettung?"/>
<node CREATED="1733805057589" ID="ID_938270964" MODIFIED="1733805072169" TEXT="irgendwie vom letzten HeteroData aus einschie&#xdf;en???"/>
</node>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1733834483620" ID="ID_585239021" MODIFIED="1733834519382" TEXT="Situation des Nutzens vergegenw&#xe4;rtigen">
<node BACKGROUND_COLOR="#c8c0b6" COLOR="#580099" CREATED="1733834483620" ID="ID_585239021" MODIFIED="1733883011509" TEXT="Situation des Nutzens vergegenw&#xe4;rtigen">
<icon BUILTIN="forward"/>
<node CREATED="1733834527058" ID="ID_1496514894" MODIFIED="1733834543856" TEXT="aufgerufen wird eine spezielle ParamNode">
<node CREATED="1733834545401" ID="ID_47691367" MODIFIED="1733834566914" TEXT="effektiv ist das dann ein Port mit speziellem WeavingPattern"/>
@ -87998,23 +88019,27 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</body>
</html></richcontent>
</node>
<node CREATED="1733836360473" ID="ID_985630587" MODIFIED="1733836394993" TEXT="zu pr&#xfc;fen w&#xe4;re also, ob der Datenrecord tats&#xe4;chlich seinem Typ gem&#xe4;&#xdf; angeh&#xe4;ngt wird"/>
<node CREATED="1733836403236" ID="ID_97000599" MODIFIED="1733836479233" TEXT="die zum Anh&#xe4;ngen notwendige Zugangs-Funktion mu&#xdf; aber ohnehin einen force-Cast machen">
<node CREATED="1733836360473" ID="ID_985630587" MODIFIED="1733872606806" TEXT="zu pr&#xfc;fen w&#xe4;re also, ob der Datenrecord tats&#xe4;chlich seinem Typ gem&#xe4;&#xdf; angeh&#xe4;ngt wird">
<icon BUILTIN="yes"/>
</node>
<node CREATED="1733836403236" ID="ID_97000599" MODIFIED="1733872599991" TEXT="die zum Anh&#xe4;ngen notwendige Zugangs-Funktion mu&#xdf; aber ohnehin einen force-Cast machen">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
eben weil wir im HeteroData-Chain selber (also dem TurnoutSystem) keine Metadaten unterbringen wollen
eben weil wir im HeteroData-Chain selber (also dem TurnoutSystem) keine Metadaten unterbringen wollen &#10233; damit aber drehen sich alle Verifikationen dieser Typ-Struktor im Kreis, auch die size()-Funktion ist ja constexpr und analysiert wieder nur die Typ-Signatur; ob tats&#228;chlich die angebilchen Tupel-Felder im Speicher liegen kann man ohne RTTI nicht pr&#252;fen
</p>
</body>
</html></richcontent>
</html>
</richcontent>
<icon BUILTIN="broken-line"/>
</node>
<node CREATED="1733836480541" ID="ID_1669530928" MODIFIED="1733836721760" TEXT="m&#xf6;glich und aber auch genau hinreichend w&#xe4;re jedoch ein Plausibilit&#xe4;ts-Check">
<node CREATED="1733836480541" ID="ID_1669530928" MODIFIED="1733872649665" TEXT="m&#xf6;glich und aber auch genau hinreichend w&#xe4;re jedoch ein Plausibilit&#xe4;ts-Check">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
...dieser Check w&#252;rde pr&#252;fen, ob wir nach einer vorkonfigurierten Anzahl an Schritten exakt hinter dem Ende des aktuellen Chain stehen &#8212; denn <i>genau dann</i>&#160;kann ein damit konform konstruierter Accessor keinen Schaden mehr anrichten: der lokale Tupel-Typ steckt ja im Kontext des Konstruktors, und wurde deshalb soeben zum Anlegen des konkreten Datentupels verwendet; solange die Vorg&#228;nger-Chain in der L&#228;nge pa&#223;t, ist es im Grunde egal, was da sonst noch f&#252;r Datenwerte liegen, so lange wir nur grade am Ende der Vorg&#228;nger-Chain auf den Pointer zu unserem neu erzeugten Datenwert landen
...dieser Check w&#252;rde pr&#252;fen, ob wir nach einer vorkonfigurierten Anzahl an Schritten exakt hinter dem Ende des aktuellen Chain stehen &#8212; denn <i>genau dann</i>&#160;kann ein damit konform konstruierter Accessor keinen Schaden mehr anrichten: der lokale Tupel-Typ steckt ja im Kontext des Konstruktors, und wurde deshalb soeben zum Anlegen des konkreten Datentupels verwendet; solange die Vorg&#228;nger-Chain in der Zahl der Segmente pa&#223;t, ist es im Grunde egal, was da sonst noch f&#252;r Datenwerte liegen, so lange wir nur grade am Ende der Vorg&#228;nger-Chain auf den Pointer zu unserem neu erzeugten Datenwert landen
</p>
</body>
</html></richcontent>
@ -88029,7 +88054,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</body>
</html></richcontent>
</node>
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1733836986637" ID="ID_1879337196" MODIFIED="1733836996216" TEXT="ist das realisierbar?">
<node COLOR="#435e98" CREATED="1733836986637" ID="ID_1879337196" MODIFIED="1733883100876" TEXT="ist das realisierbar?">
<icon BUILTIN="help"/>
<node CREATED="1733836998431" ID="ID_26398170" MODIFIED="1733837056371" TEXT="offensichtlich einfach w&#xe4;re es aus dem Konstruktor heraus">
<richcontent TYPE="NOTE"><html>
@ -88060,26 +88085,39 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<icon BUILTIN="idea"/>
</node>
</node>
<node COLOR="#2d6a67" CREATED="1733883115545" ID="ID_1100823554" MODIFIED="1733883136980" TEXT="(so konnte es tats&#xe4;chlich befriedigend gel&#xf6;st werden)"/>
</node>
</node>
<node CREATED="1733837245977" ID="ID_402273583" MODIFIED="1733837261228" TEXT="das f&#xfc;hrt zur L&#xf6;sung">
<node CREATED="1733837262561" ID="ID_74548961" MODIFIED="1733837339636">
<node BACKGROUND_COLOR="#c8c0b6" COLOR="#435e98" CREATED="1733837245977" ID="ID_402273583" MODIFIED="1733883393823" TEXT="das f&#xfc;hrt zur L&#xf6;sung">
<font BOLD="true" NAME="SansSerif" SIZE="12"/>
<icon BUILTIN="forward"/>
<node CREATED="1733837262561" ID="ID_74548961" MODIFIED="1733883225309">
<richcontent TYPE="NODE"><html>
<head/>
<body>
<p>
Daten-Record wird markiert mit Template-Parameter <b><font color="#5d0b0b" face="Monospaced"><u>prefixLen</u></font></b>
Daten-Record wird markiert mit Template-Parameter <b><font color="#5d0b0b" face="Monospaced"><u>seg</u></font></b>
</p>
</body>
</html></richcontent>
</node>
<node CREATED="1733837352697" ID="ID_1648354214" MODIFIED="1733837394585" TEXT="der bekommt eine Methode linkInto(HeteroData&amp;)"/>
<node CREATED="1733837395855" ID="ID_458018454" MODIFIED="1733837635994" TEXT="und delegiert in eine Funktion attachAtEnd(len)">
</html>
</richcontent>
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
die kann unmittelbar die L&#228;nge pr&#252;fen und dann an's Ende gehen und den Pointer dort setzen
Wir z&#228;hlen ganz einfach die Nummer der Segmente mit, die wir anh&#228;ngen. Der erste Storage-Frame wird mit 0 initialisiert, und jedesmal, wenn ein erweiterter Typ konstruiert wird, erh&#246;ht sich diese Segment-Nummer
</p>
</body>
</html>
</richcontent>
</node>
<node CREATED="1733837352697" ID="ID_1648354214" MODIFIED="1733837394585" TEXT="der bekommt eine Methode linkInto(HeteroData&amp;)"/>
<node CREATED="1733837395855" ID="ID_458018454" MODIFIED="1733883384957" TEXT="und delegiert in eine Funktion checkedTraversal(len, StorageLoc*)">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
...die kann unmittelbar die L&#228;nge pr&#252;fen und dann an's Ende gehen und den Pointer dort per Referenz exponieren; der eigentliche Check besteht lediglich darin, da&#223; wir die Segment-Anzahl in der Typ-Definition mit den beobachteten &#187;pointer-hops&#171; vergleichen. Das mag nach verbl&#252;ffend wenig aussehen, ist aber grade hinreichend. Wie oben schon gesagt: was in den fr&#252;heren Segmenten konkret gespeichert wurde, kann uns f&#252;r diesen Zugriffs-Schutz komplett egal sein, solange wir in unserem eigenen Segment bleiben, und die Zahl der Schritte bis dorthin stimmt.
</p>
</body>
</html></richcontent>
@ -88116,18 +88154,29 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<node CREATED="1733841599726" ID="ID_1990514352" MODIFIED="1733841609437" TEXT="denn davon k&#xf6;nnen dann Accessoren erzeugt werden"/>
<node CREATED="1733841610265" ID="ID_514581574" MODIFIED="1733841631218" TEXT="damit kann auch der Follow-Up-Konstruktor in diesem Typ liegen"/>
<node CREATED="1733841632372" ID="ID_1787377298" MODIFIED="1733841669645" TEXT="nochmal: das ist die Chain in der Ausbaustrufe wie vom Konstruktor letztlich erzeugt"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1733841884473" ID="ID_1863824634" MODIFIED="1733852122494" TEXT="das k&#xf6;nnte der Ansatzpunkt f&#xfc;r die Implementierung sein">
<node BACKGROUND_COLOR="#dfd4b1" COLOR="#6b4641" CREATED="1733841884473" ID="ID_1863824634" MODIFIED="1733883072558" TEXT="das ist der Ansatzpunkt f&#xfc;r die Implementierung....">
<arrowlink COLOR="#f6ffbc" DESTINATION="ID_1314165564" ENDARROW="Default" ENDINCLINATION="46;-119;" ID="Arrow_ID_1683684415" STARTARROW="None" STARTINCLINATION="-294;14;"/>
<icon BUILTIN="idea"/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1733841958666" ID="ID_1314165564" MODIFIED="1733852113174" TEXT="mit dem Chain-Konstruktor beginnen">
<node COLOR="#338800" CREATED="1733841958666" ID="ID_1314165564" MODIFIED="1733883417116" TEXT="mit dem Chain-Konstruktor beginnen">
<linktarget COLOR="#f6ffbc" DESTINATION="ID_1314165564" ENDARROW="Default" ENDINCLINATION="46;-119;" ID="Arrow_ID_1683684415" SOURCE="ID_1863824634" STARTARROW="None" STARTINCLINATION="-294;14;"/>
<icon BUILTIN="pencil"/>
<icon BUILTIN="button_ok"/>
<node CREATED="1733841974800" ID="ID_1337308066" MODIFIED="1733841991425" TEXT="er ist ein Funktor, der an diese aktuelle Chain hinten anh&#xe4;ngt"/>
<node CREATED="1733842016283" ID="ID_519146605" MODIFIED="1733842037697" TEXT="mu&#xdf; also den neuen Chain-Typ per Typlisten-Anh&#xe4;ngen erzeugen"/>
<node CREATED="1733851898302" ID="ID_1548944184" MODIFIED="1733851920386" TEXT="ansonsten mu&#xdf; ja nun der Konstruktor nur noch den Storage-Frame erzeugen"/>
<node COLOR="#435e98" CREATED="1733851898302" ID="ID_1548944184" MODIFIED="1733883449573" TEXT="ansonsten mu&#xdf; ja nun der Konstruktor nur noch den Storage-Frame erzeugen">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
denn die weitere Verkn&#252;pfung wird explizit in einem zweiten Schritt gemacht, und das ist gut so
</p>
</body>
</html>
</richcontent>
<icon BUILTIN="idea"/>
</node>
<node COLOR="#338800" CREATED="1733851922106" ID="ID_421589500" MODIFIED="1733852040199" TEXT="somit reduziert sich die Implementierung auf einige Typedefs">
<icon BUILTIN="button_ok"/>
</node>
@ -88158,8 +88207,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
...das ist dann die einzige Typ-Signatur, die der Benutzer selber schreiben mu&#223;: <font face="Monospaced" color="#2c1f5e">HeteroData&lt;X,Y,Z&gt;</font>
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
</node>
<node COLOR="#338800" CREATED="1733855818208" ID="ID_1630330383" MODIFIED="1733868356780" TEXT="diesem aber auch die Signatur eines Konstruktors geben">
@ -88193,13 +88241,86 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
denn wir haben ja alle expliziten Accessor-Funktionen direkt auf dem Objekt nochmal definiert, und zudem wird das C++ Tuple-Protokoll implementiert
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node CREATED="1733868698535" ID="ID_1014714524" MODIFIED="1733868718664" TEXT="und gilt nicht f&#xfc;r die Chain-Bl&#xf6;cke"/>
</node>
</node>
</node>
<node COLOR="#338800" CREATED="1733869974719" ID="ID_1275314387" MODIFIED="1733883480203" TEXT="Verkn&#xfc;pfung der Bl&#xf6;cke herstellen">
<icon BUILTIN="button_ok"/>
<node COLOR="#338800" CREATED="1733870004530" ID="ID_1070427353" LINK="#ID_74548961" MODIFIED="1733870588910" TEXT="Parameter f&#xfc;r Fehlverkn&#xfc;pfungs-Schutz einf&#xfc;hren">
<icon BUILTIN="button_ok"/>
</node>
<node COLOR="#338800" CREATED="1733870110558" ID="ID_739275621" MODIFIED="1733883465931" TEXT="Zugriff auf den Ankn&#xfc;pfungspunkt">
<icon BUILTIN="button_ok"/>
<node COLOR="#435e98" CREATED="1733871390896" ID="ID_283631202" MODIFIED="1733876875837" TEXT="Problem API-Zugang">
<icon BUILTIN="messagebox_warning"/>
<node CREATED="1733871417149" ID="ID_1593888377" MODIFIED="1733871439086" TEXT="bisher war die Chain-Struktur auf dem API komplett verborgen"/>
<node CREATED="1733871455757" ID="ID_52318776" MODIFIED="1733871483641" TEXT="brauche aber die rekursive Traversierung aus dem HeteroData-Template"/>
</node>
<node CREATED="1733872658263" ID="ID_1351204592" LINK="#ID_97000599" MODIFIED="1733872858228" TEXT="Vorsicht: wir k&#xf6;nnen ohnehin nur die formale Anzahl an Segmenten verifizieren">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
Nicht von der Typ-Info blenden lassen: die wird hier nur einmal im Kreis geschoben. Wir nehmen zwar irgend ein Front-End, m&#252;ssen das aber dann auf den vollen Chain-Typ force-casten (denn das ist das Grundkonzept, das uns Zugriff ohne virtuelle Funktionen erm&#246;glicht). Die einzige <b>runtime-Info</b>&#160; ist die Anzahl der &#187;Hops&#171; zum n&#228;chsten Segment, d.h. die Anzahl an Pointern, denen wir &#252;ber die Kette folgen. <i>Diese</i>&#160;mu&#223; mit der Anzahl der Komponenten im Typ zusammenpassen
</p>
</body>
</html>
</richcontent>
<icon BUILTIN="clanbomber"/>
</node>
<node COLOR="#338800" CREATED="1733872865111" ID="ID_922628201" MODIFIED="1733883463203" TEXT="ja dannn.... diese Funktionalit&#xe4;t kann genauso gut in einer freien Funktion stehen">
<icon BUILTIN="button_ok"/>
<node CREATED="1733872937569" ID="ID_1060252956" MODIFIED="1733872950084" TEXT="diese Funktion traversiert eine LInked-List"/>
<node CREATED="1733872953192" ID="ID_1260463908" MODIFIED="1733872967097" TEXT="und zerlegt gleichzeitig rekursiv eine Typliste"/>
</node>
</node>
<node COLOR="#338800" CREATED="1733870243031" ID="ID_1554305818" MODIFIED="1733883863018" TEXT="linkInto() implementieren">
<arrowlink COLOR="#65a6c0" DESTINATION="ID_1607678238" ENDARROW="Default" ENDINCLINATION="189;-12;" ID="Arrow_ID_842453741" STARTARROW="None" STARTINCLINATION="-3;109;"/>
<icon BUILTIN="button_ok"/>
<node CREATED="1733876923036" ID="ID_759114145" MODIFIED="1733876952050" TEXT="diese Funktion kann dann tats&#xe4;chlich auf dem StorageFrame sitzen"/>
<node CREATED="1733876952902" ID="ID_608957795" MODIFIED="1733877001187" TEXT="und wir k&#xf6;nnen gefahrlos einen brachialen Force-Cast machen"/>
<node CREATED="1733877002199" ID="ID_544447441" MODIFIED="1733877013578" TEXT="...solange wir irgend ein HeteroData zum Anh&#xe4;ngen bekommen"/>
</node>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1733883489383" ID="ID_155186903" MODIFIED="1733883516460" TEXT="HeteroData_test">
<icon BUILTIN="pencil"/>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1733883525530" ID="ID_1918349528" MODIFIED="1733883530794" TEXT="verify_FrontBlock">
<icon BUILTIN="pencil"/>
<node COLOR="#435e98" CREATED="1733883562026" ID="ID_941439456" MODIFIED="1733883584764" TEXT="Datenblock erstellen"/>
<node COLOR="#435e98" CREATED="1733883567253" ID="ID_252468938" MODIFIED="1733883584764" TEXT="Datenzugriff zeigen"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1733883572964" ID="ID_1308768158" MODIFIED="1733883582117" TEXT="structural binding / Tuple-Protokoll">
<icon BUILTIN="flag-yellow"/>
</node>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1733883536343" ID="ID_877333475" MODIFIED="1733883538992" TEXT="verify_ChainBlock">
<icon BUILTIN="pencil"/>
<node COLOR="#435e98" CREATED="1733883589092" ID="ID_1386279261" MODIFIED="1733883643827" TEXT="erst die Typen konstruieren"/>
<node COLOR="#435e98" CREATED="1733883604891" ID="ID_1254661884" MODIFIED="1733883643827" TEXT="Front-Block erstellen und populieren"/>
<node COLOR="#435e98" CREATED="1733883616620" ID="ID_1790631124" MODIFIED="1733883643827" TEXT="Chain-Block erstellen und populieren"/>
<node COLOR="#435e98" CREATED="1733883624829" ID="ID_1607678238" MODIFIED="1733883856067" TEXT="zusammenh&#xe4;ngen">
<linktarget COLOR="#65a6c0" DESTINATION="ID_1607678238" ENDARROW="Default" ENDINCLINATION="189;-12;" ID="Arrow_ID_842453741" SOURCE="ID_1554305818" STARTARROW="None" STARTINCLINATION="-3;109;"/>
</node>
<node COLOR="#435e98" CREATED="1733883629524" ID="ID_88656707" MODIFIED="1733883643826" TEXT="gemeinsamen Datenzugriff direkt zeigen"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1733883922133" ID="ID_745130175" MODIFIED="1733883969468" TEXT="Zugriff per Typ demonstrieren">
<linktarget COLOR="#678f9e" DESTINATION="ID_745130175" ENDARROW="Default" ENDINCLINATION="1747;-43;" ID="Arrow_ID_1832059516" SOURCE="ID_1704921041" STARTARROW="None" STARTINCLINATION="55;794;"/>
<icon BUILTIN="flag-yellow"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1733883572964" ID="ID_1694822636" MODIFIED="1733883582117" TEXT="structural binding / Tuple-Protokoll">
<icon BUILTIN="flag-yellow"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1733883656600" ID="ID_972149921" MODIFIED="1733883808249" TEXT="verify_Accessors">
<icon BUILTIN="flag-yellow"/>
<node CREATED="1733883663184" ID="ID_1127481242" MODIFIED="1733883674938" TEXT="hier nun mit mehreren Datenbl&#xf6;cken arbeiten"/>
<node CREATED="1733883682093" ID="ID_531287492" MODIFIED="1733883721468" TEXT="Zugriffe via Accessor ohne sichtbaren Cast"/>
<node CREATED="1733883747133" ID="ID_276517152" MODIFIED="1733883759060" TEXT="structural Binding mit allen Einschr&#xe4;nkungen demonstrieren"/>
<node CREATED="1733883781976" ID="ID_1919391319" MODIFIED="1733883795270" TEXT="Speicher-Adressen verifizieren"/>
<node CREATED="1733883796910" ID="ID_1268320323" MODIFIED="1733883805336" TEXT="Grenzen / Gefahren / Manipulation zeigen"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1733767161520" ID="ID_1853669534" MODIFIED="1733767188150" TEXT="Standard-Definition f&#xfc;r TurnoutSystem auf dieser Basis">