BufferProvider: establish a new buffer type from within a worker

This test setup defines one of the problematic situations
where a synchronisation is necessary.

__TODO__: actually add locking and that synchronisation to LocalBufferStage
This commit is contained in:
Fischlurch 2026-04-19 19:25:30 +02:00
parent 57cd51e3a2
commit 606d98bf9c
4 changed files with 130 additions and 18 deletions

View file

@ -502,6 +502,9 @@ namespace mem {
public:
~Table() { verify_all_buffers_freed(); }
size_t size() const { return entries_.size(); }
/** fetch metadata record, if any
* @param hashID for the Key part of the metadata entry
* @return pointer to the entry in the table or NULL
@ -721,6 +724,12 @@ namespace mem {
and entry->isAccessible();
}
size_t
cntEntries() const
{
return table_.size();
}
/* == memory management operations == */

View file

@ -89,7 +89,13 @@ namespace mem {
: registry_{}
{ }
size_t
cntEntries() const
{
return registry_.cntEntries();
}
bool
isKnown (HashVal metaID) const
{

View file

@ -18,26 +18,31 @@
#include "lib/error.hpp"
#include "test/run.hpp"
#include "test/test-frame.hpp"
//#include "test/test-frame.hpp"
#include "test/test-helper.hpp"
#include "vault/mem/buffhandle.hpp"
#include "vault/mem/engine-buffer-metadata.hpp"
#include "vault/mem/local-buffer-stage.hpp"
//#include "lib/uninitialised-storage.hpp"
#include "lib/depend-inject.hpp"
#include "lib/symbol.hpp"
#include "lib/thread.hpp"
//#include "lib/symbol.hpp"
#include "lib/util.hpp"
#include "test/diagnostic-output.hpp"////////////////TODO
#include <memory>
using std::strncpy;
using std::unique_ptr;
using test::TestFrame;
using test::testData;
using util::isSameObject;
using util::isnil;
using lib::randStr;
using lib::Literal;
//using std::strncpy;
//using std::unique_ptr;
//using test::TestFrame;
//using test::testData;
//using util::isSameObject;
//using util::isnil;
//using lib::randStr;
//using lib::Literal;
using std::this_thread::yield;
using lib::Thread;
namespace vault {
namespace mem {
@ -67,7 +72,11 @@ namespace test {
return reinterpret_cast<Buff*> (std::addressof(something));
}
// struct TestBuff
// : lib::UninitialisedStorage<TestFrame>
// {
//
// };
const size_t TEST_MAX_SIZE = 1024 * 1024;
HashVal JUST_SOMETHING = 123;
@ -107,7 +116,7 @@ namespace test {
const HashVal FAM = ranHash();
const size_t SIZ_D = sizeof(double);
const double RAND1 = 1.0 + defaultGen.uni();
const double RANDD = 1.0 + defaultGen.uni();
// create one type-key in Registry-1
metadata::Key keyD = meta1.key (FAM,SIZ_D);
@ -116,7 +125,7 @@ namespace test {
CHECK (meta1.get(keyD).isTypeKey());
// create another type-key in Registry-2, this time with a constructor
metadata::Key keyDD = meta2.key (FAM,SIZ_D, TypeHandler::create<double> (RAND1));
metadata::Key keyDD = meta2.key (FAM,SIZ_D, TypeHandler::create<double> (RANDD));
CHECK (meta2.isKnown (keyDD));
CHECK (not meta1.isKnown (keyDD));
CHECK (meta2.get(keyDD).isTypeKey());
@ -135,7 +144,7 @@ namespace test {
CHECK (eDD.state() == LOCKED);
CHECK (eDD.parentKey() == HashVal(keyDD));
// and the »constructor« was indeed invoked...
CHECK (testBuffer == RAND1);
CHECK (testBuffer == RANDD);
testBuffer += 1.1; // add marker...
// within the confines of allowed state transitions,
@ -147,7 +156,7 @@ namespace test {
CHECK (meta2.get(eDD).state() == LOCKED);
// importing the state record did not re-invoke the constructor
CHECK (testBuffer == RAND1 + 1.1);
CHECK (testBuffer == RANDD + 1.1);
meta2.get(eDD).mark(EMITTED);
CHECK (meta2.get(eDD).state() == EMITTED);
@ -173,12 +182,65 @@ namespace test {
}
/** @test simulate a standard buffer provider usage cycle
/** @test simulate a common buffer provider usage situation,
* whereby a local instance in some worker thread provides
* a new (or refined) buffer type.
* - create empty new EngineBufferMetadata end inject it as mock
* - use a free standing LocalBufferStage instance (instead of a BufferProvider)
* - launch a worker thread to conduct the test invocation of this subject
* - notably register a totally new buffer type, from within the worker
* - then also perform the steps necessary to lock and release a buffer
* - check that the new type was migrated into the central metadata hub
*/
void
verify_publishNewKey()
{
// provide a »central Metadata hub«
lib::DependInject<EngineBufferMetadata>::Local<EngineBufferMetadata> metaHub;
metaHub.triggerCreate();
CHECK (0 == metaHub->cntEntries());
// provide the test subject,
// which implements the BufferStage API
// and uses a thread-local metadata table internally
LocalBufferStage localStage{"verify_publishNewKey"};
BufferProviderSetup::Stage& stageAPI = localStage;
// setup information used for buffer type registration
const size_t SIZ_D = sizeof(double);
const double RANDD = 1.0 + defaultGen.uni();
const auto HANDLER = TypeHandler::create<double>(RANDD);
const LocalTag TAG{defaultGen.u64()};
HashVal metaID{0};
// this is our »allocated buffer«
double testBuffer{0};
Buff* alloc = mark_as_Buffer (testBuffer);
Thread testWorker{[&]
{
auto& typeKey = stageAPI.defineBufferType (SIZ_D, HANDLER, TAG);
metaID = HashVal(typeKey); // sneak out to verify later
// emulate allocation and usage of a buffer
BuffAlloc allocRecord{alloc, typeKey.storageSize(),typeKey.localTag()};
auto& stateKey = stageAPI.mark_locked (typeKey, allocRecord);
// verify the buffer constructor was applied
CHECK (testBuffer = RANDD);
// release the buffer...
stageAPI.mark_released (stateKey);
stageAPI.discard (stateKey);
}};
while (testWorker)
yield(); // wait for worker to finish
CHECK (0 != metaID);
SHOW_EXPR(metaHub->cntEntries());
/////////////////////////////////////////OOO verify the complete chain from the type key to the root
}

View file

@ -144525,7 +144525,11 @@ StM_bind(Builder&lt;R1&gt; b1, Extension&lt;R1,R2&gt; extension)
</richcontent>
</node>
</node>
<node CREATED="1776604670575" ID="ID_1448023528" MODIFIED="1776604672346" TEXT="Test">
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1776617913235" ID="ID_484033659" MODIFIED="1776617923691" TEXT="mu&#xdf; Synchronisationspunkt einschleifen">
<icon BUILTIN="flag-yellow"/>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1776604670575" ID="ID_1448023528" MODIFIED="1776619327263" TEXT="Test">
<icon BUILTIN="pencil"/>
<node COLOR="#338800" CREATED="1776604673415" ID="ID_1473562963" MODIFIED="1776612748341" TEXT="die zentralen EngineMetadata mocken">
<richcontent TYPE="NOTE"><html>
<head>
@ -144545,6 +144549,37 @@ StM_bind(Builder&lt;R1&gt; b1, Extension&lt;R1,R2&gt; extension)
<icon BUILTIN="ksmiletris"/>
</node>
</node>
<node COLOR="#338800" CREATED="1776617819504" ID="ID_1759039036" MODIFIED="1776617830911" TEXT="einen test-Thread(worker) bereitstellen">
<icon BUILTIN="button_ok"/>
</node>
<node COLOR="#338800" CREATED="1776617832875" ID="ID_1106246702" MODIFIED="1776617844968" TEXT="Daten f&#xfc;r Typ-Registrierung vorbereiten">
<icon BUILTIN="button_ok"/>
</node>
<node CREATED="1776617847069" ID="ID_1390721757" MODIFIED="1776617855687" TEXT="aus dem Thread einen Typ registrieren">
<node COLOR="#338800" CREATED="1776617861154" ID="ID_1231327024" MODIFIED="1776617886524" TEXT="Meta-Entry wurde im Thread angelegt">
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1776617887545" ID="ID_469498353" MODIFIED="1776619185986" TEXT="Metadaten wurden synchronisiert in den EngineBufferMetadata-Hub">
<icon BUILTIN="flag-pink"/>
</node>
</node>
<node CREATED="1776619194372" ID="ID_1251103269" MODIFIED="1776619205443" TEXT="au&#xdf;erdem die internen Schritte f&#xfc;r eine Allokation machen">
<node CREATED="1776619206646" ID="ID_419064528" MODIFIED="1776619213721" TEXT="aus BufferProvider kopieren..."/>
<node COLOR="#338800" CREATED="1776619214497" ID="ID_931246531" MODIFIED="1776619325326" TEXT="Buffer-Konstruktor wurde tats&#xe4;chlich aufgerufen">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
Ich verwende hier einen TypeHandler, der einen vorher im Test festgelegten random-double-Wert in den buffer pflanzt. Da wir bisher noch den Bug mit dem TypeHandler-Aliasing haben, gehat das &#187;knapp am Abgrund vorbei&#171; (aber wir verwenden ja eine komplett leere BufferMetadata registry....
</p>
</body>
</html>
</richcontent>
<icon BUILTIN="button_ok"/>
</node>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1776566459396" ID="ID_20651536" MODIFIED="1776604516229" TEXT="Verwendung im Thread &#x27f8; Typ aus Zentrale synchronisiert"/>