diff --git a/src/steam/engine/buffer-metadata.hpp b/src/steam/engine/buffer-metadata.hpp index d76d2553b..aeb92b856 100644 --- a/src/steam/engine/buffer-metadata.hpp +++ b/src/steam/engine/buffer-metadata.hpp @@ -36,6 +36,9 @@ ** configuration tag attached to the buffer access, allowing to re-access a context ** within the buffer provider implementation. ** + ** @todo 2/2026 This code has gotten overly tricky and driven by expected effect. + ** It is mandatory to factor-out an interface! //////////////////////////////////////////////////////TICKET #1410 : clean-up BufferProvider base implementation + ** ** @see buffer-provider.hpp ** @see BufferMetadata_test ** @see BufferProviderProtocol_test @@ -530,7 +533,9 @@ namespace engine { * represented as hierarchically linked hash keys. The implementation * may bind a TypeHandler to a specific type, allowing automatic invocation * of a "constructor" and "destructor" function on each buffer of this type, - * when \em locking or \em freeing the corresponding buffer. + * when _locking_ or _freeing_ the corresponding buffer. + * @todo 2/2026 must extract an interface here..... //////////////////////////////////////////////////////TICKET #1410 : clean-up BufferProvider base implementation + * */ class BufferMetadata : util::NonCopyable diff --git a/src/steam/engine/buffer-provider-setup.hpp b/src/steam/engine/buffer-provider-setup.hpp new file mode 100644 index 000000000..e44eddc20 --- /dev/null +++ b/src/steam/engine/buffer-provider-setup.hpp @@ -0,0 +1,108 @@ +/* + BUFFER-PROVIDER-SETUP.hpp - configuration of the actual BufferProvider implementation + + 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 buffer-provider-setup.hpp + ** Helper template for installing a suitable BufferProvider setup. + ** + ** @see engine-facilities.cpp + ** @see buffer-provider.hpp + */ + +#ifndef STEAM_ENGINE_BUFFR_PROVIDER_SETUP_H +#define STEAM_ENGINE_BUFFR_PROVIDER_SETUP_H + + +#include "lib/error.hpp" +#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 "lib/nocopy.hpp" + +#include +#include + + +namespace steam { +namespace engine { + + using lib::Literal; + using std::unique_ptr; + using std::forward; + + + class BufferMetadata; + + + LUMIERA_ERROR_DECLARE (BUFFER_MANAGEMENT); ///< Problem providing working buffers + + + /** + * Framework for configuring the actual BufferPovider backeind implementation. + * + * @todo WIP-WIP-WIP as of 2/2026 -- reworking BufferProvider implementation ////////////////////////////TICKET #1410 + */ + class BufferProviderSetup + : util::NonCopyable + { + public: + BufferProviderSetup (Literal implementationID); + + + uint announce (uint count, BuffDescr const&); + + BuffHandle lockBuffer (BuffDescr const&); + void emitBuffer (BuffHandle const&); + void releaseBuffer (BuffHandle const&); + + 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); + + + /** describe the kind of buffer managed by this provider */ + BuffDescr getDescriptorFor(size_t storageSize=0); + BuffDescr getDescriptorFor(size_t storageSize, TypeHandler specialTreatment); + + template + BuffDescr getDescriptor (ARGS ...args); + + + + /* === API for BuffHandle internal access === */ + + bool verifyValidity (BuffDescr const&) const; + size_t getBufferSize (HashVal typeID) const; + + protected: + BuffHandle buildHandle (HashVal typeID, Buff* storage, LocalTag const& =LocalTag::UNKNOWN); + + bool was_created_by_this_provider (BuffDescr const&) const; + }; + + + + + /* === Implementation === */ + + /** */ + + +}} // namespace steam::engine +#endif /*STEAM_ENGINE_BUFFR_PROVIDER_SETUP_H*/ diff --git a/src/steam/engine/buffer-provider.cpp b/src/steam/engine/buffer-provider.cpp index 8f73e3797..ef65297ad 100644 --- a/src/steam/engine/buffer-provider.cpp +++ b/src/steam/engine/buffer-provider.cpp @@ -47,7 +47,7 @@ namespace engine { * @param implementationID symbolic ID setting these family of buffers apart. */ BufferProvider::BufferProvider (Literal implementationID) - : meta_(new BufferMetadata (implementationID)) + : bufferStage_(new BufferMetadata (implementationID)) { } BufferProvider::~BufferProvider() { } @@ -60,28 +60,28 @@ namespace engine { bool BufferProvider::verifyValidity (BuffDescr const& bufferID) const { - return meta_->isLocked (bufferID); + return bufferStage_->isLocked (bufferID); } BuffDescr BufferProvider::getDescriptorFor (size_t storageSize) { - return BuffDescr (*this, meta_->key (storageSize)); + return BuffDescr (*this, bufferStage_->key (storageSize)); } BuffDescr BufferProvider::getDescriptorFor(size_t storageSize, TypeHandler specialTreatment) { - return BuffDescr (*this, meta_->key (storageSize, specialTreatment)); + return BuffDescr (*this, bufferStage_->key (storageSize, specialTreatment)); } size_t BufferProvider::getBufferSize (HashVal typeID) const { - metadata::Key& typeKey = meta_->get (typeID); + metadata::Key& typeKey = bufferStage_->get (typeID); return typeKey.storageSize(); } @@ -95,8 +95,8 @@ namespace engine { BuffHandle BufferProvider::buildHandle (HashVal typeID, Buff* storage, LocalTag const& localTag) { - metadata::Key& typeKey = meta_->get (typeID); - metadata::Entry& entry = meta_->markLocked(typeKey, storage, localTag); + metadata::Key& typeKey = bufferStage_->get (typeID); + metadata::Entry& entry = bufferStage_->markLocked(typeKey, storage, localTag); return BuffHandle (BuffDescr(*this, entry), storage); } @@ -162,7 +162,7 @@ namespace engine { void BufferProvider::emitBuffer (BuffHandle const& handle) { - metadata::Entry& metaEntry = meta_->get (handle.entryID()); + metadata::Entry& metaEntry = bufferStage_->get (handle.entryID()); mark_emitted (metaEntry.parentKey(), metaEntry.localTag()); metaEntry.mark(EMITTED); } @@ -179,10 +179,10 @@ namespace engine { void BufferProvider::releaseBuffer (BuffHandle const& handle) try { - metadata::Entry& metaEntry = meta_->get (handle.entryID()); + metadata::Entry& metaEntry = bufferStage_->get (handle.entryID()); metaEntry.mark(FREE); // might invoke embedded dtor function detachBuffer (metaEntry.parentKey(), metaEntry.localTag(), *handle); - meta_->release (metaEntry); + bufferStage_->release (metaEntry); } ERROR_LOG_AND_IGNORE (engine, "releasing a buffer from BufferProvider") @@ -201,8 +201,8 @@ namespace engine { void BufferProvider::attachTypeHandler (BuffHandle const& target, BuffDescr const& reference) { - metadata::Entry& metaEntry = meta_->get (target.entryID()); - metadata::Entry& refEntry = meta_->get (reference); + metadata::Entry& metaEntry = bufferStage_->get (target.entryID()); + metadata::Entry& refEntry = bufferStage_->get (reference); REQUIRE (refEntry.isTypeKey()); REQUIRE (!metaEntry.isTypeKey()); if (!metaEntry.isLocked()) @@ -223,10 +223,10 @@ namespace engine { void BufferProvider::emergencyCleanup (BuffHandle const& target, bool invokeDtor) try { - metadata::Entry& metaEntry = meta_->get (target.entryID()); + metadata::Entry& metaEntry = bufferStage_->get (target.entryID()); metaEntry.invalidate (invokeDtor); detachBuffer (metaEntry.parentKey(), metaEntry.localTag(), *target); - meta_->release (metaEntry); + 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 6f24bc314..b1f6ad87c 100644 --- a/src/steam/engine/buffer-provider.hpp +++ b/src/steam/engine/buffer-provider.hpp @@ -70,27 +70,13 @@ namespace engine { * @warning all of BufferProvider is assumed to run within a threadsafe environment. * * @todo as of 6/2011 buffer management within the engine is still a bit vague - * @todo as of 11/11 thread safety within the engine remains to be clarified ///////////////////////////TICKET #854 + * @todo as of 11/11 thread safety within the engine remains to be clarified ////////////////////////////TICKET #854 */ class BufferProvider : util::NonCopyable { - unique_ptr meta_; - - protected: /* === for Implementation by concrete providers === */ - /// placeholder marker type for an actual data buffer - using Buff = StreamType::ImplFacade::DataBuffer; - - BufferProvider (Literal implementationID); - - 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; - public: virtual ~BufferProvider(); ///< this is an ABC @@ -126,9 +112,39 @@ 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; + BuffHandle buildHandle (HashVal typeID, Buff* storage, LocalTag const& =LocalTag::UNKNOWN); 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 BufferStore + : util::NonCopyable + { + public: + virtual ~BufferStore() { } ///< this is an interface + protected: + BufferStore() = default; + + 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; + }; + + unique_ptr bufferStage_; /////////////////////////////////////////////////////////TICKET #1410 : must be turned into an internal interface + unique_ptr bufferStore_; }; diff --git a/src/steam/engine/buffer-proxy-provider.hpp b/src/steam/engine/buffer-proxy-provider.hpp index 4b724f242..949c0c060 100644 --- a/src/steam/engine/buffer-proxy-provider.hpp +++ b/src/steam/engine/buffer-proxy-provider.hpp @@ -17,6 +17,7 @@ ** with the buffer lifecycle protocol as defined by BufferProvider. ** @todo BROKEN as of 12/2024 //////////////////////////////////////////////////////////////////////////////TICKET #1387 : can not properly compose BufferProvider ** @see output-slot.hpp + ** @see output-proxy-provider-test.cpp */ #ifndef STEAM_ENGINE_BUFFER_PROXY_PROVIDER_H @@ -52,6 +53,7 @@ namespace engine { /** * Adapter to expose access to data blocks via BuffHandle and the BufferProvider protocol. * @todo WIP-WIP 12/2024 this is a design sketch to explore extension capabilities of BufferProvider + * @todo 2/2026 broken by refactoring of BufferProvider //////////////////////////////////////////////TICKET #1410 : refactoring to separate external and implementation API */ class BufferProxyProvider : util::NonCopyable diff --git a/tests/core/steam/engine/output-proxy-provider-test.cpp b/tests/core/steam/engine/output-proxy-provider-test.cpp index f6cb112d3..3e5118e4c 100644 --- a/tests/core/steam/engine/output-proxy-provider-test.cpp +++ b/tests/core/steam/engine/output-proxy-provider-test.cpp @@ -37,6 +37,9 @@ namespace test { * output data buffers provided from _some implementation._ * @todo WIP-WIP 12/2024 this turned out to be impossible, * due to inconsistencies in the default implementation. /////////////////////////////////////////////TICKET #1387 : need to consolidate BufferProvider default implementation + * @todo 2/2026 broken by refactoring of BufferProvider //////////////////////////////////////////////TICKET #1410 : refactoring to separate external and implementation API + * @todo however, something along this lines *must* + * be made possible, somehow, for OutputSlot... */ class OutputProxyProvider_test : public Test { diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index e98b23929..57374d774 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -73850,7 +73850,7 @@ - + @@ -73877,7 +73877,7 @@ - + @@ -74273,7 +74273,7 @@ - + @@ -84952,8 +84952,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200

