From 70e32a3e669423d06c1e7428c367be6b5d3e1bf4 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Fri, 13 Feb 2026 21:27:45 +0100 Subject: [PATCH] BufferProvider: clean-up types Now able to remove some obsoleted part of the old implementation. The existing implementation of the ''Buffer Provider Protocol'' is quite old and dated meanwhile; it was more like an explorative prototype and mixed up implementation and test code. At that time, notably the assumption was that the core render engine will be implemented in plain-C and will push around `void*` all over the place. The `BufferProvider` was meant as an adaptor, while questions of typing were added as an afterthought. Especially some functionality to use the `BuffHandle` in the way of a smart-ptr are completely obsoleted by the reworked design of the Render Engine (2024). --- src/steam/engine/buffer-metadata.hpp | 9 - src/steam/engine/buffer-provider.cpp | 51 ----- src/steam/engine/buffer-provider.hpp | 4 - src/steam/engine/buffhandle-attach.hpp | 125 ------------- src/steam/engine/buffhandle.hpp | 40 +++- src/steam/engine/bufftable.hpp | 158 ---------------- .../engine/diagnostic-buffer-provider.cpp | 2 +- .../engine/diagnostic-buffer-provider.hpp | 4 +- src/steam/engine/heap-mem-buffer-store.cpp | 52 +++--- src/steam/engine/heap-mem-buffer-store.hpp | 56 ++---- src/steam/engine/naive-buffer-setup.hpp | 134 +------------ src/steam/engine/weaving-pattern-builder.hpp | 1 - .../engine/buffer-provider-protocol-test.cpp | 2 - .../diagnostic-buffer-provider-test.cpp | 1 - tests/core/steam/engine/node-base-test.cpp | 2 +- .../steam/play/diagnostic-output-slot.hpp | 1 - .../steam/play/output-slot-protocol-test.cpp | 1 - wiki/thinkPad.ichthyo.mm | 176 ++++++++++++++---- 18 files changed, 219 insertions(+), 600 deletions(-) delete mode 100644 src/steam/engine/buffhandle-attach.hpp delete mode 100644 src/steam/engine/bufftable.hpp diff --git a/src/steam/engine/buffer-metadata.hpp b/src/steam/engine/buffer-metadata.hpp index 4ca64d68e..c4cfd6b9c 100644 --- a/src/steam/engine/buffer-metadata.hpp +++ b/src/steam/engine/buffer-metadata.hpp @@ -231,15 +231,6 @@ namespace engine { return newKey; } - void - useTypeHandlerFrom (Key const& ref) - { - if (nontrivial(this->instanceFunc_)) - throw error::Logic ("unable to supersede an already attached TypeHandler" - , LERR_(LIFECYCLE)); - instanceFunc_ = ref.instanceFunc_; - } - LocalTag const& localTag() const { return specifics_;} size_t storageSize() const { return storageSize_; } diff --git a/src/steam/engine/buffer-provider.cpp b/src/steam/engine/buffer-provider.cpp index e4c1d4f5c..c6ef2c5cc 100644 --- a/src/steam/engine/buffer-provider.cpp +++ b/src/steam/engine/buffer-provider.cpp @@ -188,32 +188,6 @@ namespace engine { ERROR_LOG_AND_IGNORE (engine, "releasing a buffer from BufferProvider") - - /** @warning this operation locally modifies the metadata entry of a single buffer - * to attach a TypeHandler taking ownership of an object embedded within the buffer. - * The client is responsible for actually placement-constructing the object; moreover - * the client is responsible for any damage done to already existing buffer content. - * @note the buffer must be in locked state and the underlying buffer type must not define - * an non-trivial TypeDescriptor, because there is no clean way of superseding an - * existing TypeDescriptor, which basically is just a functor and possibly - * could perform any operation on buffer clean-up. - * @note EX_STRONG - */ - void - BufferProvider::attachTypeHandler (BuffHandle const& target, BuffDescr const& reference) - { - metadata::Entry& metaEntry = bufferStage_->get (target.entryID()); - metadata::Entry& refEntry = bufferStage_->get (reference); - REQUIRE (refEntry.isTypeKey()); - REQUIRE (!metaEntry.isTypeKey()); - if (!metaEntry.isLocked()) - throw error::Logic{"unable to attach an object because buffer isn't locked for use" - , LERR_(LIFECYCLE)}; - - metaEntry.useTypeHandlerFrom (refEntry); // EX_STRONG - } - - /** @internal abort normal lifecycle, reset the underlying buffer and detach from it. * This allows to break out of normal usage and reset the handle to _invalid state_ * @param invokeDtor if possibly the clean-up function of an TypeHandler registered with @@ -308,30 +282,5 @@ namespace engine { } - /** Install a standard TypeHandler for an already locked buffer. - * This causes the dtor function to be invoked when releasing this buffer. - * The assumption is that client code will placement-construct an object - * into this buffer right away, and thus we're taking ownership on that object. - * @param type a reference BuffDescr defining an embedded TypeHandler to use - * A copy of this TypeHandler will be stored into the local metadata for - * this buffer only, not altering the basic buffer type in any way - * @throw lifecycle error when attempting to treat an buffer not in locked state - * @throw error::Logic in case of insufficient buffer space to hold the - * intended target object - * @note EX_STRONG - */ - void - BuffHandle::takeOwnershipFor(BuffDescr const& type) - { - if (!this->isValid()) - throw error::Logic ("attaching an object requires an buffer in locked state", LERR_(LIFECYCLE)); - if (this->size() < type.determineBufferSize()) - throw error::Logic ("insufficient buffer size to hold an instance of that type"); - - descriptor_.provider_->attachTypeHandler(*this, type); // EX_STRONG - } - - - }} // namespace engine diff --git a/src/steam/engine/buffer-provider.hpp b/src/steam/engine/buffer-provider.hpp index 81832018d..97538fab6 100644 --- a/src/steam/engine/buffer-provider.hpp +++ b/src/steam/engine/buffer-provider.hpp @@ -104,7 +104,6 @@ #include "lib/symbol.hpp" #include "lib/hash-value.h" #include "steam/engine/buffhandle.hpp" -//#include "steam/engine/engine-ctx.hpp" #include "steam/engine/type-handler.hpp" #include "steam/engine/buffer-local-tag.hpp" #include "steam/engine/buffer-metadata.hpp" /////////////////////////OOO must be removed from here @@ -160,9 +159,6 @@ namespace engine { template BuffHandle lockBufferFor (ARGS ...args); - /** allow for attaching and owing an object within an already created buffer */ - void attachTypeHandler (BuffHandle const& target, BuffDescr const& reference); - void emergencyCleanup (BuffHandle const& target, bool invokeDtor =false); diff --git a/src/steam/engine/buffhandle-attach.hpp b/src/steam/engine/buffhandle-attach.hpp deleted file mode 100644 index 6d92fdefe..000000000 --- a/src/steam/engine/buffhandle-attach.hpp +++ /dev/null @@ -1,125 +0,0 @@ -/* - BUFFHANDLE-ATTACH.hpp - Buffer handle extension to attach objects into the buffer - - Copyright (C) - 2008, 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 buffhandle-attach.hpp - ** Extension to allow placing objects right into the buffers, taking ownership. - ** This extension is mostly helpful for writing unit-tests, and beyond that for the - ** rather unusual case where we need to place an full-blown object into the buffer, - ** instead of just plain data. A possible use case for this mechanism is to allow for - ** state per calculation stream, feeding this local state to the individual render node - ** embedded into a "state frame". Some effect processors indeed need to maintain state - ** beyond the single frame (e.g. averaging, integrating, sound compression), which usually - ** is handled by applying an "instance" of that processor to the frames to be calculated - ** in a straight sequence. - ** - ** BuffHandle and the underlying BufferProvider standard implementation support that case - ** by attaching an object managing functor to the metadata. This way, the state can live - ** directly embedded into the frame and still be accessed like an object. To keep the - ** header and compilation footprint low, the implementation of the functions supporting - ** this special case was split out of the basic buffhandle.hpp - ** - ** @deprecated 2026-01 this extension-API does not fit into the overall concept. - ** It was created under the impression that the Render Engine will work "with void pointers" - ** Meanwhile, the BuffHandle::accessAs() turned into a core-API now; - ** all the other functionality was never used and is considered pointless //////////////////////TICKET 1410 : remove unnecessary API - ** @see BuffHandle - ** @see BufferProviderProtocol_test usage demonstration - */ - -#ifndef ENGINE_BUFFHANDLE_ATTACH_H -#define ENGINE_BUFFHANDLE_ATTACH_H - - -#include "lib/error.hpp" -#include "steam/engine/buffer-provider.hpp" -#include "steam/engine/buffhandle.hpp" - - -namespace steam { -namespace engine { - - - - - /* === BuffHandle Implementation === */ - - -#define _EXCEPTION_SAFE_INVOKE(_CTOR_) \ - try \ - { \ - return *new(pBuffer_) _CTOR_; \ - } \ - catch(...) \ - { \ - emergencyCleanup(); /* EX_FREE */ \ - pBuffer_ = 0; \ - throw; \ - } - - /** convenience shortcut: place and maintain an object within the buffer. - * This operation performs the necessary steps to attach an object; - * if the buffer isn't locked yet, it will do so. Moreover, the created - * object will be owned by the buffer management facilities, i.e. the - * destructor is registered as cleanup function. - * @throw error::Logic in case there is already another TypeHandler registered - * in charge of managing the buffer contents, or when the object to create - * would not fit into this buffer. - */ -// template -// inline BU& -// BuffHandle::create() -// { -// takeOwnershipFor(); -// _EXCEPTION_SAFE_INVOKE (BU()); -// } - -#undef _EXCEPTION_SAFE_INVOKE - - - - /** @internal helper to attach an TypeHandler after-the fact. - * @note this prepares the buffer for placement-creating an embedded object. - * It doesn't actually create an object - * @throw error::Logic in case there is already another TypeHandler registered - * in charge of managing the buffer contents, or when the object to create - * would not fit into this buffer. - */ -// template -// inline void -// BuffHandle::takeOwnershipFor() -// { -// BuffDescr howto_attach_object_automatically -// = descriptor_.provider_->getDescriptor(); -// takeOwnershipFor (howto_attach_object_automatically); // EX_STRONG -// } - - - /** convenience shortcut: access the buffer contents casted to a specific type. - * @warning this is a \em blind cast, there is no type safety. - * @note clients can utilise the metadata::LocalTag to keep track of some - * specific property of the buffer, like e.g. the type of object. - */ - template - inline BU& - BuffHandle::accessAs() - { - if (!pBuffer_) - throw error::Logic ("buffer not (yet) locked for access by clients" - , LERR_(LIFECYCLE)); - return *reinterpret_cast (pBuffer_); - } - - - -}} // namespace steam::engine -#endif diff --git a/src/steam/engine/buffhandle.hpp b/src/steam/engine/buffhandle.hpp index 43f1955a3..b09e0f471 100644 --- a/src/steam/engine/buffhandle.hpp +++ b/src/steam/engine/buffhandle.hpp @@ -41,7 +41,7 @@ ** @see BufferProvider ** @see BufferProviderProtocol_test usage demonstration ** @see OutputSlot - ** @see bufftable.hpp storage for the buffer table /////////////////////OOO where to point into the new structure for documentation? + ** @see heap-mem-buffer-store.hpp demo implementation of storage backend ** @see engine::RenderInvocation */ @@ -170,14 +170,44 @@ namespace engine { } private: - template - void takeOwnershipFor(); - void takeOwnershipFor(BuffDescr const& type); - void emergencyCleanup(); }; + /** + * Access the memory in the buffer by overlaying a specific type. + * @warning this is a **blind cast**, there is _no type safety_. + * @remark In the common usage pattern, a client has created a BuffDescr + * with suitable typing; it is assumed thus that the call context + * of the client ensures a a seamless link of type information + * at compile time (it's the clients responsibility to ensure that). + * Two flavours of this usage are conceivable: + * - the client [creates a descriptor](\ref BufferProvider::getDescriptorFor(size_t)) + * that only reserves raw storage of sufficient size, e.g. `sizeof(TY)`. When + * accessing the raw storage subsequently through this accessor function, + * the effect is to have a _virtual overlay_ — without actually creating + * a new instance of the type within the storage. + * - the client also [registers a constructor functor](\ref BufferProvider::getDescriptor), + * which implies that a new instance of the target type is constructed into the buffer + * at the moment when the buffer is locked (and is destroyed on `release()`). This + * allows to setup elaborate structures, possibly even with a _back link_, by binding + * additional constructor arguments into the TypeHandler. + * @note while clients can not access the internal type metadata, the _implementation_ + * of BufferProvider can use the HashVal to access the type registry, and can even + * attach additional information as metadata::LocalTag to keep track of some + * specific property of the buffer, like e.g. the type of object. + */ + template + inline BU& + BuffHandle::accessAs() + { + if (!pBuffer_) + throw error::Logic ("buffer not (yet) locked for access by clients" + , LERR_(LIFECYCLE)); + return *reinterpret_cast (pBuffer_); + } + + }} // namespace steam::engine diff --git a/src/steam/engine/bufftable.hpp b/src/steam/engine/bufftable.hpp deleted file mode 100644 index 4b7d16088..000000000 --- a/src/steam/engine/bufftable.hpp +++ /dev/null @@ -1,158 +0,0 @@ -/* - BUFFTABLE.hpp - Table of buffer pointers to be used by the render nodes - - Copyright (C) - 2008, 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 bufftable.hpp - ** helper for organisation of render data buffers - ** Used during the process of _"pulling"_ a render node, which recursively might - ** pull further nodes. Any node has a _render calculation function,_ which in turn - ** needs input and output buffers - ** @see buffer-provider.hpp - */ - - -#ifndef ENGINE_BUFFHTABLE_H -#define ENGINE_BUFFHTABLE_H - - -#include "lib/error.hpp" -#include "steam/engine/buffhandle.hpp" -#include "steam/engine/proc-node.hpp" -#include "lib/iter-adapter.hpp" - -#include -#include - - - -namespace steam { -namespace engine { - - using std::pair; - using std::vector; - - - /** - * Tables of buffer handles and corresponding dereferenced buffer pointers. - * Used within the invocation of a processing node to calculate data. - * The tables are further differentiated into input data buffers and output - * data buffers. The tables are supposed to be implemented as bare "C" arrays, - * thus the array of real buffer pointers can be fed directly to the - * processing function of the respective node. - * - * @todo this whole design is a first attempt and rather clumsy. It should be reworked - * to use a single contiguous memory area and just layer the object structure on top - * (by using placement new). Yet the idea of an stack-like organisation should be retained - */ - struct BuffTable - { - using PHa = BuffHandle *; - using PBu = BuffHandle::PBuff *; - - struct StorageChunk - { }; - - template - struct Storage - { - enum{size = count * sizeof(StorageChunk)}; - }; - - class Builder - { - public: - Builder& announce (uint count, BuffDescr const& type); - BuffTable& build(); - }; - - static Builder& prepare (const size_t STORAGE_SIZE, void* storage); - - void lockBuffers(); - void releaseBuffers(); - - using BuffHandleTable = vector; - using iterator = lib::RangeIter; - - iterator buffers(); - iterator inBuffers(); - iterator outBuffers(); - }; - - - - - /* === Implementation === */ - - inline BuffTable::Builder& - BuffTable::prepare (const size_t STORAGE_SIZE, void* storage) - { - UNIMPLEMENTED ("expose a builder object for outfitting a buffer pointer table"); - } - - - inline BuffTable::Builder& - BuffTable::Builder::announce (uint count, BuffDescr const& type) - { - UNIMPLEMENTED ("accept announcement of additional buffer table entries required"); - } - - - inline BuffTable& - BuffTable::Builder::build() - { - UNIMPLEMENTED ("finally drop off the newly configured buffer pointer table"); - } - - - inline void - BuffTable::lockBuffers() - { - UNIMPLEMENTED ("convenience shortcut: lock all preconfigured buffers within this table through the underlying buffer provider"); - } - - - inline void - BuffTable::releaseBuffers() - { - UNIMPLEMENTED ("convenience shortcut: release all the buffers managed through this buffer table, by forwarding to the underlying buffer provider"); - } - - - - inline BuffTable::iterator - BuffTable::buffers() - { - UNIMPLEMENTED ("expose an iterator to yield all prepared buffers within this buffer table"); - } - - - inline BuffTable::iterator - BuffTable::inBuffers() - { - UNIMPLEMENTED ("expose an iterator to access all the input buffer slots of this buffer table"); - } - - - inline BuffTable::iterator - BuffTable::outBuffers() - { - UNIMPLEMENTED ("expose an iterator to access all the output buffer slots of this buffer table"); - } - - - - - - -}} // namespace steam::engine -#endif diff --git a/src/steam/engine/diagnostic-buffer-provider.cpp b/src/steam/engine/diagnostic-buffer-provider.cpp index d9d7ecf7c..966b7920f 100644 --- a/src/steam/engine/diagnostic-buffer-provider.cpp +++ b/src/steam/engine/diagnostic-buffer-provider.cpp @@ -102,7 +102,7 @@ namespace engine { DiagnosticBufferProvider::DiagnosticBufferProvider() : NaiveBufferSetup{} - , heapStore_{dynamic_cast (*bufferStore_)} + , heapStore_{dynamic_cast (*bufferStore_)} //////////////////////////////////////////TICKET 1410 : obsolete after switch to newtracking-API , tracker_{std::make_unique()} { } diff --git a/src/steam/engine/diagnostic-buffer-provider.hpp b/src/steam/engine/diagnostic-buffer-provider.hpp index 584beb4dc..b6063f674 100644 --- a/src/steam/engine/diagnostic-buffer-provider.hpp +++ b/src/steam/engine/diagnostic-buffer-provider.hpp @@ -37,7 +37,7 @@ namespace engine { namespace error = lumiera::error; - class HeapMemProvider; //////////////////////////////OOO fällt dann weg nach dem Umbau + class HeapMemBufferStore; //////////////////////////////OOO fällt dann weg nach dem Umbau class BufferDiagnostic; namespace diagn {// state descriptors for diagnostics.... @@ -84,7 +84,7 @@ namespace engine { class DiagnosticBufferProvider : public NaiveBufferSetup { - HeapMemProvider& heapStore_; //////////////////////////////OOO fällt dann weg nach dem Umbau + HeapMemBufferStore& heapStore_; //////////////////////////////OOO fällt dann weg nach dem Umbau struct BlockTracker; std::unique_ptr tracker_; diff --git a/src/steam/engine/heap-mem-buffer-store.cpp b/src/steam/engine/heap-mem-buffer-store.cpp index 386f3d7e4..06684ed59 100644 --- a/src/steam/engine/heap-mem-buffer-store.cpp +++ b/src/steam/engine/heap-mem-buffer-store.cpp @@ -43,11 +43,13 @@ namespace engine { /////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET 1410 : need to question what implementation structures are needed, after »tracking« was extracted... /** - * Helper for implementing a diagnostic BufferProvider: - * A block of heap allocated storage, with the capability - * to store some additional tracking information. + * Simplistic implementation of buffer storage. + * Allocates a block of heap memory for buffers and never deallocates. + * This strange behaviour can be used to investigate and demonstrate + * buffer usage from a unit test setup. + * @see DiagnosticBufferProvider */ - class HeapMemProvider::Block + class HeapMemBufferStore::Block : util::NonCopyable { unique_ptr storage_; @@ -95,7 +97,7 @@ namespace engine { } - using Block = HeapMemProvider::Block; + using Block = HeapMemBufferStore::Block; /** helper to find Block entries * based on their raw memory address */ @@ -131,7 +133,7 @@ namespace engine { /////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET 1410 : need to question what implementation structures are needed, after »tracking« was extracted... - using PoolBlocks = ScopedPtrVect; + using PoolBlocks = ScopedPtrVect; /** * @internal Pool of allocated buffer Blocks of a specific size. @@ -144,7 +146,7 @@ namespace engine { * and later gets "emitted" to an output sequence, where it remains for * later investigation and diagnostics. */ - class HeapMemProvider::BlockPool + class HeapMemBufferStore::BlockPool { uint maxAllocCount_; size_t memBlockSize_; @@ -269,19 +271,19 @@ namespace engine { /** * @internal create a memory tracking BufferProvider, */ - HeapMemProvider::HeapMemProvider() + HeapMemBufferStore::HeapMemBufferStore() : pool_(new PoolTable) , outSeq_() { } - HeapMemProvider::~HeapMemProvider() { /* emit dtor of BlockPool here */ } + HeapMemBufferStore::~HeapMemBufferStore() { /* emit dtor of BlockPool here */ } /* ==== Implementation of the BufferProvider interface ==== */ uint - HeapMemProvider::prepareBuffers (uint numBuffers, size_t buffSiz, HashVal typeID) + HeapMemBufferStore::prepareBuffers (uint numBuffers, size_t buffSiz, HashVal typeID) { BlockPool& responsiblePool = getBlockPoolFor (buffSiz, typeID); return responsiblePool.prepare_for (numBuffers); @@ -289,7 +291,7 @@ namespace engine { BufferProviderSetup::Store::Slot - HeapMemProvider::provideBuffer (size_t buffSiz, HashVal typeID, LocalTag) + HeapMemBufferStore::provideBuffer (size_t buffSiz, HashVal typeID, LocalTag) { BlockPool& blocks = getBlockPoolFor (buffSiz, typeID); Block& newBlock = blocks.createBlock(); @@ -299,7 +301,7 @@ namespace engine { void - HeapMemProvider::mark_emitted (size_t buffSiz, HashVal typeID, LocalTag const& specifics) + HeapMemBufferStore::mark_emitted (size_t buffSiz, HashVal typeID, LocalTag const& specifics) { Block* block4buffer = locateBlock (buffSiz, typeID, specifics); if (!block4buffer) @@ -320,7 +322,7 @@ namespace engine { /** mark a buffer as officially discarded */ void - HeapMemProvider::detachBuffer (size_t buffSiz, HashVal typeID, Slot alloc) + HeapMemBufferStore::detachBuffer (size_t buffSiz, HashVal typeID, Slot alloc) { auto& [storage, specifics] = alloc; Block* block4buffer = locateBlock (buffSiz, typeID, specifics); @@ -333,30 +335,32 @@ namespace engine { /* ==== Implementation details ==== */ +#if false ////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1410 : this additional tracking API is obsolete and need to be removed size_t - HeapMemProvider::emittedCnt() const + HeapMemBufferStore::emittedCnt() const { return outSeq_.size(); } void - HeapMemProvider::markAllEmitted() + HeapMemBufferStore::markAllEmitted() { for (auto& [_, blockPool] : *pool_) blockPool.discard(); } - HeapMemProvider::Block& - HeapMemProvider::access_emitted (uint bufferID) + HeapMemBufferStore::Block& + HeapMemBufferStore::access_emitted (uint bufferID) { if (!withinOutputSequence (bufferID)) return emptyPlaceholder; ////////////////////////////////TICKET #856 else return outSeq_[bufferID]; } +#endif ////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1410 : (End) obsoleted API bool - HeapMemProvider::withinOutputSequence (uint bufferID) const + HeapMemBufferStore::withinOutputSequence (uint bufferID) const { if (bufferID >= MAX_BUFFERS) throw error::Fatal ("hardwired internal limit for test buffers exceeded"); @@ -364,8 +368,8 @@ namespace engine { return bufferID < outSeq_.size(); } - HeapMemProvider::BlockPool& - HeapMemProvider::getBlockPoolFor (size_t buffSiz, HashVal typeID) + HeapMemBufferStore::BlockPool& + HeapMemBufferStore::getBlockPoolFor (size_t buffSiz, HashVal typeID) { BlockPool& pool = (*pool_)[typeID]; if (not pool) @@ -373,8 +377,8 @@ namespace engine { return pool; } - HeapMemProvider::Block* - HeapMemProvider::locateBlock (size_t buffSiz, HashVal typeID, void* storage) + HeapMemBufferStore::Block* + HeapMemBufferStore::locateBlock (size_t buffSiz, HashVal typeID, void* storage) { BlockPool& pool = getBlockPoolFor (buffSiz, typeID); Block* block4buffer = pool.find (storage); ////////////////////////////////TICKET #856 @@ -384,8 +388,8 @@ namespace engine { - HeapMemProvider::Block* - HeapMemProvider::searchInOutSeqeuence (void* blockLocation) + HeapMemBufferStore::Block* + HeapMemBufferStore::searchInOutSeqeuence (void* blockLocation) { return pick_Block_by_storage (outSeq_, blockLocation); ////////////////////////////////TICKET #856 } diff --git a/src/steam/engine/heap-mem-buffer-store.hpp b/src/steam/engine/heap-mem-buffer-store.hpp index 9c277738d..c87f48797 100644 --- a/src/steam/engine/heap-mem-buffer-store.hpp +++ b/src/steam/engine/heap-mem-buffer-store.hpp @@ -49,27 +49,21 @@ namespace engine { namespace error = lumiera::error; + using std::unique_ptr; using lib::ScopedPtrVect; using lib::HashVal; - namespace diagn { - - using std::unique_ptr; - - - } - /** - * 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". + * Naive demo implementation of the BufferProvider::BufferStore. + * This is kind of a faked implementation of the BufferProvider backend and uses a + * linearly growing table of heap allocated buffer blocks, which will never be discarded, + * unless the object is discarded as a whole. Paired with the instrumentation and diagnostics + * API of DiagnosticBufferProvider, this can be used to confirm assumptions regarding + * buffer usage from a unit test setup. Even blocks already marked as "released" + * are actually retained and can be investigated after the fact. */ - class HeapMemProvider + class HeapMemBufferStore : public BufferProviderSetup::Store { public: /////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1410 : looks like I'll re-implement the storage from scratch, since »tracking« is no longer required here @@ -89,9 +83,10 @@ namespace engine { virtual void detachBuffer (size_t,HashVal, Slot alloc) override; public: - ~HeapMemProvider(); - HeapMemProvider(); + ~HeapMemBufferStore(); + HeapMemBufferStore(); +#if false ////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1410 : this additional tracking API is obsolete and need to be removed size_t emittedCnt() const; Block& access_emitted (uint bufferID); @@ -100,6 +95,7 @@ namespace engine { TY& accessAs (uint bufferID); void markAllEmitted(); +#endif ////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1410 : (End) obsoleted API private: bool withinOutputSequence (uint bufferID) const; @@ -110,31 +106,5 @@ namespace engine { - /** 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"); - - Block& memoryBlock = access_emitted (bufferID); - NOTREACHED ("TICKET #1410 : tracking implementation -> DiagnosticBufferProvider"); -// TY* converted = std::launder (reinterpret_cast (memoryBlock.accessMemory())); /////////////////////TICKET 1410 : my assumption is that Block will be implemented differently -- at least not used this way... - -// REQUIRE (converted); -// return *converted; - } - - - - }} // namespace steam::engine #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 index 41d1d6b1a..6e7886727 100644 --- a/src/steam/engine/naive-buffer-setup.hpp +++ b/src/steam/engine/naive-buffer-setup.hpp @@ -18,17 +18,10 @@ ** 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 + ** @see render-environment.cpp */ #ifndef STEAM_ENGINE_NAIVE_BUFFER_STEUP_H @@ -36,12 +29,9 @@ #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 @@ -50,65 +40,6 @@ 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. @@ -128,70 +59,9 @@ namespace engine { { } 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 + 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/weaving-pattern-builder.hpp b/src/steam/engine/weaving-pattern-builder.hpp index dec25a2c9..9b82b57bc 100644 --- a/src/steam/engine/weaving-pattern-builder.hpp +++ b/src/steam/engine/weaving-pattern-builder.hpp @@ -136,7 +136,6 @@ #include "steam/engine/proc-id.hpp" #include "steam/engine/engine-ctx.hpp" #include "steam/engine/buffer-provider.hpp" -#include "steam/engine/buffhandle-attach.hpp" ///////////////////////////////////////////////////////////TICKET 1410 : unnecessary API -- only accessAs() needs to be retained! #include "steam/engine/media-weaving-pattern.hpp" #include "lib/meta/tuple-closure.hpp" #include "lib/meta/tuple-helper.hpp" diff --git a/tests/core/steam/engine/buffer-provider-protocol-test.cpp b/tests/core/steam/engine/buffer-provider-protocol-test.cpp index 78eac783f..afc66d19f 100644 --- a/tests/core/steam/engine/buffer-provider-protocol-test.cpp +++ b/tests/core/steam/engine/buffer-provider-protocol-test.cpp @@ -24,8 +24,6 @@ #include "steam/engine/testframe.hpp" #include "steam/engine/test-rand-ontology.hpp" #include "steam/engine/diagnostic-buffer-provider.hpp" -#include "steam/engine/buffhandle-attach.hpp" ///////////////////////////////////////////////////////////TICKET 1410 : remove unnecessary API -#include "steam/engine/bufftable.hpp" using util::isSameObject; using util::for_each; diff --git a/tests/core/steam/engine/diagnostic-buffer-provider-test.cpp b/tests/core/steam/engine/diagnostic-buffer-provider-test.cpp index 059410006..445001f6f 100644 --- a/tests/core/steam/engine/diagnostic-buffer-provider-test.cpp +++ b/tests/core/steam/engine/diagnostic-buffer-provider-test.cpp @@ -19,7 +19,6 @@ #include "lib/error.hpp" #include "lib/test/run.hpp" #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 diff --git a/tests/core/steam/engine/node-base-test.cpp b/tests/core/steam/engine/node-base-test.cpp index 04e8f7788..663f28524 100644 --- a/tests/core/steam/engine/node-base-test.cpp +++ b/tests/core/steam/engine/node-base-test.cpp @@ -26,7 +26,7 @@ #include "steam/engine/turnout-system.hpp" #include "steam/engine/feed-manifold.hpp" #include "steam/engine/node-builder.hpp" -#include "steam/engine/buffhandle-attach.hpp" ///////////////////////////////////////////////////////////TICKET 1410 : remove unnecessary API +#include "steam/engine/buffhandle.hpp" #include "lib/test/test-helper.hpp" #include "lib/util.hpp" diff --git a/tests/core/steam/play/diagnostic-output-slot.hpp b/tests/core/steam/play/diagnostic-output-slot.hpp index 609c5b0c8..ad702e97c 100644 --- a/tests/core/steam/play/diagnostic-output-slot.hpp +++ b/tests/core/steam/play/diagnostic-output-slot.hpp @@ -58,7 +58,6 @@ namespace play { using steam::engine::BuffDescr; using steam::engine::test::TestFrame; using steam::engine::NaiveBufferSetup; - namespace diagn = steam::engine::diagn; //using std::vector; using std::shared_ptr; diff --git a/tests/core/steam/play/output-slot-protocol-test.cpp b/tests/core/steam/play/output-slot-protocol-test.cpp index 19eaae3dc..c18c103d5 100644 --- a/tests/core/steam/play/output-slot-protocol-test.cpp +++ b/tests/core/steam/play/output-slot-protocol-test.cpp @@ -20,7 +20,6 @@ #include "steam/play/diagnostic-output-slot.hpp" #include "steam/engine/buffhandle.hpp" -#include "steam/engine/buffhandle-attach.hpp" ///////////////////////////////////////////////////////////TICKET 1410 : remove unnecessary API #include "steam/engine/testframe.hpp" diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 7731ba498..a5d114624 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -111706,8 +111706,13 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + + + + + + @@ -112282,7 +112287,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + @@ -112291,12 +112296,12 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)

- + - + - + @@ -112306,32 +112311,32 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + - - + + - + - + - + - - - - + + + + - + - - - - + + + + @@ -112351,18 +112356,18 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - - - - - - + + + + + + - - + + - + @@ -112378,7 +112383,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + @@ -112389,10 +112394,10 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + - + @@ -112402,7 +112407,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + @@ -112412,7 +112417,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + @@ -112422,7 +112427,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + @@ -112435,7 +112440,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + @@ -112444,6 +112449,9 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) + + + @@ -112596,6 +112604,91 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) + + + + + + + + +

+ weil dort die tatsächlichen Zustandsübergänge stattfinden... +

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

+ Und zwar weil das BufferProvider-Interface auch erweiterte Funktionalität ansteuern soll, wie den Cache oder die OutputSink. Diese brauchen zwingend den emit()-Aufruf. Zwar könnte man jetzt versuchen, diese Delegation aus beiden Zonen zusammenzubauen — aber das widerspricht der Idee dieses Refactorings zur Trennung der Zonen. Also läuft es darauf hinaus, daß solche Spezial-Implementierungen die generische Metadaten/Zustands-Implementierung verwenden, aber einen speziellen BufferStore. Somit müssen alle Zustandsübergänge tatsächlich an beide Implementierungs-Säulen propagiert werden +

+ + +
+ + +
+
+ + + +
+ + + + + + + + + + + + +
+ + + + + @@ -112618,13 +112711,14 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + - + - + + @@ -112705,6 +112799,10 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) + + + +