diff --git a/src/steam/engine/buffhandle.hpp b/src/steam/engine/buffhandle.hpp index 0a6d18269..6dc6477ac 100644 --- a/src/steam/engine/buffhandle.hpp +++ b/src/steam/engine/buffhandle.hpp @@ -151,6 +151,8 @@ namespace engine { return *pBuffer_; } + operator HashVal() const { return descriptor_; } + bool isValid() const { diff --git a/src/steam/engine/diagnostic-buffer-provider.cpp b/src/steam/engine/diagnostic-buffer-provider.cpp index e46ad4086..d9d7ecf7c 100644 --- a/src/steam/engine/diagnostic-buffer-provider.cpp +++ b/src/steam/engine/diagnostic-buffer-provider.cpp @@ -26,18 +26,78 @@ #include "steam/engine/diagnostic-buffer-provider.hpp" #include "steam/engine/heap-mem-buffer-store.hpp" +#include "lib/format-string.hpp" +#include "lib/util.hpp" + +#include namespace steam { namespace engine { + using util::_Fmt; + using util::unConst; + using diagn::Block; + using diagn::StateReg; + using std::ranges::find_if; + + /** * Implementation of tracking and instrumentation */ - class DiagnosticBufferProvider::BlockTracker + struct DiagnosticBufferProvider::BlockTracker + : util::NonCopyable { - + StateReg created; + StateReg emitted; + StateReg released; }; + + Block::Block (BuffHandle const& handle) + : handle{handle} + { } + + Block::Block (BuffDescr const& descr) + : handle{descr} + { } + + + size_t + StateReg::cnt() const + { + return reg_.size(); + } + + StateReg::Result + StateReg::operator[] (size_t seqNr) const + { + if (seqNr < cnt()) + return * reg_[seqNr]; + else + return error::Invalid(_Fmt{"no Buffer with seq-nr %d (%d known entries)"} + % seqNr % cnt() + , LERR_(BOTTOM_VALUE)); + } + + StateReg::Result + StateReg::byHandle (HashVal handle) const + { + if (auto pos = find_if (reg_, [&](auto& entry){ return handle == HashVal(*entry); }) + ;pos != reg_.end() + ) + return **pos; + else + return error::Invalid("requested Buffer never encountered" + , LERR_(BOTTOM_VALUE)); + } + + + /* ====== Accounting API ====== */ + void + StateReg::record (BuffHandle const& handle) + { + + } DiagnosticBufferProvider::DiagnosticBufferProvider() @@ -51,7 +111,13 @@ namespace engine { // INFO (proc_mem, "discarding %zu diagnostic buffer entries", outSeq_.size()); ////////////OOO implement based on dedicated tracking information in-object } - + BufferDiagnostic::BufferDiagnostic (DiagnosticBufferProvider& thePro) + : dbp_{thePro} + , created{dbp_.tracker_->created} + , emitted{dbp_.tracker_->emitted} + , released{dbp_.tracker_->released} + { } + /* === diagnostic API === */ @@ -79,24 +145,6 @@ namespace engine { // return dbp_.heapStore_.access_emitted(bufferID).accessMemory(); ///////////////////////////////////////TICKET 1410 : switch to newly defined tracking-API } - diagn::StateReg& - BufferDiagnostic::created () - { - UNIMPLEMENTED ("track all created buffer blocks"); - } - - diagn::StateReg& - BufferDiagnostic::emitted () - { - UNIMPLEMENTED ("track all emitted buffer blocks"); - } - - diagn::StateReg& - BufferDiagnostic::released() - { - UNIMPLEMENTED ("track all released buffer blocks"); - } - diff --git a/src/steam/engine/diagnostic-buffer-provider.hpp b/src/steam/engine/diagnostic-buffer-provider.hpp index 6673af5b0..584beb4dc 100644 --- a/src/steam/engine/diagnostic-buffer-provider.hpp +++ b/src/steam/engine/diagnostic-buffer-provider.hpp @@ -25,9 +25,11 @@ #include "lib/util.hpp" #include "steam/engine/type-handler.hpp" ///////////////OOO warum? #include "steam/engine/naive-buffer-setup.hpp" +#include "lib/result.hpp" #include "lib/nocopy.hpp" #include +#include namespace steam { @@ -40,22 +42,34 @@ namespace engine { namespace diagn {// state descriptors for diagnostics.... + /** represent the status of one allocation */ struct Block - : BuffHandle - , util::NonCopyable { + BuffHandle handle; + void* storage{nullptr}; + void* accessMemory() const { return storage; } - Block(BuffHandle const& handle) : BuffHandle{handle} { } - Block(BuffDescr const& descr) : BuffHandle{descr} { } + Block (BuffHandle const&); + Block (BuffDescr const&); + operator HashVal() const { return handle; } }; + class StateReg : util::NonCopyable { + using Registry = std::vector>; + Registry reg_; + public: + /* ========= Information API ========= */ + using Result = lib::Result; + Result operator[] (size_t seqNr) const; + Result byHandle (HashVal handle) const; size_t cnt() const; - Block const& operator[] (size_t seqNr) const; - Block const& byHandle (HashVal handle) const; + + /* ========= Accounting API ========= */ + void record (BuffHandle const&); }; }//(End)diagnostic descriptors. @@ -71,7 +85,7 @@ namespace engine { : public NaiveBufferSetup { HeapMemProvider& heapStore_; //////////////////////////////OOO fällt dann weg nach dem Umbau - class BlockTracker; + struct BlockTracker; std::unique_ptr tracker_; public: @@ -83,23 +97,22 @@ namespace engine { friend class BufferDiagnostic; }; + + /** Accessor-proxy to investigate transactions */ class BufferDiagnostic : util::MoveOnly { DiagnosticBufferProvider& dbp_; public: - BufferDiagnostic (DiagnosticBufferProvider& thePro) - : dbp_{thePro} - { } - + BufferDiagnostic (DiagnosticBufferProvider&); 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 all_buffers_released(); - diagn::StateReg& created (); - diagn::StateReg& emitted (); - diagn::StateReg& released(); + diagn::StateReg const& created; + diagn::StateReg const& emitted; + diagn::StateReg const& released; }; inline BufferDiagnostic diff --git a/tests/core/steam/engine/diagnostic-buffer-provider-test.cpp b/tests/core/steam/engine/diagnostic-buffer-provider-test.cpp index b2b5d8fc7..059410006 100644 --- a/tests/core/steam/engine/diagnostic-buffer-provider-test.cpp +++ b/tests/core/steam/engine/diagnostic-buffer-provider-test.cpp @@ -21,6 +21,7 @@ #include "steam/engine/diagnostic-buffer-provider.hpp" #include "steam/engine/buffhandle-attach.hpp" ///////////////////////////////////////////////////////////TICKET 1410 : remove unnecessary API #include "steam/engine/testframe.hpp" +#include "lib/test/diagnostic-output.hpp"//////////////////TODO #include @@ -97,8 +98,14 @@ namespace test { provider.emitBuffer (testBuff); provider.releaseBuffer(testBuff); -// diagn::Block& block0 = provider.access_emitted(0); ///////////////////////////////OOO provide suitable diagnostic API! -// CHECK (testData(dataID) == block0.accessMemory()); +SHOW_EXPR(watch(provider).created.cnt()) +SHOW_EXPR(watch(provider).emitted.cnt()) +SHOW_EXPR(watch(provider).released.cnt()) + CHECK (1 == watch(provider).created.cnt()); + CHECK (1 == watch(provider).emitted.cnt()); + CHECK (1 == watch(provider).released.cnt()); + diagn::Block block0 = watch(provider).emitted[0]; + CHECK (testData(dataID) == block0.accessMemory()); } diff --git a/tests/core/steam/engine/testframe.cpp b/tests/core/steam/engine/testframe.cpp index f0c7d550e..31e618c24 100644 --- a/tests/core/steam/engine/testframe.cpp +++ b/tests/core/steam/engine/testframe.cpp @@ -133,11 +133,11 @@ namespace test { } - TestFrame& - accessAsTestFrame (void* memoryLocation) + TestFrame const& + accessAsTestFrame (void const* memoryLocation) { REQUIRE (memoryLocation); - return *reinterpret_cast (memoryLocation); + return *reinterpret_cast (memoryLocation); } @@ -304,9 +304,9 @@ namespace test { } bool - TestFrame::operator== (void* memLocation) const + TestFrame::operator== (void const* memLocation) const { - TestFrame& candidate (accessAsTestFrame (memLocation)); + TestFrame const& candidate (accessAsTestFrame (memLocation)); return candidate.isSane() and candidate == *this; } @@ -420,14 +420,14 @@ namespace test { bool TestFrame::isAlive (void* memLocation) { - TestFrame& candidate (accessAsTestFrame (memLocation)); + TestFrame const& candidate (accessAsTestFrame (memLocation)); return candidate.isAlive(); } bool TestFrame::isDead (void* memLocation) { - TestFrame& candidate (accessAsTestFrame (memLocation)); + TestFrame const& candidate (accessAsTestFrame (memLocation)); return candidate.isDead(); } diff --git a/tests/core/steam/engine/testframe.hpp b/tests/core/steam/engine/testframe.hpp index 8a7aba91f..86a510242 100644 --- a/tests/core/steam/engine/testframe.hpp +++ b/tests/core/steam/engine/testframe.hpp @@ -126,7 +126,7 @@ namespace test { bool isValid() const; bool isPristine() const; - bool operator== (void* memLocation) const; + bool operator== (void const* memLocation) const; friend bool operator== (TestFrame const& f1, TestFrame const& f2) { return f1.contentEquals(f2); } friend bool operator!= (TestFrame const& f1, TestFrame const& f2) { return !f1.contentEquals(f2); } diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 25cd4c1f7..302ebf1e4 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -111992,8 +111992,9 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + + @@ -112008,8 +112009,39 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + + + + + + +

+ technisch wird das realisiert, indem wir den Block nur einmal erzeugen und dann in verschiedene Registries eintragen und aktualisieren; eingetragen wird er als shared-ptr, aber das API verbirgt das +

+ +
+
+ + + + +

+ Im Block(descriptor) selber stehen nur Protokoll-Werte, wie z.B. ein Status-ENUM; das ist alles potentiell fehleranfällig, denn naheliegenderweise zieht sich der user davon eine Kopie; eine solche Kopie bekommt aber keine Updates mehr mit +

+ +
+
+ + + + +

+ ...und hier wird die Sache noch verwirrender: das Buff-Handle selber ist zwar ein Value-Objekt, repräsentiert aber eine Referenz-Semantik. Das bedeutet, die Informations-Funktionen könnten einen aktualisierten Status-Wert sehen, der den materialisierten Feldern im Block(descriptor) wirderspricht +

+ +
+
@@ -112046,12 +112078,36 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) + + + + +
+ + + + + + +