- - + +
@@ -85777,7 +85777,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + @@ -85797,7 +85797,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + @@ -104822,13 +104822,13 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + - + @@ -104858,7 +104858,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)

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

- ...und zwar schon längere Zeit bezüglich der Implementierung  des BufferProvider — das Konzept halte ich für sehr wichtig und auch gelngen. Aber immer wieder, wenn ich dann die Implementierung anschaue, dann springt man irgendwo zwischen dieser Default-Implementierung und dem TrackingHeapBlockProvider hin und her — und der ganze Code „riecht schief“, irgendwie (weiß aber nicht warum) ... Hinzu kommen Probleme (und, wie ich inzwischen weiß, tatsächliche Bugs) in der Typ-Registrierung, also BufferMetadata + ...und zwar schon längere Zeit bezüglich der Implementierung des BufferProvider — das Konzept halte ich für sehr wichtig und auch gelngen. Aber immer wieder, wenn ich dann die Implementierung anschaue, dann springt man irgendwo zwischen dieser Default-Implementierung und dem TrackingHeapBlockProvider hin und her — und der ganze Code „riecht schief“, irgendwie (weiß aber nicht warum) ... Hinzu kommen Probleme (und, wie ich inzwischen weiß, tatsächliche Bugs) in der Typ-Registrierung, also BufferMetadata

@@ -104970,7 +104970,8 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
- + + @@ -105057,7 +105058,9 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + + + @@ -110266,9 +110269,10 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + + @@ -110708,8 +110712,9 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + + @@ -110793,8 +110798,20 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + + + + + + +

+ ...und da steck ich jetzt fest... +

+ +
+ +
@@ -110957,6 +110974,11 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) + + + + + @@ -110969,8 +110991,16 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - - + + + + +

+ is ja schön befriedigend, erst mal einen neuen Test anzulegen; auch der "simple case" ist rasch zusammengezimmert. Aber beim ersten ernsthaften Testfall bleibt man dann stecken — aus eben dem Grund, warum man einen Test wollte: es ist nicht klar was gebraucht wird +

+ +
+
@@ -111133,6 +111163,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
+ @@ -111181,6 +111212,11 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) + + + + + @@ -111198,12 +111234,14 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + + - + + @@ -111444,9 +111482,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - - - +

wir haben hier nix zu verbergen @@ -111484,6 +111520,197 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) + + + + + + + + +

+ shared-ptr nehmen +

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

+ weil das Protokoll seinerzeit anhand eines Prototypen konkretisiert wurde; dabei hat sich zwar nichts gezeigt, was eine Erweiterung des Protokolls notwendig machen würde — aber die konkrete Bedeutung des Protokolls wird nur anhand dieser Prototyp- oder Demo-Implementierung klar, und das ist aktuell das Problem (sie ist nämlich nicht klar, und nicht konsistent mit dem Output-Slot-Protokoll) +

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

