Invocation: apply a consistent ordering on the chained hash calculation

...this seems to be a tricky aspect; we use hash-chaining to create
derived entries, which may cause the identity of an entry to depend
on the order of specialisation. Looked through the possible code paths,
but these seem to be quite complicated; I see the lurking danger of
creating a second entry (with a different hash), and then in worst case
even locking/unlocking a given buffer twice....
This commit is contained in:
Fischlurch 2024-07-27 23:53:27 +02:00
parent 6d7a814495
commit 72c7386435
2 changed files with 70 additions and 69 deletions

View file

@ -217,17 +217,20 @@ namespace engine {
forEntry (Key const& parent, const void* bufferAddr, LocalTag const& localTag =LocalTag::UNKNOWN)
{
Key newKey{parent}; // copy of parent as baseline
if (nontrivial(localTag))
{
if (nontrivial(parent.specifics_))
throw error::Logic{"Implementation defined local key should not be overridden. "
"Underlying buffer type already defines a nontrivial LocalTag"};
newKey.parent_ = HashVal(parent);
newKey.hashID_ = chainedHash(newKey.hashID_, localTag);
newKey.specifics_ = localTag;
}
if (bufferAddr)
{
newKey.parent_ = HashVal(parent);
newKey.hashID_ = chainedHash(parent, bufferAddr);
if (nontrivial(localTag))
{
if (nontrivial(parent.specifics_))
throw error::Logic{"Implementation defined local key should not be overridden. "
"Underlying buffer type already defines a nontrivial LocalTag"};
newKey.specifics_ = localTag;
} }
newKey.hashID_ = chainedHash(newKey.hashID_, bufferAddr);
}
return newKey;
}
@ -482,9 +485,8 @@ namespace engine {
Entry&
store (Entry const& newEntry)
{
using std::make_pair;
REQUIRE (!fetch (newEntry), "duplicate buffer metadata entry");
MetadataStore::iterator pos = entries_.insert (make_pair (HashVal(newEntry), newEntry))
MetadataStore::iterator pos = entries_.emplace (HashVal(newEntry), newEntry)
.first;
ENSURE (pos != entries_.end());
@ -610,7 +612,7 @@ namespace engine {
Key const&
key (Key const& parentKey, void* concreteBuffer, LocalTag const& specifics =LocalTag::UNKNOWN)
{
Key derivedKey = Key::forEntry (parentKey, concreteBuffer);
Key derivedKey = Key::forEntry (parentKey, concreteBuffer, specifics);
Entry* existing = table_.fetch (derivedKey);
return existing? *existing
@ -619,16 +621,18 @@ namespace engine {
/** core operation to access or create a concrete buffer metadata entry.
* The hashID of the entry in question is built, based on the parentKey,
* which denotes a buffer type, and the concrete buffer address. If yet
* unknown, a new concrete buffer metadata Entry is created and initialised
* to LOCKED state. Otherwise just the existing Entry is fetched.
* which denotes a buffer type, optionally a implementation defined LocalTag,
* and the concrete buffer address. If yet unknown, a new concrete buffer
* metadata Entry is created and initialised to LOCKED state. Otherwise
* just the existing Entry is fetched and locked.
* @note this function really \em activates the buffer.
* In case the type (Key) involves a TypeHandler (functor),
* its constructor function will be invoked, if actually a new
* entry gets created. Typically this mechanism will be used
* to placement-create an object into the buffer.
* @param parentKey a key describing the \em type of the buffer
* @param parentKey a key describing the _type_ of the buffer
* @param concreteBuffer storage pointer, must not be NULL
* @param specifics an implementation defined tag
* @param onlyNew disallow fetching an existing entry
* @throw error::Logic when #onlyNew is set, but an equivalent entry
* was registered previously. This indicates a serious error
@ -660,8 +664,8 @@ namespace engine {
throw error::Logic{"Attempt to re-lock a buffer still in use"
, LERR_(LIFECYCLE)};
if (!existing)
return store_and_lock (newEntry); // actual creation
if (not existing)
return store_as_locked (newEntry); // actual creation
else
return existing->lock (concreteBuffer);
}
@ -753,7 +757,7 @@ namespace engine {
Key
trackKey (PAR parent, DEF specialisation)
{
Key newKey (parent,specialisation);
Key newKey{parent, specialisation};
maybeStore (newKey);
return newKey;
}
@ -762,12 +766,20 @@ namespace engine {
maybeStore (Key const& key)
{
if (isKnown (key)) return;
table_.store (Entry (key, NULL));
table_.store (Entry{key, nullptr});
}
/** store a fully populated entry immediately starting with locked state
* @remark the (optional) constructor function for a type embedded into the
* buffer is invoked when a _persistent_ entry transitions to _locked_ state;
* since a new buffer created with storage location is already marked as _locked,_
* for sake of consistency the embedded constructor must now be invoked; if this
* fails, the state has to be transitioned back to FREE before re-throwing.
*/
Entry&
store_and_lock (Entry const& metadata)
store_as_locked (Entry const& metadata)
{
REQUIRE (metadata.isLocked());
Entry& newEntry = table_.store (metadata);
try
{

View file

@ -4686,9 +4686,7 @@
</node>
<node CREATED="1483909984005" ID="ID_590392737" MODIFIED="1518487921058">
<richcontent TYPE="NODE"><html>
<head>
</head>
<head/>
<body>
<p>
<i>aber</i>&#160;ist nicht auf dem Visitor-Interface darstellbar
@ -4702,9 +4700,7 @@
<node CREATED="1483910056243" ID="ID_967619584" MODIFIED="1518487921058" TEXT="da Record eine Payload ist"/>
<node CREATED="1483910117819" ID="ID_117939525" MODIFIED="1576282358145" TEXT="man k&#xf6;nnte....">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
....&#252;ber einen GenNode-Visitor nachdenken
@ -4785,9 +4781,7 @@
<node CREATED="1483921149368" ID="ID_1028150245" MODIFIED="1518487921058" TEXT="im GUI nur noch Command-IDs"/>
<node CREATED="1483924872930" ID="ID_242219866" MODIFIED="1582487507380">
<richcontent TYPE="NODE"><html>
<head>
</head>
<head/>
<body>
<p>
...das w&#228;re eine <b>Protokoll-Erweiterung</b>
@ -4803,9 +4797,7 @@
</node>
<node CREATED="1483927472385" HGAP="30" ID="ID_774425061" MODIFIED="1582487441000" VSHIFT="13">
<richcontent TYPE="NODE"><html>
<head>
</head>
<head/>
<body>
<p>
letztlich verworfen; siehe Ticket <font color="#c52a05">#1058</font>
@ -4838,9 +4830,7 @@
</node>
<node CREATED="1483924903190" ID="ID_1436586014" MODIFIED="1576282358144" TEXT="wenn man das Design akzeptiert">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
...das hei&#223;t,
@ -5118,9 +5108,7 @@
</node>
<node CREATED="1553902425206" ID="ID_908225698" MODIFIED="1576282358142" TEXT="verwendet im Hintergrund noch den alten PanelManager">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
...der aber irgendwann (demn&#228;chst in diesem Theater) umgebaut/zur&#252;ckgebaut werden soll
@ -5909,9 +5897,7 @@
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1678573145778" ID="ID_529832770" MODIFIED="1678576114059">
<richcontent TYPE="NODE"><html>
<head>
</head>
<head/>
<body>
<p>
<font size="5">Style-Scheme</font>&#160;for Lumiera
@ -7746,9 +7732,7 @@
</node>
<node CREATED="1506723746120" ID="ID_154958112" MODIFIED="1506723790105" TEXT="unit-test dazu">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
VariadicArgumentPicker_test
@ -10012,9 +9996,7 @@
<icon BUILTIN="yes"/>
<node CREATED="1513396293343" ID="ID_861758487" MODIFIED="1513396293343">
<richcontent TYPE="NODE"><html>
<head>
</head>
<head/>
<body>
<p>
...das ist n&#228;mlich der triviale Workaround
@ -13607,9 +13589,7 @@
<icon BUILTIN="hourglass"/>
<node CREATED="1518745809189" ID="ID_334346990" MODIFIED="1518746202442" TEXT="hier geht es um einen subtilen Punkt im Gebrauch des UI-Raumes">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
Man m&#246;chte, da&#223; f&#252;r spezielle Sub-Elemente,
@ -52562,9 +52542,7 @@
</node>
<node CREATED="1492167970338" FOLDED="true" ID="ID_1983035921" MODIFIED="1613945160418" TEXT="InteractionState &#x27fa; Invocation-Instance">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
...ist jetzt gekl&#228;rt.
@ -52657,9 +52635,7 @@
</node>
<node CREATED="1492173887792" ID="ID_552249287" MODIFIED="1576282357981" TEXT="wozu Ausl&#xf6;sung &#xfc;ber BusTerm eines Widgets">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
...wenn es doch offenbar f&#252;r den &quot;fire-and-forget&quot;-Fall
@ -88649,8 +88625,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
hei&#223;t: wir vergeben diese null&#228;re Optimierung und legen fest, da&#223; das Ergebnis einfach in einem Buffer im Arbeitsspeicher liegt. Jeder Render-Job bekommt dann einen explizit gecodeten Kopier-Schritt
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node CREATED="1721866917499" ID="ID_1329080039" MODIFIED="1722005129923" TEXT="ein spezielles Tag im Buffer-Descriptor ablegen">
<richcontent TYPE="NOTE"><html>
@ -88660,8 +88635,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
das m&#252;&#223;te eine Marke sein, die die spezielle BufferProvider-Implementierung &#8212; also der OutputBufferProvider &#8212; erkennt und daraufhin den konkreten extrnen Output-Buffer herausgibt
</p>
</body>
</html>
</richcontent>
</html></richcontent>
<linktarget COLOR="#4395d3" DESTINATION="ID_1329080039" ENDARROW="Default" ENDINCLINATION="-105;0;" ID="Arrow_ID_1999279188" SOURCE="ID_1451110951" STARTARROW="None" STARTINCLINATION="6;-21;"/>
</node>
<node CREATED="1721867643305" ID="ID_327945127" MODIFIED="1721947494363" TEXT="aus dem Schema ausbrechen und diesen Buffer dirrekt durchgeben">
@ -88682,8 +88656,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
Diese Annahme kann man ziemlich sicher machen; eine Abweichung davon w&#228;re nur m&#246;glich bei einem ziemlich speziellen Setup, bei dem dann setets mehrere Ergebnise auf verschiedenen Ebenen aber im gleichen Rechenproze&#223; anfallen
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1721956892200" ID="ID_1451110951" MODIFIED="1721956974355" TEXT="strukturell w&#xe4;re das Spezial-Tag die beste L&#xf6;sung">
@ -88727,8 +88700,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
...dieser eigentliche Buffer kann auch nochmal per TypeHandler einen &#187;Inlay-Type&#171; bekommen; aber hier beim TrackingHeapBlockProvider ist ja der entscheidenden Punkt, jede Allokation nochmal sekund&#228;r zu verzeichnen und nachzuverfolgen, um entsprechende Verifikationen in den Tests zu erm&#246;glichen
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
</node>
<node CREATED="1721962165891" ID="ID_1229002680" MODIFIED="1722091876751" TEXT="das LocalTag darf in jeder Hierarchie genau einmal gesetzt werden">
@ -88759,8 +88731,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
deshalb habe ich <b>genau f&#252;r diesen Zweck</b>&#160;bereits einen Mechanismus geschaffen
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node CREATED="1721962371425" ID="ID_1532700922" MODIFIED="1722091708754">
<richcontent TYPE="NODE"><html>
@ -88770,8 +88741,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
dieses <font color="#1b40b4" face="Monospaced">LocalTag</font>&#160;ist aber nicht &#252;berall auf das Buffer-Provider-API herausgef&#252;hrt
</p>
</body>
</html>
</richcontent>
</html></richcontent>
<icon BUILTIN="messagebox_warning"/>
</node>
</node>
@ -88801,9 +88771,28 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
im Besonderen an die Reihenfolge denken ... mir f&#228;llt auf, da&#223; ich <i>chainedHash</i>&#160; verwende; damit w&#228;re der Hash-Key <i>pfadabh&#228;ngig</i>
</p>
</body>
</html></richcontent>
<icon BUILTIN="messagebox_warning"/>
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1722129822146" ID="ID_768909598" MODIFIED="1722129849880" TEXT="hilft eine feste Reihenfolge?">
<icon BUILTIN="help"/>
<node CREATED="1722129884245" ID="ID_732292850" MODIFIED="1722129899976" TEXT="Ausgangspunkt: gegebener (parent)Type-hash"/>
<node CREATED="1722129857702" ID="ID_114268361" MODIFIED="1722129879231" TEXT="sinnvollerweise: LocalKey stets zuerst, dann die Adresse"/>
</node>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#980e5e" CREATED="1722129450311" ID="ID_584023703" MODIFIED="1722129479340" TEXT="hab ein ganz ungutes Gef&#xfc;hl hier">
<icon BUILTIN="smily_bad"/>
</node>
<node BACKGROUND_COLOR="#fafe99" COLOR="#fa002a" CREATED="1722129503142" ID="ID_791304404" MODIFIED="1722129798643" TEXT="Gefahr, einen bereits bestehenden Eintrag nicht mehr zu finden">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
...und zwar je nachdem, in welcher Reihenfolge das LocalTag und die Buffer-Adresse gegeben waren: war das LocalTag zuerst da, dann w&#252;rde das bereits Teil des Hash; wenn dann sp&#228;ter jemand mit der gleichen Buffer-Adresse ankommt, aber ohne das LocalTag, dann wird der bestehende (schlimmstenfalls bereits gelockte) Eintrag nicht gefunden &#10233; es wird ein neuer Eintrag erzeugt und somit <b>zweimal gelockt.</b>
</p>
</body>
</html>
</richcontent>
<icon BUILTIN="messagebox_warning"/>
<icon BUILTIN="broken-line"/>
</node>
</node>
</node>
<node COLOR="#338800" CREATED="1722006993331" ID="ID_1387727951" MODIFIED="1722091917790" TEXT="mu&#xdf; mehrfach-Spezialisierung unterbinden">