Invocation: analyse usage of buffer metadata entries
Code clean-up: mark all buffers with a dedicated tagging type The point in question is: if we work the LocalTag into the type-hash, could it be possible to miss an existing entry in the metadata registry? This could cause two entries to be locked for a single buffer address, leading to data corruption. As far as I can see, in the current usage this would not happen, but unfortunately this problem can not be ruled out, since the BufferProvider API and protocol is designed to be open for various usage patterns. However, the same potentially disastrous pattern could also materialise when registering two different buffer types, and then locking each for the same buffer location.
This commit is contained in:
parent
72c7386435
commit
9a23aa773b
8 changed files with 170 additions and 81 deletions
|
|
@ -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?"
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
|
|
|
|||
|
|
@ -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<Buff*> (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();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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 <cstdlib>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
|
||||
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<typename TY>
|
||||
TY&
|
||||
accessAs (metadata::Entry& entry)
|
||||
|
|
@ -71,6 +60,23 @@ namespace test {
|
|||
ASSERT (ptr);
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
template<typename X>
|
||||
metadata::Buff*
|
||||
mark_as_Buffer(X& something)
|
||||
{
|
||||
return reinterpret_cast<metadata::Buff*> (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<size_t>(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());
|
||||
|
|
|
|||
|
|
@ -4882,9 +4882,7 @@
|
|||
<node CREATED="1482464758148" ID="ID_545671857" MODIFIED="1518487921059" TEXT="triggert sofort"/>
|
||||
<node CREATED="1492205571235" ID="ID_166892291" MODIFIED="1576282358143" TEXT="Zukunft: partiell schließen">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
es wäre denkbar, an dieser Stelle
|
||||
|
|
@ -4923,9 +4921,7 @@
|
|||
</node>
|
||||
<node CREATED="1482466509953" ID="ID_565604124" MODIFIED="1576282358143" TEXT="...dient der Sicherheit">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
denn es erzwingt,
|
||||
|
|
@ -4965,9 +4961,7 @@
|
|||
</node>
|
||||
<node CREATED="1482466587807" ID="ID_135147405" MODIFIED="1518487921059">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
reine ID-Wirtschaft <i>wäre möglich</i>
|
||||
|
|
@ -5502,9 +5496,7 @@
|
|||
</node>
|
||||
<node CREATED="1665801312049" ID="ID_904420529" MODIFIED="1665801548562" TEXT="Styles kann man bisweilen vereinfachen">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
...und Inkscape wird das erhalten, solange man die betr. Features nicht wieder aktiviert. Im Besonderen kann man
|
||||
|
|
@ -6406,9 +6398,7 @@
|
|||
</node>
|
||||
<node CREATED="1563020429008" ID="ID_873763889" MODIFIED="1678461929265" TEXT="Delegate herausgelöst: UIStyle">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<ul>
|
||||
<li>
|
||||
|
|
@ -8003,9 +7993,7 @@
|
|||
<icon BUILTIN="yes"/>
|
||||
<node CREATED="1508540093004" ID="ID_277252077" MODIFIED="1576282358124" TEXT="Kinder-IDs sind eindeutig">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
Innerhalb einer Kinder-Folge gibt es keine duplikaten IDs.
|
||||
|
|
@ -10273,9 +10261,7 @@
|
|||
</body>
|
||||
</html></richcontent>
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
...das war nur ein unnötiger Fix nach dem Gießkannen-Prinzip.
|
||||
|
|
@ -13652,9 +13638,7 @@
|
|||
<icon BUILTIN="hourglass"/>
|
||||
<node CREATED="1518830375356" ID="ID_580870700" MODIFIED="1518830460134">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
<i>nur eingeschränkt</i> auf die TypID?
|
||||
|
|
@ -52461,9 +52445,7 @@
|
|||
<node CREATED="1491005078409" ID="ID_1515823316" MODIFIED="1492391288793" TEXT="...muß ich wissen, wie newInstance verwendet wird"/>
|
||||
<node CREATED="1491005491226" ID="ID_1986906306" MODIFIED="1576282357983" TEXT="und das hängt von InvocationTrail ab">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
invocationTral wurde aufgegeben.
|
||||
|
|
@ -52483,9 +52465,7 @@
|
|||
<node CREATED="1492391227720" ID="ID_475537616" MODIFIED="1492391288793" TEXT="d.h. eine reine Command-ID wird stillschweigend geklont"/>
|
||||
<node CREATED="1492391240086" ID="ID_687060412" MODIFIED="1492391288793">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
allerdings, wenn man eine <b>explizite</b> Instanz-ID angibt,
|
||||
|
|
@ -52503,9 +52483,7 @@
|
|||
<icon BUILTIN="help"/>
|
||||
<node CREATED="1491494779796" ID="ID_1437580350" MODIFIED="1576282357982" TEXT="oder nur Prototypen?">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
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<br/>
|
|||
...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 <b>zweimal gelockt.</b>
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<icon BUILTIN="broken-line"/>
|
||||
<node BACKGROUND_COLOR="#f8f1cb" COLOR="#a50125" CREATED="1722174380744" ID="ID_267908880" MODIFIED="1722174427410" TEXT="Zielkonflikt im Rahmen des bestehenden Systems">
|
||||
<icon BUILTIN="clanbomber"/>
|
||||
<node CREATED="1722174447615" ID="ID_1522763793" MODIFIED="1722174491095" TEXT="Anforderung-1 : für eine Buffer-Addresse darf es höchstens einen Eintrag geben"/>
|
||||
<node CREATED="1722174500520" ID="ID_1587953083" MODIFIED="1722174647262" TEXT="Anforderung-2 : (abstrakter)Typ-Eintrag wird durch LocalTag differenziert"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1722183960753" ID="ID_1728122357" MODIFIED="1722187113886" TEXT="mögliche Lösung: LocalTag nur für abstrakte Einträge in den Hash aufnehmen">
|
||||
<icon BUILTIN="idea"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#f8f1cb" COLOR="#a50125" CREATED="1722174881847" ID="ID_1281056403" MODIFIED="1722174898085" TEXT="die Bedeutung der abstrakten Typ-Einträge ist unklar">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
<node CREATED="1722174903945" ID="ID_244030292" MODIFIED="1722174919751" TEXT="derzeit zeichnet sich ab, sie für Buffer-Descriptoren zu verwenden"/>
|
||||
<node CREATED="1722174958776" ID="ID_1387037031" MODIFIED="1722175397721" TEXT="später einmal könnte auf dieser Basis auch ein Memory-Block-Pool verwaltet werden">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
...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 <b>im Voraus anzukündigen</b>. Die Steuerung der Pool-Größe könnte dann im Hintergrund erfolgen, was <i>möglicherweise eine relevante Optimierung auf Durchsatz</i> ermöglicht
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1722175400457" ID="ID_299028104" MODIFIED="1722175484518" TEXT="hierzu wäre eine Betrachtung des Buffer-Lebenszyklus notwengig">
|
||||
<icon BUILTIN="hourglass"/>
|
||||
<node CREATED="1722175526112" ID="ID_80353444" MODIFIED="1722178333993" TEXT="was passiert nach dem Ende einer Buffer-Verwendung?">
|
||||
<icon BUILTIN="help"/>
|
||||
<node CREATED="1722178721896" ID="ID_1494898122" MODIFIED="1722178748459" TEXT="BufferProvider::releaseBuffer(BuffHandle)">
|
||||
<node CREATED="1722178755399" ID="ID_46030515" MODIFIED="1722178782104" TEXT="findet den Entry">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
anhand der Hash-ID, die zum Entry gehört, welcher beim Erzeugen des Handles gespeichert wurde
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
<node CREATED="1722178787002" ID="ID_1918650261" MODIFIED="1722178803804" TEXT="überführt ihn ⟼ FREE">
|
||||
<node CREATED="1722178807616" ID="ID_66134104" MODIFIED="1722178819618" TEXT="attached-dtor">
|
||||
<font NAME="SansSerif" SIZE="11"/>
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1722178828605" ID="ID_866216305" MODIFIED="1722178839388" TEXT="virtual : detachBuffer"/>
|
||||
<node CREATED="1722178863904" ID="ID_420990968" MODIFIED="1722178895514">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
der Entry wird aus der Metadaten-Tabelle <b>gelöscht</b>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1722175512970" ID="ID_771752357" MODIFIED="1722183934557" TEXT="welche Einträge durchlaufen welche Lebenszyklus-Phasen?">
|
||||
<icon BUILTIN="help"/>
|
||||
<node CREATED="1722183802974" ID="ID_558175102" MODIFIED="1722183818351" TEXT="abstrakte Typ-Einträge bleiben im Status FREE"/>
|
||||
<node CREATED="1722183840449" ID="ID_817136084" MODIFIED="1722183914707" TEXT="Einträge mit Speicheradresse laufen LOCKED ⟼ EMITTED | BLOCKED ⟼ FREE ⟼ (gelöscht)"/>
|
||||
</node>
|
||||
<node CREATED="1722183936308" ID="ID_1490912654" MODIFIED="1722183942726" TEXT="vorläufige Analyse">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#fed399" COLOR="#fa002a" CREATED="1722187122172" ID="ID_1081153017" MODIFIED="1722187151227" TEXT="AUA: das ist ein grundätzliches Problem">
|
||||
<icon BUILTIN="broken-line"/>
|
||||
<node CREATED="1722187174269" ID="ID_1527056830" MODIFIED="1722187190070" TEXT="man könnte nämlich auch mit zwei verschiedenen BufferTypes einsteigen"/>
|
||||
<node CREATED="1722187190971" ID="ID_1915656776" MODIFIED="1722187217883" TEXT="damit bekäme man jeweils einen separaten Hash und Entry"/>
|
||||
<node CREATED="1722187254401" ID="ID_1600797508" MODIFIED="1722187297320" TEXT="man könnte nun jedem die jeweils gleiche Adresse zuordnen"/>
|
||||
<node CREATED="1722187298244" ID="ID_1405182769" MODIFIED="1722187322085" TEXT="und dann jeden Eintrag locken, ohne daß die Metadatenverlwaltung Alarm schlägt"/>
|
||||
<node CREATED="1722187373789" ID="ID_1380501144" MODIFIED="1722187434046" TEXT="wenn sich aber die Implementierung an das implizierte Protokoll hält ⟹ keine Gefahr">
|
||||
<node CREATED="1722187437073" ID="ID_967644037" MODIFIED="1722187460993" TEXT="die Impl. kann den State zu einer Adresse nicht wissen"/>
|
||||
<node CREATED="1722187463676" ID="ID_1266347109" MODIFIED="1722187482519" TEXT="erwartet wird, daß sie für jede Anfrage eine neue Adresse belegt"/>
|
||||
<node CREATED="1722187483627" ID="ID_1498778966" MODIFIED="1722187504963" TEXT="und nur Adressen wiederverwendet, die per detachBuffer() zurückgegeben wurden"/>
|
||||
</node>
|
||||
</node>
|
||||
<node COLOR="#435e98" CREATED="1722187531132" ID="ID_849426679" MODIFIED="1722187575744" TEXT="Fazit">
|
||||
<font BOLD="true" NAME="SansSerif" SIZE="12"/>
|
||||
<icon BUILTIN="forward"/>
|
||||
<node CREATED="1722187535395" ID="ID_9598554" MODIFIED="1722187568052" TEXT="Gefahr besteht — ist aber aktuell nicht virulent"/>
|
||||
<node CREATED="1722187540798" ID="ID_120157543" MODIFIED="1722187552833" TEXT="es gibt aber ein implizites Implementierungs-Protokoll"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1722187577286" ID="ID_439948385" MODIFIED="1722187586617" TEXT="Ticket aufmachen">
|
||||
<icon BUILTIN="yes"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
|
|
|
|||
Loading…
Reference in a new issue