+ ...deshalb muß man nämlich häufig in eine explizit getypte lokale Kopie materialisieren, da ich lib::Result mit einem Target-Typ-Operator ausgestattet habe — und nicht mit operator*(). Hier greifen also die Regeln für implizite Konversionen in C++, und diese sind inzwischen (C++17) deutlich restriktiver geworden; sie werden nur noch in einem getypten Zielkontext wirksam, also wenn sich aus dem Empfänger des Wertes der erwartete Typ ergibt; der Aufruf einer Funktion gehört da wohl nicht dazu. +

+ +
+ +
+
+ +
- - + + + + + @@ -112310,7 +112366,9 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + + + @@ -112326,6 +112384,116 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) + + + + + + + + + + + + + + +

+ möchte ich bieten weil man's machen kann +

+ +
+
+ + + + + +

+ wenn man diese Möglichkeit überhaupt bieten möchte, dann besser als dedizierte Funktion, denn die Status-Abfragen für einen Descriptor sind notwendigerweise nicht kongruent mit denen eines Handles (der Descriptor kann sowohl einen »Typ« repräsentieren, alsauch eine konkrete Allokation)i +

+ +
+
+ + + + + + + + + + + + + +

+ aber damit ist das Feature nur noch halb so nützlich +

+ +
+
+ + + + + + + +

+ ...weil ich mich nun dummerweise darauf festgelegt habe, den Block(descriptor) kongruent zu einem BuffHandle zu machen; das bedetuet, der Descriptor hat eine Back-Referenz auf einen BufferProvider, und verwendet diese auch zur Implementierung von Informationsfunktionen. Oder er könnte es tun (dies ist dann naheliegend ⟹ Wartungsproblem ↯). Da der Null-Value aus den Suchfunktionen der Registry erzeugt wird, brauchen wir einen Backlink auf die zugehörige Instanz des DiagnosticBufferProvider. Jaaa, das ist machbar.... +

+ +
+
+ + + + + + + + + + + + + +
+
+ + + + +

+ std::ranges::find_if mit Zugriffs-λ +

+ +
+ +
+
+
+ + + + + + + + + + + + + + + + + + + @@ -112410,8 +112578,8 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - +