From 9b6933b572f8c078609303f10c344504e0c87615 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Tue, 17 Mar 2026 00:35:54 +0100 Subject: [PATCH] OutputSlot: consider how to integrate the proxy provider ...which still looks like a nasty task * the good part is, we have a working `BufferProxyAdaptor` now * yet this setup does not seem to fit into the `OutputSlot::AllocState` As an aside, several test definitions need to be relocated to the Vault, since the whole compound around `BufferProvider` migrated down --- src/vault/mem/buffer-proxy-adaptor.hpp | 18 ++++++--- ...ault-memory.tests => 31vault-memory.tests} | 0 tests/47engine.tests | 2 +- ...test.cpp => buffer-proxy-adaptor-test.cpp} | 28 +++++++------ wiki/thinkPad.ichthyo.mm | 40 +++++++++++++------ 5 files changed, 57 insertions(+), 31 deletions(-) rename tests/{11vault-memory.tests => 31vault-memory.tests} (100%) rename tests/vault/mem/{output-proxy-provider-test.cpp => buffer-proxy-adaptor-test.cpp} (73%) diff --git a/src/vault/mem/buffer-proxy-adaptor.hpp b/src/vault/mem/buffer-proxy-adaptor.hpp index e2321c967..131c42685 100644 --- a/src/vault/mem/buffer-proxy-adaptor.hpp +++ b/src/vault/mem/buffer-proxy-adaptor.hpp @@ -86,20 +86,21 @@ namespace mem { BuffAlloc provideBuffer (HashVal,size_t siz,LocalTag targetMarker) override { - CONF::on_lock(); - return {asBuffer(targetMarker), siz, targetMarker}; + BuffAlloc storageSlot{asBuffer(targetMarker), siz, targetMarker}; + CONF::on_lock (storageSlot); + return storageSlot; } void mark_emitted (HashVal, BuffAlloc storageSlot) override { - CONF::on_emit(); + CONF::on_emit (storageSlot); } void detachBuffer (HashVal, BuffAlloc storageSlot) override { - CONF::on_release(); + CONF::on_release (storageSlot); } public: @@ -142,11 +143,18 @@ namespace mem { : proxyProvider_{Setup{move(policy)}} { } + template + BuffDescr + getDescriptorFor (TAR& dataBlock) + { + return proxyProvider_.registerBuffer(&dataBlock, sizeof(TAR)); + } + template BuffHandle lockBuffer (TAR& dataBlock) { - BuffDescr buffType = proxyProvider_.registerBuffer(&dataBlock, sizeof(TAR)); + BuffDescr buffType = getDescriptorFor (dataBlock); ENSURE (buffType.isValid()); return buffType.lockBuffer(); } diff --git a/tests/11vault-memory.tests b/tests/31vault-memory.tests similarity index 100% rename from tests/11vault-memory.tests rename to tests/31vault-memory.tests diff --git a/tests/47engine.tests b/tests/47engine.tests index 0a9690d21..ff3948c01 100644 --- a/tests/47engine.tests +++ b/tests/47engine.tests @@ -27,7 +27,7 @@ return: 0 END -PLANNED "Proxy Buffer-provider" BufferProxyProvider_test < @@ -11,8 +11,8 @@ * *****************************************************************/ -/** @file output-proxy-provider-test.cpp - ** unit test \ref OutputProxyProvider_test +/** @file buffer-proxy-adaptorr-test.cpp + ** unit test \ref BufferProxyAdaptor_test */ @@ -37,12 +37,16 @@ namespace test { /***************************************************************//** - * @test verify the design of OutputSlot and BufferProvider by - * implementing a delegating BufferProvider to expose - * output data buffers provided from _some implementation._ - * @todo 2/2026 now using this setup for prototyping /////////////////////////////////////////////////TICKET #1415 : explore this design idea through prototyping + * @test demonstrate a configuration of the BufferProvider implementation, + * rigged such that a pre-existing given buffer (address) can be + * passed through and exposed as BuffHandle. + * @remark while this looks like a rather convoluted implementation setup, + * this feature is crucial to make the »Output Slot Protocol« + * mesh up well ([1415]) with the »Buffer Provider Protocol«, + * used internally within the Render Engine + * [1415]: https://issues.lumiera.org/ticket/1415] */ - class OutputProxyProvider_test : public Test + class BufferProxyAdaptor_test : public Test { virtual void run (Arg) @@ -51,9 +55,9 @@ namespace test { // setup with notification callback BufferProxyAdaptor proxPro{PropBuilder() - .define (PROP_FIELD(on_lock), [&]{ state = LOCKED; }) - .define (PROP_FIELD(on_emit), [&]{ state = EMITTED;}) - .define (PROP_FIELD(on_release),[&]{ state = FREE; }) + .define (PROP_FIELD(on_lock), [&](BuffAlloc){ state = LOCKED; }) + .define (PROP_FIELD(on_emit), [&](BuffAlloc){ state = EMITTED;}) + .define (PROP_FIELD(on_release),[&](BuffAlloc){ state = FREE; }) }; // Assuming some data block is »given« @@ -90,7 +94,7 @@ namespace test { /** Register this test class... */ - LAUNCHER (OutputProxyProvider_test, "unit play"); + LAUNCHER (BufferProxyAdaptor_test, "unit play"); diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 2e67d8384..c7503389e 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -115054,7 +115054,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + @@ -115179,8 +115179,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) Und damit spielt sich das System dann irgendwann auf einen festen Pool von Buffer-»Slots« ein, die permanent im Speicher bleiben. Allerdings bedeutet das dann für die Metadaten ein Cartesisches Produkt  zwischen der Zahl der Memory-Slots und der Zahl der verschiedenen Buffer-Typen....

- - +
@@ -115190,8 +115189,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) Ob das also gefährlich wird, oder eine etwas ausufernde Metadaten-Storage durchaus überkompensiert wird von dem Wegfall der permanenten Allokation/Deallokation (und Hashtable-Pflege), kann nicht auf theoretischer Ebene abgehandelt werden. Mehr noch: es ist sogar zweifelhaft, ob sich diese Frage überhaupt zuverlässig beantworten läßt, auch empirisch! Dazu müßte man einen Weg finden, um die Stabilität des Verhaltens zu beurteilen, über verschieden Nutzszenarien hinweg

- -
+
@@ -115201,8 +115199,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) Allerdings, wenn man sich darauf einläßt, Speicher nicht wegzuräumen, dann muß man explizit den Fall betrachten, daß der Speicher volläuft. In dem Fall bräuchte es einen »Sweep«, der über die Metadaten-Tabelle iteriert und alle Einträge pauschal löscht, die als FREE markiert sind. The usual trade-offs apply.

- -
+
@@ -115214,8 +115211,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) Einsicht: nicht re-Locking sondern das onlyNew ist hier redundant

- - + @@ -137523,8 +137519,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) fragwürdig ist im Besonderen der hierarchische Ansatz, der die konkreten Storage-Metadaten als Spezialisierung eines Typ-Eintrags behandelt.

- - +
@@ -137534,8 +137529,10 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) Im Besonderen stehen dort all die relevanten Infos, die jeder Memory-Allocator benötigt: die konkrete Adresse und die Size (möglicherweise sogar ein MRU-counter, oder ähnliche technische Informationen)

- -
+ + + +
@@ -138021,6 +138018,23 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) + + + + + + + + +

+ In der aktuellen Konfiguration hat jeder BufferProvider seine eigenes BufferStage-Implementierung, und darin eingebettet eine eigene Metadaten-Hashtable. Im Falle des BufferProxyAdaptors bedeutet das, für jede Allokation eines OutputSlot erneut eine Metadaten-Verwaltung zu konstruieren, die dann aber nur für wenige Buffer-Einträge genutzt wird. Da Output-Slots durchaus längerfristig leben, stellt das kein Performance-Problem da, aber könnte letztlich schon zu einigem Bloat führen +

+ + +
+ +
+