From ec9b73d4181b7ca0748c1e54578ad1e6c5dd8eb3 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Mon, 23 Mar 2026 23:19:09 +0100 Subject: [PATCH] OutputSlot: skeleton for a lightweight new tracking implementation - can now throw away the old convoluted `TrackingInMemoryBlockSequence` - instead use a simplistic implementation of the Connection interface - do not perform any kind of validation, allocate new buffer for each frame - use the `NaiveBufferSetup` (`BufferProvider`) as implementation backend. --- src/vault/out/diagnostic-output-slot.cpp | 106 +++++-- src/vault/out/diagnostic-output-slot.hpp | 340 +---------------------- wiki/thinkPad.ichthyo.mm | 129 ++++++++- 3 files changed, 215 insertions(+), 360 deletions(-) diff --git a/src/vault/out/diagnostic-output-slot.cpp b/src/vault/out/diagnostic-output-slot.cpp index 9ef766983..15467e009 100644 --- a/src/vault/out/diagnostic-output-slot.cpp +++ b/src/vault/out/diagnostic-output-slot.cpp @@ -18,45 +18,110 @@ */ -#include "lib/error.hpp" +#include "lib/integral.hpp" #include "lib/nocopy.hpp" #include "vault/out/diagnostic-output-slot.hpp" //#include "vault/out/output-slot-connection.hpp" +#include "vault/mem/buffhandle.hpp" +#include "vault/mem/naive-buffer-setup.hpp" +#include "vault/real-clock.hpp" +#include "lib/util.hpp" //#include #include +#include +#include +#include +using util::contains; +// using std::vector; +// using Config = DiagnosticOutputSlot::Config; +using std::byte; +using std::move; +using std::make_unique; +using std::make_shared; +using std::function; + +using vault::mem::NaiveBufferSetup; +using vault::mem::BuffHandle; +using vault::mem::BuffDescr; namespace vault { namespace out { namespace err = lumiera::error; -// using std::vector; -// using Config = DiagnosticOutputSlot::Config; - using std::move; - using std::make_unique; - namespace { // Implementation details of tracking - + inline void + zeroFill (void* buf, size_t siz) + { + auto begin = static_cast (buf); + std::fill (begin, begin+siz, byte(0)); + } }//(End)Impl details class DiagnosticOutputSlot::OutputTracker : public Config , util::NonCopyable { + std::vector feed_; + NaiveBufferSetup buffProvider_; + BuffDescr bufferType_; + + public: OutputTracker (Config&& config) : Config{move (config)} + , feed_{config.numDataFeeds} + , buffProvider_{} + , bufferType_{buffProvider_.getDescriptorFor (bufferSize + ,mem::TypeHandler{[siz=bufferSize](void* buff){ zeroFill (buff, siz);} + ,[](void*){ /* do nothing on release */ } + })} { } + + /** configurable functor: what is used as _current time_ + * @remark allows the test framework to mark "now" as some + * specific fixed time; default is to return system time + */ + function currentTime{[]{ return RealClock::now(); }}; + + + BuffHandle + getNewBuffer() + { + return bufferType_.lockBuffer(); + } + + diagn::FeedLog const& + getFeed (uint feedNr) + { + REQUIRE (feedNr < feed_.size()); + return feed_[feedNr]; + } }; + /** + * Front-end for access by test code. + * @note tolerates access to arbitrary feeds + */ + diagn::FeedLog const& + OutputDiagnostic::feed (uint feedNr) + { + if (feedNr < dos_.tracker_->numDataFeeds) + return dos_.tracker_->getFeed (feedNr); + else + return lib::NullValue::get(); + } + + class DiagnosticOutputSlot::DummyConnection : public OutputSlot::Connection - , util::NonCopyable { OutputTracker& tracker_; + std::map buffIdx_; + /* === Connection API === */ @@ -69,19 +134,31 @@ namespace out { Buff* claimBufferFor(FrameID frame) override { - UNIMPLEMENTED ("lock new buffer"); + BuffHandle handle = tracker_.getNewBuffer(); + REQUIRE (handle.isValid()); + Buff* buff = handle.rawStorage(); + ENSURE (not contains (buffIdx_, buff)); + buffIdx_.insert ({buff, handle}); + UNIMPLEMENTED ("track new buffer"); + return buff; } void publish (Buff* buff) override { - UNIMPLEMENTED ("publish buffer"); + REQUIRE (contains (buffIdx_,buff)); + auto handle = buffIdx_.find(buff)->second; + handle.emit(); + UNIMPLEMENTED ("track publish buffer"); } void release (Buff* buff) override { - UNIMPLEMENTED ("release buffer"); + REQUIRE (contains (buffIdx_,buff)); + auto handle = buffIdx_.find(buff)->second; + handle.release(); + UNIMPLEMENTED ("track release buffer"); } void @@ -130,7 +207,7 @@ namespace out { shared_ptr DiagnosticOutputSlot::setupOutputTracker (Config&& config) { - + return make_shared (move (config)); } unique_ptr @@ -143,11 +220,6 @@ namespace out { ,[&](ConStorage& storage){ storage.create (outputTracker); } ); } - - - - /** */ - diff --git a/src/vault/out/diagnostic-output-slot.hpp b/src/vault/out/diagnostic-output-slot.hpp index 06e4666cf..cd58389fb 100644 --- a/src/vault/out/diagnostic-output-slot.hpp +++ b/src/vault/out/diagnostic-output-slot.hpp @@ -70,188 +70,8 @@ namespace out { namespace { // diagnostics & internals.... const uint DEFAULT_DATAFEEDS = 5; - - inline PGrid - getTestTimeGrid() - { -#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1410 : disabled code to disentangle BufferProvider implementation - Symbol gridID("DiagnosticOutputSlot-buffer-grid"); - vessel::advice::Request query4grid(gridID) ; - PGrid testGrid25 = query4grid.getAdvice(); - - if (!testGrid25) - testGrid25 = TimeGrid::build (gridID, FrameRate::PAL); - - ENSURE (testGrid25); -#endif /////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1410 : (end) disabled code - PGrid testGrid; ////////OOO Kaboooom! - return testGrid; - } } - - /** - * Diagnostic output connection for a single channel, - * allowing to track generated frames and verify - * the processing protocol for output buffers. - */ - class TrackingInMemoryBlockSequence - : public OutputSlot::Connection - , util::NonCopyable - { - - typedef std::unordered_set FrameTrackingInfo; - - - NaiveBufferSetup buffProvider_; - BuffDescr bufferType_; - - FrameTrackingInfo frameTrackingIndex_; - PGrid frameGrid_; - - bool closed_; - - - BuffHandle - trackFrame (FrameID frameNr, BuffHandle const& newBuffer) - { - TRACE (test, "Con=%p : track buffer %zu for frame-#%lu" - , this, HashVal(newBuffer), frameNr); - REQUIRE (!contains (frameTrackingIndex_,frameNr), - "attempt to lock already used frame %lu", frameNr); - - frameTrackingIndex_.insert (frameNr); - return newBuffer; - } - - TimeValue - deadlineFor (FrameID frameNr) - { - // a real world implementation - // would offset by a latency here - return frameGrid_->timeOf (frameNr); - } - - - - - /* === Connection API === */ - - size_t - getBufferSize() const override - { - UNIMPLEMENTED ("wtf buff?"); - } - - Buff* - claimBufferFor (FrameID frameNr) override - { -#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1410 : disabled code due to OutputSlot refactoring - TRACE (test, "Con=%p : lock buffer for frame-#%lu", this, frameNr); - REQUIRE (!closed_); - - return trackFrame (frameNr, - buffProvider_.lockBuffer (bufferType_)); -#endif /////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1410 : (end) disabled code - } - - void - publish (Buff* filledBuffer) override - { -#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1410 : disabled code due to OutputSlot refactoring - TRACE (test, "Con=%p : transfer buffer %zu" - , this, HashVal(filledBuffer)); - REQUIRE (!closed_); - - pushout (filledBuffer); -#endif /////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1410 : (end) disabled code - } - - void - release (Buff* data4output) override - { -#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1410 : disabled code due to OutputSlot refactoring - REQUIRE (!closed_); - buffProvider_.emitBuffer (data4output); - buffProvider_.releaseBuffer(data4output); -#endif /////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1410 : (end) disabled code - } - - void - shutDown() override - { - closed_ = true; - } - - public: - TrackingInMemoryBlockSequence() - : buffProvider_() - , bufferType_(buffProvider_.getDescriptor()) - , frameTrackingIndex_() - , frameGrid_(getTestTimeGrid()) /////////////TODO should rather pass that in as part of a "timings" definition - , closed_(false) - { - INFO (engine_dbg, "building in-memory diagnostic output sequence (at %p)", this); - } - - virtual - ~TrackingInMemoryBlockSequence() - { - INFO (engine_dbg, "releasing diagnostic output sequence (at %p)", this); - } - - - /* === Diagnostic API === */ - - TestFrame const * - accessEmittedFrame (uint frameNr) const - { - UNIMPLEMENTED ("suitable diagnostic API"); -// if (frameNr < buffProvider_.emittedCnt()) ///////////////////////////////OOO provide suitable diagnostic API! -// return & accessFrame(frameNr); -// else -// return 0; ////////////////////////////////TICKET #856 - } - -#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1410 : disabled code to disentangle BufferProvider implementation - diagn::Block const * - accessEmittedBuffer (uint bufferNr) const - { - UNIMPLEMENTED ("suitable diagnostic API"); -// if (bufferNr < buffProvider_.emittedCnt()) ///////////////////////////////OOO provide suitable diagnostic API! -// return & accessBlock(bufferNr); -// else -// return 0; - } -#endif /////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1410 : (end) disabled code - - bool - wasAllocated (uint frameNr) const - { - TRACE (test, "query wasAllocated. Con=%p", this); - - return contains (frameTrackingIndex_, frameNr); - } - - private: - TestFrame const& - accessFrame (uint frameNr) const - { - UNIMPLEMENTED ("suitable diagnostic API"); -// return unConst(this)->buffProvider_.accessAs (frameNr); ///////////////////////////////OOO provide suitable diagnostic API! - } - -#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1410 : disabled code to disentangle BufferProvider implementation - diagn::Block const& - accessBlock (uint bufferNr) const - { - UNIMPLEMENTED ("suitable diagnostic API"); -// return unConst(this)->buffProvider_.access_emitted (bufferNr); ///////////////////////////////OOO provide suitable diagnostic API! - } -#endif /////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1410 : (end) disabled code - }; - - /////////////////////////////////////////////////////////////////////// /// /////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1395 : draft compatible Tracking-API @@ -338,67 +158,6 @@ namespace out { class DiagnosticOutputSlot : public OutputSlot { - - static const uint MAX_CHANNELS = 5; ///////////////////////////////OOO Build heap-based implementation with arbitrary number of feeds!! - - /** @note a real OutputSlot implementation - * would rely on some kind of embedded - * configuration here */ - uint - getOutputChannelCount() - { - return MAX_CHANNELS; /////////////OOO No! - } - - - /** - * Special diagnostic connection state implementation, - * establishing diagnostic output connections for each channel, - * thus allowing to verify the handling of individual buffers - */ - class SimulatedOutputSequences - : public AllocState - { - using _Base = AllocState; - - public: - SimulatedOutputSequences (uint numChannels) - : _Base{ numChannels - ,[](ConnectionStorage& storage) - { - UNIMPLEMENTED ("new Tracking implementation for DiagnosticOutputSlot"); -#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1410 : disabled code to disentangle BufferProvider implementation - storage.create(); -#endif /////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1410 : (end) disabled code - }} - { } - }; - - - - /** hook into the OutputSlot frontend */ - unique_ptr - buildState() - { - return make_unique ( - getOutputChannelCount()); - } - - - /** @internal access the implementation object - * representing a single stream connection - */ - TrackingInMemoryBlockSequence const& - accessSequence (uint channel) - { -#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1410 : disabled code to disentangle BufferProvider implementation - REQUIRE (!isFree(), "diagnostic OutputSlot not (yet) connected"); - REQUIRE (channel <= getOutputChannelCount()); -// return static_cast (state_->access (channel)); -#endif /////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1410 : (end) disabled code - UNIMPLEMENTED ("the old tracking API is abandoned, the new one not yet implemented"); - } - class OutputTracker; shared_ptr tracker_; @@ -446,95 +205,6 @@ namespace out { static shared_ptr setupOutputTracker(Config&&); static unique_ptr setupTrackingConnections(OutputTracker&); - - /* === diagnostics API === */ - - /** - * diagnostic facility to verify test data frames - * written to this Test/Dummy "output". It exposes - * the emitted Data as a sequence of TestFrame objects. - */ - class OutputFramesLog - : public lib::IterSource - , util::NonCopyable - { - TrackingInMemoryBlockSequence const& outSeq_; - uint currentFrame_; - - - virtual Pos //////////////////////////////////////////////TICKET #1125 : this API should use three control functions, similar to IterStateWrapper - firstResult () override - { - REQUIRE (0 == currentFrame_); - return outSeq_.accessEmittedFrame (currentFrame_); - } - - virtual void - nextResult (Pos& pos) override - { - ++currentFrame_; - pos = outSeq_.accessEmittedFrame(currentFrame_); - } - - public: - OutputFramesLog (TrackingInMemoryBlockSequence const& bs) - : outSeq_(bs) - , currentFrame_(0) - { } - }; - - typedef OutputFramesLog::iterator OutFrames; - - - OutFrames - getChannel (uint channel) - { -#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1410 : disabled code to disentangle BufferProvider implementation - REQUIRE (channel < MAX_CHANNELS); - return OutputFramesLog::build( - new OutputFramesLog ( - accessSequence(channel))); -#endif /////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1410 : (end) disabled code - } - - - bool - frame_was_allocated (uint channel, FrameID nominalFrame) - { -#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1410 : disabled code to disentangle BufferProvider implementation - return accessSequence(channel) - .wasAllocated(nominalFrame); -#endif /////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1410 : (end) disabled code - } - - - bool - output_was_emitted (uint channel, FrameID outputFrame) - { -#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1410 : disabled code to disentangle BufferProvider implementation - diagn::Block const *block = accessSequence(channel) - .accessEmittedBuffer(outputFrame); - return block - and block->was_used(); -#endif /////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1410 : (end) disabled code - } - - - bool - output_was_closed (uint channel, FrameID outputFrame) - { -#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1410 : disabled code to disentangle BufferProvider implementation - diagn::Block const *block = accessSequence(channel) - .accessEmittedBuffer(outputFrame); - return block - and block->was_closed(); -#endif /////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1410 : (end) disabled code - } - - ///////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1395 : draft compatible Tracking-API - - std::vector feed_; - private: /// „backdoor“ to watch instrumentation from tests friend class OutputDiagnostic; @@ -556,14 +226,8 @@ namespace out { uint cntEmitted() { return 0; } uint cntReleased() { return 0; } - auto const& - feed (uint feedNr) - { - if (feedNr < dos_.feed_.size()) - return dos_.feed_[feedNr]; - else - return lib::NullValue::get(); - } + diagn::FeedLog const& + feed (uint feedNr); auto getFeed (uint feedNr) diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 4832fd21e..d6d9b1b23 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -138012,7 +138012,9 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + + + @@ -138023,9 +138025,11 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + + - + + @@ -138034,8 +138038,22 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)

