diff --git a/src/steam/engine/diagnostic-buffer-provider.cpp b/src/steam/engine/diagnostic-buffer-provider.cpp index 17f1c48eb..ef3ab2f93 100644 --- a/src/steam/engine/diagnostic-buffer-provider.cpp +++ b/src/steam/engine/diagnostic-buffer-provider.cpp @@ -257,11 +257,10 @@ namespace engine { } - void* - BufferDiagnostic::accessMemory (uint bufferID) - { - NOTREACHED ("shall use new API only"); -// return dbp_.heapStore_.access_emitted(bufferID).accessMemory(); ///////////////////////////////////////TICKET 1410 : switch to newly defined tracking-API + Buff* + BufferDiagnostic::accessMemory (HashVal id) + { // may throw when found + return created.byHandle(id).get().accessMemory(); } bool diff --git a/src/steam/engine/diagnostic-buffer-provider.hpp b/src/steam/engine/diagnostic-buffer-provider.hpp index fe1d02988..11ef0bea2 100644 --- a/src/steam/engine/diagnostic-buffer-provider.hpp +++ b/src/steam/engine/diagnostic-buffer-provider.hpp @@ -143,12 +143,12 @@ namespace engine { bool buffer_was_used (uint bufferID); ///< @deprecated ////////////////////////////////////////TICKET 1410 bool buffer_was_closed (uint bufferID); ///< @deprecated ////////////////////////////////////////TICKET 1410 - void* accessMemory (uint bufferID); ///< @deprecated ////////////////////////////////////////TICKET 1410 bool was_created (HashVal); bool was_emitted (HashVal); bool was_released (HashVal); bool is_in_use (HashVal); bool was_used (HashVal); + Buff* accessMemory(HashVal); bool all_buffers_released(); diagn::StateReg const& created; diagn::StateReg const& emitted; diff --git a/tests/core/steam/engine/buffer-provider-protocol-test.cpp b/tests/core/steam/engine/buffer-provider-protocol-test.cpp index a551d5481..e14eb5646 100644 --- a/tests/core/steam/engine/buffer-provider-protocol-test.cpp +++ b/tests/core/steam/engine/buffer-provider-protocol-test.cpp @@ -21,12 +21,16 @@ #include "lib/test/test-helper.hpp" #include "lib/test/tracking-dummy.hpp" #include "lib/util-foreach.hpp" +#include "lib/iter-zip.hpp" #include "steam/engine/testframe.hpp" #include "steam/engine/test-rand-ontology.hpp" #include "steam/engine/diagnostic-buffer-provider.hpp" +#include "lib/test/diagnostic-output.hpp"////////////////////TODO using util::isSameObject; using util::for_each; +using lib::HashVal; +using lib::zip; namespace steam { @@ -55,10 +59,10 @@ namespace test { *(data+i) = work.data()[i]; return work.getChecksum(); } - } + /**************************************************************************//** * @test document the usage patterns of the »Buffer Provider Protocol« * Notably this protocol is used by the Render Engine during recursive `pull()` @@ -77,7 +81,7 @@ namespace test { run (Arg) { verifySimpleUsage(); - verifyRenderingUsage(); + verifyRenderingUse(); // verifyObjectAttachment(); // verifyObjectAttachmentFailure(); //////////////////////////OOO need a completely new test case to cover behaviour of failed ctor calls } @@ -101,21 +105,21 @@ namespace test { buff.emit(); buff.release(); - CHECK (!buff.isValid()); + CHECK (not buff.isValid()); VERIFY_ERROR (LIFECYCLE, buff.accessAs() ); - auto diagnostic = watch(provider); - CHECK (diagnostic.buffer_was_used (0)); - CHECK (diagnostic.buffer_was_closed (0)); + auto inspect = watch(provider); + CHECK (inspect.was_used (buff)); + CHECK (inspect.was_released(buff)); - CHECK (testData(0) == diagnostic.accessMemory (0)); + CHECK (testData(0) == inspect.accessMemory(buff)); } /** @test demonstrate the full sequence of invocations during rendering */ void - verifyRenderingUsage() + verifyRenderingUse() { // Test fixture: allows to track/verify allocations after the fact DiagnosticBufferProvider provider; @@ -131,8 +135,8 @@ namespace test { CHECK (desc3.isValid()); uint num1 = desc1.announce(TEST_ELMS); - uint num2 = desc1.announce(TEST_ELMS + 1); - uint num3 = desc2.announce(TEST_ELMS * 2); + uint num2 = desc2.announce(TEST_ELMS + 1); + uint num3 = desc3.announce(TEST_ELMS * 2); // announce more than we actually use (which is tolerated) CHECK (num1 == TEST_ELMS); CHECK (num2 == TEST_ELMS + 1); CHECK (num3 == TEST_ELMS * 2); @@ -173,10 +177,49 @@ namespace test { workBuff.release(); // note: not every buffer need be emitted. CHECK (!workBuff); - auto diagnostic = watch(provider); - CHECK (diagnostic.buffer_was_used (0)); - CHECK (diagnostic.buffer_was_closed (0)); -// CHECK (diagnostic.all_buffers_released()); ///////////////OOO do we need this API? + auto inspect = watch(provider); + CHECK (inspect.created.cnt() == 3*TEST_ELMS + 1); + CHECK (inspect.was_used (workBuff)); + CHECK (inspect.was_released (workBuff)); + CHECK (not inspect.was_emitted (workBuff)); + CHECK (inspect.all_buffers_released()); + + // now peek into buffer memory + // to prove that that the complete computation chain + // was in fact performed, and was using the memory as intended + uint last = inspect.released.cnt() - 1; + diagn::Block lastWork = inspect.released[last]; + diagn::Block lastMark = inspect.released[last-1]; + diagn::Block lastData = inspect.released[last-2]; + + // due to the way this chained-hash dummy computation was defined, + // the last data buffer should contain the same random numbers as the last work buffer... + auto& workBuffContent = lastWork.accessAs().data(); + auto& dataBuffContent = lastData.accessAs(); + + for (auto [c,v] : zip(workBuffContent,dataBuffContent)) + CHECK (c == v); + + // furthermore, the last recorded checksum mark + // should match the checksum of the last work buffer, + // because that is where the last computation was carried out. + CHECK (endSum == lastMark.accessAs()); + + // we can also verify that all data in emitted buffers is correct, + // by re-computing the checksum for each step, using data in the buffers + for (uint i=0; i(); // note const -- can not corrupt data in memory + ont::Param param = src.getChecksum(); + TestFrame newWorkBuff; + ont::manipulateFrame (&newWorkBuff, &src, param); + + // the checksum recoded during the test run matches the re-computed sum, + // based on combining data in memory for a second time with the same chained-hash function + CHECK (markBuff.accessAs() == newWorkBuff.getChecksum()); + } } diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 033fe07b5..9b32a18a8 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -110365,7 +110365,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + @@ -110639,8 +110639,8 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - - + + @@ -110722,7 +110722,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + @@ -110731,6 +110731,19 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)

+ +
+ + + + +

+ Man kann damit nämlich zeigen, daß tatsächlich Buffer in der gewünschten Reihenfolge belegt und verwendet werden, indem man anschaut, daß am Ende die Checksumme mit aufgezeichneten Werten übereinstimmt, und in den zugehörigen Dummy-Buffern auch tatsächlich (noch) die Daten der letzten Berechnungsschritte liegen +

+ +
+ +
@@ -110739,11 +110752,16 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - - + + + + + + +
@@ -112164,16 +112182,13 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - - - +

Zufallszahlen in lokal gehaltenem Vektor; müßten dann auch im Speicherblock zu finden sein...

- -
+
@@ -112183,16 +112198,13 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - - - +

das zeigt nämlich gut die Stelle, an der ich in die Falle gefallen bin; stattessen haben wir nun (hoffentlich) deklarative Diagnose-Funktionen

- -
+
@@ -112214,9 +112226,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - - - +

benenne die Variable verbal:  @@ -112225,8 +112235,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) auto inspect = watch(provider);

