BufferProvider: switch to the new implementation structure
More or less forcibly squeeze all the existing implementation into the new basic structure with two separate »pillars« **Breakages** - existing code expected the `BufferStore` to transition to ''locked'' state - existing code expected `provideLockedBuffer(typeID)` to tail-call the `buildHandle()` function of the enclosing `BufferProvider` base implementation - various diagnostic usages bypassed the official APIs and called directly into the implementation. This is no longer possible; rather, `DiagnosticBufferProvider` needs to provide additional diagnostic API to suit those purposes
This commit is contained in:
parent
a9bdad2c66
commit
9c5eb11b0c
13 changed files with 580 additions and 133 deletions
|
|
@ -25,10 +25,8 @@
|
|||
#include "lib/error.hpp"
|
||||
#include "lib/symbol.hpp"
|
||||
#include "lib/hash-value.h"
|
||||
#include "steam/engine/buffhandle.hpp"
|
||||
#include "steam/engine/buffer-provider.hpp"
|
||||
//#include "steam/engine/engine-ctx.hpp"
|
||||
#include "steam/engine/type-handler.hpp"
|
||||
#include "steam/engine/buffer-local-tag.hpp"
|
||||
#include "lib/nocopy.hpp"
|
||||
|
||||
#include <utility>
|
||||
|
|
@ -40,14 +38,12 @@ namespace engine {
|
|||
|
||||
using lib::Literal;
|
||||
using std::unique_ptr;
|
||||
using std::forward;
|
||||
// using std::forward;
|
||||
using std::move;
|
||||
|
||||
|
||||
class BufferMetadata;
|
||||
|
||||
|
||||
LUMIERA_ERROR_DECLARE (BUFFER_MANAGEMENT); ///< Problem providing working buffers
|
||||
|
||||
|
||||
/**
|
||||
* Framework for configuring the actual BufferPovider backend implementation.
|
||||
|
|
@ -58,18 +54,34 @@ namespace engine {
|
|||
: public BufferProvider
|
||||
{
|
||||
public:
|
||||
BufferProviderSetup (Literal implementationID);
|
||||
/**
|
||||
* Build a new BufferProvider setup to manage a number of buffers.
|
||||
* The metadata of these buffers is organised hierarchically based on
|
||||
* chained hash values, using an `implementationID` as a seed.
|
||||
* The \a CONF configuration record controls the actual implementation
|
||||
* of lifecycle transitions and storage management.
|
||||
*/
|
||||
template<class CONF>
|
||||
BufferProviderSetup (CONF&& confRec)
|
||||
: BufferProvider{}
|
||||
{
|
||||
bufferStage_ = move (confRec.buildStage());
|
||||
bufferStore_ = move (confRec.buildStore());
|
||||
}
|
||||
|
||||
class Stage
|
||||
: protected BufferStage
|
||||
: public BufferStage
|
||||
{
|
||||
public:
|
||||
using BufferStage::BufferStage; ///////////////////////////////////////////////////////////TICKET #1410 : actual implementation structures should move down into this classes implementation
|
||||
|
||||
};
|
||||
|
||||
class Store
|
||||
: protected BufferStore
|
||||
: public BufferStore
|
||||
{
|
||||
|
||||
protected:
|
||||
using Buff = BufferProvider::Buff;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -41,14 +41,6 @@ namespace engine {
|
|||
LUMIERA_ERROR_DEFINE (BUFFER_MANAGEMENT, "Problem providing working buffers");
|
||||
|
||||
|
||||
/** build a new provider instance, managing a family of buffers.
|
||||
* The metadata of these buffers is organised hierarchically based on
|
||||
* chained hash values, using the #implementationID as a seed.
|
||||
* @param implementationID symbolic ID setting these family of buffers apart.
|
||||
*/
|
||||
BufferProvider::BufferProvider (Literal implementationID)
|
||||
: bufferStage_(new BufferStage{implementationID})
|
||||
{ }
|
||||
|
||||
BufferProvider::~BufferProvider() { }
|
||||
|
||||
|
|
@ -117,7 +109,7 @@ namespace engine {
|
|||
uint
|
||||
BufferProvider::announce (uint count, BuffDescr const& type)
|
||||
{
|
||||
uint actually_possible = prepareBuffers (count, type);
|
||||
uint actually_possible = bufferStore_->prepareBuffers (count, type);
|
||||
if (!actually_possible)
|
||||
throw error::State ("unable to fulfil request for buffers"
|
||||
,LUMIERA_ERROR_BUFFER_MANAGEMENT);
|
||||
|
|
@ -143,7 +135,7 @@ namespace engine {
|
|||
{
|
||||
REQUIRE (was_created_by_this_provider (type));
|
||||
|
||||
return provideLockedBuffer (type);
|
||||
return bufferStore_->provideLockedBuffer (type);
|
||||
} // is expected to call buildHandle() --> state transition
|
||||
|
||||
|
||||
|
|
@ -163,7 +155,7 @@ namespace engine {
|
|||
BufferProvider::emitBuffer (BuffHandle const& handle)
|
||||
{
|
||||
metadata::Entry& metaEntry = bufferStage_->get (handle.entryID());
|
||||
mark_emitted (metaEntry.parentKey(), metaEntry.localTag());
|
||||
bufferStore_->mark_emitted (metaEntry.parentKey(), metaEntry.localTag());
|
||||
metaEntry.mark(EMITTED);
|
||||
}
|
||||
|
||||
|
|
@ -181,7 +173,7 @@ namespace engine {
|
|||
try {
|
||||
metadata::Entry& metaEntry = bufferStage_->get (handle.entryID());
|
||||
metaEntry.mark(FREE); // might invoke embedded dtor function
|
||||
detachBuffer (metaEntry.parentKey(), metaEntry.localTag(), *handle);
|
||||
bufferStore_->detachBuffer (metaEntry.parentKey(), metaEntry.localTag(), *handle);
|
||||
bufferStage_->release (metaEntry);
|
||||
}
|
||||
ERROR_LOG_AND_IGNORE (engine, "releasing a buffer from BufferProvider")
|
||||
|
|
@ -225,7 +217,7 @@ namespace engine {
|
|||
try {
|
||||
metadata::Entry& metaEntry = bufferStage_->get (target.entryID());
|
||||
metaEntry.invalidate (invokeDtor);
|
||||
detachBuffer (metaEntry.parentKey(), metaEntry.localTag(), *target);
|
||||
bufferStore_->detachBuffer (metaEntry.parentKey(), metaEntry.localTag(), *target);
|
||||
bufferStage_->release (metaEntry);
|
||||
}
|
||||
ERROR_LOG_AND_IGNORE (engine, "cleanup of buffer metadata while handling an error")
|
||||
|
|
|
|||
|
|
@ -113,8 +113,6 @@ namespace engine {
|
|||
size_t getBufferSize (HashVal typeID) const;
|
||||
|
||||
protected:
|
||||
BufferProvider (Literal implementationID);
|
||||
|
||||
/// placeholder marker type for an actual data buffer
|
||||
using Buff = StreamType::ImplFacade::DataBuffer;
|
||||
|
||||
|
|
@ -122,13 +120,6 @@ namespace engine {
|
|||
|
||||
bool was_created_by_this_provider (BuffDescr const&) const;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////OOO
|
||||
virtual uint prepareBuffers (uint count, HashVal typeID) =0;
|
||||
|
||||
virtual BuffHandle provideLockedBuffer (HashVal typeID) =0;
|
||||
virtual void mark_emitted (HashVal, LocalTag const&) =0;
|
||||
virtual void detachBuffer (HashVal, LocalTag const&, Buff&) =0;
|
||||
///////////////////////////////////////////////////////////////////////////////OOO
|
||||
|
||||
class BufferStage
|
||||
: public BufferMetadata /////////////////////////////////////////////////////////////////////TICKET #1410 : mix-in exiting old implementation -- for sake of refactoring only!
|
||||
|
|
@ -137,7 +128,6 @@ namespace engine {
|
|||
virtual ~BufferStage() { } ///< this is an interface
|
||||
|
||||
using BufferMetadata::BufferMetadata; ///////////////////////////////////////////////////////////TICKET #1410 : actual implementation structures should move down into this classes implementation
|
||||
protected:
|
||||
};
|
||||
|
||||
class BufferStore
|
||||
|
|
@ -145,7 +135,7 @@ namespace engine {
|
|||
{
|
||||
public:
|
||||
virtual ~BufferStore() { } ///< this is an interface
|
||||
protected:
|
||||
|
||||
virtual uint prepareBuffers (uint count, HashVal typeID) =0;
|
||||
virtual BuffHandle provideLockedBuffer (HashVal typeID) =0;
|
||||
virtual void mark_emitted (HashVal, LocalTag const&) =0;
|
||||
|
|
|
|||
|
|
@ -62,10 +62,11 @@ namespace engine {
|
|||
using Listener = std::function<void(size_t,BufferState)>;
|
||||
|
||||
class ForwardingBufferProvider
|
||||
: public BufferProvider
|
||||
: public BufferProvider /////////////////////////////////////////////////////////////TICKET #1410 : its clear now (2/26) that this must be some other base type; maybe we'll offer the ability to decorate, directly through BufferProviderSetup?
|
||||
{
|
||||
Listener listener_;
|
||||
|
||||
#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1410 : disabled code to while BufferProvider is being refactored...
|
||||
/* === BufferProvider API === */
|
||||
|
||||
uint
|
||||
|
|
@ -93,9 +94,10 @@ namespace engine {
|
|||
{
|
||||
|
||||
}
|
||||
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1410 : (end) disabled code
|
||||
public:
|
||||
ForwardingBufferProvider (Listener listener)
|
||||
: BufferProvider{"BufferProxyProvider"}
|
||||
: BufferProvider{}
|
||||
, listener_{std::move (listener)}
|
||||
{ }
|
||||
};
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
//#include "lib/meta/function.hpp"
|
||||
|
||||
#include "steam/engine/diagnostic-buffer-provider.hpp"
|
||||
#include "steam/engine/heap-mem-provider.hpp"
|
||||
#include "steam/engine/heap-mem-buffer-store.hpp"
|
||||
|
||||
|
||||
namespace steam {
|
||||
|
|
@ -33,7 +33,8 @@ namespace engine {
|
|||
|
||||
|
||||
DiagnosticBufferProvider::DiagnosticBufferProvider()
|
||||
: BufferProvider{"Diagnostic_HeapAllocated"}
|
||||
: NaiveBufferSetup{}
|
||||
, heapStore_{dynamic_cast<HeapMemProvider&> (*bufferStore_)}
|
||||
{ }
|
||||
|
||||
DiagnosticBufferProvider::~DiagnosticBufferProvider()
|
||||
|
|
@ -49,21 +50,21 @@ namespace engine {
|
|||
bool
|
||||
BufferDiagnostic::buffer_was_used (uint bufferID)
|
||||
{
|
||||
return dbp_.heapMemProvider_.access_emitted(bufferID).was_used();
|
||||
return dbp_.heapStore_.access_emitted(bufferID).was_used();
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BufferDiagnostic::buffer_was_closed (uint bufferID)
|
||||
{
|
||||
return dbp_.heapMemProvider_.access_emitted(bufferID).was_closed();
|
||||
return dbp_.heapStore_.access_emitted(bufferID).was_closed();
|
||||
}
|
||||
|
||||
|
||||
void*
|
||||
BufferDiagnostic::accessMemory (uint bufferID)
|
||||
{
|
||||
return dbp_.heapMemProvider_.access_emitted(bufferID).accessMemory();
|
||||
return dbp_.heapStore_.access_emitted(bufferID).accessMemory();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
#include "lib/error.hpp"
|
||||
#include "lib/util.hpp"
|
||||
#include "steam/engine/type-handler.hpp" ///////////////OOO warum?
|
||||
#include "steam/engine/heap-mem-provider.hpp"
|
||||
#include "steam/engine/naive-buffer-setup.hpp"
|
||||
#include "lib/nocopy.hpp"
|
||||
|
||||
#include <memory>
|
||||
|
|
@ -35,6 +35,7 @@ namespace engine {
|
|||
|
||||
namespace error = lumiera::error;
|
||||
|
||||
class HeapMemProvider;
|
||||
class BufferDiagnostic;
|
||||
|
||||
|
||||
|
|
@ -45,17 +46,9 @@ namespace engine {
|
|||
* @todo write type comment
|
||||
*/
|
||||
class DiagnosticBufferProvider
|
||||
: public BufferProvider
|
||||
: public NaiveBufferSetup
|
||||
{
|
||||
HeapMemProvider heapMemProvider_;
|
||||
|
||||
|
||||
/* === delegate BufferProvider API === */
|
||||
|
||||
uint prepareBuffers (uint count, HashVal typeID) override { return heapMemProvider_.prepareBuffers (count,typeID);}
|
||||
BuffHandle provideLockedBuffer (HashVal typeID) override { return heapMemProvider_.provideLockedBuffer (typeID); }
|
||||
void mark_emitted (HashVal h, LocalTag const& t) override { heapMemProvider_.mark_emitted(h,t); }
|
||||
void detachBuffer (HashVal h, LocalTag const& t, Buff& b) override { heapMemProvider_.detachBuffer(h,t,b); }
|
||||
HeapMemProvider& heapStore_;
|
||||
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
HeapMemProvider - plain heap allocating BufferProvider implementation for tests
|
||||
HeapMemBufferStore - plain heap allocating BufferProvider storage implementation for tests
|
||||
|
||||
Copyright (C)
|
||||
2011, Hermann Vosseler <Ichthyostega@web.de>
|
||||
2011,2026 Hermann Vosseler <Ichthyostega@web.de>
|
||||
|
||||
**Lumiera** is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
|
|
@ -12,8 +12,8 @@
|
|||
* *****************************************************************/
|
||||
|
||||
|
||||
/** @file heap-mem-provider.cpp
|
||||
** Implementation details of a mock engine::BufferProvider for unit testing
|
||||
/** @file heap-mem-buffer-store.cpp
|
||||
** Implementation details of simple heap based engine::BufferProvider storage.
|
||||
*/
|
||||
|
||||
|
||||
|
|
@ -22,7 +22,7 @@
|
|||
#include "lib/scoped-ptrvect.hpp"
|
||||
#include "lib/util-foreach.hpp"
|
||||
|
||||
#include "steam/engine/heap-mem-provider.hpp"
|
||||
#include "steam/engine/heap-mem-buffer-store.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
|
@ -223,8 +223,7 @@ namespace engine {
|
|||
* @internal create a memory tracking BufferProvider,
|
||||
*/
|
||||
HeapMemProvider::HeapMemProvider()
|
||||
: BufferProvider ("Naive_HeapAllocated")
|
||||
, pool_(new diagn::PoolTable)
|
||||
: pool_(new diagn::PoolTable)
|
||||
, outSeq_()
|
||||
{ }
|
||||
|
||||
|
|
@ -247,7 +246,8 @@ namespace engine {
|
|||
{
|
||||
diagn::BlockPool& blocks = getBlockPoolFor (typeID);
|
||||
diagn::Block& newBlock = blocks.createBlock();
|
||||
return buildHandle (typeID, asBuffer(newBlock.accessMemory()), &newBlock);
|
||||
UNIMPLEMENTED ("Separate tasks into two distinct APIs");
|
||||
// return buildHandle (typeID, asBuffer(newBlock.accessMemory()), &newBlock); /////////////////////////////OOO instead return a tuple (buffer, localTag)
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -320,8 +320,9 @@ namespace engine {
|
|||
HeapMemProvider::getBlockPoolFor (HashVal typeID)
|
||||
{
|
||||
diagn::BlockPool& pool = (*pool_)[typeID];
|
||||
if (!pool)
|
||||
pool.initialise(getBufferSize(typeID));
|
||||
UNIMPLEMENTED ("Separate tasks into two distinct APIs");
|
||||
// if (!pool)
|
||||
// pool.initialise(getBufferSize(typeID)); //////////////////////////OOO getBufferSize is a helper function in the BufferProvider protected API. Need to be "here"
|
||||
return pool;
|
||||
}
|
||||
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
HEAP-MEM-PROVIDER.hpp - plain heap allocating BufferProvider implementation for tests
|
||||
HEAP-MEM-BUFFER_STORE.hpp - plain heap allocating BufferProvider implementation for tests
|
||||
|
||||
Copyright (C)
|
||||
2011, Hermann Vosseler <Ichthyostega@web.de>
|
||||
2011,2026 Hermann Vosseler <Ichthyostega@web.de>
|
||||
|
||||
**Lumiera** is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
|
|
@ -12,10 +12,11 @@
|
|||
*/
|
||||
|
||||
/** @file heap-mem-provider.hpp
|
||||
** Dummy implementation of the BufferProvider interface to support writing unit tests.
|
||||
** This BufferProvider implementation is notably straight forward and silly: it just
|
||||
** claims more and more heap blocks and never releases any memory dynamically. This allows
|
||||
** to investigate additional tracking status flags for each allocated block after the fact.
|
||||
** Dummy implementation engine::BufferProvider storage, for sake of conceptual
|
||||
** demonstration and unit testing. This BufferProvider implementation is notably straight forward,
|
||||
** if not outright silly: it happily claims more and more heap blocks and never releases any memory
|
||||
** dynamically. This both demonstrates the simplest possible implementation of storage handling, and
|
||||
** allows to investigate additional tracking status flags for each allocated block after the fact.
|
||||
**
|
||||
** @todo 1/2026 for sake of implementation clarity, the following instrumentation functionality
|
||||
** must be relocated into the DiagnosticOutputProvider: Allocated buffers are numbered
|
||||
|
|
@ -30,13 +31,13 @@
|
|||
** @see buffer-provider-protocol-test.cpp
|
||||
*/
|
||||
|
||||
#ifndef STEAM_ENGINE_HEAP_MEM_PROVIDER_H
|
||||
#define STEAM_ENGINE_HEAP_MEM_PROVIDER_H
|
||||
#ifndef STEAM_ENGINE_HEAP_MEM_BUFFER_STORE_H
|
||||
#define STEAM_ENGINE_HEAP_MEM_BUFFER_STORE_H
|
||||
|
||||
|
||||
#include "lib/error.hpp"
|
||||
#include "lib/hash-value.h"
|
||||
#include "steam/engine/buffer-provider.hpp"
|
||||
#include "steam/engine/buffer-provider-setup.hpp"
|
||||
#include "lib/scoped-ptrvect.hpp"
|
||||
|
||||
#include <unordered_map>
|
||||
|
|
@ -117,13 +118,13 @@ namespace engine {
|
|||
* tracked usage information, even when blocks are already marked as "released".
|
||||
*/
|
||||
class HeapMemProvider
|
||||
: public BufferProvider
|
||||
: public BufferProviderSetup::Store
|
||||
{
|
||||
unique_ptr<diagn::PoolTable> pool_;
|
||||
ScopedPtrVect<diagn::Block> outSeq_;
|
||||
|
||||
public:
|
||||
/* === BufferProvider interface === */
|
||||
/* === BufferStore interface === */
|
||||
|
||||
virtual uint prepareBuffers (uint count, HashVal typeID) override;
|
||||
virtual BuffHandle provideLockedBuffer (HashVal typeID) override;
|
||||
|
|
@ -178,4 +179,4 @@ namespace engine {
|
|||
|
||||
|
||||
}} // namespace steam::engine
|
||||
#endif /*STEAM_ENGINE_HEAP_MEM_PROVIDER_H*/
|
||||
#endif /*STEAM_ENGINE_HEAP_MEM_BUFFER_STORE_H*/
|
||||
197
src/steam/engine/naive-buffer-setup.hpp
Normal file
197
src/steam/engine/naive-buffer-setup.hpp
Normal file
|
|
@ -0,0 +1,197 @@
|
|||
/*
|
||||
NAIVE-BUFFER_SETUP.hpp - plain heap allocating BufferProvider implementation for tests
|
||||
|
||||
Copyright (C)
|
||||
2026, Hermann Vosseler <Ichthyostega@web.de>
|
||||
|
||||
**Lumiera** is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version. See the file COPYING for further details.
|
||||
|
||||
*/
|
||||
|
||||
/** @file naive-buffer-setup.hpp
|
||||
** Dummy implementation of the BufferProvider interface to support writing unit tests.
|
||||
** This setup for a BufferProvider is notably straight forward and basically allocates
|
||||
** a new heap block for any buffer, without deallocating memory ever. This allows to
|
||||
** attach additional tracking status flags for each allocated block and validate
|
||||
** allocator behaviour after the fact.
|
||||
**
|
||||
** @todo 1/2026 for sake of implementation clarity, the following instrumentation functionality
|
||||
** must be relocated into the DiagnosticOutputProvider: Allocated buffers are numbered
|
||||
** with a simple ascending sequence of integers, used as LocalTag (see BufferMetadata).
|
||||
** Clients can request a Buffer with the given number, causing that block to be allocated.
|
||||
** There is a "backdoor", allowing to access any allocated block, even if it is considered
|
||||
** "released" by the terms of the usual lifecycle. Only when the provider object itself
|
||||
** gets destroyed, all allocated blocks will be discarded.
|
||||
**
|
||||
** @see DiagnosticOutputSlot
|
||||
** @see DiagnosticBufferProvider
|
||||
** @see buffer-provider-protocol-test.cpp
|
||||
*/
|
||||
|
||||
#ifndef STEAM_ENGINE_NAIVE_BUFFER_STEUP_H
|
||||
#define STEAM_ENGINE_NAIVE_BUFFER_STEUP_H
|
||||
|
||||
|
||||
#include "lib/error.hpp"
|
||||
#include "lib/hash-value.h"
|
||||
#include "steam/engine/buffer-provider-setup.hpp"
|
||||
#include "steam/engine/heap-mem-buffer-store.hpp"
|
||||
#include "lib/scoped-ptrvect.hpp"
|
||||
|
||||
#include <unordered_map>
|
||||
#include <memory>
|
||||
|
||||
|
||||
namespace steam {
|
||||
namespace engine {
|
||||
|
||||
namespace error = lumiera::error;
|
||||
|
||||
// using lib::HashVal;
|
||||
|
||||
#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1410 : disabled code to disentangle BufferProvider implementation
|
||||
namespace diagn {
|
||||
|
||||
using std::unique_ptr;
|
||||
|
||||
|
||||
/**
|
||||
* Helper for implementing a diagnostic BufferProvider:
|
||||
* A block of heap allocated storage, with the capability
|
||||
* to store some additional tracking information.
|
||||
*/
|
||||
class Block
|
||||
: util::NonCopyable
|
||||
{
|
||||
unique_ptr<char[]> storage_;
|
||||
|
||||
bool was_released_;
|
||||
|
||||
public:
|
||||
explicit
|
||||
Block(size_t bufferSize)
|
||||
: storage_(bufferSize? new char[bufferSize] : NULL)
|
||||
, was_released_(false)
|
||||
{ }
|
||||
|
||||
bool
|
||||
was_used() const
|
||||
{
|
||||
return bool(storage_);
|
||||
}
|
||||
|
||||
bool
|
||||
was_closed() const
|
||||
{
|
||||
return was_released_;
|
||||
}
|
||||
|
||||
void*
|
||||
accessMemory() const
|
||||
{
|
||||
REQUIRE (storage_, "Block was never prepared for use");
|
||||
return storage_.get();
|
||||
}
|
||||
|
||||
void
|
||||
markReleased()
|
||||
{
|
||||
was_released_ = true;
|
||||
}
|
||||
};
|
||||
|
||||
class BlockPool;
|
||||
|
||||
using PoolTable = std::unordered_map<HashVal,BlockPool>;
|
||||
}
|
||||
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1410 : (end) disabled code
|
||||
|
||||
|
||||
/**
|
||||
* simple BufferProvider implementation with additional allocation tracking.
|
||||
* @internal used as PImpl by DiagnosticBufferProvider and DiagnosticOutputSlot.
|
||||
*
|
||||
* This dummy implementation of the BufferProvider interface uses a linearly growing
|
||||
* table of heap allocated buffer blocks, which will never be discarded, unless the object
|
||||
* is discarded as a whole. There is an additional testing/diagnostics API to access the
|
||||
* tracked usage information, even when blocks are already marked as "released".
|
||||
*/
|
||||
class NaiveBufferSetup
|
||||
: public BufferProviderSetup
|
||||
{
|
||||
public:
|
||||
NaiveBufferSetup()
|
||||
: BufferProviderSetup{*this}
|
||||
{ }
|
||||
|
||||
auto buildStage() { return std::make_unique<Stage> ("Naive_HeapAllocated"); }
|
||||
auto buildStore() { return std::make_unique<HeapMemProvider>(); } /////////////////////////////////TICKET #1410 : turn into a subclass of BufferSetup::Store and push down implementation
|
||||
};
|
||||
|
||||
#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1410 : disabled code to disentangle BufferProvider implementation
|
||||
class HeapMemProvider
|
||||
: public BufferProvider
|
||||
{
|
||||
unique_ptr<diagn::PoolTable> pool_;
|
||||
ScopedPtrVect<diagn::Block> outSeq_;
|
||||
|
||||
public:
|
||||
/* === BufferProvider interface === */
|
||||
|
||||
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:
|
||||
~HeapMemProvider();
|
||||
HeapMemProvider();
|
||||
|
||||
size_t emittedCnt() const;
|
||||
|
||||
diagn::Block& access_emitted (uint bufferID);
|
||||
|
||||
template<typename TY>
|
||||
TY& accessAs (uint bufferID);
|
||||
|
||||
void markAllEmitted();
|
||||
|
||||
private:
|
||||
bool withinOutputSequence (uint bufferID) const;
|
||||
diagn::BlockPool& getBlockPoolFor (HashVal typeID);
|
||||
diagn::Block* locateBlock (HashVal typeID, void*);
|
||||
diagn::Block* searchInOutSeqeuence (void* storage);
|
||||
};
|
||||
|
||||
|
||||
|
||||
/** convenience shortcut: access the buffer with the given number,
|
||||
* then try to convert the raw memory to the templated type.
|
||||
* @throw error::Invalid if the required fame number is beyond
|
||||
* the number of buffers marked as "emitted"
|
||||
* @throw error::Fatal if conversion is not possible or the
|
||||
* conversion path chosen doesn't work (which might
|
||||
* be due to RTTI indicating an incompatible type).
|
||||
*/
|
||||
template<typename TY>
|
||||
TY&
|
||||
HeapMemProvider::accessAs (uint bufferID)
|
||||
{
|
||||
if (!withinOutputSequence (bufferID))
|
||||
throw error::Invalid ("Buffer with the given ID not yet emitted");
|
||||
|
||||
diagn::Block& memoryBlock = access_emitted (bufferID);
|
||||
TY* converted = std::launder (reinterpret_cast<TY*> (memoryBlock.accessMemory()));
|
||||
|
||||
REQUIRE (converted);
|
||||
return *converted;
|
||||
}
|
||||
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1410 : (end) disabled code
|
||||
|
||||
|
||||
|
||||
}} // namespace steam::engine
|
||||
#endif /*STEAM_ENGINE_NAIVE_BUFFER_STEUP_H*/
|
||||
|
|
@ -24,8 +24,8 @@
|
|||
|
||||
#include "steam/engine/render-environment.hpp"
|
||||
#include "steam/engine/engine-facilities.hpp"
|
||||
#include "steam/engine/naive-buffer-setup.hpp"
|
||||
#include "steam/engine/buffer-provider.hpp"
|
||||
#include "steam/engine/heap-mem-provider.hpp"
|
||||
|
||||
|
||||
namespace steam {
|
||||
|
|
@ -38,7 +38,7 @@ namespace engine{
|
|||
BufferProvider&
|
||||
getNaiveBufferManager()
|
||||
{
|
||||
static HeapMemProvider buffProvider; ////////////////////////////////////////////////////TICKET #1367 : only suitable for first prototype; should implement a bare bone memory manager instead
|
||||
static NaiveBufferSetup buffProvider; ///////////////////////////////////////////////////TICKET #1367 : only suitable for first prototype; should implement a bare bone memory manager instead
|
||||
return buffProvider;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
#include "lib/error.hpp"
|
||||
#include "lib/test/run.hpp"
|
||||
#include "steam/engine/heap-mem-provider.hpp"
|
||||
#include "steam/engine/diagnostic-buffer-provider.hpp"
|
||||
#include "steam/engine/buffhandle-attach.hpp"
|
||||
#include "steam/engine/testframe.hpp"
|
||||
|
||||
|
|
@ -60,7 +60,7 @@ namespace test {
|
|||
|
||||
/******************************************************************//**
|
||||
* @test verify support to write mock components for buffer management.
|
||||
* - HeapMemProvider is a „braindead“ implementation of the BufferProvider
|
||||
* - HeapMemBufferStore is a „braindead“ implementation of the BufferProvider
|
||||
* interface: it just claims new heap blocks and never de-allocates them.
|
||||
* - adding a layer of instrumentation, the DiagnosticBufferProvider allows
|
||||
* to count and verify allocated buffers and their content after the fact.
|
||||
|
|
@ -81,7 +81,7 @@ namespace test {
|
|||
void
|
||||
simpleExample()
|
||||
{
|
||||
HeapMemProvider provider; /////////////////////////////////////OOO should be DiagnosticBufferProvider
|
||||
DiagnosticBufferProvider provider;
|
||||
|
||||
BuffHandle testBuff = provider.lockBufferFor<TestFrame>();
|
||||
CHECK (testBuff);
|
||||
|
|
@ -93,15 +93,15 @@ namespace test {
|
|||
provider.emitBuffer (testBuff);
|
||||
provider.releaseBuffer(testBuff);
|
||||
|
||||
diagn::Block& block0 = provider.access_emitted(0);
|
||||
CHECK (testData(dataID) == block0.accessMemory());
|
||||
// diagn::Block& block0 = provider.access_emitted(0); ///////////////////////////////OOO provide suitable diagnostic API!
|
||||
// CHECK (testData(dataID) == block0.accessMemory());
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
verifyStandardCase()
|
||||
{
|
||||
HeapMemProvider provider; /////////////////////////////////////OOO should be DiagnosticBufferProvider
|
||||
DiagnosticBufferProvider provider;
|
||||
|
||||
BuffDescr buffType = provider.getDescriptorFor(TEST_ELM_SIZE);
|
||||
uint numElms = provider.announce(MAX_ELMS, buffType);
|
||||
|
|
@ -118,7 +118,7 @@ namespace test {
|
|||
|
||||
for (uint nr=0; nr<numElms; ++nr)
|
||||
{
|
||||
CHECK (verifyUsedBlock (nr, provider.access_emitted(nr)));
|
||||
// CHECK (verifyUsedBlock (nr, provider.access_emitted(nr))); ///////////////////////////////OOO provide suitable diagnostic API!
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -126,7 +126,7 @@ namespace test {
|
|||
void
|
||||
verifyTestProtocol()
|
||||
{
|
||||
HeapMemProvider provider; /////////////////////////////////////OOO should be DiagnosticBufferProvider
|
||||
DiagnosticBufferProvider provider;
|
||||
|
||||
BuffDescr buffType = provider.getDescriptorFor(TEST_ELM_SIZE);
|
||||
|
||||
|
|
@ -139,11 +139,11 @@ namespace test {
|
|||
// buffers are locked,
|
||||
// but still within the per-type allocation pool
|
||||
// while the output sequence is still empty
|
||||
CHECK (!provider.access_emitted(0).was_used());
|
||||
CHECK (!provider.access_emitted(1).was_used());
|
||||
CHECK (!provider.access_emitted(2).was_used());
|
||||
CHECK (!provider.access_emitted(3).was_used());
|
||||
CHECK (!provider.access_emitted(4).was_used());
|
||||
// CHECK (!provider.access_emitted(0).was_used()); ///////////////////////////////OOO provide suitable diagnostic API!
|
||||
// CHECK (!provider.access_emitted(1).was_used());
|
||||
// CHECK (!provider.access_emitted(2).was_used());
|
||||
// CHECK (!provider.access_emitted(3).was_used());
|
||||
// CHECK (!provider.access_emitted(4).was_used());
|
||||
|
||||
// can use the buffers for real
|
||||
bu1.accessAs<uint>() = 1;
|
||||
|
|
@ -152,7 +152,7 @@ namespace test {
|
|||
bu4.accessAs<uint>() = 4;
|
||||
bu5.accessAs<uint>() = 5;
|
||||
|
||||
CHECK (0 == provider.emittedCnt());
|
||||
// CHECK (0 == provider.emittedCnt()); ///////////////////////////////OOO provide suitable diagnostic API!
|
||||
|
||||
// now emit buffers in shuffled order
|
||||
provider.emitBuffer (bu3);
|
||||
|
|
@ -161,41 +161,41 @@ namespace test {
|
|||
provider.emitBuffer (bu4);
|
||||
provider.emitBuffer (bu2);
|
||||
|
||||
CHECK (5 == provider.emittedCnt());
|
||||
// CHECK (5 == provider.emittedCnt()); ///////////////////////////////OOO provide suitable diagnostic API!
|
||||
|
||||
CHECK (3 == provider.accessAs<uint>(0));
|
||||
CHECK (1 == provider.accessAs<uint>(1));
|
||||
CHECK (5 == provider.accessAs<uint>(2));
|
||||
CHECK (4 == provider.accessAs<uint>(3));
|
||||
CHECK (2 == provider.accessAs<uint>(4));
|
||||
// CHECK (3 == provider.accessAs<uint>(0)); ///////////////////////////////OOO provide suitable diagnostic API!
|
||||
// CHECK (1 == provider.accessAs<uint>(1));
|
||||
// CHECK (5 == provider.accessAs<uint>(2));
|
||||
// CHECK (4 == provider.accessAs<uint>(3));
|
||||
// CHECK (2 == provider.accessAs<uint>(4));
|
||||
|
||||
CHECK ( provider.access_emitted(0).was_used());
|
||||
CHECK ( provider.access_emitted(1).was_used());
|
||||
CHECK ( provider.access_emitted(2).was_used());
|
||||
CHECK ( provider.access_emitted(3).was_used());
|
||||
CHECK ( provider.access_emitted(4).was_used());
|
||||
// CHECK ( provider.access_emitted(0).was_used()); ///////////////////////////////OOO provide suitable diagnostic API!
|
||||
// CHECK ( provider.access_emitted(1).was_used());
|
||||
// CHECK ( provider.access_emitted(2).was_used());
|
||||
// CHECK ( provider.access_emitted(3).was_used());
|
||||
// CHECK ( provider.access_emitted(4).was_used());
|
||||
|
||||
CHECK (!provider.access_emitted(0).was_closed());
|
||||
CHECK (!provider.access_emitted(1).was_closed());
|
||||
CHECK (!provider.access_emitted(2).was_closed());
|
||||
CHECK (!provider.access_emitted(3).was_closed());
|
||||
CHECK (!provider.access_emitted(4).was_closed());
|
||||
// CHECK (!provider.access_emitted(0).was_closed());
|
||||
// CHECK (!provider.access_emitted(1).was_closed());
|
||||
// CHECK (!provider.access_emitted(2).was_closed());
|
||||
// CHECK (!provider.access_emitted(3).was_closed());
|
||||
// CHECK (!provider.access_emitted(4).was_closed());
|
||||
|
||||
bu5.release();
|
||||
CHECK (!provider.access_emitted(0).was_closed());
|
||||
CHECK (!provider.access_emitted(1).was_closed());
|
||||
CHECK ( provider.access_emitted(2).was_closed());
|
||||
CHECK (!provider.access_emitted(3).was_closed());
|
||||
CHECK (!provider.access_emitted(4).was_closed());
|
||||
// CHECK (!provider.access_emitted(0).was_closed());
|
||||
// CHECK (!provider.access_emitted(1).was_closed());
|
||||
// CHECK ( provider.access_emitted(2).was_closed());
|
||||
// CHECK (!provider.access_emitted(3).was_closed());
|
||||
// CHECK (!provider.access_emitted(4).was_closed());
|
||||
|
||||
bu2.release();
|
||||
bu2.release();
|
||||
bu5.release();
|
||||
CHECK (!provider.access_emitted(0).was_closed());
|
||||
CHECK (!provider.access_emitted(1).was_closed());
|
||||
CHECK ( provider.access_emitted(2).was_closed());
|
||||
CHECK (!provider.access_emitted(3).was_closed());
|
||||
CHECK ( provider.access_emitted(4).was_closed());
|
||||
// CHECK (!provider.access_emitted(0).was_closed());
|
||||
// CHECK (!provider.access_emitted(1).was_closed());
|
||||
// CHECK ( provider.access_emitted(2).was_closed());
|
||||
// CHECK (!provider.access_emitted(3).was_closed());
|
||||
// CHECK ( provider.access_emitted(4).was_closed());
|
||||
|
||||
CHECK (!bu2);
|
||||
CHECK (bu3);
|
||||
|
|
@ -204,7 +204,7 @@ namespace test {
|
|||
bu3.release();
|
||||
bu4.release();
|
||||
|
||||
CHECK (5 == provider.emittedCnt());
|
||||
// CHECK (5 == provider.emittedCnt()); ///////////////////////////////OOO provide suitable diagnostic API!
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
#include "steam/play/output-slot-connection.hpp"
|
||||
#include "steam/asset/meta/time-grid.hpp"
|
||||
#include "steam/engine/buffhandle.hpp"
|
||||
#include "steam/engine/heap-mem-provider.hpp"
|
||||
#include "steam/engine/naive-buffer-setup.hpp"
|
||||
#include "lib/time/timevalue.hpp"
|
||||
#include "lib/scoped-ptrvect.hpp"
|
||||
#include "lib/iter-source.hpp"
|
||||
|
|
@ -57,7 +57,7 @@ namespace play {
|
|||
using steam::asset::meta::TimeGrid;
|
||||
using steam::engine::BuffDescr;
|
||||
using steam::engine::test::TestFrame;
|
||||
using steam::engine::HeapMemProvider;
|
||||
using steam::engine::NaiveBufferSetup;
|
||||
namespace diagn = steam::engine::diagn;
|
||||
|
||||
//using std::vector;
|
||||
|
|
@ -94,7 +94,7 @@ namespace play {
|
|||
typedef std::unordered_set<FrameID> FrameTrackingInfo;
|
||||
|
||||
|
||||
HeapMemProvider buffProvider_;
|
||||
NaiveBufferSetup buffProvider_;
|
||||
BuffDescr bufferType_;
|
||||
|
||||
FrameTrackingInfo frameTrackingIndex_;
|
||||
|
|
@ -205,19 +205,21 @@ namespace play {
|
|||
TestFrame const *
|
||||
accessEmittedFrame (uint frameNr) const
|
||||
{
|
||||
if (frameNr < buffProvider_.emittedCnt())
|
||||
return & accessFrame(frameNr);
|
||||
else
|
||||
return 0; ////////////////////////////////TICKET #856
|
||||
UNIMPLEMENTED ("suitable diagnostic API");
|
||||
// if (frameNr < buffProvider_.emittedCnt()) ///////////////////////////////OOO provide suitable diagnostic API!
|
||||
// return & accessFrame(frameNr);
|
||||
// else
|
||||
// return 0; ////////////////////////////////TICKET #856
|
||||
}
|
||||
|
||||
diagn::Block const *
|
||||
accessEmittedBuffer (uint bufferNr) const
|
||||
{
|
||||
if (bufferNr < buffProvider_.emittedCnt())
|
||||
return & accessBlock(bufferNr);
|
||||
else
|
||||
return 0;
|
||||
UNIMPLEMENTED ("suitable diagnostic API");
|
||||
// if (bufferNr < buffProvider_.emittedCnt()) ///////////////////////////////OOO provide suitable diagnostic API!
|
||||
// return & accessBlock(bufferNr);
|
||||
// else
|
||||
// return 0;
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
@ -232,13 +234,15 @@ namespace play {
|
|||
TestFrame const&
|
||||
accessFrame (uint frameNr) const
|
||||
{
|
||||
return unConst(this)->buffProvider_.accessAs<TestFrame> (frameNr);
|
||||
UNIMPLEMENTED ("suitable diagnostic API");
|
||||
// return unConst(this)->buffProvider_.accessAs<TestFrame> (frameNr); ///////////////////////////////OOO provide suitable diagnostic API!
|
||||
}
|
||||
|
||||
diagn::Block const&
|
||||
accessBlock (uint bufferNr) const
|
||||
{
|
||||
return unConst(this)->buffProvider_.access_emitted (bufferNr);
|
||||
UNIMPLEMENTED ("suitable diagnostic API");
|
||||
// return unConst(this)->buffProvider_.access_emitted (bufferNr); ///////////////////////////////OOO provide suitable diagnostic API!
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -111619,8 +111619,50 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
|
|||
<node CREATED="1770670620982" ID="ID_1374029931" MODIFIED="1770670637618" TEXT="bisheriges »meta« wird zu BufferStage"/>
|
||||
<node CREATED="1770670643410" ID="ID_1778176571" MODIFIED="1770670684703" STYLE="fork" TEXT="bisheriges protected-Interface ⟶ als BufferStore herausziehen">
|
||||
<font NAME="SansSerif" SIZE="12"/>
|
||||
<node BACKGROUND_COLOR="#f8f1cb" COLOR="#a50125" CREATED="1770769772202" ID="ID_528640678" MODIFIED="1770769794715" TEXT="hier gibt es ein Problem: BufferProvider::buildHandle">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
<node CREATED="1770769806729" ID="ID_6936764" MODIFIED="1770769894796" TEXT="BuffHandle provideLockedBuffer(HashVal typeID) ⟶ sollte einen buildHandle() tail-call machen"/>
|
||||
<node CREATED="1770769796738" ID="ID_734223464" MODIFIED="1770769804669" TEXT="das war immer schon ein verwirrendes Ping-Pong"/>
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1770769951879" ID="ID_1852318741" MODIFIED="1770769977165" TEXT="noch schlimmer: es vermischt die Zonen der Implementierung">
|
||||
<icon BUILTIN="clanbomber"/>
|
||||
</node>
|
||||
<node CREATED="1770686248066" ID="ID_1851008076" MODIFIED="1770686264665" TEXT="Problem: Direktzugriffe auf die Implementierung">
|
||||
<node BACKGROUND_COLOR="#fafe99" COLOR="#fa002a" CREATED="1770769896480" ID="ID_426983823" MODIFIED="1770770474699" TEXT="und jetzt geht das nicht mehr: es wäre in einem anderen Objekt">
|
||||
<linktarget COLOR="#fe474d" DESTINATION="ID_426983823" ENDARROW="Default" ENDINCLINATION="387;17;" ID="Arrow_ID_1775599184" SOURCE="ID_1432411040" STARTARROW="None" STARTINCLINATION="57;-420;"/>
|
||||
<icon BUILTIN="broken-line"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#f8f1cb" COLOR="#a50125" CREATED="1770771226721" ID="ID_1487577652" MODIFIED="1770771248247" TEXT="auch der DiagnosticBufferProvider verwendet ein Basis_API: getBufferSize()">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1770770126934" ID="ID_850948251" MODIFIED="1770770161242" TEXT="⟹ API-Anpassung notwendig">
|
||||
<icon BUILTIN="yes"/>
|
||||
<node COLOR="#5b280f" CREATED="1770770251820" ID="ID_415070649" MODIFIED="1770770275197" TEXT="das bisherge API vermischt ohnehin die Themen">
|
||||
<icon BUILTIN="closed"/>
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#8a050d" CREATED="1770770278057" ID="ID_1578952294" MODIFIED="1770770325897" TEXT="da muß noch mehr aufgeräumt werden">
|
||||
<font NAME="SansSerif" SIZE="10"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#b9010b" CREATED="1770770286619" ID="ID_7825032" MODIFIED="1770770342689">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
auch <font face="Monospaced"><b>mark_emitted</b></font> ist gar nicht die Aufgabe des Store!
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
<font NAME="SansSerif" SIZE="10"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1770770350662" ID="ID_1511113078" MODIFIED="1770770378417" TEXT="Lösung ist offensichtlich: auseinander-fädeln">
|
||||
<icon BUILTIN="yes"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#f8f1cb" COLOR="#a50125" CREATED="1770686248066" ID="ID_1851008076" MODIFIED="1770757878094" TEXT="Problem: Direktzugriffe auf die Implementierung">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
<node CREATED="1770686275053" ID="ID_209445247" MODIFIED="1770686293057" TEXT="DiagnosticBufferProvider"/>
|
||||
<node CREATED="1770686294571" ID="ID_863555746" MODIFIED="1770686305232" TEXT="die Unit-Tests, auch der Default-Impl"/>
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1770686306406" ID="ID_1827512455" MODIFIED="1770686326442" TEXT="der DiagnosticOutputSlot">
|
||||
|
|
@ -111745,6 +111787,163 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
|
|||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1770757859605" ID="ID_163465122" MODIFIED="1770757872278" TEXT="HeapMemProvider umbauen">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node CREATED="1770757895680" ID="ID_1960520353" MODIFIED="1770757908583" TEXT="Vorgabe: soll weiterhin einfach default-konstruierbar sein"/>
|
||||
<node CREATED="1770757909670" ID="ID_899228213" MODIFIED="1770757919979" TEXT="in zwei Klassen zerlegen">
|
||||
<node CREATED="1770757938096" ID="ID_1866831594" MODIFIED="1770757943634" TEXT="NaiveBufferSetup">
|
||||
<node CREATED="1770757989787" ID="ID_618017726" MODIFIED="1770757995233" TEXT="header-only"/>
|
||||
<node CREATED="1770757996216" ID="ID_1198089703" MODIFIED="1770758004237" TEXT="lediglich ein Config-Record"/>
|
||||
</node>
|
||||
<node CREATED="1770757944571" ID="ID_1207399538" MODIFIED="1770757950804" TEXT="HeapMemBufferStore">
|
||||
<node CREATED="1770757971118" ID="ID_1706663250" MODIFIED="1770757975834" TEXT="hpp|cpp"/>
|
||||
<node CREATED="1770762597016" ID="ID_1432411040" MODIFIED="1770770474699" TEXT="glücklicher Zufall: die Implementierung greift fast nicht auf BufferProvider-Interna durch">
|
||||
<arrowlink COLOR="#fe474d" DESTINATION="ID_426983823" ENDARROW="Default" ENDINCLINATION="387;17;" ID="Arrow_ID_1775599184" STARTARROW="None" STARTINCLINATION="57;-420;"/>
|
||||
<linktarget COLOR="#feeace" DESTINATION="ID_1432411040" ENDARROW="Default" ENDINCLINATION="-12;81;" ID="Arrow_ID_76937966" SOURCE="ID_100975131" STARTARROW="None" STARTINCLINATION="-199;19;"/>
|
||||
<icon BUILTIN="idea"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1770762458610" ID="ID_875010759" MODIFIED="1770762816021" TEXT="DiagnosticBufferProvider anpassen">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node CREATED="1770762470929" ID="ID_424124774" MODIFIED="1770762479035" TEXT="das bleibt definitiv ein BufferProvider"/>
|
||||
<node CREATED="1770762480074" ID="ID_491907312" MODIFIED="1770762498009" TEXT="⟹ muß nun von BufferProviderSetup erben"/>
|
||||
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1770762499600" ID="ID_578552888" MODIFIED="1770762808614" TEXT="wird sich dann aber in die Implementierungen einschleifen">
|
||||
<icon BUILTIN="yes"/>
|
||||
<icon BUILTIN="hourglass"/>
|
||||
<node CREATED="1770762537848" ID="ID_744233976" MODIFIED="1770762552653" TEXT="zunächst noch delegiert er direkt an HeapMemBufferStore">
|
||||
<node CREATED="1770762554389" ID="ID_1159011250" MODIFIED="1770762561380" TEXT="das war ja früher mal ein BufferProvider"/>
|
||||
<node CREATED="1770762562345" ID="ID_1608322135" MODIFIED="1770762574873" TEXT="und hat ein (ungeschickt) verbreitertes API"/>
|
||||
<node CREATED="1770762576523" ID="ID_100975131" MODIFIED="1770766811720" TEXT="hatte aber Glück im Unglück">
|
||||
<arrowlink COLOR="#feeace" DESTINATION="ID_1432411040" ENDARROW="Default" ENDINCLINATION="-12;81;" ID="Arrow_ID_76937966" STARTARROW="None" STARTINCLINATION="-199;19;"/>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1770762675673" ID="ID_246224479" MODIFIED="1770762789759" TEXT="soll dann aber im nächsten Schritt das Tracking selber implementieren">
|
||||
<icon BUILTIN="hourglass"/>
|
||||
</node>
|
||||
<node CREATED="1770762688231" ID="ID_1626867644" MODIFIED="1770762782204" TEXT="und wird sich dafür vstl. Dekoratoren über die Implementierungs-Klassen legen">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
idealerweise funktioniert das sogar ohne dynamic-cast: denn die Dekoratoren könnten direkt per callback-λ verdrahtet sein
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
<icon BUILTIN="idea"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1770765035161" ID="ID_763895589" MODIFIED="1770765044567" TEXT="wie generisch wird das sein?">
|
||||
<icon BUILTIN="help"/>
|
||||
<node CREATED="1770765047151" ID="ID_1369329762" MODIFIED="1770765133094">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
<u><font color="#210aa6">Frage</font></u><font color="#210aa6">:</font> kann <font face="Monospaced" color="#5b3535">ProviderBufferProvider</font> einen <i>beliebigen</i>  <font face="Monospaced" color="#5b3535">DiagnosticBuffer</font> instrumentieren?
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
<node CREATED="1770765146770" ID="ID_763561545" MODIFIED="1770765167773" TEXT="⟹ gewisse Limitierungen sind zwangsläufig">
|
||||
<node CREATED="1770765183203" ID="ID_798928441" MODIFIED="1770765202678" TEXT="die Instrumentierung muß vor dem Einsatz aufgebaut werden"/>
|
||||
<node CREATED="1770765205184" ID="ID_1324258640" MODIFIED="1770765221801" TEXT="insofern muß die DiagnosticBufferProvider-Instanz vorher existieren"/>
|
||||
<node CREATED="1770765224298" ID="ID_20191492" MODIFIED="1770765244749" TEXT="aus Gründen der Einfachheit soll DiagnosticProvider selber der BufferProvider sein"/>
|
||||
<node CREATED="1770765260219" ID="ID_901586804" MODIFIED="1770765300102" TEXT="⟹ das bedeutet: das Ziel der Instrumentierung muß »kanibalisiert« werden">
|
||||
<font NAME="SansSerif" SIZE="12"/>
|
||||
</node>
|
||||
<node CREATED="1770765321000" ID="ID_1181670397" MODIFIED="1770765383761">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
⟹ jedweder State des BufferProvider <b>muß</b> in den zwei Implementierungs-Säulen liegen
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
<node CREATED="1770765436568" ID="ID_149178331" MODIFIED="1770765532514">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
(alternativ müßte <i>ausschließlich</i> ein Diagnose-Accessor erzeugt werden)
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
das sagt auch der Name, es wäre dann kein <font face="Monospaced">BufferProvider</font>...
|
||||
</p>
|
||||
<p>
|
||||
Und ein solches <i>alternatives</i> Nutz-Szenario wäre in der Tat denkbar, müßte dann aber eigens und daneben stehend implementiert werden
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1770765542064" ID="ID_33780277" MODIFIED="1770765572176" TEXT="idealerweise sollte aber DiagnosticBufferProvider nicht von der konkreten Impl abhängig sein">
|
||||
<icon BUILTIN="yes"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#ccb59b" COLOR="#6e2a38" CREATED="1770765576724" ID="ID_1961847255" MODIFIED="1770765581656" TEXT="Beschluß">
|
||||
<font ITALIC="true" NAME="SansSerif" SIZE="14"/>
|
||||
<icon BUILTIN="yes"/>
|
||||
<node CREATED="1770765583502" ID="ID_1200358280" MODIFIED="1770765677346" TEXT="wir halten diese Möglichkeiten alle explizit offen">
|
||||
<icon BUILTIN="yes"/>
|
||||
</node>
|
||||
<node CREATED="1770765595718" ID="ID_962837679" MODIFIED="1770766950666" TEXT="zunächst wird aber nur die einfachste Lösung implementiert (KISS)">
|
||||
<icon BUILTIN="yes"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1770765611528" ID="ID_930758460" MODIFIED="1770766965294" TEXT="und das wäre, direkt von NaiveBufferSetup zu erben">
|
||||
<icon BUILTIN="forward"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1770765634549" ID="ID_802045878" MODIFIED="1770765677346" TEXT="Konsequenz ⟹ BufferProviderSetup muß die Dekorations-Mechanik generisch anbieten">
|
||||
<icon BUILTIN="yes"/>
|
||||
<node CREATED="1770765700160" ID="ID_1579675471" LINK="https://en.cppreference.com/w/cpp/language/access.html#Protected_member_access" MODIFIED="1770766571232" TEXT="Thema: Sichtbarkeit von protected elements">
|
||||
<arrowlink COLOR="#4f5d8f" DESTINATION="ID_1070045765" ENDARROW="Default" ENDINCLINATION="-1154;119;" ID="Arrow_ID_484648111" STARTARROW="None" STARTINCLINATION="-1340;84;"/>
|
||||
</node>
|
||||
<node CREATED="1770766854965" ID="ID_164565147" MODIFIED="1770766871197" TEXT="man muß einen unique_ptr eines Dekorators erzeugen können"/>
|
||||
<node CREATED="1770766872225" ID="ID_1590901542" MODIFIED="1770766901998" TEXT="dieser Dekorator muß den ursprünglichen unique_ptr „huckepack“ nehmen"/>
|
||||
<node CREATED="1770766910933" ID="ID_1255549720" MODIFIED="1770766930079" TEXT="damit kann sich eine abgeleitete Klasse in bestehende Chains »einschleifen«"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1770771357183" ID="ID_1793741597" MODIFIED="1770771891888" TEXT="DiagnosticBufferProviderTest anpassen">
|
||||
<icon BUILTIN="flag-pink"/>
|
||||
<node COLOR="#d70247" CREATED="1770771371541" ID="ID_318424657" MODIFIED="1770771443467" TEXT="der hat bisher gar nicht auf dem DiagnosticBufferProvider gearbeitet">
|
||||
<icon BUILTIN="broken-line"/>
|
||||
</node>
|
||||
<node COLOR="#5b280f" CREATED="1770771385939" ID="ID_1071035672" MODIFIED="1770771428112" TEXT="sondern „wild“ auf das HeapMemProvider-API daneben zugegriffen">
|
||||
<icon BUILTIN="closed"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1770771747922" ID="ID_246706757" MODIFIED="1770771768414" TEXT="gilt auch für DiagnosticOutputSlot">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
</node>
|
||||
<node CREATED="1770771469374" ID="ID_733817882" MODIFIED="1770771479444" TEXT="problematische Zugriffe">
|
||||
<node CREATED="1770771484104" ID="ID_833241344" MODIFIED="1770771491247" TEXT="provider.accessEmitted(nr)"/>
|
||||
<node CREATED="1770771513515" ID="ID_1719397050" MODIFIED="1770771523955" TEXT="provider.accessAs<Type>(nr)"/>
|
||||
<node CREATED="1770771552023" ID="ID_1783764547" MODIFIED="1770771558695" TEXT="provider.emittedCnt()"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
|
|
@ -158620,7 +158819,7 @@ std::cout << tmpl.render({"what", "World"}) << s
|
|||
<node CREATED="1734709116112" ID="ID_1235302182" MODIFIED="1734709126137" TEXT="unterscheide explizit und implizit">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
</node>
|
||||
<node CREATED="1734708975355" ID="ID_1311116905" MODIFIED="1734712892968" TEXT="explicit convertible">
|
||||
<node CREATED="1734708975355" FOLDED="true" ID="ID_1311116905" MODIFIED="1734712892968" TEXT="explicit convertible">
|
||||
<linktarget COLOR="#8c85c9" DESTINATION="ID_1311116905" ENDARROW="Default" ENDINCLINATION="-3938;658;" ID="Arrow_ID_974872159" SOURCE="ID_1098163848" STARTARROW="None" STARTINCLINATION="-405;33;"/>
|
||||
<node CREATED="1734708872513" ID="ID_179340258" MODIFIED="1734709676425" TEXT="es ist nicht ganz klar was damit gemeint ist....">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
|
|
@ -158656,6 +158855,61 @@ std::cout << tmpl.render({"what", "World"}) << s
|
|||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1770766014454" ID="ID_1109377879" MODIFIED="1770766020966" TEXT="rules...">
|
||||
<node CREATED="1770766044584" ID="ID_397656010" MODIFIED="1770766178305" TEXT="private member access">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
Gilt stets auch für <i>andere Objekt-Instanzen</i> des gleichen Typs. Gilt auch für nested Classes, und member functions, und nested Classes in member functions; wobei allerdings, die Instanz muß man explizit in der Hand haben (es gibt hier keine solche »magic« wie in Java, wo eine non-static nested class automatisch auch einen outer.this-ptr bekommt)
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
<node CREATED="1770765867372" ID="ID_1070045765" MODIFIED="1770766571232" TEXT="protected member access">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
konzeptionell: das ist ein separates API für abgeleitete Klassen
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
<linktarget COLOR="#4f5d8f" DESTINATION="ID_1070045765" ENDARROW="Default" ENDINCLINATION="-1154;119;" ID="Arrow_ID_484648111" SOURCE="ID_1579675471" STARTARROW="None" STARTINCLINATION="-1340;84;"/>
|
||||
<node CREATED="1770765894191" ID="ID_399765269" MODIFIED="1770766423176" TEXT="nur auf Instanzen des gleichen, abgeleiteten Typs">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
Man muß unterscheiden zwischen Deklarationen und dem Zugang zu konkreten Members. <i>Deklarationen</i> sieht jede abgeleitete Klasse. Aber auf <i>protected Members</i> in einer Basisklasse zugreifen kann man <b>nur</b> durch eine Instanz einer abgeleiteten Klasse; und zwar muß der Typ dieser Instanz <b>gleich</b> (oder abgeleitet) sein wie der Typ, aus dem heraus der Code zugreift. Konkret: auf base.member kann ich nur durch eine derived& zugreifen (das schließt *this ein). Aber nicht durch irgend ein anderes Objekt oder eine base&
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
<node CREATED="1770765911615" ID="ID_247300867" MODIFIED="1770766562132" TEXT="sonst könnte eine abgeleitete Klasse eine fremde abgeleitete Klasse manipulieren">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
Ohne diese Regel wären wilde Kreuz-Zugriffe auf komplett andere Vererbungslinien möglich; man bedenke im Besonderen, daß die Situation durch Mehrfachvererbung ziemlich komplex sein kann; zudem kann eine andere abgeleitete Klasse die Basis auf komplexe Weise instrumentiert haben, und ein solcher Kreuz-Zugriff könnte das alles unterlaufen. Es ist ja ohnehin ein Zugeständnis, daß man auf was anderes als *this überhaupt zugreifen darf.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1734712757872" ID="ID_562062528" MODIFIED="1734712773062" TEXT="λ">
|
||||
<font NAME="SansSerif" SIZE="16"/>
|
||||
<node CREATED="1734711676585" ID="ID_338918761" MODIFIED="1734712797437" TEXT="λ-Funktionspointer decay">
|
||||
|
|
|
|||
Loading…
Reference in a new issue