BufferProvider: investigate and fix broken allocation

Since the BufferStore implementation component is now supposed
to handle only the memory allocation, a complete end-to end data flow
must be ensured, so that allocation / deallocation functions get all
the relevant information. Notably, the `LocalTag` is now used as an
implementation-defined conduit for further (opaque) marker data.

Since all data passed over this API are simple values (even `LocalTag`
is effectively a 64bit integer), we can now avoid relying on output
parameters or similar side-effect tricks.
This commit is contained in:
Fischlurch 2026-02-13 00:36:45 +01:00
parent 75cda5ebc6
commit c3ebade5d2
7 changed files with 44 additions and 27 deletions

View file

@ -138,10 +138,10 @@ namespace engine {
BufferProvider::lockBuffer (BuffDescr const& type)
{
REQUIRE (was_created_by_this_provider (type));
size_t buffSiz = getBufferSize (type);
LocalTag implMarker;
Buff& storage = bufferStore_->provideBuffer (buffSiz, type, implMarker);
return buildHandle (type, &storage, implMarker);
metadata::Entry& metaEntry = bufferStage_->get (type);
size_t buffSiz = metaEntry.storageSize();
auto [storage, implMarker] = bufferStore_->provideBuffer (buffSiz, type, metaEntry.localTag());
return buildHandle (type, storage, implMarker);
}
@ -181,7 +181,8 @@ namespace engine {
metadata::Entry& metaEntry = bufferStage_->get (handle.entryID());
size_t buffSiz = metaEntry.storageSize();
metaEntry.mark(FREE); // might invoke embedded dtor function
bufferStore_->detachBuffer (buffSiz, metaEntry.parentKey(), metaEntry.localTag(), *handle);
bufferStore_->detachBuffer (buffSiz, metaEntry.parentKey()
,std::make_tuple (handle.rawStorage(), metaEntry.localTag()));
bufferStage_->release (metaEntry);
}
ERROR_LOG_AND_IGNORE (engine, "releasing a buffer from BufferProvider")
@ -226,7 +227,8 @@ namespace engine {
metadata::Entry& metaEntry = bufferStage_->get (target.entryID());
size_t buffSiz = metaEntry.storageSize();
metaEntry.invalidate (invokeDtor);
bufferStore_->detachBuffer (buffSiz, metaEntry.parentKey(), metaEntry.localTag(), *target);
bufferStore_->detachBuffer (buffSiz, metaEntry.parentKey()
,std::make_tuple (target.rawStorage(), metaEntry.localTag()));
bufferStage_->release (metaEntry);
}
ERROR_LOG_AND_IGNORE (engine, "cleanup of buffer metadata while handling an error")

View file

@ -112,6 +112,7 @@
#include <utility>
#include <memory>
#include <tuple>
namespace steam {
@ -200,13 +201,15 @@ namespace engine {
class BufferStore
: util::NonCopyable
{
protected:
using Slot = std::tuple<Buff*,LocalTag>;
public:
virtual ~BufferStore() { } ///< this is an interface
virtual uint prepareBuffers (uint cnt, size_t,HashVal typeID) =0;
virtual Buff& provideBuffer (size_t,HashVal typeID, LocalTag&) =0;
virtual void mark_emitted (size_t,HashVal, LocalTag const&) =0;
virtual void detachBuffer (size_t,HashVal, LocalTag, Buff&) =0;
virtual uint prepareBuffers (uint cnt, size_t,HashVal typeID) =0;
virtual Slot provideBuffer (size_t,HashVal typeID, LocalTag) =0;
virtual void mark_emitted (size_t,HashVal, LocalTag const&) =0;
virtual void detachBuffer (size_t,HashVal, Slot alloc) =0;
};
unique_ptr<BufferStage> bufferStage_; ///////////////////////////////////////////////////////////TICKET #1410 : must be turned into an internal interface

View file

@ -141,14 +141,11 @@ namespace engine {
template<typename BU>
BU& accessAs();
//////////////////////////////////////////TICKET #249 this operator looks obsolete. The Buff type is a placeholder type,
//////////////////////////////////////////TODO it should never be accessed directly from within Lumiera engine code
Buff&
operator* () const
Buff*
rawStorage() const
{
ENSURE (pBuffer_);
return *pBuffer_;
return pBuffer_;
}
operator HashVal() const { return descriptor_; }

View file

@ -288,13 +288,13 @@ namespace engine {
}
Buff&
HeapMemProvider::provideBuffer (size_t buffSiz, HashVal typeID, LocalTag&)
BufferProviderSetup::Store::Slot
HeapMemProvider::provideBuffer (size_t buffSiz, HashVal typeID, LocalTag)
{
BlockPool& blocks = getBlockPoolFor (buffSiz, typeID);
Block& newBlock = blocks.createBlock();
LocalTag specifics{&newBlock}; // used by this implementation to find the storage to release later
return * asBuffer(newBlock.accessMemory());
return std::make_tuple (asBuffer(newBlock.accessMemory()), specifics);
}
@ -320,8 +320,9 @@ namespace engine {
/** mark a buffer as officially discarded */
void
HeapMemProvider::detachBuffer (size_t buffSiz, HashVal typeID, LocalTag specifics, Buff& storage)
HeapMemProvider::detachBuffer (size_t buffSiz, HashVal typeID, Slot alloc)
{
auto& [storage, specifics] = alloc;
Block* block4buffer = locateBlock (buffSiz, typeID, specifics);
REQUIRE (block4buffer, "releasing a buffer not allocated through this provider");
REQUIRE (util::isSameAdr (storage, block4buffer->accessMemory()));

View file

@ -84,9 +84,9 @@ namespace engine {
/* === BufferStore interface === */
virtual uint prepareBuffers (uint cnt, size_t,HashVal typeID) override;
virtual Buff& provideBuffer (size_t,HashVal, LocalTag&) override;
virtual void mark_emitted (size_t,HashVal, LocalTag const&) override;
virtual void detachBuffer (size_t,HashVal, LocalTag, Buff&) override;
virtual Slot provideBuffer (size_t,HashVal, LocalTag) override;
virtual void mark_emitted (size_t,HashVal, LocalTag const&) override;
virtual void detachBuffer (size_t,HashVal, Slot alloc) override;
public:
~HeapMemProvider();

View file

@ -257,7 +257,7 @@ namespace test {
CHECK (m1.outBuff[0].accessAs<long>() == -55);
m1.connect(); // instruct the manifold to connect buffers to arguments
CHECK (isSameAdr (m1.outArgs, *buff));
CHECK (isSameAdr (m1.outArgs, buff.rawStorage()));
CHECK (*m1.outArgs == -55);
m1.invoke(); // invoke the adapted processing function (fun_singleOut)
@ -295,8 +295,8 @@ namespace test {
// connect arguments to buffers
m2.connect();
CHECK (isSameAdr (m2.inArgs, *buff));
CHECK (isSameAdr (m2.outArgs, *buffOut));
CHECK (isSameAdr (m2.inArgs, buff.rawStorage()));
CHECK (isSameAdr (m2.outArgs, buffOut.rawStorage()));
CHECK (*m2.outArgs == -55); ////////////////////////////////OOO should be -99
m2.invoke();

View file

@ -111868,8 +111868,11 @@ StM_bind(Builder&lt;R1&gt; b1, Extension&lt;R1,R2&gt; extension)
<node BACKGROUND_COLOR="#fafe99" COLOR="#fa002a" CREATED="1770835660209" ID="ID_1699942357" MODIFIED="1770835664104" TEXT="BufferProviderProtocol_test">
<icon BUILTIN="broken-line"/>
</node>
<node BACKGROUND_COLOR="#fafe99" COLOR="#fa002a" CREATED="1770935307254" ID="ID_1256898924" MODIFIED="1770935316691" TEXT="DiagnosticBufferProvider_test">
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1770935307254" ID="ID_1256898924" MODIFIED="1770947504816" TEXT="DiagnosticBufferProvider_test">
<icon BUILTIN="broken-line"/>
<node BACKGROUND_COLOR="#eae2af" COLOR="#690f14" CREATED="1770947507396" ID="ID_1663548893" MODIFIED="1770947541484" TEXT="l&#xe4;uft nun bis auf fehlendes Tracking...">
<font NAME="SansSerif" SIZE="11"/>
</node>
</node>
<node COLOR="#2c619a" CREATED="1770835671749" ID="ID_661880079" MODIFIED="1770939247723" TEXT="der buildHandle()-Aufruf mu&#xdf; entflochten werden">
<arrowlink COLOR="#3a91fe" DESTINATION="ID_1511113078" ENDARROW="Default" ENDINCLINATION="243;15;" ID="Arrow_ID_1668459979" STARTARROW="None" STARTINCLINATION="820;0;"/>
@ -112690,6 +112693,17 @@ StM_bind(Builder&lt;R1&gt; b1, Extension&lt;R1,R2&gt; extension)
</richcontent>
</node>
</node>
<node COLOR="#435e98" CREATED="1770947363915" ID="ID_1352298488" MODIFIED="1770947427286" TEXT="aber ein Zwischending...">
<icon BUILTIN="yes"/>
<node CREATED="1770947376890" ID="ID_2121271" MODIFIED="1770947388988" TEXT="Slot = tuple&lt;Buffer*, LocalTag&gt;">
<node CREATED="1770947436245" ID="ID_1453619086" MODIFIED="1770947451096" TEXT="damit generell: Buffer* verwenden">
<font NAME="SansSerif" SIZE="11"/>
</node>
<node CREATED="1770947452831" ID="ID_263962280" MODIFIED="1770947477138" TEXT="BuffHandle::rawStorage()"/>
</node>
<node CREATED="1770947390336" ID="ID_1722157621" MODIFIED="1770947419160" TEXT="das wird von der Allokation erzeugt..."/>
<node CREATED="1770947399557" ID="ID_1598745754" MODIFIED="1770947411455" TEXT="und der de-Allokation wieder angeliefert"/>
</node>
</node>
</node>
</node>