- -
+
@@ -112234,16 +112243,13 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
- - - +

außerdem: TestFrame kann inzwischen viel mehr ....

- -
+ @@ -112253,6 +112259,41 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) + + + + +

+ vorausgegangen war eine Analyse der Nutzmuster in dem letztes Jahr entwickelten Node-Invocation-Code +

+ +
+
+ + + + +

+ Für diesen Testfall hatte ich bereits in einer einfachen Schleife dieses Nutzungsmuster nachtestellt, und dafür meine neue TestRandOntology verwendet; das heißt, wir rechnen jetzt wirklich einen vollen Bufferhinhalt durch, und jedes einzelne Datenwort ist am Ende verifizierbar, vermöge der verketteten Hash-Berechnung +

+ +
+ +
+ + + + +

+ Da es sich um eine verkettete Hash-Berechnung handelt, müßte man streng genommen die Berechnung nochmal wiederholen, und die festgestellte Prüfsumme vergleichen. Mit dem Argument, daß dieses an anderer Stelle bereits getan wurde (NodeLink_test), kann ich argumentieren, daß es hier nur darauf ankommt, daß die korrekten Daten dort im Speicher liegen, wo man sie aufgrund der Logik auch erwarten würde +

+ +
+
+ + + +
@@ -113083,9 +113124,9 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
- + - + @@ -113114,9 +113155,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - - - +

Seit 2024 bin ich nun mehrfach durch den Kern der Implementierung durchgegangen, und konnte keine offensichtliche Lücke finden (nur ein paar lokale Inkonsistenzen, wie z.B. daß wir uns den aktuellen Buffer-Pointer im Entry speichern, obwohl es genügen würde, ihn nur in den Hash einzurechnen). Auch der Zugangs-Funktionen, BufferMetadata::key(...) sind konsistent und korrekt strukturiert: es gibe eine einzige Funktion, mit der man »aus dem Nichts« einsteigen kann (und in dieser Funktion hatte ich 2024 die Reihenfolge der Qualifizierungen in ein verbindliches Schema geordnet). Außerdem gibt es ein paar weitere Funktionen, mit denen man einen bereits bestehenden Key verfeinern kann, und eine Funktion, die verwendet wird, um daraus einen Entry zu machen. @@ -113314,9 +113353,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - - - +

Inhaltlich ist sie redundant, denn Zustandsübergänge werden auch in den Metadaten geprüft. Jedoch ist die ganze Struktur relativ offen, und es gibt sogar die »Unschärfe«, daß u.U der Pointer im Handle nicht auf NULL gesetzt wird (hab das gestern durchdacht und bin zu dem Schluß gekommen, daß sich das nur um den Preis eines kompletten Umbaues beheben ließe, wozu ich keinen Anlaß sehe) @@ -113328,9 +113365,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - - - +

ich halte dieses Prädikat für sinnvoller, als ein isEmitted(); es bedeutet, daß noch eine Allokation »dran hängt« @@ -113861,9 +113896,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - - - +

derzeit kann ich gar nix mehr ändern