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:
parent
57cd51e3a2
commit
606d98bf9c
4 changed files with 130 additions and 18 deletions
|
|
@ -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 == */
|
||||
|
|
|
|||
|
|
@ -89,7 +89,13 @@ namespace mem {
|
|||
: registry_{}
|
||||
{ }
|
||||
|
||||
|
||||
|
||||
size_t
|
||||
cntEntries() const
|
||||
{
|
||||
return registry_.cntEntries();
|
||||
}
|
||||
|
||||
bool
|
||||
isKnown (HashVal metaID) const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -144525,7 +144525,11 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> 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ß 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<R1> b1, Extension<R1,R2> 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ü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ßerdem die internen Schritte fü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ä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 »knapp am Abgrund vorbei« (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 ⟸ Typ aus Zentrale synchronisiert"/>
|
||||
|
|
|
|||
Loading…
Reference in a new issue