diff --git a/src/steam/engine/buffer-metadata.hpp b/src/steam/engine/buffer-metadata.hpp index 6dfb85ac0..255aa4067 100644 --- a/src/steam/engine/buffer-metadata.hpp +++ b/src/steam/engine/buffer-metadata.hpp @@ -59,6 +59,7 @@ #include "lib/hash-value.h" #include "lib/util-foreach.hpp" #include "include/logging.h" +#include "steam/streamtype.hpp" #include "steam/engine/type-handler.hpp" #include "steam/engine/buffer-local-key.hpp" #include "lib/nocopy.hpp" @@ -76,6 +77,8 @@ namespace engine { namespace error = lumiera::error; namespace metadata { + using Buff = StreamType::ImplFacade::DataBuffer; + class Key; class Entry; } @@ -214,7 +217,7 @@ namespace engine { * For NULL buffer a copy of the parent is returned. */ static Key - forEntry (Key const& parent, const void* bufferAddr, LocalTag const& localTag =LocalTag::UNKNOWN) + forEntry (Key const& parent, const Buff* bufferAddr, LocalTag const& localTag =LocalTag::UNKNOWN) { Key newKey{parent}; // copy of parent as baseline if (nontrivial(localTag)) @@ -270,11 +273,11 @@ namespace engine { : public Key { BufferState state_; - void* buffer_; + Buff* buffer_; protected: Entry (Key const& parent - ,void* bufferPtr =nullptr + ,Buff* bufferPtr =nullptr ,LocalTag const& specialTag =LocalTag::UNKNOWN ) : Key{Key::forEntry (parent, bufferPtr, specialTag)} @@ -313,7 +316,7 @@ namespace engine { return state_; } - void* + Buff* access() { __must_not_be_NIL(); @@ -350,7 +353,7 @@ namespace engine { } Entry& - lock (void* newBuffer) + lock (Buff* newBuffer) { __must_be_FREE(); buffer_ = newBuffer; @@ -362,7 +365,7 @@ namespace engine { { if (buffer_ and invokeDtor) invokeEmbeddedDtor_and_clear(); - buffer_ = 0; + buffer_ = nullptr; state_ = FREE; return *this; } @@ -610,7 +613,7 @@ namespace engine { * @note might create/register a new Entry as a side-effect */ Key const& - key (Key const& parentKey, void* concreteBuffer, LocalTag const& specifics =LocalTag::UNKNOWN) + key (Key const& parentKey, metadata::Buff* concreteBuffer, LocalTag const& specifics =LocalTag::UNKNOWN) { Key derivedKey = Key::forEntry (parentKey, concreteBuffer, specifics); Entry* existing = table_.fetch (derivedKey); @@ -645,7 +648,7 @@ namespace engine { */ Entry& lock (Key const& parentKey - ,void* concreteBuffer + ,metadata::Buff* concreteBuffer ,LocalTag const& specifics =LocalTag::UNKNOWN ,bool onlyNew =false) { @@ -717,7 +720,7 @@ namespace engine { * created, but is marked as FREE */ Entry& - markLocked (Key const& parentKey, void* buffer, LocalTag const& specifics =LocalTag::UNKNOWN) + markLocked (Key const& parentKey, metadata::Buff* buffer, LocalTag const& specifics =LocalTag::UNKNOWN) { if (!buffer) throw error::Fatal{"Attempt to lock for a NULL buffer. Allocation floundered?" diff --git a/src/steam/engine/buffer-provider.cpp b/src/steam/engine/buffer-provider.cpp index 2c759e6a3..0763acdd8 100644 --- a/src/steam/engine/buffer-provider.cpp +++ b/src/steam/engine/buffer-provider.cpp @@ -102,7 +102,7 @@ namespace engine { * actual buffer, which is locked for exclusive use by one client. */ BuffHandle - BufferProvider::buildHandle (HashVal typeID, void* storage, LocalTag const& localTag) + BufferProvider::buildHandle (HashVal typeID, Buff* storage, LocalTag const& localTag) { metadata::Key& typeKey = meta_->get (typeID); metadata::Entry& entry = meta_->markLocked(typeKey, storage, localTag); @@ -189,7 +189,7 @@ namespace engine { try { metadata::Entry& metaEntry = meta_->get (handle.entryID()); metaEntry.mark(FREE); // might invoke embedded dtor function - detachBuffer (metaEntry.parentKey(), metaEntry.localTag()); + detachBuffer (metaEntry.parentKey(), metaEntry.localTag(), *handle); meta_->release (metaEntry); } ERROR_LOG_AND_IGNORE (engine, "releasing a buffer from BufferProvider") @@ -233,7 +233,7 @@ namespace engine { try { metadata::Entry& metaEntry = meta_->get (target.entryID()); metaEntry.invalidate (invokeDtor); - detachBuffer (metaEntry.parentKey(), metaEntry.localTag()); + detachBuffer (metaEntry.parentKey(), metaEntry.localTag(), *target); meta_->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 be0ced686..a4f2f32e1 100644 --- a/src/steam/engine/buffer-provider.hpp +++ b/src/steam/engine/buffer-provider.hpp @@ -88,13 +88,16 @@ namespace engine { 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 typeID, LocalTag const&) =0; - virtual void detachBuffer (HashVal typeID, LocalTag const&) =0; + virtual void mark_emitted (HashVal, LocalTag const&) =0; + virtual void detachBuffer (HashVal, LocalTag const&, Buff&) =0; public: @@ -131,7 +134,7 @@ namespace engine { size_t getBufferSize (HashVal typeID) const; protected: - BuffHandle buildHandle (HashVal typeID, void* storage, LocalTag const& =LocalTag::UNKNOWN); + BuffHandle buildHandle (HashVal typeID, Buff* storage, LocalTag const& =LocalTag::UNKNOWN); bool was_created_by_this_provider (BuffDescr const&) const; }; diff --git a/src/steam/engine/buffhandle.hpp b/src/steam/engine/buffhandle.hpp index cae55fb9a..c44919fa3 100644 --- a/src/steam/engine/buffhandle.hpp +++ b/src/steam/engine/buffhandle.hpp @@ -119,7 +119,7 @@ namespace engine { */ class BuffHandle { - typedef StreamType::ImplFacade::DataBuffer Buff; + using Buff = StreamType::ImplFacade::DataBuffer; ///< marker type for an actual data buffer BuffDescr descriptor_; Buff* pBuffer_; diff --git a/src/steam/engine/tracking-heap-block-provider.cpp b/src/steam/engine/tracking-heap-block-provider.cpp index 8bc7137b5..bd93ee4f0 100644 --- a/src/steam/engine/tracking-heap-block-provider.cpp +++ b/src/steam/engine/tracking-heap-block-provider.cpp @@ -49,9 +49,18 @@ namespace engine { namespace error = lumiera::error; + using Buff = StreamType::ImplFacade::DataBuffer; + namespace { // implementation helpers... + inline Buff* + asBuffer(void* mem) + {// type tag to mark memory address as Buffer + return static_cast (mem); + } + + using diagn::Block; /** helper to find Block entries @@ -247,7 +256,7 @@ namespace engine { { diagn::BlockPool& blocks = getBlockPoolFor (typeID); diagn::Block& newBlock = blocks.createBlock(); - return buildHandle (typeID, newBlock.accessMemory(), &newBlock); + return buildHandle (typeID, asBuffer(newBlock.accessMemory()), &newBlock); } @@ -265,10 +274,11 @@ namespace engine { /** mark a buffer as officially discarded */ void - TrackingHeapBlockProvider::detachBuffer (HashVal typeID, LocalTag const& specifics) + TrackingHeapBlockProvider::detachBuffer (HashVal typeID, LocalTag const& specifics, Buff& storage) { diagn::Block* block4buffer = locateBlock (typeID, specifics); REQUIRE (block4buffer, "releasing a buffer not allocated through this provider"); + REQUIRE (util::isSameObject(storage, block4buffer->accessMemory())); block4buffer->markReleased(); } diff --git a/src/steam/engine/tracking-heap-block-provider.hpp b/src/steam/engine/tracking-heap-block-provider.hpp index f0e30671b..f46104b13 100644 --- a/src/steam/engine/tracking-heap-block-provider.hpp +++ b/src/steam/engine/tracking-heap-block-provider.hpp @@ -134,10 +134,10 @@ namespace engine { public: /* === BufferProvider interface === */ - virtual uint prepareBuffers (uint count, HashVal typeID); - virtual BuffHandle provideLockedBuffer (HashVal typeID); - virtual void mark_emitted (HashVal entryID, LocalTag const&); - virtual void detachBuffer (HashVal entryID, LocalTag const&); + virtual uint prepareBuffers (uint count, HashVal typeID) override; + virtual BuffHandle provideLockedBuffer (HashVal typeID) override; + virtual void mark_emitted (HashVal, LocalTag const&) override; + virtual void detachBuffer (HashVal, LocalTag const&, Buff&) override; public: TrackingHeapBlockProvider(); diff --git a/tests/core/steam/engine/buffer-metadata-test.cpp b/tests/core/steam/engine/buffer-metadata-test.cpp index 52cb796be..3ad3dca00 100644 --- a/tests/core/steam/engine/buffer-metadata-test.cpp +++ b/tests/core/steam/engine/buffer-metadata-test.cpp @@ -28,12 +28,10 @@ #include "lib/error.hpp" #include "lib/test/run.hpp" #include "lib/test/test-helper.hpp" -#include "lib/util.hpp" #include "steam/engine/buffer-metadata.hpp" #include "steam/engine/testframe.hpp" +#include "lib/util.hpp" -#include -#include #include using std::strncpy; @@ -54,15 +52,6 @@ namespace test { namespace { // Test fixture - const size_t TEST_MAX_SIZE = 1024 * 1024; - - const size_t SIZE_A = 1 + rand() % TEST_MAX_SIZE; - const size_t SIZE_B = 1 + rand() % TEST_MAX_SIZE; - - HashVal JUST_SOMETHING = 123; - void* const SOME_POINTER = &JUST_SOMETHING; - - template TY& accessAs (metadata::Entry& entry) @@ -71,6 +60,23 @@ namespace test { ASSERT (ptr); return *ptr; } + + template + metadata::Buff* + mark_as_Buffer(X& something) + { + return reinterpret_cast (std::addressof(something)); + } + + + const size_t TEST_MAX_SIZE = 1024 * 1024; + + const size_t SIZE_A = 1 + rand() % TEST_MAX_SIZE; + const size_t SIZE_B = 1 + rand() % TEST_MAX_SIZE; + + HashVal JUST_SOMETHING = 123; + auto SOME_POINTER = mark_as_Buffer(JUST_SOMETHING); + }//(End) Test fixture and helpers @@ -214,7 +220,7 @@ namespace test { // embedded into a Buffer Descriptor... // later, when it comes to actually *locking* those buffers... - typedef char RawBuffer[SIZE_B]; + using RawBuffer = std::byte; void* storage = malloc (2*SIZE_B); // do the necessary memory allocations behind the scenes... @@ -222,12 +228,12 @@ namespace test { TestFrame* frames = new TestFrame[3]; // a real-world BufferProvider would use some kind of allocator // track individual buffers by metadata entries - metadata::Entry& f0 = meta_->markLocked(bufferType1, &frames[0]); - metadata::Entry& f1 = meta_->markLocked(bufferType1, &frames[1]); - metadata::Entry& f2 = meta_->markLocked(bufferType1, &frames[2]); + metadata::Entry& f0 = meta_->markLocked(bufferType1, mark_as_Buffer(frames[0])); + metadata::Entry& f1 = meta_->markLocked(bufferType1, mark_as_Buffer(frames[1])); + metadata::Entry& f2 = meta_->markLocked(bufferType1, mark_as_Buffer(frames[2])); - metadata::Entry& r0 = meta_->markLocked(rawBuffType, &rawbuf[0]); - metadata::Entry& r1 = meta_->markLocked(rawBuffType, &rawbuf[1]); + metadata::Entry& r0 = meta_->markLocked(rawBuffType, mark_as_Buffer(rawbuf[ 0])); + metadata::Entry& r1 = meta_->markLocked(rawBuffType, mark_as_Buffer(rawbuf[SIZE_B])); CHECK (LOCKED == f0.state()); CHECK (LOCKED == f1.state()); @@ -241,12 +247,13 @@ namespace test { CHECK (transaction2 == r0.localTag()); CHECK (transaction2 == r1.localTag()); + auto adr =[](auto* x){ return reinterpret_cast(x); }; - CHECK (f0.access() == frames+0); - CHECK (f1.access() == frames+1); - CHECK (f2.access() == frames+2); - CHECK (r0.access() == rawbuf+0); - CHECK (r1.access() == rawbuf+1); + CHECK (adr(f0.access()) == adr(frames+0)); + CHECK (adr(f1.access()) == adr(frames+1)); + CHECK (adr(f2.access()) == adr(frames+2)); + CHECK (adr(r0.access()) == adr(rawbuf+0 )); + CHECK (adr(r1.access()) == adr(rawbuf+SIZE_B)); TestFrame defaultFrame; CHECK (defaultFrame == f0.access()); @@ -359,8 +366,8 @@ namespace test { VERIFY_ERROR (FATAL, entry.mark(NIL) ); // re-use buffer slot, start new lifecycle - void* OTHER_LOCATION = this; - entry.lock (OTHER_LOCATION); + auto* SOME_OTHER_LOCATION = mark_as_Buffer(*this); + entry.lock (SOME_OTHER_LOCATION); CHECK (LOCKED == entry.state()); CHECK (entry.isLocked()); @@ -373,7 +380,7 @@ namespace test { VERIFY_ERROR (FATAL, entry.mark(BLOCKED) ); VERIFY_ERROR (FATAL, entry.mark(NIL) ); - CHECK (OTHER_LOCATION == entry.access()); + CHECK (SOME_OTHER_LOCATION == entry.access()); entry.mark (FREE); CHECK (!entry.isLocked()); diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 4d4c28beb..f58d08831 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -4882,9 +4882,7 @@ - - - +

