BufferProvider: remove rest of the old implementation
__note__: regarding hash-standard.hpp see Ticket #1422 Mostly this hack worked -- but it is very likely not needed any more. Today I had to re-wire a partial specialisation for hashing pointers, that was added somewhere in the past into the STL.
This commit is contained in:
parent
7652ca05cd
commit
5686694999
4 changed files with 51 additions and 365 deletions
|
|
@ -44,9 +44,11 @@
|
||||||
** Please ensure it is always included _before_ the latter. Failing to do so will result
|
** Please ensure it is always included _before_ the latter. Failing to do so will result
|
||||||
** in mysterious failures.
|
** in mysterious failures.
|
||||||
**
|
**
|
||||||
** @todo 4/2014 doesn't work as expected. My suspicion is that in the actual use case (PlacementIndex),
|
** @todo 4/2026 this shady trickery works without problems since many years now,
|
||||||
** the type providing the hasher is mixed in through inheritance, and the template specialisation
|
** while it is not clear if we actually need to do these horrible things any more.
|
||||||
** for this base type is not considered on lookup. ///////TICKET #722
|
** Even while we may retain that automatic bridge to boost-functional hash, doing so
|
||||||
|
** should be possible with the current STDLIB without having to patch and rewire
|
||||||
|
** the library implementation. //////////////////////////////////////////////////////////////////////TICKET #1422 : re-assess the situation !
|
||||||
**
|
**
|
||||||
** @see HashIndexed
|
** @see HashIndexed
|
||||||
** @see LUID
|
** @see LUID
|
||||||
|
|
@ -106,10 +108,6 @@ namespace std {
|
||||||
{
|
{
|
||||||
static_assert (sizeof(TY) < 0, "No hash implementation found. "
|
static_assert (sizeof(TY) < 0, "No hash implementation found. "
|
||||||
"Either specialise std::hash or provide a boost-style hash_value via ADL.");
|
"Either specialise std::hash or provide a boost-style hash_value via ADL.");
|
||||||
|
|
||||||
// the default provides *no* hash implementation
|
|
||||||
// and adds a marker type for metaprogramming
|
|
||||||
typedef int NotHashable;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -129,8 +127,8 @@ namespace std {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Primary class template for std::hash.
|
* Primary class template for std::hash.
|
||||||
* We provide no default implementation, but a marker type
|
* We provide no default implementation, but bridge automatically
|
||||||
* to allow detection of custom implementation through metaprogramming
|
* when a boost-style hash function can be picked up via ADL.
|
||||||
*
|
*
|
||||||
* @note this definition has been \em hijacked by Lumiera
|
* @note this definition has been \em hijacked by Lumiera
|
||||||
* to add an automatic bridge to use boost::hash functions
|
* to add an automatic bridge to use boost::hash functions
|
||||||
|
|
@ -140,12 +138,14 @@ namespace std {
|
||||||
: public _HashImplementationSelector<TY>
|
: public _HashImplementationSelector<TY>
|
||||||
{ };
|
{ };
|
||||||
|
|
||||||
}
|
}// namespace std
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* ==== Evil Evil ==== */
|
|
||||||
|
|
||||||
|
/* ==== Evil Evil ==== */ ////////////////////////////////////////////////////////////////TICKET #1422 : very likely we do not need this manipulation any more !!!
|
||||||
|
|
||||||
#define hash hash_HIDDEN
|
#define hash hash_HIDDEN
|
||||||
#define _Hash_impl _Hash_impl_HIDDEN
|
#define _Hash_impl _Hash_impl_HIDDEN
|
||||||
|
|
@ -204,6 +204,12 @@ namespace std {
|
||||||
STD_HASH_IMPL (long double)
|
STD_HASH_IMPL (long double)
|
||||||
|
|
||||||
#undef STD_HASH_IMPL
|
#undef STD_HASH_IMPL
|
||||||
}
|
|
||||||
|
/** rewire the partial specialisation for pointer types */
|
||||||
|
template<typename TY>
|
||||||
|
struct hash<TY*> : public hash_HIDDEN<TY*> { };
|
||||||
|
|
||||||
|
|
||||||
|
}// namespace std
|
||||||
|
|
||||||
#endif /*LIB_HASH_STANDARD_H*/
|
#endif /*LIB_HASH_STANDARD_H*/
|
||||||
|
|
|
||||||
|
|
@ -27,8 +27,9 @@
|
||||||
** are configured as part of starting the steam::engine::RenderEnvironment.
|
** are configured as part of starting the steam::engine::RenderEnvironment.
|
||||||
** @todo who is responsible for setup of the services for the actual render engine?
|
** @todo who is responsible for setup of the services for the actual render engine?
|
||||||
** Might be closely related to brining up façade interfaces.
|
** Might be closely related to brining up façade interfaces.
|
||||||
** @todo WIP-WIP 1/2026 provide a default implementation for test
|
** @todo WIP-WIP 1/2026
|
||||||
** and find a way to populate the Facilities with the
|
** - ✔ provide a default implementation for test
|
||||||
|
** - 🔁 find a way to populate the Facilities with the
|
||||||
** production variant of the services...
|
** production variant of the services...
|
||||||
**
|
**
|
||||||
** @see engine-ctx-test.cpp
|
** @see engine-ctx-test.cpp
|
||||||
|
|
|
||||||
|
|
@ -14,262 +14,38 @@
|
||||||
|
|
||||||
/** @file heap-mem-buffer-store.cpp
|
/** @file heap-mem-buffer-store.cpp
|
||||||
** Implementation details of simple heap based engine::BufferProvider storage.
|
** Implementation details of simple heap based engine::BufferProvider storage.
|
||||||
|
** This BufferStore implementation is configured by default and thus used primarily
|
||||||
|
** from the unit tests; for that reasons, some additional sanity checks were added,
|
||||||
|
** and the implementation is wasteful and not performance oriented. Furthermore,
|
||||||
|
** aspects of concurrency safety were not considered.
|
||||||
|
**
|
||||||
|
** For each allocation, a new vault::mem::HeapMemBufferStore::Alloc entry is attached
|
||||||
|
** to the index table, which allows follow-up calls to rediscover this management entry
|
||||||
|
** just based on the memory address of the allocation. These entries manage the actual
|
||||||
|
** allocations, and **will be retained** for the lifespan of the BufferStore instance.
|
||||||
|
** This allows diagnostic code to investigate the contents of the buffers
|
||||||
|
** after invoking the code subject to testing.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "lib/error.hpp"
|
#include "lib/error.hpp"
|
||||||
#include "lib/integral.hpp"
|
#include "lib/integral.hpp"
|
||||||
#include "include/logging.h"
|
|
||||||
#include "lib/scoped-ptrvect.hpp"
|
|
||||||
#include "vault/mem/buffer-metadata.hpp"
|
#include "vault/mem/buffer-metadata.hpp"
|
||||||
#include "lib/format-string.hpp"
|
#include "lib/format-string.hpp"
|
||||||
#include "lib/format-obj.hpp"
|
#include "lib/format-obj.hpp"
|
||||||
#include "lib/util-foreach.hpp"
|
|
||||||
#include "lib/nocopy.hpp"
|
#include "lib/nocopy.hpp"
|
||||||
|
|
||||||
#include "vault/mem/heap-mem-buffer-store.hpp"
|
#include "vault/mem/heap-mem-buffer-store.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <vector>
|
|
||||||
#include <array>
|
|
||||||
|
|
||||||
using util::and_all;
|
|
||||||
using std::vector;
|
|
||||||
using std::array;
|
|
||||||
using lib::ScopedPtrVect;
|
|
||||||
using util::contains;
|
using util::contains;
|
||||||
using util::_Fmt;
|
using util::_Fmt;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
namespace vault {
|
namespace vault {
|
||||||
namespace mem {
|
namespace mem {
|
||||||
namespace err = lumiera::error;
|
namespace err = lumiera::error;
|
||||||
|
|
||||||
|
namespace { // internal config and helpers...
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET 1410 : need to question what implementation structures are needed, after »tracking« was extracted...
|
|
||||||
/**
|
|
||||||
* Simplistic implementation of buffer storage.
|
|
||||||
* Allocates a block of heap memory for buffers and never deallocates.
|
|
||||||
* This strange behaviour can be used to investigate and demonstrate
|
|
||||||
* buffer usage from a unit test setup.
|
|
||||||
* @see DiagnosticBufferProvider
|
|
||||||
*/
|
|
||||||
class HeapMemBufferStore::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;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
namespace { // implementation helpers...
|
|
||||||
|
|
||||||
inline Buff*
|
|
||||||
asBuffer(void* mem)
|
|
||||||
{// type tag to mark memory address as Buffer
|
|
||||||
return static_cast<Buff*> (mem);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
using Block = HeapMemBufferStore::Block;
|
|
||||||
|
|
||||||
/** helper to find Block entries
|
|
||||||
* based on their raw memory address */
|
|
||||||
inline bool
|
|
||||||
identifyBlock (Block const& inQuestion, void* storage)
|
|
||||||
{
|
|
||||||
return storage == &inQuestion;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** build a searching predicate */
|
|
||||||
inline function<bool(Block const&)>
|
|
||||||
search_for_block_using_this_storage (void* storage)
|
|
||||||
{
|
|
||||||
return bind (identifyBlock, _1, storage);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class VEC>
|
|
||||||
inline Block*
|
|
||||||
pick_Block_by_storage (VEC& vec, void* blockLocation)
|
|
||||||
{
|
|
||||||
typename VEC::iterator pos
|
|
||||||
= std::find_if (vec.begin(),vec.end()
|
|
||||||
,search_for_block_using_this_storage(blockLocation));
|
|
||||||
if (pos!=vec.end())
|
|
||||||
return &(*pos);
|
|
||||||
else
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET 1410 : need to question what implementation structures are needed, after »tracking« was extracted...
|
|
||||||
|
|
||||||
using PoolBlocks = ScopedPtrVect<HeapMemBufferStore::Block>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @internal Pool of allocated buffer Blocks of a specific size.
|
|
||||||
* Helper for implementing a Diagnostic BufferProvider; actually does
|
|
||||||
* just heap allocations for the Blocks, but keeps a collection of
|
|
||||||
* allocated Blocks around. Individual entries can be retrieved
|
|
||||||
* and thus removed from the responsibility of BlockPool.
|
|
||||||
*
|
|
||||||
* The idea is that each buffer starts its lifecycle within some pool
|
|
||||||
* and later gets "emitted" to an output sequence, where it remains for
|
|
||||||
* later investigation and diagnostics.
|
|
||||||
*/
|
|
||||||
class HeapMemBufferStore::BlockPool
|
|
||||||
{
|
|
||||||
uint maxAllocCount_;
|
|
||||||
size_t memBlockSize_;
|
|
||||||
using PoolBlocks = ScopedPtrVect<Block>;
|
|
||||||
PoolBlocks blockList_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
BlockPool()
|
|
||||||
: maxAllocCount_(0) // unlimited by default
|
|
||||||
, memBlockSize_(0)
|
|
||||||
, blockList_{}
|
|
||||||
{ }
|
|
||||||
|
|
||||||
void
|
|
||||||
initialise (size_t blockSize)
|
|
||||||
{
|
|
||||||
memBlockSize_ = blockSize;
|
|
||||||
}
|
|
||||||
// standard copy operations are valid, but will
|
|
||||||
// raise an runtime error, once BlockPool is initialised.
|
|
||||||
|
|
||||||
~BlockPool()
|
|
||||||
{
|
|
||||||
if (!verify_all_children_idle())
|
|
||||||
ERROR (test, "Block actively in use while shutting down BufferProvider "
|
|
||||||
"allocation pool. This might lead to Segfault and memory leaks.");
|
|
||||||
}
|
|
||||||
|
|
||||||
/** mark all managed blocks as disposed */
|
|
||||||
void
|
|
||||||
discard()
|
|
||||||
{
|
|
||||||
for (Block& block : blockList_)
|
|
||||||
block.markReleased();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint
|
|
||||||
prepare_for (uint number_of_expected_buffers)
|
|
||||||
{
|
|
||||||
if (maxAllocCount_ &&
|
|
||||||
maxAllocCount_ < blockList_.size() + number_of_expected_buffers)
|
|
||||||
{
|
|
||||||
ASSERT (maxAllocCount_ >= blockList_.size());
|
|
||||||
return maxAllocCount_ - blockList_.size();
|
|
||||||
}
|
|
||||||
// currently no hard limit imposed
|
|
||||||
return number_of_expected_buffers;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Block&
|
|
||||||
createBlock()
|
|
||||||
{
|
|
||||||
return blockList_.manage (new Block(memBlockSize_));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Block*
|
|
||||||
find (void* blockLocation)
|
|
||||||
{
|
|
||||||
return pick_Block_by_storage (blockList_, blockLocation);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Block*
|
|
||||||
transferResponsibility (Block* allocatedBlock)
|
|
||||||
{
|
|
||||||
return blockList_.detach (allocatedBlock);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
size_t
|
|
||||||
size() const
|
|
||||||
{
|
|
||||||
return blockList_.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
isValid() const
|
|
||||||
{
|
|
||||||
return not blockList_.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
explicit
|
|
||||||
operator bool() const
|
|
||||||
{
|
|
||||||
return isValid();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool
|
|
||||||
verify_all_children_idle()
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
return and_all (blockList_, is_in_sane_state);
|
|
||||||
}
|
|
||||||
ERROR_LOG_AND_IGNORE (test, "State verification of diagnostic BufferProvider allocation pool");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static bool
|
|
||||||
is_in_sane_state (Block const& block)
|
|
||||||
{
|
|
||||||
return not block.was_used() or block.was_closed();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET 1410 : need to question what implementation structures are needed, after »tracking« was extracted...
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
namespace { // Details of allocation and accounting
|
|
||||||
|
|
||||||
const uint MAX_BUFFERS = 50;
|
|
||||||
|
|
||||||
Block emptyPlaceholder(0);
|
|
||||||
|
|
||||||
using StorageWord = uint64_t;
|
using StorageWord = uint64_t;
|
||||||
constexpr inline size_t WORD_SIZ = sizeof(StorageWord);
|
constexpr inline size_t WORD_SIZ = sizeof(StorageWord);
|
||||||
|
|
@ -285,19 +61,21 @@ namespace mem {
|
||||||
{
|
{
|
||||||
return ceilDiv (sizeRequest, WORD_SIZ);
|
return ceilDiv (sizeRequest, WORD_SIZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
static_assert (0 == wordCnt(0));
|
static_assert (0 == wordCnt(0));
|
||||||
static_assert (1 == wordCnt(1));
|
static_assert (1 == wordCnt(1));
|
||||||
static_assert (1 == wordCnt(WORD_SIZ));
|
static_assert (1 == wordCnt(WORD_SIZ));
|
||||||
|
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
zeroFill (void* buf, size_t cnt)
|
zeroFill (void* buf, size_t cnt)
|
||||||
{
|
{
|
||||||
auto begin = static_cast<StorageWord*> (buf);
|
auto begin = static_cast<StorageWord*> (buf);
|
||||||
std::fill (begin, begin+cnt, StorageWord(0));
|
std::fill (begin, begin+cnt, StorageWord(0));
|
||||||
}
|
}
|
||||||
|
} //(END) Internals
|
||||||
} // (END) Details of allocation and accounting
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -313,7 +91,7 @@ namespace mem {
|
||||||
Buff* mem_{nullptr};
|
Buff* mem_{nullptr};
|
||||||
size_t siz_{0};
|
size_t siz_{0};
|
||||||
BufferState state_{NIL};
|
BufferState state_{NIL};
|
||||||
|
|
||||||
void
|
void
|
||||||
__requireState (BufferState expected)
|
__requireState (BufferState expected)
|
||||||
{
|
{
|
||||||
|
|
@ -324,7 +102,7 @@ namespace mem {
|
||||||
,LERR_(LIFECYCLE)
|
,LERR_(LIFECYCLE)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
allocate (size_t cnt)
|
allocate (size_t cnt)
|
||||||
{
|
{
|
||||||
|
|
@ -412,13 +190,10 @@ namespace mem {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @internal create a memory tracking BufferProvider,
|
|
||||||
*/
|
|
||||||
HeapMemBufferStore::HeapMemBufferStore()
|
HeapMemBufferStore::HeapMemBufferStore()
|
||||||
: allocIdx_{}
|
: allocIdx_{}
|
||||||
, pool_(new PoolTable)
|
|
||||||
, outSeq_()
|
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
HeapMemBufferStore::~HeapMemBufferStore() { /* dtor of index table -> de-allocation here */ }
|
HeapMemBufferStore::~HeapMemBufferStore() { /* dtor of index table -> de-allocation here */ }
|
||||||
|
|
@ -427,6 +202,7 @@ namespace mem {
|
||||||
|
|
||||||
/* ==== Implementation of the BufferProvider interface ==== */
|
/* ==== Implementation of the BufferProvider interface ==== */
|
||||||
|
|
||||||
|
/** @note pre-anouncement is ignored */
|
||||||
uint
|
uint
|
||||||
HeapMemBufferStore::prepareBuffers (HashVal, uint numBuffers, size_t)
|
HeapMemBufferStore::prepareBuffers (HashVal, uint numBuffers, size_t)
|
||||||
{
|
{
|
||||||
|
|
@ -434,6 +210,7 @@ namespace mem {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** API: create a new buffer allocation */
|
||||||
BuffAlloc
|
BuffAlloc
|
||||||
HeapMemBufferStore::provideBuffer (HashVal, size_t buffSiz, LocalTag specifics, int64_t)
|
HeapMemBufferStore::provideBuffer (HashVal, size_t buffSiz, LocalTag specifics, int64_t)
|
||||||
{
|
{
|
||||||
|
|
@ -442,6 +219,7 @@ namespace mem {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** API: mark a buffer as _emitted_ */
|
||||||
void
|
void
|
||||||
HeapMemBufferStore::mark_emitted (HashVal, BuffAlloc storageSlot)
|
HeapMemBufferStore::mark_emitted (HashVal, BuffAlloc storageSlot)
|
||||||
{
|
{
|
||||||
|
|
@ -457,7 +235,7 @@ namespace mem {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** mark a buffer as officially discarded */
|
/** API: mark a buffer as officially discarded */
|
||||||
void
|
void
|
||||||
HeapMemBufferStore::detachBuffer (HashVal, BuffAlloc storageSlot)
|
HeapMemBufferStore::detachBuffer (HashVal, BuffAlloc storageSlot)
|
||||||
{
|
{
|
||||||
|
|
@ -473,68 +251,4 @@ namespace mem {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* ==== Implementation details ==== */
|
|
||||||
|
|
||||||
#if false ////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1410 : this additional tracking API is obsolete and need to be removed
|
|
||||||
size_t
|
|
||||||
HeapMemBufferStore::emittedCnt() const
|
|
||||||
{
|
|
||||||
return outSeq_.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
HeapMemBufferStore::markAllEmitted()
|
|
||||||
{
|
|
||||||
for (auto& [_, blockPool] : *pool_)
|
|
||||||
blockPool.discard();
|
|
||||||
}
|
|
||||||
|
|
||||||
HeapMemBufferStore::Block&
|
|
||||||
HeapMemBufferStore::access_emitted (uint bufferID)
|
|
||||||
{
|
|
||||||
if (!withinOutputSequence (bufferID))
|
|
||||||
return emptyPlaceholder; ////////////////////////////////TICKET #856
|
|
||||||
else
|
|
||||||
return outSeq_[bufferID];
|
|
||||||
}
|
|
||||||
#endif ////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1410 : (End) obsoleted API
|
|
||||||
|
|
||||||
bool
|
|
||||||
HeapMemBufferStore::withinOutputSequence (uint bufferID) const
|
|
||||||
{
|
|
||||||
if (bufferID >= MAX_BUFFERS)
|
|
||||||
throw err::Fatal ("hardwired internal limit for test buffers exceeded");
|
|
||||||
|
|
||||||
return bufferID < outSeq_.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
HeapMemBufferStore::BlockPool&
|
|
||||||
HeapMemBufferStore::getBlockPoolFor (size_t buffSiz, HashVal typeID)
|
|
||||||
{
|
|
||||||
BlockPool& pool = (*pool_)[typeID];
|
|
||||||
if (not pool)
|
|
||||||
pool.initialise (buffSiz);
|
|
||||||
return pool;
|
|
||||||
}
|
|
||||||
|
|
||||||
HeapMemBufferStore::Block*
|
|
||||||
HeapMemBufferStore::locateBlock (size_t buffSiz, HashVal typeID, void* storage)
|
|
||||||
{
|
|
||||||
BlockPool& pool = getBlockPoolFor (buffSiz, typeID);
|
|
||||||
Block* block4buffer = pool.find (storage); ////////////////////////////////TICKET #856
|
|
||||||
return block4buffer? block4buffer
|
|
||||||
: searchInOutSeqeuence (storage);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
HeapMemBufferStore::Block*
|
|
||||||
HeapMemBufferStore::searchInOutSeqeuence (void* blockLocation)
|
|
||||||
{
|
|
||||||
return pick_Block_by_storage (outSeq_, blockLocation); ////////////////////////////////TICKET #856
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}} // namespace vault::mem
|
}} // namespace vault::mem
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** @file heap-mem-provider.hpp
|
/** @file heap-mem-provider.hpp
|
||||||
** Dummy engine::BufferProvider storage implementation, for sake of conceptual
|
** Dummy engine::BufferProvider BufferStore implementation, for sake of conceptual
|
||||||
** demonstration and unit testing. This BufferProvider implementation is notably straight forward,
|
** demonstration and unit testing. Notably this buffer allocator implementation is straight forward,
|
||||||
** if not outright silly: it happily claims more and more heap blocks and never releases any memory
|
** 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
|
** 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.
|
** allows to investigate additional tracking status flags for each allocated block after the fact.
|
||||||
|
|
@ -21,33 +21,22 @@
|
||||||
** @see DiagnosticOutputSlot
|
** @see DiagnosticOutputSlot
|
||||||
** @see DiagnosticBufferProvider
|
** @see DiagnosticBufferProvider
|
||||||
** @see buffer-provider-protocol-test.cpp
|
** @see buffer-provider-protocol-test.cpp
|
||||||
|
** @see engine-ctx.hpp
|
||||||
|
** @see naive-buffer-setup.hpp
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef VAULT_MEM_HEAP_MEM_BUFFER_STORE_H
|
#ifndef VAULT_MEM_HEAP_MEM_BUFFER_STORE_H
|
||||||
#define VAULT_MEM_HEAP_MEM_BUFFER_STORE_H
|
#define VAULT_MEM_HEAP_MEM_BUFFER_STORE_H
|
||||||
|
|
||||||
|
|
||||||
#include "lib/hash-value.h"
|
|
||||||
#include "vault/mem/buffer-provider-setup.hpp"
|
#include "vault/mem/buffer-provider-setup.hpp"
|
||||||
#include "lib/scoped-ptrvect.hpp"
|
|
||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
|
|
||||||
namespace std {
|
|
||||||
/// Partial specializations for pointer types.
|
|
||||||
template<typename _Tp>
|
|
||||||
struct hash<_Tp*> : public hash_HIDDEN<_Tp*> { };
|
|
||||||
|
|
||||||
}
|
|
||||||
namespace vault {
|
namespace vault {
|
||||||
namespace mem {
|
namespace mem {
|
||||||
|
|
||||||
using std::unique_ptr;
|
|
||||||
using lib::ScopedPtrVect;
|
|
||||||
using lib::HashVal;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Naive demo implementation of the BufferProvider::BufferStore.
|
* Naive demo implementation of the BufferProvider::BufferStore.
|
||||||
|
|
@ -65,15 +54,8 @@ namespace mem {
|
||||||
using Index = std::unordered_map<Buff*,Alloc>;
|
using Index = std::unordered_map<Buff*,Alloc>;
|
||||||
|
|
||||||
Index allocIdx_;
|
Index allocIdx_;
|
||||||
public: /////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1410 : looks like I'll re-implement the storage from scratch, since »tracking« is no longer required here
|
|
||||||
class Block;
|
|
||||||
class BlockPool;
|
|
||||||
private:
|
|
||||||
using PoolTable = std::unordered_map<HashVal,BlockPool>;
|
|
||||||
unique_ptr<PoolTable> pool_;
|
|
||||||
ScopedPtrVect<Block> outSeq_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
/* === BufferStore interface === */
|
/* === BufferStore interface === */
|
||||||
|
|
||||||
uint prepareBuffers (HashVal typeID, uint cnt, size_t) override;
|
uint prepareBuffers (HashVal typeID, uint cnt, size_t) override;
|
||||||
|
|
@ -84,23 +66,6 @@ namespace mem {
|
||||||
public:
|
public:
|
||||||
~HeapMemBufferStore();
|
~HeapMemBufferStore();
|
||||||
HeapMemBufferStore();
|
HeapMemBufferStore();
|
||||||
|
|
||||||
#if false ////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1410 : this additional tracking API is obsolete and need to be removed
|
|
||||||
size_t emittedCnt() const;
|
|
||||||
|
|
||||||
Block& access_emitted (uint bufferID);
|
|
||||||
|
|
||||||
template<typename TY>
|
|
||||||
TY& accessAs (uint bufferID);
|
|
||||||
|
|
||||||
void markAllEmitted();
|
|
||||||
#endif ////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1410 : (End) obsoleted API
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool withinOutputSequence (uint bufferID) const;
|
|
||||||
BlockPool& getBlockPoolFor (size_t,HashVal typeID);
|
|
||||||
Block* locateBlock (size_t,HashVal typeID, void*);
|
|
||||||
Block* searchInOutSeqeuence (void* storage);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue