diff --git a/src/steam/engine/buffer-provider-setup.hpp b/src/steam/engine/buffer-provider-setup.hpp index bef065774..55cc8e581 100644 --- a/src/steam/engine/buffer-provider-setup.hpp +++ b/src/steam/engine/buffer-provider-setup.hpp @@ -25,10 +25,8 @@ #include "lib/error.hpp" #include "lib/symbol.hpp" #include "lib/hash-value.h" -#include "steam/engine/buffhandle.hpp" +#include "steam/engine/buffer-provider.hpp" //#include "steam/engine/engine-ctx.hpp" -#include "steam/engine/type-handler.hpp" -#include "steam/engine/buffer-local-tag.hpp" #include "lib/nocopy.hpp" #include @@ -40,14 +38,12 @@ namespace engine { using lib::Literal; using std::unique_ptr; - using std::forward; +// using std::forward; + using std::move; - class BufferMetadata; - LUMIERA_ERROR_DECLARE (BUFFER_MANAGEMENT); ///< Problem providing working buffers - /** * Framework for configuring the actual BufferPovider backend implementation. @@ -58,18 +54,34 @@ namespace engine { : public BufferProvider { public: - BufferProviderSetup (Literal implementationID); + /** + * Build a new BufferProvider setup to manage a number of buffers. + * The metadata of these buffers is organised hierarchically based on + * chained hash values, using an `implementationID` as a seed. + * The \a CONF configuration record controls the actual implementation + * of lifecycle transitions and storage management. + */ + template + BufferProviderSetup (CONF&& confRec) + : BufferProvider{} + { + bufferStage_ = move (confRec.buildStage()); + bufferStore_ = move (confRec.buildStore()); + } class Stage - : protected BufferStage + : public BufferStage { + public: + using BufferStage::BufferStage; ///////////////////////////////////////////////////////////TICKET #1410 : actual implementation structures should move down into this classes implementation }; class Store - : protected BufferStore + : public BufferStore { - + protected: + using Buff = BufferProvider::Buff; }; diff --git a/src/steam/engine/buffer-provider.cpp b/src/steam/engine/buffer-provider.cpp index c20d2d9ab..61572249c 100644 --- a/src/steam/engine/buffer-provider.cpp +++ b/src/steam/engine/buffer-provider.cpp @@ -41,14 +41,6 @@ namespace engine { LUMIERA_ERROR_DEFINE (BUFFER_MANAGEMENT, "Problem providing working buffers"); - /** build a new provider instance, managing a family of buffers. - * The metadata of these buffers is organised hierarchically based on - * chained hash values, using the #implementationID as a seed. - * @param implementationID symbolic ID setting these family of buffers apart. - */ - BufferProvider::BufferProvider (Literal implementationID) - : bufferStage_(new BufferStage{implementationID}) - { } BufferProvider::~BufferProvider() { } @@ -117,7 +109,7 @@ namespace engine { uint BufferProvider::announce (uint count, BuffDescr const& type) { - uint actually_possible = prepareBuffers (count, type); + uint actually_possible = bufferStore_->prepareBuffers (count, type); if (!actually_possible) throw error::State ("unable to fulfil request for buffers" ,LUMIERA_ERROR_BUFFER_MANAGEMENT); @@ -143,7 +135,7 @@ namespace engine { { REQUIRE (was_created_by_this_provider (type)); - return provideLockedBuffer (type); + return bufferStore_->provideLockedBuffer (type); } // is expected to call buildHandle() --> state transition @@ -163,7 +155,7 @@ namespace engine { BufferProvider::emitBuffer (BuffHandle const& handle) { metadata::Entry& metaEntry = bufferStage_->get (handle.entryID()); - mark_emitted (metaEntry.parentKey(), metaEntry.localTag()); + bufferStore_->mark_emitted (metaEntry.parentKey(), metaEntry.localTag()); metaEntry.mark(EMITTED); } @@ -181,7 +173,7 @@ namespace engine { try { metadata::Entry& metaEntry = bufferStage_->get (handle.entryID()); metaEntry.mark(FREE); // might invoke embedded dtor function - detachBuffer (metaEntry.parentKey(), metaEntry.localTag(), *handle); + bufferStore_->detachBuffer (metaEntry.parentKey(), metaEntry.localTag(), *handle); bufferStage_->release (metaEntry); } ERROR_LOG_AND_IGNORE (engine, "releasing a buffer from BufferProvider") @@ -225,7 +217,7 @@ namespace engine { try { metadata::Entry& metaEntry = bufferStage_->get (target.entryID()); metaEntry.invalidate (invokeDtor); - detachBuffer (metaEntry.parentKey(), metaEntry.localTag(), *target); + bufferStore_->detachBuffer (metaEntry.parentKey(), metaEntry.localTag(), *target); bufferStage_->release (metaEntry); } ERROR_LOG_AND_IGNORE (engine, "cleanup of buffer metadata while handling an error") diff --git a/src/steam/engine/buffer-provider.hpp b/src/steam/engine/buffer-provider.hpp index 25962e37f..58170c6ec 100644 --- a/src/steam/engine/buffer-provider.hpp +++ b/src/steam/engine/buffer-provider.hpp @@ -113,8 +113,6 @@ namespace engine { size_t getBufferSize (HashVal typeID) const; protected: - BufferProvider (Literal implementationID); - /// placeholder marker type for an actual data buffer using Buff = StreamType::ImplFacade::DataBuffer; @@ -122,13 +120,6 @@ namespace engine { bool was_created_by_this_provider (BuffDescr const&) const; -///////////////////////////////////////////////////////////////////////////////OOO - virtual uint prepareBuffers (uint count, HashVal typeID) =0; - - virtual BuffHandle provideLockedBuffer (HashVal typeID) =0; - virtual void mark_emitted (HashVal, LocalTag const&) =0; - virtual void detachBuffer (HashVal, LocalTag const&, Buff&) =0; -///////////////////////////////////////////////////////////////////////////////OOO class BufferStage : public BufferMetadata /////////////////////////////////////////////////////////////////////TICKET #1410 : mix-in exiting old implementation -- for sake of refactoring only! @@ -137,7 +128,6 @@ namespace engine { virtual ~BufferStage() { } ///< this is an interface using BufferMetadata::BufferMetadata; ///////////////////////////////////////////////////////////TICKET #1410 : actual implementation structures should move down into this classes implementation - protected: }; class BufferStore @@ -145,7 +135,7 @@ namespace engine { { public: virtual ~BufferStore() { } ///< this is an interface - protected: + virtual uint prepareBuffers (uint count, HashVal typeID) =0; virtual BuffHandle provideLockedBuffer (HashVal typeID) =0; virtual void mark_emitted (HashVal, LocalTag const&) =0; diff --git a/src/steam/engine/buffer-proxy-provider.hpp b/src/steam/engine/buffer-proxy-provider.hpp index 949c0c060..3852f924b 100644 --- a/src/steam/engine/buffer-proxy-provider.hpp +++ b/src/steam/engine/buffer-proxy-provider.hpp @@ -62,10 +62,11 @@ namespace engine { using Listener = std::function; class ForwardingBufferProvider - : public BufferProvider + : public BufferProvider /////////////////////////////////////////////////////////////TICKET #1410 : its clear now (2/26) that this must be some other base type; maybe we'll offer the ability to decorate, directly through BufferProviderSetup? { Listener listener_; +#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1410 : disabled code to while BufferProvider is being refactored... /* === BufferProvider API === */ uint @@ -93,9 +94,10 @@ namespace engine { { } +#endif /////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1410 : (end) disabled code public: ForwardingBufferProvider (Listener listener) - : BufferProvider{"BufferProxyProvider"} + : BufferProvider{} , listener_{std::move (listener)} { } }; diff --git a/src/steam/engine/diagnostic-buffer-provider.cpp b/src/steam/engine/diagnostic-buffer-provider.cpp index d809bd5b5..2b0bb6aa5 100644 --- a/src/steam/engine/diagnostic-buffer-provider.cpp +++ b/src/steam/engine/diagnostic-buffer-provider.cpp @@ -25,7 +25,7 @@ //#include "lib/meta/function.hpp" #include "steam/engine/diagnostic-buffer-provider.hpp" -#include "steam/engine/heap-mem-provider.hpp" +#include "steam/engine/heap-mem-buffer-store.hpp" namespace steam { @@ -33,7 +33,8 @@ namespace engine { DiagnosticBufferProvider::DiagnosticBufferProvider() - : BufferProvider{"Diagnostic_HeapAllocated"} + : NaiveBufferSetup{} + , heapStore_{dynamic_cast (*bufferStore_)} { } DiagnosticBufferProvider::~DiagnosticBufferProvider() @@ -49,21 +50,21 @@ namespace engine { bool BufferDiagnostic::buffer_was_used (uint bufferID) { - return dbp_.heapMemProvider_.access_emitted(bufferID).was_used(); + return dbp_.heapStore_.access_emitted(bufferID).was_used(); } bool BufferDiagnostic::buffer_was_closed (uint bufferID) { - return dbp_.heapMemProvider_.access_emitted(bufferID).was_closed(); + return dbp_.heapStore_.access_emitted(bufferID).was_closed(); } void* BufferDiagnostic::accessMemory (uint bufferID) { - return dbp_.heapMemProvider_.access_emitted(bufferID).accessMemory(); + return dbp_.heapStore_.access_emitted(bufferID).accessMemory(); } diff --git a/src/steam/engine/diagnostic-buffer-provider.hpp b/src/steam/engine/diagnostic-buffer-provider.hpp index 54d68fec2..237a09ae7 100644 --- a/src/steam/engine/diagnostic-buffer-provider.hpp +++ b/src/steam/engine/diagnostic-buffer-provider.hpp @@ -24,7 +24,7 @@ #include "lib/error.hpp" #include "lib/util.hpp" #include "steam/engine/type-handler.hpp" ///////////////OOO warum? -#include "steam/engine/heap-mem-provider.hpp" +#include "steam/engine/naive-buffer-setup.hpp" #include "lib/nocopy.hpp" #include @@ -35,6 +35,7 @@ namespace engine { namespace error = lumiera::error; + class HeapMemProvider; class BufferDiagnostic; @@ -45,17 +46,9 @@ namespace engine { * @todo write type comment */ class DiagnosticBufferProvider - : public BufferProvider + : public NaiveBufferSetup { - HeapMemProvider heapMemProvider_; - - - /* === delegate BufferProvider API === */ - - uint prepareBuffers (uint count, HashVal typeID) override { return heapMemProvider_.prepareBuffers (count,typeID);} - BuffHandle provideLockedBuffer (HashVal typeID) override { return heapMemProvider_.provideLockedBuffer (typeID); } - void mark_emitted (HashVal h, LocalTag const& t) override { heapMemProvider_.mark_emitted(h,t); } - void detachBuffer (HashVal h, LocalTag const& t, Buff& b) override { heapMemProvider_.detachBuffer(h,t,b); } + HeapMemProvider& heapStore_; public: diff --git a/src/steam/engine/heap-mem-provider.cpp b/src/steam/engine/heap-mem-buffer-store.cpp similarity index 91% rename from src/steam/engine/heap-mem-provider.cpp rename to src/steam/engine/heap-mem-buffer-store.cpp index bede22ebd..d1a32f367 100644 --- a/src/steam/engine/heap-mem-provider.cpp +++ b/src/steam/engine/heap-mem-buffer-store.cpp @@ -1,8 +1,8 @@ /* - HeapMemProvider - plain heap allocating BufferProvider implementation for tests + HeapMemBufferStore - plain heap allocating BufferProvider storage implementation for tests Copyright (C) - 2011, Hermann Vosseler + 2011,2026 Hermann Vosseler   **Lumiera** is free software; you can redistribute it and/or modify it   under the terms of the GNU General Public License as published by the @@ -12,8 +12,8 @@ * *****************************************************************/ -/** @file heap-mem-provider.cpp - ** Implementation details of a mock engine::BufferProvider for unit testing +/** @file heap-mem-buffer-store.cpp + ** Implementation details of simple heap based engine::BufferProvider storage. */ @@ -22,7 +22,7 @@ #include "lib/scoped-ptrvect.hpp" #include "lib/util-foreach.hpp" -#include "steam/engine/heap-mem-provider.hpp" +#include "steam/engine/heap-mem-buffer-store.hpp" #include #include @@ -223,8 +223,7 @@ namespace engine { * @internal create a memory tracking BufferProvider, */ HeapMemProvider::HeapMemProvider() - : BufferProvider ("Naive_HeapAllocated") - , pool_(new diagn::PoolTable) + : pool_(new diagn::PoolTable) , outSeq_() { } @@ -247,7 +246,8 @@ namespace engine { { diagn::BlockPool& blocks = getBlockPoolFor (typeID); diagn::Block& newBlock = blocks.createBlock(); - return buildHandle (typeID, asBuffer(newBlock.accessMemory()), &newBlock); + UNIMPLEMENTED ("Separate tasks into two distinct APIs"); +// return buildHandle (typeID, asBuffer(newBlock.accessMemory()), &newBlock); /////////////////////////////OOO instead return a tuple (buffer, localTag) } @@ -320,8 +320,9 @@ namespace engine { HeapMemProvider::getBlockPoolFor (HashVal typeID) { diagn::BlockPool& pool = (*pool_)[typeID]; - if (!pool) - pool.initialise(getBufferSize(typeID)); + UNIMPLEMENTED ("Separate tasks into two distinct APIs"); +// if (!pool) +// pool.initialise(getBufferSize(typeID)); //////////////////////////OOO getBufferSize is a helper function in the BufferProvider protected API. Need to be "here" return pool; } diff --git a/src/steam/engine/heap-mem-provider.hpp b/src/steam/engine/heap-mem-buffer-store.hpp similarity index 84% rename from src/steam/engine/heap-mem-provider.hpp rename to src/steam/engine/heap-mem-buffer-store.hpp index f5a1011de..f2056675d 100644 --- a/src/steam/engine/heap-mem-provider.hpp +++ b/src/steam/engine/heap-mem-buffer-store.hpp @@ -1,8 +1,8 @@ /* - HEAP-MEM-PROVIDER.hpp - plain heap allocating BufferProvider implementation for tests + HEAP-MEM-BUFFER_STORE.hpp - plain heap allocating BufferProvider implementation for tests Copyright (C) - 2011, Hermann Vosseler + 2011,2026 Hermann Vosseler   **Lumiera** is free software; you can redistribute it and/or modify it   under the terms of the GNU General Public License as published by the @@ -12,10 +12,11 @@ */ /** @file heap-mem-provider.hpp - ** Dummy implementation of the BufferProvider interface to support writing unit tests. - ** This BufferProvider implementation is notably straight forward and silly: it just - ** claims more and more heap blocks and never releases any memory dynamically. This allows - ** to investigate additional tracking status flags for each allocated block after the fact. + ** Dummy implementation engine::BufferProvider storage, for sake of conceptual + ** demonstration and unit testing. This BufferProvider implementation is notably straight forward, + ** if not outright silly: it happily claims more and more heap blocks and never releases any memory + ** dynamically. This both demonstrates the simplest possible implementation of storage handling, and + ** allows to investigate additional tracking status flags for each allocated block after the fact. ** ** @todo 1/2026 for sake of implementation clarity, the following instrumentation functionality ** must be relocated into the DiagnosticOutputProvider: Allocated buffers are numbered @@ -30,13 +31,13 @@ ** @see buffer-provider-protocol-test.cpp */ -#ifndef STEAM_ENGINE_HEAP_MEM_PROVIDER_H -#define STEAM_ENGINE_HEAP_MEM_PROVIDER_H +#ifndef STEAM_ENGINE_HEAP_MEM_BUFFER_STORE_H +#define STEAM_ENGINE_HEAP_MEM_BUFFER_STORE_H #include "lib/error.hpp" #include "lib/hash-value.h" -#include "steam/engine/buffer-provider.hpp" +#include "steam/engine/buffer-provider-setup.hpp" #include "lib/scoped-ptrvect.hpp" #include @@ -117,13 +118,13 @@ namespace engine { * tracked usage information, even when blocks are already marked as "released". */ class HeapMemProvider - : public BufferProvider + : public BufferProviderSetup::Store { unique_ptr pool_; ScopedPtrVect outSeq_; public: - /* === BufferProvider interface === */ + /* === BufferStore interface === */ virtual uint prepareBuffers (uint count, HashVal typeID) override; virtual BuffHandle provideLockedBuffer (HashVal typeID) override; @@ -178,4 +179,4 @@ namespace engine { }} // namespace steam::engine -#endif /*STEAM_ENGINE_HEAP_MEM_PROVIDER_H*/ +#endif /*STEAM_ENGINE_HEAP_MEM_BUFFER_STORE_H*/ diff --git a/src/steam/engine/naive-buffer-setup.hpp b/src/steam/engine/naive-buffer-setup.hpp new file mode 100644 index 000000000..41d1d6b1a --- /dev/null +++ b/src/steam/engine/naive-buffer-setup.hpp @@ -0,0 +1,197 @@ +/* + NAIVE-BUFFER_SETUP.hpp - plain heap allocating BufferProvider implementation for tests + + Copyright (C) + 2026, Hermann Vosseler + +  **Lumiera** is free software; you can redistribute it and/or modify it +  under the terms of the GNU General Public License as published by the +  Free Software Foundation; either version 2 of the License, or (at your +  option) any later version. See the file COPYING for further details. + +*/ + +/** @file naive-buffer-setup.hpp + ** Dummy implementation of the BufferProvider interface to support writing unit tests. + ** This setup for a BufferProvider is notably straight forward and basically allocates + ** a new heap block for any buffer, without deallocating memory ever. This allows to + ** attach additional tracking status flags for each allocated block and validate + ** allocator behaviour after the fact. + ** + ** @todo 1/2026 for sake of implementation clarity, the following instrumentation functionality + ** must be relocated into the DiagnosticOutputProvider: Allocated buffers are numbered + ** with a simple ascending sequence of integers, used as LocalTag (see BufferMetadata). + ** Clients can request a Buffer with the given number, causing that block to be allocated. + ** There is a "backdoor", allowing to access any allocated block, even if it is considered + ** "released" by the terms of the usual lifecycle. Only when the provider object itself + ** gets destroyed, all allocated blocks will be discarded. + ** + ** @see DiagnosticOutputSlot + ** @see DiagnosticBufferProvider + ** @see buffer-provider-protocol-test.cpp + */ + +#ifndef STEAM_ENGINE_NAIVE_BUFFER_STEUP_H +#define STEAM_ENGINE_NAIVE_BUFFER_STEUP_H + + +#include "lib/error.hpp" +#include "lib/hash-value.h" +#include "steam/engine/buffer-provider-setup.hpp" +#include "steam/engine/heap-mem-buffer-store.hpp" +#include "lib/scoped-ptrvect.hpp" + +#include +#include + + +namespace steam { +namespace engine { + + namespace error = lumiera::error; + +// using lib::HashVal; + +#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1410 : disabled code to disentangle BufferProvider implementation + namespace diagn { + + using std::unique_ptr; + + + /** + * Helper for implementing a diagnostic BufferProvider: + * A block of heap allocated storage, with the capability + * to store some additional tracking information. + */ + class Block + : util::NonCopyable + { + unique_ptr storage_; + + bool was_released_; + + public: + explicit + Block(size_t bufferSize) + : storage_(bufferSize? new char[bufferSize] : NULL) + , was_released_(false) + { } + + bool + was_used() const + { + return bool(storage_); + } + + bool + was_closed() const + { + return was_released_; + } + + void* + accessMemory() const + { + REQUIRE (storage_, "Block was never prepared for use"); + return storage_.get(); + } + + void + markReleased() + { + was_released_ = true; + } + }; + + class BlockPool; + + using PoolTable = std::unordered_map; + } +#endif /////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1410 : (end) disabled code + + + /** + * simple BufferProvider implementation with additional allocation tracking. + * @internal used as PImpl by DiagnosticBufferProvider and DiagnosticOutputSlot. + * + * This dummy implementation of the BufferProvider interface uses a linearly growing + * table of heap allocated buffer blocks, which will never be discarded, unless the object + * is discarded as a whole. There is an additional testing/diagnostics API to access the + * tracked usage information, even when blocks are already marked as "released". + */ + class NaiveBufferSetup + : public BufferProviderSetup + { + public: + NaiveBufferSetup() + : BufferProviderSetup{*this} + { } + + auto buildStage() { return std::make_unique ("Naive_HeapAllocated"); } + auto buildStore() { return std::make_unique(); } /////////////////////////////////TICKET #1410 : turn into a subclass of BufferSetup::Store and push down implementation + }; + +#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1410 : disabled code to disentangle BufferProvider implementation + class HeapMemProvider + : public BufferProvider + { + unique_ptr pool_; + ScopedPtrVect outSeq_; + + public: + /* === BufferProvider interface === */ + + virtual uint prepareBuffers (uint count, HashVal typeID) override; + virtual BuffHandle provideLockedBuffer (HashVal typeID) override; + virtual void mark_emitted (HashVal, LocalTag const&) override; + virtual void detachBuffer (HashVal, LocalTag const&, Buff&) override; + + public: + ~HeapMemProvider(); + HeapMemProvider(); + + size_t emittedCnt() const; + + diagn::Block& access_emitted (uint bufferID); + + template + TY& accessAs (uint bufferID); + + void markAllEmitted(); + + private: + bool withinOutputSequence (uint bufferID) const; + diagn::BlockPool& getBlockPoolFor (HashVal typeID); + diagn::Block* locateBlock (HashVal typeID, void*); + diagn::Block* searchInOutSeqeuence (void* storage); + }; + + + + /** convenience shortcut: access the buffer with the given number, + * then try to convert the raw memory to the templated type. + * @throw error::Invalid if the required fame number is beyond + * the number of buffers marked as "emitted" + * @throw error::Fatal if conversion is not possible or the + * conversion path chosen doesn't work (which might + * be due to RTTI indicating an incompatible type). + */ + template + TY& + HeapMemProvider::accessAs (uint bufferID) + { + if (!withinOutputSequence (bufferID)) + throw error::Invalid ("Buffer with the given ID not yet emitted"); + + diagn::Block& memoryBlock = access_emitted (bufferID); + TY* converted = std::launder (reinterpret_cast (memoryBlock.accessMemory())); + + REQUIRE (converted); + return *converted; + } +#endif /////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1410 : (end) disabled code + + + +}} // namespace steam::engine +#endif /*STEAM_ENGINE_NAIVE_BUFFER_STEUP_H*/ diff --git a/src/steam/engine/render-environment.cpp b/src/steam/engine/render-environment.cpp index 062b4486b..ef8b5bef0 100644 --- a/src/steam/engine/render-environment.cpp +++ b/src/steam/engine/render-environment.cpp @@ -24,8 +24,8 @@ #include "steam/engine/render-environment.hpp" #include "steam/engine/engine-facilities.hpp" +#include "steam/engine/naive-buffer-setup.hpp" #include "steam/engine/buffer-provider.hpp" -#include "steam/engine/heap-mem-provider.hpp" namespace steam { @@ -38,7 +38,7 @@ namespace engine{ BufferProvider& getNaiveBufferManager() { - static HeapMemProvider buffProvider; ////////////////////////////////////////////////////TICKET #1367 : only suitable for first prototype; should implement a bare bone memory manager instead + static NaiveBufferSetup buffProvider; ///////////////////////////////////////////////////TICKET #1367 : only suitable for first prototype; should implement a bare bone memory manager instead return buffProvider; } } diff --git a/tests/core/steam/engine/diagnostic-buffer-provider-test.cpp b/tests/core/steam/engine/diagnostic-buffer-provider-test.cpp index 0a67b84fc..b8538b2bc 100644 --- a/tests/core/steam/engine/diagnostic-buffer-provider-test.cpp +++ b/tests/core/steam/engine/diagnostic-buffer-provider-test.cpp @@ -18,7 +18,7 @@ #include "lib/error.hpp" #include "lib/test/run.hpp" -#include "steam/engine/heap-mem-provider.hpp" +#include "steam/engine/diagnostic-buffer-provider.hpp" #include "steam/engine/buffhandle-attach.hpp" #include "steam/engine/testframe.hpp" @@ -60,7 +60,7 @@ namespace test { /******************************************************************//** * @test verify support to write mock components for buffer management. - * - HeapMemProvider is a „braindead“ implementation of the BufferProvider + * - HeapMemBufferStore is a „braindead“ implementation of the BufferProvider * interface: it just claims new heap blocks and never de-allocates them. * - adding a layer of instrumentation, the DiagnosticBufferProvider allows * to count and verify allocated buffers and their content after the fact. @@ -81,7 +81,7 @@ namespace test { void simpleExample() { - HeapMemProvider provider; /////////////////////////////////////OOO should be DiagnosticBufferProvider + DiagnosticBufferProvider provider; BuffHandle testBuff = provider.lockBufferFor(); CHECK (testBuff); @@ -93,15 +93,15 @@ namespace test { provider.emitBuffer (testBuff); provider.releaseBuffer(testBuff); - diagn::Block& block0 = provider.access_emitted(0); - CHECK (testData(dataID) == block0.accessMemory()); +// diagn::Block& block0 = provider.access_emitted(0); ///////////////////////////////OOO provide suitable diagnostic API! +// CHECK (testData(dataID) == block0.accessMemory()); } void verifyStandardCase() { - HeapMemProvider provider; /////////////////////////////////////OOO should be DiagnosticBufferProvider + DiagnosticBufferProvider provider; BuffDescr buffType = provider.getDescriptorFor(TEST_ELM_SIZE); uint numElms = provider.announce(MAX_ELMS, buffType); @@ -118,7 +118,7 @@ namespace test { for (uint nr=0; nr() = 1; @@ -152,7 +152,7 @@ namespace test { bu4.accessAs() = 4; bu5.accessAs() = 5; - CHECK (0 == provider.emittedCnt()); +// CHECK (0 == provider.emittedCnt()); ///////////////////////////////OOO provide suitable diagnostic API! // now emit buffers in shuffled order provider.emitBuffer (bu3); @@ -161,41 +161,41 @@ namespace test { provider.emitBuffer (bu4); provider.emitBuffer (bu2); - CHECK (5 == provider.emittedCnt()); +// CHECK (5 == provider.emittedCnt()); ///////////////////////////////OOO provide suitable diagnostic API! - CHECK (3 == provider.accessAs(0)); - CHECK (1 == provider.accessAs(1)); - CHECK (5 == provider.accessAs(2)); - CHECK (4 == provider.accessAs(3)); - CHECK (2 == provider.accessAs(4)); +// CHECK (3 == provider.accessAs(0)); ///////////////////////////////OOO provide suitable diagnostic API! +// CHECK (1 == provider.accessAs(1)); +// CHECK (5 == provider.accessAs(2)); +// CHECK (4 == provider.accessAs(3)); +// CHECK (2 == provider.accessAs(4)); - CHECK ( provider.access_emitted(0).was_used()); - CHECK ( provider.access_emitted(1).was_used()); - CHECK ( provider.access_emitted(2).was_used()); - CHECK ( provider.access_emitted(3).was_used()); - CHECK ( provider.access_emitted(4).was_used()); +// CHECK ( provider.access_emitted(0).was_used()); ///////////////////////////////OOO provide suitable diagnostic API! +// CHECK ( provider.access_emitted(1).was_used()); +// CHECK ( provider.access_emitted(2).was_used()); +// CHECK ( provider.access_emitted(3).was_used()); +// CHECK ( provider.access_emitted(4).was_used()); - CHECK (!provider.access_emitted(0).was_closed()); - CHECK (!provider.access_emitted(1).was_closed()); - CHECK (!provider.access_emitted(2).was_closed()); - CHECK (!provider.access_emitted(3).was_closed()); - CHECK (!provider.access_emitted(4).was_closed()); +// CHECK (!provider.access_emitted(0).was_closed()); +// CHECK (!provider.access_emitted(1).was_closed()); +// CHECK (!provider.access_emitted(2).was_closed()); +// CHECK (!provider.access_emitted(3).was_closed()); +// CHECK (!provider.access_emitted(4).was_closed()); bu5.release(); - CHECK (!provider.access_emitted(0).was_closed()); - CHECK (!provider.access_emitted(1).was_closed()); - CHECK ( provider.access_emitted(2).was_closed()); - CHECK (!provider.access_emitted(3).was_closed()); - CHECK (!provider.access_emitted(4).was_closed()); +// CHECK (!provider.access_emitted(0).was_closed()); +// CHECK (!provider.access_emitted(1).was_closed()); +// CHECK ( provider.access_emitted(2).was_closed()); +// CHECK (!provider.access_emitted(3).was_closed()); +// CHECK (!provider.access_emitted(4).was_closed()); bu2.release(); bu2.release(); bu5.release(); - CHECK (!provider.access_emitted(0).was_closed()); - CHECK (!provider.access_emitted(1).was_closed()); - CHECK ( provider.access_emitted(2).was_closed()); - CHECK (!provider.access_emitted(3).was_closed()); - CHECK ( provider.access_emitted(4).was_closed()); +// CHECK (!provider.access_emitted(0).was_closed()); +// CHECK (!provider.access_emitted(1).was_closed()); +// CHECK ( provider.access_emitted(2).was_closed()); +// CHECK (!provider.access_emitted(3).was_closed()); +// CHECK ( provider.access_emitted(4).was_closed()); CHECK (!bu2); CHECK (bu3); @@ -204,7 +204,7 @@ namespace test { bu3.release(); bu4.release(); - CHECK (5 == provider.emittedCnt()); +// CHECK (5 == provider.emittedCnt()); ///////////////////////////////OOO provide suitable diagnostic API! } }; diff --git a/tests/core/steam/play/diagnostic-output-slot.hpp b/tests/core/steam/play/diagnostic-output-slot.hpp index 790d16396..18952c5c0 100644 --- a/tests/core/steam/play/diagnostic-output-slot.hpp +++ b/tests/core/steam/play/diagnostic-output-slot.hpp @@ -29,7 +29,7 @@ #include "steam/play/output-slot-connection.hpp" #include "steam/asset/meta/time-grid.hpp" #include "steam/engine/buffhandle.hpp" -#include "steam/engine/heap-mem-provider.hpp" +#include "steam/engine/naive-buffer-setup.hpp" #include "lib/time/timevalue.hpp" #include "lib/scoped-ptrvect.hpp" #include "lib/iter-source.hpp" @@ -57,7 +57,7 @@ namespace play { using steam::asset::meta::TimeGrid; using steam::engine::BuffDescr; using steam::engine::test::TestFrame; - using steam::engine::HeapMemProvider; + using steam::engine::NaiveBufferSetup; namespace diagn = steam::engine::diagn; //using std::vector; @@ -94,7 +94,7 @@ namespace play { typedef std::unordered_set FrameTrackingInfo; - HeapMemProvider buffProvider_; + NaiveBufferSetup buffProvider_; BuffDescr bufferType_; FrameTrackingInfo frameTrackingIndex_; @@ -205,19 +205,21 @@ namespace play { TestFrame const * accessEmittedFrame (uint frameNr) const { - if (frameNr < buffProvider_.emittedCnt()) - return & accessFrame(frameNr); - else - return 0; ////////////////////////////////TICKET #856 + UNIMPLEMENTED ("suitable diagnostic API"); +// if (frameNr < buffProvider_.emittedCnt()) ///////////////////////////////OOO provide suitable diagnostic API! +// return & accessFrame(frameNr); +// else +// return 0; ////////////////////////////////TICKET #856 } diagn::Block const * accessEmittedBuffer (uint bufferNr) const { - if (bufferNr < buffProvider_.emittedCnt()) - return & accessBlock(bufferNr); - else - return 0; + UNIMPLEMENTED ("suitable diagnostic API"); +// if (bufferNr < buffProvider_.emittedCnt()) ///////////////////////////////OOO provide suitable diagnostic API! +// return & accessBlock(bufferNr); +// else +// return 0; } bool @@ -232,13 +234,15 @@ namespace play { TestFrame const& accessFrame (uint frameNr) const { - return unConst(this)->buffProvider_.accessAs (frameNr); + UNIMPLEMENTED ("suitable diagnostic API"); +// return unConst(this)->buffProvider_.accessAs (frameNr); ///////////////////////////////OOO provide suitable diagnostic API! } diagn::Block const& accessBlock (uint bufferNr) const { - return unConst(this)->buffProvider_.access_emitted (bufferNr); + UNIMPLEMENTED ("suitable diagnostic API"); +// return unConst(this)->buffProvider_.access_emitted (bufferNr); ///////////////////////////////OOO provide suitable diagnostic API! } }; diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index ab5f17c2c..7d5a61e59 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -111619,8 +111619,50 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) + + + + + + - + + + + + + + + + + + + + + + + + + + + + +

+ auch mark_emitted ist gar nicht die Aufgabe des Store! +

+ + +
+ +
+
+ + + +
+
+ + @@ -111745,6 +111787,163 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ idealerweise funktioniert das sogar ohne dynamic-cast: denn die Dekoratoren könnten direkt per callback-λ verdrahtet sein +

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

+ Frage: kann ProviderBufferProvider einen beliebigen  DiagnosticBuffer instrumentieren? +

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

+ ⟹ jedweder State des BufferProvider muß in den zwei Implementierungs-Säulen liegen +

+ + +
+
+ + + + + + +

+ (alternativ müßte ausschließlich ein Diagnose-Accessor erzeugt werden) +

+ + +
+ + + + + +

+ das sagt auch der Name, es wäre dann kein BufferProvider... +

+

+ Und ein solches alternatives Nutz-Szenario wäre in der Tat denkbar, müßte dann aber eigens und daneben stehend implementiert werden +

+ + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -158620,7 +158819,7 @@ std::cout << tmpl.render({"what", "World"}) << s - + @@ -158656,6 +158855,61 @@ std::cout << tmpl.render({"what", "World"}) << s + + + + + + + +

+ Gilt stets auch für andere Objekt-Instanzen des gleichen Typs. Gilt auch für nested Classes, und member functions, und nested Classes in member functions; wobei allerdings, die Instanz muß man explizit in der Hand haben (es gibt hier keine solche »magic« wie in Java, wo eine non-static nested class automatisch auch einen outer.this-ptr bekommt) +

+ + +
+
+ + + + + + +

+ konzeptionell: das ist ein separates API für abgeleitete Klassen +

+ + +
+ + + + + + + +

+ Man muß unterscheiden zwischen Deklarationen und dem Zugang zu konkreten Members. Deklarationen sieht jede abgeleitete Klasse. Aber auf protected Members in einer Basisklasse zugreifen kann man nur durch eine Instanz einer abgeleiteten Klasse; und zwar muß der Typ dieser Instanz gleich (oder abgeleitet) sein wie der Typ, aus dem heraus der Code zugreift. Konkret: auf base.member kann ich nur durch eine derived& zugreifen (das schließt *this ein). Aber nicht durch irgend ein anderes Objekt oder eine base& +

+ + +
+
+ + + + + + +

+ Ohne diese Regel wären wilde Kreuz-Zugriffe auf komplett andere Vererbungslinien möglich; man bedenke im Besonderen, daß die Situation durch Mehrfachvererbung ziemlich komplex sein kann; zudem kann eine andere abgeleitete Klasse die Basis auf komplexe Weise instrumentiert haben, und ein solcher Kreuz-Zugriff könnte das alles unterlaufen. Es ist ja ohnehin ein Zugeständnis, daß man auf was anderes als *this überhaupt zugreifen darf. +

+ + +
+
+
+