+ + + + + + + +

+ Diese Zeit ist dann fest ⟹ heißt, wir brauchen einen Funktor, der entweder die Systemzeit holt (≙default) oder eben eine feste Zeit liefert. »Zeit« ≡ Lumiera Time +

+ +
+
+
@@ -139349,16 +139367,117 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - +

- dieser wird transient als Konstruktor-Argument gebaut + dieser wird transient als Konstruktor-Argument gebaut

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

+ Beschluß: zunächst Basis-Funktionalität ohne jedwede Konsistenzchecks +

+ +
+ + + +

+ Das war vermutlich die Stelle, an der ich damals falsch abgebogen bin:  Ich wollte, test-getrieben, das ganze Thema der »Konsistenz-Checks und Timings« ausloten. Dazu habe ich dann fantasiert, was denn »Konsistenz« meinen könnte. +

+

+ +

+

+ Dem entsprechend werde ich dieses mal versuchen, die dämlichst-mögliche Implementierung zu bauen: wer einen Buffer will, bekommt ihn. Wir zeichnen lediglich diesen Umstand auf +

+ +
+ +
+ + + + +

+ Konsequenz: sogar über das interne Tracking-API schicken wir nur Buff* +

+ +
+ + + + + +

+ Kein Zugriff auf irgend einen Service hier. Das ist Konsequenz daraus, daß wir diese Komponente in die Vault verlegt haben +

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