BufferProvider: connect the first wire-tap to record locked state
...this turns out to be surprisingly difficult, due to various subclass / protected visibility problems. Not sure if the component design within `DiagnosticBufferProvider` is sane yet...
This commit is contained in:
parent
43c4f7a518
commit
945636c446
5 changed files with 95 additions and 32 deletions
|
|
@ -81,7 +81,7 @@ namespace engine {
|
|||
BufferProvider::getDescriptorFor (size_t storageSize)
|
||||
{
|
||||
auto& typeKey = bufferStage_->defineBufferType (storageSize, TypeHandler::RAW);
|
||||
return BuffDescr (*this, typeKey);
|
||||
return buildDescriptor (typeKey);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -89,7 +89,7 @@ namespace engine {
|
|||
BufferProvider::getDescriptorFor(size_t storageSize, TypeHandler specialTreatment)
|
||||
{
|
||||
auto& typeKey = bufferStage_->defineBufferType (storageSize, move (specialTreatment));
|
||||
return BuffDescr (*this, typeKey);
|
||||
return buildDescriptor (typeKey);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -143,7 +143,7 @@ namespace engine {
|
|||
auto [storage, localTag] = bufferStore_->provideBuffer (typeKey.storageSize(), type, typeKey.localTag());
|
||||
auto& stateKey = bufferStage_->mark_locked (typeKey, storage, localTag);
|
||||
|
||||
return BuffHandle (BuffDescr(*this, HashVal(stateKey)), storage);
|
||||
return BuffHandle (buildDescriptor(stateKey), storage);
|
||||
} // NOTE: not the underlying parent descriptor!
|
||||
|
||||
|
||||
|
|
@ -211,6 +211,12 @@ namespace engine {
|
|||
|
||||
/* === BuffDescr and BuffHandle === */
|
||||
|
||||
BuffDescr
|
||||
BufferProvider::buildDescriptor (HashVal key)
|
||||
{
|
||||
return {*this, key};
|
||||
}
|
||||
|
||||
bool
|
||||
BufferProvider::was_created_by_this_provider (BuffDescr const& descr) const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -187,6 +187,7 @@ namespace engine {
|
|||
protected:
|
||||
~BufferProvider();
|
||||
|
||||
BuffDescr buildDescriptor (HashVal);
|
||||
bool was_created_by_this_provider (BuffDescr const&) const;
|
||||
|
||||
using Buff = StreamType::ImplFacade::DataBuffer; ///< marker type for an actual data buffer
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include "lib/util.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
#include <memory>
|
||||
|
||||
|
||||
|
|
@ -42,27 +43,34 @@ namespace engine {
|
|||
using diagn::StateReg;
|
||||
using std::unique_ptr;
|
||||
using std::ranges::find_if;
|
||||
using std::move;
|
||||
|
||||
using metadata::Key;
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of tracking and instrumentation
|
||||
*/
|
||||
struct DiagnosticBufferProvider::BlockTracker
|
||||
: util::NonCopyable
|
||||
{
|
||||
StateReg created;
|
||||
StateReg emitted;
|
||||
StateReg released;
|
||||
};
|
||||
|
||||
Block::Block (BuffHandle const& handle)
|
||||
: handle{handle}
|
||||
|
||||
/* ====== Accounting API ====== */
|
||||
|
||||
Block::Block (BuffDescr typeDescriptor, Key stateKey, Buff* mem)
|
||||
: handle{typeDescriptor, mem}
|
||||
, storage{mem}
|
||||
{ }
|
||||
|
||||
Block::Block (BuffDescr const& descr)
|
||||
: handle{descr}
|
||||
{ }
|
||||
|
||||
void
|
||||
StateReg::record (PBlock blockRef)
|
||||
{
|
||||
reg_.emplace_back (move (blockRef));
|
||||
}
|
||||
|
||||
void
|
||||
StateReg::record (Block block)
|
||||
{
|
||||
record (std::make_shared<Block> (block));
|
||||
}
|
||||
|
||||
size_t
|
||||
StateReg::cnt() const
|
||||
|
|
@ -93,6 +101,32 @@ namespace engine {
|
|||
, LERR_(BOTTOM_VALUE));
|
||||
}
|
||||
|
||||
bool
|
||||
StateReg::contains (HashVal handle) const
|
||||
{
|
||||
return bool(byHandle (handle));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of tracking and instrumentation
|
||||
*/
|
||||
struct DiagnosticBufferProvider::BlockTracker
|
||||
: util::NonCopyable
|
||||
{
|
||||
StateReg created;
|
||||
StateReg emitted;
|
||||
StateReg released;
|
||||
|
||||
void
|
||||
record_locked (BuffDescr typeDescriptor, Key stateKey, Buff* mem)
|
||||
{
|
||||
REQUIRE (not created.contains (typeDescriptor));
|
||||
created.record (Block{typeDescriptor, stateKey, mem});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class DiagnosticBufferProvider::InstrumentedStageProxy
|
||||
: public BufferProviderSetup::Stage
|
||||
|
|
@ -102,6 +136,7 @@ namespace engine {
|
|||
|
||||
StageImp stage_;
|
||||
Tracker& tracker_;
|
||||
DiagnosticBufferProvider& provider_;
|
||||
|
||||
|
||||
/* === BufferStage proxy implementation === */
|
||||
|
|
@ -127,7 +162,9 @@ namespace engine {
|
|||
ID
|
||||
mark_locked (ID typeKey, Buff* storage, LocalTag implMark) override
|
||||
{
|
||||
return stage_->mark_locked (typeKey, storage, implMark);
|
||||
ID stateKey = stage_->mark_locked (typeKey, storage, implMark);
|
||||
tracker_.record_locked (provider_.buildDescriptor(stateKey), stateKey, storage);
|
||||
return stateKey;
|
||||
}
|
||||
|
||||
ID
|
||||
|
|
@ -155,18 +192,13 @@ namespace engine {
|
|||
}
|
||||
|
||||
public:
|
||||
InstrumentedStageProxy (StageImp rawImpl, Tracker& tracker)
|
||||
InstrumentedStageProxy (StageImp rawImpl, Tracker& tracker, DiagnosticBufferProvider& provider)
|
||||
: stage_{move(rawImpl)}
|
||||
, tracker_{tracker}
|
||||
, provider_{provider}
|
||||
{ }
|
||||
};
|
||||
|
||||
/* ====== Accounting API ====== */
|
||||
void
|
||||
StateReg::record (BuffHandle const& handle)
|
||||
{
|
||||
reg_.emplace_back (std::make_shared<Block> (handle));
|
||||
}
|
||||
|
||||
|
||||
DiagnosticBufferProvider::DiagnosticBufferProvider()
|
||||
|
|
@ -174,7 +206,7 @@ namespace engine {
|
|||
, heapStore_{dynamic_cast<HeapMemBufferStore&> (*bufferStore_)} //////////////////////////////////////////TICKET 1410 : obsolete after switch to newtracking-API
|
||||
, tracker_{std::make_unique<BlockTracker>()}
|
||||
{
|
||||
decorate<InstrumentedStageProxy> (bufferStage_, *tracker_);
|
||||
decorate<InstrumentedStageProxy> (bufferStage_, *tracker_, *this);
|
||||
}
|
||||
|
||||
DiagnosticBufferProvider::~DiagnosticBufferProvider()
|
||||
|
|
|
|||
|
|
@ -37,6 +37,8 @@ namespace engine {
|
|||
|
||||
namespace error = lumiera::error;
|
||||
|
||||
using Buff = StreamType::ImplFacade::DataBuffer; ///////////TODO consider to define that marker type at some suitable central location
|
||||
|
||||
class HeapMemBufferStore; //////////////////////////////OOO fällt dann weg nach dem Umbau
|
||||
class BufferDiagnostic;
|
||||
|
||||
|
|
@ -46,10 +48,10 @@ namespace engine {
|
|||
struct Block
|
||||
{
|
||||
BuffHandle handle;
|
||||
void* storage{nullptr};
|
||||
void* accessMemory() const { return storage; }
|
||||
Buff* storage{nullptr};
|
||||
Buff* accessMemory() const { return storage; }
|
||||
|
||||
Block (BuffHandle const&);
|
||||
Block (BuffDescr, metadata::Key, Buff* mem);
|
||||
Block (BuffDescr const&);
|
||||
operator HashVal() const { return handle; }
|
||||
};
|
||||
|
|
@ -58,7 +60,8 @@ namespace engine {
|
|||
class StateReg
|
||||
: util::NonCopyable
|
||||
{
|
||||
using Registry = std::vector<std::shared_ptr<Block>>;
|
||||
using PBlock = std::shared_ptr<Block>;
|
||||
using Registry = std::vector<PBlock>;
|
||||
Registry reg_;
|
||||
|
||||
public:
|
||||
|
|
@ -66,10 +69,12 @@ namespace engine {
|
|||
using Result = lib::Result<Block const&>;
|
||||
Result operator[] (size_t seqNr) const;
|
||||
Result byHandle (HashVal handle) const;
|
||||
bool contains (HashVal handle) const;
|
||||
size_t cnt() const;
|
||||
|
||||
/* ========= Accounting API ========= */
|
||||
void record (BuffHandle const&);
|
||||
void record (Block);
|
||||
void record (PBlock);
|
||||
};
|
||||
|
||||
}//(End)diagnostic descriptors.
|
||||
|
|
|
|||
|
|
@ -112855,6 +112855,26 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
|
|||
<node CREATED="1771276666297" ID="ID_80656960" MODIFIED="1771276686235" TEXT="mit dem nun angelegten API genügt es, die BufferStage zu dekorieren">
|
||||
<icon BUILTIN="idea"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1771282492426" ID="ID_1137207493" MODIFIED="1771284960337" TEXT="muß auch die zugehörige (umschließende) DiagnosticBufferProvider-Instanz zugänglich machen">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
...und zwar, weil wir ein BuffHandle speichern wollen, das einen BufferProvider einschließt. Dazu brauchen wir die Rückreferenz auf den Provider. Und das darf eigentlich nur BufferProvider selber...
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
<icon BUILTIN="yes"/>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1771282534052" ID="ID_1418547018" MODIFIED="1771282553829" TEXT="es gibt eigentlich nur eine Konstruktor-Funktion: beim Locking"/>
|
||||
<node BACKGROUND_COLOR="#f8f1cb" COLOR="#a50125" CREATED="1771282627528" ID="ID_1818084511" MODIFIED="1771282645961" TEXT="Sichtbarkeits-Problem: nur BufferProvider kann einen BuffDescr erzeugen">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
<node CREATED="1771282651196" ID="ID_1065300465" MODIFIED="1771282682996" TEXT="klarer Fall: muß die Funktion per protected-API zugänglich machen"/>
|
||||
<node CREATED="1771282684240" ID="ID_1294774953" MODIFIED="1771282696183" TEXT="kann dann auch überall im BufferProvider selber verwendet werden"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
|
|
@ -113165,8 +113185,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
|
|||
Deshalb nenne ich es auch ein »Protocol« — wollten wir etwas wirklich <i>wasserdichtes,</i>  dann müßten wir die Struktur ganz anders anlegen, und vermutlich auch deutlich rigider, und mehr interne Zugriffe verwenden.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
<arrowlink COLOR="#6d4975" DESTINATION="ID_693750944" ENDARROW="Default" ENDINCLINATION="-1078;42;" ID="Arrow_ID_480988688" STARTARROW="None" STARTINCLINATION="-465;29;"/>
|
||||
</node>
|
||||
</node>
|
||||
|
|
|
|||
Loading…
Reference in a new issue