BufferProvider: remove the lock-onlyNew feature
This might have seemed like a good idea, adding an additional ''consistency check''... However — we ''do have'' a generic check, insofar `BufferMetadata` is a **state engine**. As long as we're able to prevent, reliably, that the same buffer address ends up being classified as a different buffer type, this should be enough to prevent double-use of any buffer (letting aside that `BufferProvider` is backed by an implementing memory allocator, which in itself should prevent any double-use. Removing this feature resolves some ambiguity in the overall design, and allows to turn `BufferMetadata::lock(type, address)` into a private implementation function. In the old code, there were some external access paths directly entering into that implementation function, which caused a lot of confusion (at least for me...)
This commit is contained in:
parent
7463228d38
commit
94320d2d23
3 changed files with 119 additions and 15 deletions
|
|
@ -704,7 +704,7 @@ namespace mem {
|
|||
throw err::Fatal{"Attempt to lock for a NULL buffer. Allocation floundered?"
|
||||
, LERR_(BOTTOM_VALUE)};
|
||||
|
||||
return this->lock (parentKey, buffer, specifics, true); // force creation of a new entry
|
||||
return BufferMetadata::lock (parentKey, buffer, specifics);
|
||||
}
|
||||
|
||||
/** purge the bare metadata Entry from the metadata tables.
|
||||
|
|
@ -731,6 +731,7 @@ namespace mem {
|
|||
}
|
||||
|
||||
|
||||
private:
|
||||
/** Core low-level operation to access or create a buffer metadata entry.
|
||||
* The hashID of the entry in question is built, based on the parentKey,
|
||||
* which designates a buffer type, optionally an implementation defined
|
||||
|
|
@ -759,8 +760,7 @@ namespace mem {
|
|||
Entry&
|
||||
lock (Key const& parentKey
|
||||
,Buff* concreteBuffer
|
||||
,LocalTag const& specifics =LocalTag::UNKNOWN
|
||||
,bool onlyNew =false)
|
||||
,LocalTag const& specifics =LocalTag::UNKNOWN)
|
||||
{
|
||||
if (!concreteBuffer)
|
||||
throw err::Invalid{"Attempt to lock a slot for a NULL buffer"
|
||||
|
|
@ -769,10 +769,6 @@ namespace mem {
|
|||
Entry newEntry{parentKey, concreteBuffer, specifics};
|
||||
Entry* existing = table_.fetch (newEntry);
|
||||
|
||||
if (existing and onlyNew)
|
||||
throw err::Logic{"Attempt to lock a slot for a new buffer, "
|
||||
"while actually the old buffer is still locked"
|
||||
, LERR_(LIFECYCLE)};
|
||||
if (existing and existing->isLocked())
|
||||
throw err::Logic{"Attempt to re-lock a buffer still in use"
|
||||
, LERR_(LIFECYCLE)};
|
||||
|
|
@ -784,8 +780,6 @@ namespace mem {
|
|||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
template<typename PAR, typename DEF>
|
||||
Key
|
||||
trackKey (PAR parent, DEF specialisation)
|
||||
|
|
|
|||
|
|
@ -333,7 +333,7 @@ namespace test {
|
|||
VERIFY_ERROR (LIFECYCLE, meta_->get(key).mark(NIL) );
|
||||
|
||||
// now build a concrete buffer entry
|
||||
metadata::Entry& entry = meta_->markLocked(key, SOME_POINTER);
|
||||
metadata::Entry& entry = meta_->markLocked (key, SOME_POINTER);
|
||||
CHECK (LOCKED == entry.state());
|
||||
CHECK (not entry.isTypeKey());
|
||||
|
||||
|
|
@ -369,7 +369,7 @@ namespace test {
|
|||
CHECK (LOCKED == entry.state());
|
||||
CHECK (entry.isLocked());
|
||||
|
||||
VERIFY_ERROR (LIFECYCLE, entry.lock(SOME_POINTER));
|
||||
VERIFY_ERROR (LIFECYCLE, entry.lock (SOME_POINTER));
|
||||
|
||||
entry.mark (BLOCKED); // go directly to the blocked state
|
||||
CHECK (BLOCKED == entry.state());
|
||||
|
|
@ -384,7 +384,7 @@ namespace test {
|
|||
CHECK (not entry.isLocked());
|
||||
VERIFY_ERROR (LIFECYCLE, entry.access() );
|
||||
|
||||
meta_->lock(key, SOME_POINTER);
|
||||
meta_->markLocked (key, SOME_POINTER);
|
||||
CHECK (entry.isLocked());
|
||||
|
||||
entry.mark (EMITTED);
|
||||
|
|
|
|||
|
|
@ -115145,17 +115145,93 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
|
|||
<node BACKGROUND_COLOR="#fec499" COLOR="#cb0b50" CREATED="1773621726683" ID="ID_526151796" MODIFIED="1773621770302" TEXT="ungeklärt: ist das notwendig? kann das passieren?">
|
||||
<icon BUILTIN="broken-line"/>
|
||||
<node CREATED="1773621841418" ID="ID_1292818494" MODIFIED="1773621860523" TEXT="von markLocked() kommend setzen wir onlyNew ≔ true"/>
|
||||
<node BACKGROUND_COLOR="#f8f1cb" COLOR="#a50125" CREATED="1773621875203" ID="ID_1034512279" MODIFIED="1773621897458" TEXT="das funktioniert nur in unserem Test-Setup, wo wir nie einen buffer wiederverwenden">
|
||||
<node COLOR="#5b280f" CREATED="1773621875203" ID="ID_1034512279" MODIFIED="1773684156215" TEXT="funktioniert wohl nur in unserem Test-Setup, wo wir nie einen buffer wiederverwenden?">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
<icon BUILTIN="button_cancel"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1773621904288" ID="ID_712968134" MODIFIED="1773684163574" TEXT="tatsächlich wird regelmäßig vorkommen exakt die gleiche Adresse wiederzuverwenden...">
|
||||
<icon BUILTIN="help"/>
|
||||
</node>
|
||||
<node CREATED="1773684093307" ID="ID_1100900074" MODIFIED="1773684137239" TEXT="aber derzeit ist es so gecodet, daß BufferProvider::release() ⟶ discard() aufruft">
|
||||
<icon BUILTIN="info"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1773684193958" ID="ID_339106431" MODIFIED="1773686475190" TEXT="was sich aber durchaus ändern könnte....">
|
||||
<arrowlink COLOR="#794397" DESTINATION="ID_867612305" ENDARROW="Default" ENDINCLINATION="-1231;58;" ID="Arrow_ID_535246973" STARTARROW="None" STARTINCLINATION="-148;960;"/>
|
||||
<icon BUILTIN="hourglass"/>
|
||||
<node CREATED="1773684224455" ID="ID_1521194179" MODIFIED="1773684997338" TEXT="daß sich die Buffer-Entries auf einem Level einpendeln erscheint plausibel">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
Und damit spielt sich das System dann irgendwann auf einen festen Pool von Buffer-»Slots« ein, die permanent im Speicher bleiben. Allerdings bedeutet das dann für die Metadaten ein <b>Cartesisches Produkt</b>  zwischen der Zahl der Memory-Slots und der Zahl der verschiedenen Buffer-Typen....
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
<node CREATED="1773684209259" ID="ID_1502362582" MODIFIED="1773685168035" TEXT="zur Beurteilung dessen brauchen wir aber Praxiserfahrung">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
Ob das also gefährlich wird, oder eine etwas ausufernde Metadaten-Storage durchaus überkompensiert wird von dem Wegfall der permanenten Allokation/Deallokation (und Hashtable-Pflege), kann nicht auf theoretischer Ebene abgehandelt werden. Mehr noch: es ist sogar zweifelhaft, ob sich <i>diese Frage überhaupt zuverlässig beantworten läßt, auch empirisch!</i> Dazu müßte man einen Weg finden, um die <i>Stabilität</i> des Verhaltens zu beurteilen, über verschieden Nutzszenarien hinweg
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
<node CREATED="1773684267099" ID="ID_223570720" MODIFIED="1773685274668" TEXT="und dann möglicherweise einen Garbage-sweep">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
Allerdings, wenn man sich darauf einläßt, Speicher nicht wegzuräumen, dann muß man explizit den Fall betrachten, daß der Speicher volläuft. In dem Fall bräuchte es einen »Sweep«, der über die Metadaten-Tabelle iteriert und alle Einträge pauschal löscht, die als FREE markiert sind. <i>The usual trade-offs apply.</i>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1773686502401" ID="ID_128640725" MODIFIED="1773686541496">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
Einsicht: nicht re-Locking sondern das <font face="Monospaced" color="#684e4e"><b>onlyNew</b></font> ist hier redundant
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
<icon BUILTIN="idea"/>
|
||||
<node CREATED="1773686546507" ID="ID_1896242135" MODIFIED="1773686555542" TEXT="das ist so ein pseudo-Konsistenzcheck"/>
|
||||
<node CREATED="1773686569345" ID="ID_811960003" MODIFIED="1773686579555" TEXT="dabei haben wir ohnehin eine State-Machine"/>
|
||||
<node COLOR="#5b280f" CREATED="1773686580886" ID="ID_611442402" MODIFIED="1773686661536" TEXT="daher kann es auf Ebene des Entry keine Doppelverwendung geben">
|
||||
<icon BUILTIN="stop-sign"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1773686631685" ID="ID_1569031870" MODIFIED="1773686650443" TEXT="das eigentliche Risiko ist vielmehr ein abweichender Typ-Zugangspfad">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1773621904288" ID="ID_712968134" MODIFIED="1773624101097" TEXT="tatsächlich wird regelmäßig vorkommen exakt die gleiche Adresse wiederzuverwenden">
|
||||
<icon BUILTIN="clanbomber"/>
|
||||
<node CREATED="1773686872825" ID="ID_750826408" MODIFIED="1773686932093" TEXT="onlyNew zurückbauen">
|
||||
<arrowlink COLOR="#429cd0" DESTINATION="ID_207080029" ENDARROW="Default" ENDINCLINATION="37;0;" ID="Arrow_ID_1636373225" STARTARROW="None" STARTINCLINATION="-95;13;"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1773621537410" ID="ID_383386793" MODIFIED="1773621721313" TEXT="im Code ganz nach unten schieben (und im Kommentar kennzeichnen)">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1773686891293" ID="ID_207080029" MODIFIED="1773686967587" TEXT="damit kann die lock()-Funktion doch noch private werden">
|
||||
<linktarget COLOR="#429cd0" DESTINATION="ID_207080029" ENDARROW="Default" ENDINCLINATION="37;0;" ID="Arrow_ID_1636373225" SOURCE="ID_750826408" STARTARROW="None" STARTINCLINATION="-95;13;"/>
|
||||
<icon BUILTIN="pencil"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
|
|
@ -137416,6 +137492,40 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
|
|||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1773685342412" ID="ID_1607917578" MODIFIED="1773685348439" TEXT="Laststeuerung">
|
||||
<node CREATED="1773685352696" ID="ID_1581471688" MODIFIED="1773685358427" TEXT="Rolle der Buffer-Metadaten">
|
||||
<node CREATED="1773685359633" ID="ID_537180155" MODIFIED="1773685430482" TEXT="2026 haben wir nur einen Entwurf »ins Blaue«">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
fragwürdig ist im Besonderen der hierarchische Ansatz, der die konkreten Storage-Metadaten als Spezialisierung eines Typ-Eintrags behandelt.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
<node CREATED="1773685436937" ID="ID_1194997795" MODIFIED="1773685524347" TEXT="Buffer-Metadaten werden mutmaßlich auch vom Storage-Backend mitverwendet">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
Im Besonderen stehen dort all die relevanten Infos, die jeder Memory-Allocator benötigt: die konkrete Adresse und die Size (möglicherweise sogar ein MRU-counter, oder ähnliche technische Informationen)
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1773686351857" ID="ID_867612305" MODIFIED="1773686475190" TEXT="Performance und Zusammenspiel mit dem Betriebszustand?">
|
||||
<linktarget COLOR="#794397" DESTINATION="ID_867612305" ENDARROW="Default" ENDINCLINATION="-1231;58;" ID="Arrow_ID_535246973" SOURCE="ID_339106431" STARTARROW="None" STARTINCLINATION="-148;960;"/>
|
||||
<icon BUILTIN="help"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1771524034579" ID="ID_1231941531" MODIFIED="1771524054570" TEXT="Strukturen im Buffer-Manager">
|
||||
<node CREATED="1771524063463" ID="ID_994256058" MODIFIED="1771524067869" TEXT="Zentral-Instanz"/>
|
||||
|
|
|
|||
Loading…
Reference in a new issue