+ Buffer-Provider-Protokoll ⟻ die öffentliche Schnittstelle +

+ +
+
+ + + + +

+ Buffer-Provider ⟻ konkrete Parametrisierung die dieses Protokoll unterstützt +

+ +
+
+ + + + +

+ Buffer-Stage ⟻ Steuerung der Protokoll-Phasen +

+ +
+
+ + + + +

+ Buffer-Store ⟻ Zugang zum Buffer-Speicher +

+ +
+
+ + + + +

+ Disposition  ⟻ Verfügung, Anordnung, Anweisung für konkreten Buffer-Gebrauch +

+ +
+
+
+ + + + +

+ dementsprechend vorläufig umordnen.... +

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

+ die dort anscheinend direkt für diesen Zweck eingebaut wurden... +

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

+ also die Basis-Impl des BufferProviders muß ohnehin eine Konfigurations-Möglichkeit bekommen, insofern nicht mehr der Konstruktor selber die Implementierungs-Komponenten erzeugen darf. Deshalb könnte man die gesamte bisherige Struktur erhalten, und hätte dann erst mal aufgedoppelte Vererbungs-Ketten, die dann in einem zweiten Schritt aufzuräumen wären. +

+ +
+ + + + + + + + +

+ Per Dekret wird festgestellt: alles was bisher in Subklassen passiert ist, war letztlich Implementierung der Speicherverwaltung. Also wird es ohne Rücksicht auf Verluste in die Implementierungsklasse des BufferStore gedrückt. Daraufhin brechen praktisch alle Verwendungen und müssen schrittweise repariert werden. Am Ende befindet sich der ganze Müll im HeapMemProvider. Und so wollte ich es ja — um dann das Tracking gar nicht mehr verstehen zu müssen, sondern direkt sauber neu zu implementieren. +

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

+ ...da sind wir wieder bei dem Thema mit einer kompletten Trennung von Interface und Implementierung: eine solche Trennung würde mich zwingen, alle Methoden entweder virtuell zu machen, oder komplett aufzudoppeln. Ich werde den code behind einfach nicht los (und das liegt auch daran, daß eigentlich ein Protokoll implementiert wird). Andererseits will ich keinesfalls die Implementierungs-Interfaces public machen +

+ +
+
+ + + + +

+ also muß ich erstmal in die saure Matrjoska-Variante beißen +

+ +
+
+ + + + + + + + + + + + + + +
+
@@ -111494,7 +111721,10 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + + + + @@ -111626,6 +111856,39 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) + + + + + + + + +
    +
  • + »Buffer-Provider-Protokoll« ⟻ die öffentliche Schnittstelle +
  • +
  • + »Buffer-Provider« ⟻ konkrete Parametrisierung die dieses Protokoll unterstützt +
  • +
  • + »Buffer-Stage« ⟻ Steuerung der Protokoll-Phasen +
  • +
  • + »Buffer-Store« ⟻ Zugang zum Buffer-Speicher +
  • +
  • + »Disposition«  ⟻ Verfügung, Anordnung, Anweisung für konkreten Buffer-Gebrauch +
  • +
+ +
+
+ + + + +
@@ -144991,7 +145254,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
- + @@ -149426,7 +149689,7 @@ std::cout << tmpl.render({"what", "World"}) << s - + @@ -150041,7 +150304,7 @@ std::cout << tmpl.render({"what", "World"}) << s - + @@ -150922,7 +151185,7 @@ std::cout << tmpl.render({"what", "World"}) << s - + @@ -152072,7 +152335,9 @@ std::cout << tmpl.render({"what", "World"}) << s - + + + @@ -152156,11 +152421,46 @@ std::cout << tmpl.render({"what", "World"}) << s - + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -152194,7 +152494,7 @@ std::cout << tmpl.render({"what", "World"}) << s - + @@ -152204,7 +152504,7 @@ std::cout << tmpl.render({"what", "World"}) << s - + @@ -153776,8 +154076,11 @@ std::cout << tmpl.render({"what", "World"}) << s + + + - +