es wäre denkbar, an dieser Stelle @@ -4923,9 +4921,7 @@ - - - +

denn es erzwingt, @@ -4965,9 +4961,7 @@ - - - +

reine ID-Wirtschaft wäre möglich @@ -5502,9 +5496,7 @@ - - - +

...und Inkscape wird das erhalten, solange man die betr. Features nicht wieder aktiviert. Im Besonderen kann man @@ -6406,9 +6398,7 @@ - - - +

  • @@ -8003,9 +7993,7 @@ - - - +

    Innerhalb einer Kinder-Folge gibt es keine duplikaten IDs. @@ -10273,9 +10261,7 @@ - - - +

    ...das war nur ein unnötiger Fix nach dem Gießkannen-Prinzip. @@ -13652,9 +13638,7 @@ - - - +

    nur eingeschränkt auf die TypID? @@ -52461,9 +52445,7 @@ - - - +

    invocationTral wurde aufgegeben. @@ -52483,9 +52465,7 @@ - - - +

    allerdings, wenn man eine explizite Instanz-ID angibt, @@ -52503,9 +52483,7 @@ - - - +

    das heißt, es geht um die Haupt-Registry für Commands. @@ -88789,9 +88767,97 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
    ...und zwar je nachdem, in welcher Reihenfolge das LocalTag und die Buffer-Adresse gegeben waren: war das LocalTag zuerst da, dann würde das bereits Teil des Hash; wenn dann später jemand mit der gleichen Buffer-Adresse ankommt, aber ohne das LocalTag, dann wird der bestehende (schlimmstenfalls bereits gelockte) Eintrag nicht gefunden ⟹ es wird ein neuer Eintrag erzeugt und somit zweimal gelockt.

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

    + ...da mit jedem Buffer-Typ auch eine bestimmte Memory-Block-Größe verbunden ist, könnte man dahinter mehrere kachelnde Basis-Allokatoren anordnen — und in einer solchen Struktur wäre es sinnvoll, zu erwartende Buffer-Allokationen im Voraus anzukündigen. Die Steuerung der Pool-Größe könnte dann im Hintergrund erfolgen, was möglicherweise eine relevante Optimierung auf Durchsatz ermöglicht +

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

    + anhand der Hash-ID, die zum Entry gehört, welcher beim Erzeugen des Handles gespeichert wurde +

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

    + der Entry wird aus der Metadaten-Tabelle gelöscht +

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