BufferProvider: propagate the actual buffer-size info
This is a nasty new requirement, discovered as an aside while looking into ways to resolve the ''crucial mismatch'' between the `OutputSlot` and `BufferProvider`, using the proxy-implementation of `BufferProvider` (thereby expanding on the recent draft with the `BufferProxyAdaptor`) The point is, if the BufferMetadata will be used beyond the internal coordination within BufferProvider, then it will be used as part of actual buffer storage. And this implies that the actual size of the allocation may differ (be greater) than the nominally required size (since we'll very likely employ some kind of memory tiling, for reasons of performance). This leads again to an analysis of `BufferMetadata` usage, with the conclusion to add the actual storage size directly into the API, but treat it as an ''extra'' and not integrated into the ''buffer type'' Phew ... quite complex alltogether
This commit is contained in:
parent
94320d2d23
commit
ea0ae5f78e
8 changed files with 185 additions and 98 deletions
|
|
@ -286,13 +286,18 @@ namespace mem {
|
|||
|
||||
protected:
|
||||
Entry (Key const& parent
|
||||
,Buff* bufferPtr =nullptr
|
||||
,Buff* bufferPtr =nullptr
|
||||
,size_t actualSize =0
|
||||
,LocalTag const& specialTag =LocalTag::UNKNOWN
|
||||
)
|
||||
: Key{Key::forEntry (parent, bufferPtr, specialTag)}
|
||||
, state_{bufferPtr? LOCKED:NIL}
|
||||
, buffer_{bufferPtr}
|
||||
{ }
|
||||
{
|
||||
if (bufferPtr and actualSize)
|
||||
Key::storageSize_ = actualSize;
|
||||
ENSURE (Key::storageSize() >= parent.storageSize());
|
||||
}
|
||||
|
||||
/// BufferMetadata is allowed to create
|
||||
friend class vault::mem::BufferMetadata;
|
||||
|
|
@ -372,10 +377,11 @@ namespace mem {
|
|||
}
|
||||
|
||||
Entry&
|
||||
lock (Buff* newBuffer)
|
||||
lock (Buff* newBuffer, size_t actualSize =0)
|
||||
{
|
||||
__must_be_FREE();
|
||||
buffer_ = newBuffer;
|
||||
storageSize_ = std::max (actualSize, storageSize_);
|
||||
return mark (LOCKED);
|
||||
}
|
||||
|
||||
|
|
@ -692,19 +698,44 @@ namespace mem {
|
|||
* metadata Entry to account for this fact. This might include
|
||||
* invoking a constructor function, in case the type (Key)
|
||||
* defines a (nontrivial) TypeHandler.
|
||||
* @param parentKey designates the _buffer type_ to base on
|
||||
* @param buffer an actual memory address, which defines a distinct Entry
|
||||
* @param size the size of the actual allocation. When size ≡ 0,
|
||||
* the nominal size is assumed, as defined through parentKey.
|
||||
* Otherwise, the actual size must be _larger_.
|
||||
* @param specifics an optional qualification marker, which is managed
|
||||
* and evaluated by the BufferStore implementation and treated as
|
||||
* opaque data, as far as BufferMetadata is concerned. However,
|
||||
* the LocalTag becomes part of the identity of the metadata record.
|
||||
* Thus, either the parentKey must not include a LocalTag, or the
|
||||
* LocalTag given here must be identical to what was associate
|
||||
* with the _buffer type_ represented by parentKey.
|
||||
* @throw error::Fatal when locking a NULL buffer
|
||||
* @throw exceptions which might be raised by a TypeHandler's
|
||||
* constructor function. In this case, the Entry remains
|
||||
* created, but is marked as FREE
|
||||
*/
|
||||
Entry&
|
||||
markLocked (Key const& parentKey, Buff* buffer, LocalTag const& specifics =LocalTag::UNKNOWN)
|
||||
markLocked (Key const& parentKey
|
||||
,Buff* buffer
|
||||
,size_t actualSize =0
|
||||
,LocalTag const& specifics =LocalTag::UNKNOWN)
|
||||
{
|
||||
if (!buffer)
|
||||
if (not buffer)
|
||||
throw err::Fatal{"Attempt to lock for a NULL buffer. Allocation floundered?"
|
||||
, LERR_(BOTTOM_VALUE)};
|
||||
if (not actualSize)
|
||||
actualSize = parentKey.storageSize();
|
||||
REQUIRE (parentKey.storageSize() <= actualSize);
|
||||
|
||||
return BufferMetadata::lock (parentKey, buffer, specifics);
|
||||
return BufferMetadata::lock (parentKey, buffer, actualSize, specifics);
|
||||
}
|
||||
|
||||
/** variation to use when a LocalTag is given, yet size is implicitly taken from parent */
|
||||
Entry&
|
||||
markLocked (Key const& parentKey, Buff* buffer, LocalTag const& specifics)
|
||||
{
|
||||
return markLocked (parentKey, buffer, size_t(0), specifics);
|
||||
}
|
||||
|
||||
/** purge the bare metadata Entry from the metadata tables.
|
||||
|
|
@ -760,13 +791,14 @@ namespace mem {
|
|||
Entry&
|
||||
lock (Key const& parentKey
|
||||
,Buff* concreteBuffer
|
||||
,size_t actualSize
|
||||
,LocalTag const& specifics =LocalTag::UNKNOWN)
|
||||
{
|
||||
if (!concreteBuffer)
|
||||
if (not concreteBuffer)
|
||||
throw err::Invalid{"Attempt to lock a slot for a NULL buffer"
|
||||
, LERR_(BOTTOM_VALUE)};
|
||||
|
||||
Entry newEntry{parentKey, concreteBuffer, specifics};
|
||||
Entry newEntry{parentKey, concreteBuffer, actualSize, specifics};
|
||||
Entry* existing = table_.fetch (newEntry);
|
||||
|
||||
if (existing and existing->isLocked())
|
||||
|
|
@ -774,9 +806,9 @@ namespace mem {
|
|||
, LERR_(LIFECYCLE)};
|
||||
|
||||
if (not existing)
|
||||
return store_as_locked (newEntry); // actual creation
|
||||
return store_as_locked (newEntry); // store new Entry marked as locked
|
||||
else
|
||||
return existing->lock (concreteBuffer);
|
||||
return existing->lock (concreteBuffer, actualSize);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -149,12 +149,12 @@ namespace mem {
|
|||
BufferProvider::lockBuffer (BuffDescr const& type)
|
||||
{
|
||||
REQUIRE (was_created_by_this_provider (type));
|
||||
auto& typeKey = bufferStage_->lookup (type);
|
||||
auto [storage, actualSize, localTag] = bufferStore_->provideBuffer (type,typeKey.storageSize(),typeKey.localTag());
|
||||
auto& stateKey = bufferStage_->mark_locked (typeKey, storage, localTag);
|
||||
auto& typeKey = bufferStage_->lookup (type);
|
||||
BuffAlloc alloc= bufferStore_->provideBuffer (type,typeKey.storageSize(),typeKey.localTag());
|
||||
auto& stateKey = bufferStage_->mark_locked (typeKey, alloc);
|
||||
|
||||
return BuffHandle (buildDescriptor(stateKey), storage);
|
||||
} // NOTE: not the underlying parent descriptor!
|
||||
return BuffHandle (buildDescriptor(stateKey), getAddr(alloc));
|
||||
} // NOTE: not the underlying parent descriptor!
|
||||
|
||||
|
||||
/** BufferProvider API: state transition to _emitted state_.
|
||||
|
|
|
|||
|
|
@ -100,6 +100,15 @@
|
|||
** highly complex setup for the production-grade implementation variant, attempts
|
||||
** towards such a refactoring were postponed, after re-evaluation 2/2026.
|
||||
**
|
||||
** @warning buffer management via BufferProvider and BuffHandle does not automatically
|
||||
** _maintain proper alignment_. Rather, it relies on the storage allocator to
|
||||
** provide a buffer suitably aligned for the target type to hold. In most cases,
|
||||
** this target location will actually be storage located on the heap, yet some
|
||||
** processing might impose additional constraints regarding alignment to memory
|
||||
** blocks, causing degraded performance when violated; so this topic is a
|
||||
** possible subtle pitfall.
|
||||
** @todo 2026 we might consider adding alignment information to the associated TypeHandler.
|
||||
**
|
||||
** @see buffer-provider-protocol-test.cpp
|
||||
** @see output-slot.hpp
|
||||
** @see engine-ctx.hpp
|
||||
|
|
@ -142,6 +151,8 @@ namespace mem {
|
|||
* @remark LocalTag can be used by the storage-impl. */
|
||||
using BuffAlloc = std::tuple<Buff*,size_t,LocalTag>;
|
||||
|
||||
inline Buff* getAddr (BuffAlloc& alloc) { return std::get<0> (alloc); }
|
||||
inline size_t getSize (BuffAlloc& alloc) { return std::get<1> (alloc); }
|
||||
|
||||
|
||||
LUMIERA_ERROR_DECLARE (BUFFER_MANAGEMENT); ///< Problem providing working buffers
|
||||
|
|
@ -207,14 +218,14 @@ namespace mem {
|
|||
virtual ~BufferStage() { } ///< this is an interface
|
||||
|
||||
virtual ID defineBufferType (size_t, TypeHandler =TypeHandler::RAW, LocalTag =LocalTag::UNKNOWN) =0;
|
||||
virtual ID lookup (HashVal) =0;
|
||||
virtual ID mark_locked (ID typeKey, Buff*, LocalTag) =0;
|
||||
virtual ID mark_emitted (HashVal stateKey) =0;
|
||||
virtual ID mark_released (HashVal stateKey) =0;
|
||||
virtual ID abandon (HashVal, bool destroy=false) =0;
|
||||
virtual void discard (HashVal stateKey) =0;
|
||||
virtual bool isAllotted (HashVal stateKey) const =0;
|
||||
virtual bool isAccessible (HashVal stateKey) const =0;
|
||||
virtual ID lookup (HashVal) =0;
|
||||
virtual ID mark_locked (ID typeKey, BuffAlloc) =0;
|
||||
virtual ID mark_emitted (HashVal stateKey) =0;
|
||||
virtual ID mark_released (HashVal stateKey) =0;
|
||||
virtual ID abandon (HashVal, bool destroy=false) =0;
|
||||
virtual void discard (HashVal stateKey) =0;
|
||||
virtual bool isAllotted (HashVal stateKey) const =0;
|
||||
virtual bool isAccessible (HashVal stateKey) const =0;
|
||||
};
|
||||
|
||||
class BufferStore
|
||||
|
|
@ -225,10 +236,10 @@ namespace mem {
|
|||
public:
|
||||
virtual ~BufferStore() { } ///< this is an interface
|
||||
|
||||
virtual uint prepareBuffers (HashVal typeID, uint cnt, size_t) =0;
|
||||
virtual BuffAlloc provideBuffer (HashVal typeID, size_t, LocalTag) =0;
|
||||
virtual void mark_emitted (HashVal typeID, BuffAlloc) =0;
|
||||
virtual void detachBuffer (HashVal typeID, BuffAlloc) =0;
|
||||
virtual uint prepareBuffers (HashVal typeID, uint cnt, size_t) =0;
|
||||
virtual BuffAlloc provideBuffer (HashVal typeID, size_t, LocalTag) =0;
|
||||
virtual void mark_emitted (HashVal typeID, BuffAlloc) =0;
|
||||
virtual void detachBuffer (HashVal typeID, BuffAlloc) =0;
|
||||
};
|
||||
|
||||
unique_ptr<BufferStage> bufferStage_;
|
||||
|
|
|
|||
|
|
@ -15,28 +15,39 @@
|
|||
** A front-end to support the buffer management within the render nodes.
|
||||
** When pulling data from predecessor nodes and calculating new data, each render node
|
||||
** needs several input and output buffers. These may be allocated and provided by various
|
||||
** different "buffer providers" (for example the frame cache). Typically, the real buffers
|
||||
** will be passed as parameters to the actual job instance when scheduled, drawing on the
|
||||
** results of prerequisite jobs. Yet the actual job implementation remains agnostic with
|
||||
** respect to the way actual buffers are provided; the invocation just pushes BuffHandle
|
||||
** objects around. The actual render function gets an array of C-pointers to the actual
|
||||
** buffers, and for accessing those buffers, the node needs to keep a table of buffer
|
||||
** pointers, and for releasing the buffers later on, we utilise the buffer handles.
|
||||
** different [»buffer providers«](\ref buffer-provider.hpp) (for example the frame cache).
|
||||
** Buffers are classified by a _buffer type,_ which essentially is the size of the storage,
|
||||
** but could optionally also include a constructor and destructor function. Which type of
|
||||
** buffer is used at some node invocation and which provider is backing and managing the
|
||||
** allocation is considered static configuration of the Render Node Network and established
|
||||
** by the **Builder**. Typically the actual render job is unaware of these details and only
|
||||
** provides a parameter, that _just happens to select_ the proper source buffer for the
|
||||
** frame to be computed.
|
||||
**
|
||||
** These buffer handles are based on a [Buffer Descriptor record](\ref BuffDescr),
|
||||
** which is opaque as far as the client is concerned. BuffDescr acts as a representation
|
||||
** of the type or kind of buffer. The only way to obtain such a BuffDescr is from a concrete
|
||||
** BufferProvider implementation. A back-link to this owning and managing provider is embedded
|
||||
** into the BuffDescr, which thus may be used as a _configuration tag,_ allowing to retrieve a
|
||||
** concrete buffer handle when needed, corresponding to an actual buffer provided and managed
|
||||
** behind the scenes. There is no automatic resource management; clients are responsible to
|
||||
** invoke BuffHandle#release when done.
|
||||
** However, the Node Network as such is strictly typed (at compile time). Information regarding
|
||||
** the _buffer type_ are encoded into a [Buffer Descriptor](\ref BuffDescr). These descriptors
|
||||
** are embedded into the _feed prototype_ of each node and used, by the actual _Node invocation_,
|
||||
** to retrieve a [Buffer Handle](\ref BuffHandle). On the other hand, the _feed prototype_ was
|
||||
** also attached to a typed context at build time, so that the invocation of the actual
|
||||
** _processing function_ can access the buffers and any further parameters strictly typed.
|
||||
**
|
||||
** @warning buffer management via BuffHandle and BuffDescr does _not automatically maintain
|
||||
** proper alignment._ Rather, it relies on the storage allocator to provide a buffer
|
||||
** suitably aligned for the target type to hold. In most cases, this target location
|
||||
** will actually be storage maintained on heap through some STL collection;
|
||||
** this topic is a possible subtle pitfall non the less.
|
||||
** Usage of these descriptors and handles is organised in accordance to the »Buffer Provider Protocol«,
|
||||
** which also explains the structure of the BufferProvider API.
|
||||
** - the first step is to obtain a BuffDescr from the BufferProvider, which implies
|
||||
** to define at least the required storage size (optionally also a constructor/destructor).
|
||||
** - the usage of some buffers with a given type can be _announced_ optionally, which allows
|
||||
** to pre-arrange some storage space and associate it with the calling thread.
|
||||
** - an actual allocation is initiated by _locking_ the descriptor, which yields a BuffHandle.
|
||||
** - from this handle, the buffer memory can be accessed.
|
||||
** - the client is then responsible to [»emit«](\ref BuffHandle::emit) on the handle,
|
||||
** once the computation is complete and data can be published. This step can be omitted,
|
||||
** and it depends on the actual situation if invoking this operation matters. For example,
|
||||
** it is very relevant for a result sent to some output sink, or for a buffer attached
|
||||
** to the frame cache. Without _emitting_, the data will not be propagated in those cases.
|
||||
** - however, it is always mandatory to [»release«](\ref BuffHandle::release) the handle.
|
||||
**
|
||||
** @note both BuffDescr and BuffHandle store a back-link to the managing BufferProvider.
|
||||
** @warning BuffHandle is _not a smart-ptr_ — the client is responsible to `release()`
|
||||
**
|
||||
** @see BufferProvider
|
||||
** @see BufferProviderProtocol_test usage demonstration
|
||||
|
|
@ -53,8 +64,8 @@
|
|||
#include "lib/hash-value.h"
|
||||
|
||||
|
||||
namespace vault{
|
||||
namespace mem {
|
||||
namespace vault {
|
||||
namespace mem {
|
||||
namespace err = lumiera::error;
|
||||
|
||||
using lib::HashVal;
|
||||
|
|
@ -75,10 +86,10 @@ namespace mem {
|
|||
* An opaque descriptor to identify the type and further properties of a data buffer.
|
||||
* For each kind of buffer, there is somewhere a BufferProvider responsible for the
|
||||
* actual storage management. This provider may "lock" a buffer for actual use,
|
||||
* returning a BuffHandle.
|
||||
* @note this descriptor and especially the #subClassification_ is really owned
|
||||
* by the BufferProvider, which may use (and even change) the opaque contents
|
||||
* to organise the internal buffer management.
|
||||
* returning a BuffHandle. BuffDescr is a convenient front-end to represent the arrangement
|
||||
* for some type / kind of buffer, and to [allocate](\ref BuffDescr::lockBuffer) it actually.
|
||||
* @note this descriptor and especially meaning of the #subClassification_ is
|
||||
* implementation-defined and tied to a specific BufferProvider.
|
||||
*/
|
||||
class BuffDescr
|
||||
{
|
||||
|
|
@ -111,8 +122,16 @@ namespace mem {
|
|||
|
||||
|
||||
/**
|
||||
* Handle for a buffer for processing data, abstracting away the actual implementation.
|
||||
* The real buffer pointer can be retrieved by dereferencing this smart-handle class.
|
||||
* Handle to designate a buffer with data for processing, thereby abstracting from the
|
||||
* memory management implementation. The buffer content can be accessed through an unchecked
|
||||
* cast operation, assuming that the client has otherwise complete control over the data type
|
||||
* to be accessed, since the only way to retrieve such a handle is from a BuffDescr.
|
||||
* Besides some information function, BuffHandle exposes the important API functions
|
||||
* - `emit()` : indicate that processing is complete and the data can be used / published
|
||||
* - `release()` : indicate that the client will not touch this handle any more, so that
|
||||
* storage can be repurposed.
|
||||
* @note This is a low-level feature and not a *smart-handle* — it is the clien's sole
|
||||
* responsibility to invoke the `release()` function reliably.
|
||||
*/
|
||||
class BuffHandle
|
||||
{
|
||||
|
|
@ -123,9 +142,9 @@ namespace mem {
|
|||
public:
|
||||
/** @internal a buffer handle may be obtained by "locking"
|
||||
* a buffer from the corresponding BufferProvider */
|
||||
BuffHandle(BuffDescr const& typeInfo, void* storage = 0)
|
||||
: descriptor_(typeInfo)
|
||||
, pBuffer_(static_cast<Buff*>(storage))
|
||||
BuffHandle(BuffDescr const& typeInfo, Buff* storage =nullptr)
|
||||
: descriptor_{typeInfo}
|
||||
, pBuffer_{storage}
|
||||
{ }
|
||||
|
||||
// using standard copy operations
|
||||
|
|
|
|||
|
|
@ -170,10 +170,10 @@ namespace mem {
|
|||
}
|
||||
|
||||
ID
|
||||
mark_locked (ID typeKey, Buff* storage, LocalTag implMark) override
|
||||
mark_locked (ID typeKey, BuffAlloc storage) override
|
||||
{
|
||||
ID stateKey = stage_->mark_locked (typeKey, storage, implMark);
|
||||
tracker_.record_locked (stateKey, storage);
|
||||
ID stateKey = stage_->mark_locked (typeKey, storage);
|
||||
tracker_.record_locked (stateKey, getAddr(storage));
|
||||
return stateKey;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -72,8 +72,9 @@ namespace mem {
|
|||
} // deliberately: create storage, and return reference to it
|
||||
|
||||
ID
|
||||
mark_locked (ID typeKey, Buff* storage, LocalTag implMark) override
|
||||
mark_locked (ID typeKey, BuffAlloc alloc) override
|
||||
{
|
||||
auto& [storage,size,implMark] = alloc;
|
||||
return metadata_.markLocked (typeKey, storage, implMark);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -155,7 +155,7 @@ namespace test {
|
|||
CHECK (LOCKED == m2.state());
|
||||
CHECK (SOME_POINTER == m2.access()); // buffer pointer associated
|
||||
|
||||
// entries are unique and identifiable
|
||||
// entries are unique and identifiable by a memory address
|
||||
HashVal keyX = meta_->key(key1, SOME_POINTER);
|
||||
CHECK (meta_->isLocked(keyX));
|
||||
CHECK (keyX != key1);
|
||||
|
|
@ -385,6 +385,7 @@ namespace test {
|
|||
VERIFY_ERROR (LIFECYCLE, entry.access() );
|
||||
|
||||
meta_->markLocked (key, SOME_POINTER);
|
||||
//Note: we locked the key and this changed the existing entry
|
||||
CHECK (entry.isLocked());
|
||||
|
||||
entry.mark (EMITTED);
|
||||
|
|
|
|||
|
|
@ -114290,6 +114290,9 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
|
|||
<node CREATED="1771535088123" ID="ID_1559134812" MODIFIED="1771535104984" TEXT="nun einen DiagnosticBufferProvider »Huckepack« nehmen"/>
|
||||
<node CREATED="1771535954283" ID="ID_83611307" MODIFIED="1771536165619" TEXT="muß hier sofort einen ProxyBufferStore vorsehen und anlegen">
|
||||
<linktarget COLOR="#ff0020" DESTINATION="ID_83611307" ENDARROW="Default" ENDINCLINATION="-142;6;" ID="Arrow_ID_47613106" SOURCE="ID_1312596627" STARTARROW="None" STARTINCLINATION="6;-31;"/>
|
||||
<node CREATED="1773699166727" ID="ID_497122958" MODIFIED="1773699899454" TEXT="dazu muß ich aber sinnvolle Infos durch die BufferProvider-Implementierung durschschleusen">
|
||||
<arrowlink COLOR="#4b1ec1" DESTINATION="ID_49953306" ENDARROW="Default" ENDINCLINATION="-1107;45;" ID="Arrow_ID_474360109" STARTARROW="None" STARTINCLINATION="687;22;"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1771535979276" ID="ID_117213353" MODIFIED="1771536009626" TEXT="alles andere wegholzen und erst mal sonst nichts machen">
|
||||
<icon BUILTIN="yes"/>
|
||||
|
|
@ -114593,8 +114596,8 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
|
|||
</html></richcontent>
|
||||
<arrowlink COLOR="#65343f" DESTINATION="ID_560454050" ENDARROW="Default" ENDINCLINATION="428;-25;" ID="Arrow_ID_267752890" STARTARROW="Default" STARTINCLINATION="-454;26;"/>
|
||||
</node>
|
||||
<node CREATED="1773620654297" ID="ID_1491048372" MODIFIED="1773620896713" TEXT="Aufruf-Pfad noch etwas stringenter gemacht">
|
||||
<arrowlink COLOR="#5c3fb5" DESTINATION="ID_1308293417" ENDARROW="Default" ENDINCLINATION="-48;-555;" ID="Arrow_ID_948177354" STARTARROW="None" STARTINCLINATION="1026;0;"/>
|
||||
<node CREATED="1773620654297" ID="ID_1491048372" MODIFIED="1773698533165" TEXT="Aufruf-Pfad noch etwas stringenter gemacht">
|
||||
<arrowlink COLOR="#5c3fb5" DESTINATION="ID_1308293417" ENDARROW="Default" ENDINCLINATION="-64;-875;" ID="Arrow_ID_948177354" STARTARROW="None" STARTINCLINATION="1103;-40;"/>
|
||||
<node BACKGROUND_COLOR="#e4dfbe" COLOR="#2b41b1" CREATED="1773620912607" HGAP="28" ID="ID_303989240" MODIFIED="1773621083885" TEXT="im Grunde ist das eine Kaskade" VSHIFT="11">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
|
|
@ -115001,7 +115004,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
|
|||
</node>
|
||||
<node CREATED="1772129891226" ID="ID_1405915409" MODIFIED="1772129902229" TEXT="Überlegungen zum BuffeStore-API">
|
||||
<node CREATED="1772129905244" ID="ID_545569208" MODIFIED="1772129929698" TEXT="eigentlich tritt ein charakteristisches Tupel bei jeder Transition auf"/>
|
||||
<node CREATED="1772129931304" ID="ID_1142410309" MODIFIED="1773599703401" TEXT="⟹ man könnte den »Slot«-Datentyp erweitern...">
|
||||
<node BACKGROUND_COLOR="#c8c0b6" COLOR="#435e98" CREATED="1772129931304" ID="ID_1142410309" MODIFIED="1773698831171" TEXT="⟹ man könnte den »Slot«-Datentyp erweitern...">
|
||||
<linktarget COLOR="#a04e3e" DESTINATION="ID_1142410309" ENDARROW="Default" ENDINCLINATION="-791;48;" ID="Arrow_ID_1325165991" SOURCE="ID_1990206387" STARTARROW="None" STARTINCLINATION="309;21;"/>
|
||||
<node CREATED="1772129959849" ID="ID_1378157373" MODIFIED="1772130000767" TEXT="(storage, size, localTag)"/>
|
||||
<node CREATED="1773601187335" ID="ID_916507010" MODIFIED="1773601229263">
|
||||
|
|
@ -115015,7 +115018,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
|
|||
</html></richcontent>
|
||||
<linktarget COLOR="#a9b4c1" DESTINATION="ID_916507010" ENDARROW="Default" ENDINCLINATION="187;0;" ID="Arrow_ID_1685002660" SOURCE="ID_931674085" STARTARROW="None" STARTINCLINATION="11;-53;"/>
|
||||
</node>
|
||||
<node CREATED="1773601269645" ID="ID_1119705517" MODIFIED="1773601285461">
|
||||
<node CREATED="1773601269645" ID="ID_1119705517" MODIFIED="1773698803897">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
|
|
@ -115024,9 +115027,12 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
|
|||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<arrowlink COLOR="#c1f1af" DESTINATION="ID_751533457" ENDARROW="Default" ENDINCLINATION="91;-109;" ID="Arrow_ID_1493821089" STARTARROW="None" STARTINCLINATION="-128;13;"/>
|
||||
<font NAME="SansSerif" SIZE="12"/>
|
||||
</node>
|
||||
<node CREATED="1773599779915" ID="ID_487073922" MODIFIED="1773599804006" TEXT="wird relevant für die Verbindung mit dem OutputSlot"/>
|
||||
<node CREATED="1773599779915" ID="ID_487073922" MODIFIED="1773700405307" TEXT="wird relevant für die Verbindung mit dem OutputSlot">
|
||||
<linktarget COLOR="#4d50c8" DESTINATION="ID_487073922" ENDARROW="Default" ENDINCLINATION="2209;124;" ID="Arrow_ID_1151349135" SOURCE="ID_1831855764" STARTARROW="None" STARTINCLINATION="1795;-84;"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1772209019999" ID="ID_903636266" MODIFIED="1772209035932" TEXT="wirft aber wieder das Problem mit den Marker-Typen auf">
|
||||
|
|
@ -115042,16 +115048,19 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
|
|||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1773604353753" ID="ID_751533457" MODIFIED="1773604359674" TEXT="BuffAlloc einführen">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node COLOR="#338800" CREATED="1773604353753" ID="ID_751533457" MODIFIED="1773698803897" TEXT="BuffAlloc einführen">
|
||||
<linktarget COLOR="#c1f1af" DESTINATION="ID_751533457" ENDARROW="Default" ENDINCLINATION="91;-109;" ID="Arrow_ID_1493821089" SOURCE="ID_1119705517" STARTARROW="None" STARTINCLINATION="-128;13;"/>
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node COLOR="#338800" CREATED="1773604361248" ID="ID_720105604" MODIFIED="1773604407072" TEXT="in das BufferStore-API und Implementierungen">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#f8f1cb" COLOR="#a50125" CREATED="1773604377214" ID="ID_200162330" MODIFIED="1773604392207" TEXT="muß die Size-Info in die Metadaten weitergeben">
|
||||
<node BACKGROUND_COLOR="#c8c0b6" COLOR="#435e98" CREATED="1773604377214" FOLDED="true" ID="ID_200162330" MODIFIED="1773700514964" TEXT="muß die Size-Info in die Metadaten weitergeben">
|
||||
<linktarget COLOR="#1c07d0" DESTINATION="ID_200162330" ENDARROW="Default" ENDINCLINATION="-77;817;" ID="Arrow_ID_1474651143" SOURCE="ID_49953306" STARTARROW="None" STARTINCLINATION="1030;40;"/>
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
<node CREATED="1773606726737" ID="ID_1617991320" MODIFIED="1773606747708" TEXT="die BufferMetadata::markLocked() muß eine abweichende BufferSize speichern"/>
|
||||
<node CREATED="1773606769685" ID="ID_1643754781" MODIFIED="1773606794678" TEXT="das führt in BufferMetadata::lock(parentKey, Buff*, LocalTag,...)"/>
|
||||
<node CREATED="1773612115286" ID="ID_282545244" MODIFIED="1773612174969" TEXT="Frage: bricht das die Systematik?">
|
||||
<node COLOR="#435e98" CREATED="1773612115286" ID="ID_282545244" MODIFIED="1773698165853" TEXT="Frage: bricht das die Systematik?">
|
||||
<icon BUILTIN="button_cancel"/>
|
||||
<node CREATED="1773612180193" ID="ID_956161008" MODIFIED="1773612197124" TEXT="die nominale buffer-size ist ja in den parentKey eingerechnet"/>
|
||||
<node CREATED="1773612219933" ID="ID_1463108347" MODIFIED="1773612283946" TEXT="ein Qualifizieren des Typs per size wäre theoretisch möglich / vorgesehen">
|
||||
<node CREATED="1773613319606" ID="ID_624178218" MODIFIED="1773613344348" TEXT="man könnte Key::forEntry() erweitern"/>
|
||||
|
|
@ -115088,12 +115097,15 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
|
|||
<icon BUILTIN="info"/>
|
||||
</node>
|
||||
<node CREATED="1773613635076" ID="ID_1863050688" MODIFIED="1773613650403" TEXT="Konsequenz: das ist ein zusätzliches Datenfeld in den Metadaten"/>
|
||||
<node CREATED="1773616741024" ID="ID_1266121816" MODIFIED="1773616777395" TEXT="allerdings sollte das keine redundante Storage sein ⟹ also das Feld im Key(Basis) nutzen"/>
|
||||
<node COLOR="#435e98" CREATED="1773616741024" ID="ID_1266121816" MODIFIED="1773698145064" TEXT="allerdings sollte das keine redundante Storage sein ⟹ also das Feld im Key(Basis) nutzen">
|
||||
<icon BUILTIN="yes"/>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1773620718648" ID="ID_1308293417" MODIFIED="1773620896713" TEXT="Struktur der BufferMetadata nochmal klären und Validieren">
|
||||
<linktarget COLOR="#5c3fb5" DESTINATION="ID_1308293417" ENDARROW="Default" ENDINCLINATION="-48;-555;" ID="Arrow_ID_948177354" SOURCE="ID_1491048372" STARTARROW="None" STARTINCLINATION="1026;0;"/>
|
||||
<node CREATED="1773621103140" ID="ID_18529012" MODIFIED="1773621105927" TEXT="Einsichten">
|
||||
</node>
|
||||
<node COLOR="#4c4398" CREATED="1773620718648" ID="ID_1308293417" MODIFIED="1773698662500" TEXT="Struktur der BufferMetadata nochmal klären und Validieren">
|
||||
<linktarget COLOR="#5c3fb5" DESTINATION="ID_1308293417" ENDARROW="Default" ENDINCLINATION="-64;-875;" ID="Arrow_ID_948177354" SOURCE="ID_1491048372" STARTARROW="None" STARTINCLINATION="1103;-40;"/>
|
||||
<node CREATED="1773621103140" ID="ID_18529012" MODIFIED="1773698671785" TEXT="Einsichten">
|
||||
<icon BUILTIN="idea"/>
|
||||
<node CREATED="1773621106819" ID="ID_1944288889" MODIFIED="1773621199192" TEXT="der Einstiegspunkt ist in der Mitte des Quellcodes. Das verwirrt">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
|
|
@ -115152,7 +115164,8 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
|
|||
<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">
|
||||
<node CREATED="1773684093307" ID="ID_1100900074" MODIFIED="1773698507609" TEXT="aber derzeit ist es so gecodet, daß BufferProvider::release() ⟶ discard() aufruft">
|
||||
<linktarget COLOR="#6585ab" DESTINATION="ID_1100900074" ENDARROW="Default" ENDINCLINATION="-252;9;" ID="Arrow_ID_1243882082" SOURCE="ID_1611649683" STARTARROW="None" STARTINCLINATION="468;15;"/>
|
||||
<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....">
|
||||
|
|
@ -115160,9 +115173,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
|
|||
<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>
|
||||
<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....
|
||||
|
|
@ -115173,9 +115184,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
|
|||
</node>
|
||||
<node CREATED="1773684209259" ID="ID_1502362582" MODIFIED="1773685168035" TEXT="zur Beurteilung dessen brauchen wir aber Praxiserfahrung">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</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
|
||||
|
|
@ -115186,9 +115195,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
|
|||
</node>
|
||||
<node CREATED="1773684267099" ID="ID_223570720" MODIFIED="1773685274668" TEXT="und dann möglicherweise einen Garbage-sweep">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</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>
|
||||
|
|
@ -115201,9 +115208,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
|
|||
</node>
|
||||
<node CREATED="1773686502401" ID="ID_128640725" MODIFIED="1773686541496">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
Einsicht: nicht re-Locking sondern das <font face="Monospaced" color="#684e4e"><b>onlyNew</b></font> ist hier redundant
|
||||
|
|
@ -115220,7 +115225,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
|
|||
<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 CREATED="1773686872825" ID="ID_750826408" MODIFIED="1773686932093" TEXT="onlyNew zurückbauen">
|
||||
<node COLOR="#435e98" CREATED="1773686872825" ID="ID_750826408" MODIFIED="1773689900441" 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>
|
||||
|
|
@ -115228,12 +115233,24 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
|
|||
<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">
|
||||
<node COLOR="#338800" CREATED="1773686891293" ID="ID_207080029" MODIFIED="1773689907012" 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"/>
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1773698211457" ID="ID_485099126" MODIFIED="1773698217366" TEXT="es gibt noch Unschärfen">
|
||||
<node CREATED="1773698220718" ID="ID_344879972" MODIFIED="1773698239407" TEXT="die meisten der Key-Generierungs-Funktionen werden nur vom Unit-Test aufgerufen"/>
|
||||
<node CREATED="1773698241384" ID="ID_1721048513" MODIFIED="1773698266019" TEXT="es gibt einen Abkürzungspfad der einen Entry sofort als LOCKED erzeugt"/>
|
||||
<node CREATED="1773698278788" ID="ID_1611649683" MODIFIED="1773698507608" TEXT="ob wir Metadata-Einträge stets verwerfen, wird explizit als Gestaltungs-Option offengehalten">
|
||||
<arrowlink COLOR="#6585ab" DESTINATION="ID_1100900074" ENDARROW="Default" ENDINCLINATION="-252;9;" ID="Arrow_ID_1243882082" STARTARROW="None" STARTINCLINATION="468;15;"/>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1773698551282" ID="ID_1035949625" MODIFIED="1773698562250" TEXT="es zeichnen sich drei Layer ab....">
|
||||
<node CREATED="1773698567503" ID="ID_1799622771" MODIFIED="1773698578642" TEXT="Key, Entry und die Hash-Verknüpfung"/>
|
||||
<node CREATED="1773698583888" ID="ID_1941798995" MODIFIED="1773698616837" TEXT="BufferMetadata / Zustandsübergänge"/>
|
||||
<node CREATED="1773698617984" ID="ID_647410294" MODIFIED="1773698626088" TEXT="die Metadata-Table"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
|
|
@ -117793,6 +117810,10 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
|
|||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1773077173730" ID="ID_76417582" MODIFIED="1773167628789" TEXT="Neubau Diagnose-API ⟺ Vorentwurf Implementierung">
|
||||
<linktarget COLOR="#604371" DESTINATION="ID_76417582" ENDARROW="Default" ENDINCLINATION="-588;-641;" ID="Arrow_ID_1083444621" SOURCE="ID_1377276921" STARTARROW="None" STARTINCLINATION="-741;71;"/>
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node CREATED="1773700274163" ID="ID_1831855764" MODIFIED="1773700492223" TEXT="muß dazu das direkte DataSink::emit() ablösen durch ein Proxying">
|
||||
<arrowlink COLOR="#4d50c8" DESTINATION="ID_487073922" ENDARROW="Default" ENDINCLINATION="2209;124;" ID="Arrow_ID_1151349135" STARTARROW="None" STARTINCLINATION="1795;-84;"/>
|
||||
<arrowlink COLOR="#5a22df" DESTINATION="ID_49953306" ENDARROW="Default" ENDINCLINATION="770;-33;" ID="Arrow_ID_886780269" STARTARROW="None" STARTINCLINATION="751;0;"/>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1773077306179" ID="ID_791772240" MODIFIED="1773078563511" TEXT="Analyse muß dieses Mal bottom-up vorgehen">
|
||||
<arrowlink COLOR="#df165b" DESTINATION="ID_597179173" ENDARROW="Default" ENDINCLINATION="-647;-29;" ID="Arrow_ID_694305976" STARTARROW="None" STARTINCLINATION="-136;1688;"/>
|
||||
|
|
@ -137496,9 +137517,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
|
|||
<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>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
fragwürdig ist im Besonderen der hierarchische Ansatz, der die konkreten Storage-Metadaten als Spezialisierung eines Typ-Eintrags behandelt.
|
||||
|
|
@ -137509,9 +137528,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
|
|||
</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>
|
||||
<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)
|
||||
|
|
@ -137999,6 +138016,12 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
|
|||
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1773423131415" ID="ID_1566753229" MODIFIED="1773423147739" TEXT="wer muß wen konkret getypt sehen?">
|
||||
<icon BUILTIN="help"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#f8f1cb" COLOR="#a50125" CREATED="1773699216800" ID="ID_49953306" MODIFIED="1773700514964" TEXT="wirft sofort das Problem auf wie man die Proxy-Callbacks implementiert">
|
||||
<arrowlink COLOR="#1c07d0" DESTINATION="ID_200162330" ENDARROW="Default" ENDINCLINATION="-77;817;" ID="Arrow_ID_1474651143" STARTARROW="None" STARTINCLINATION="1030;40;"/>
|
||||
<linktarget COLOR="#4b1ec1" DESTINATION="ID_49953306" ENDARROW="Default" ENDINCLINATION="-1107;45;" ID="Arrow_ID_474360109" SOURCE="ID_497122958" STARTARROW="None" STARTINCLINATION="687;22;"/>
|
||||
<linktarget COLOR="#5a22df" DESTINATION="ID_49953306" ENDARROW="Default" ENDINCLINATION="770;-33;" ID="Arrow_ID_886780269" SOURCE="ID_1831855764" STARTARROW="None" STARTINCLINATION="751;0;"/>
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1773456815562" ID="ID_1123444875" MODIFIED="1773589752521" TEXT="Doku">
|
||||
<arrowlink COLOR="#7e454b" DESTINATION="ID_1937537099" ENDARROW="Default" ENDINCLINATION="1647;-115;" ID="Arrow_ID_1049807970" STARTARROW="None" STARTINCLINATION="-377;112;"/>
|
||||
|
|
|
|||
Loading…
Reference in a new issue