LUMIERA.clone/src/vault/mem/diagnostic-buffer-provider.hpp
Ichthyostega 7652ca05cd BufferProvider: add simplistic heap-based BufferStore implementation
Now able to reap the rewards: since all that convoluted and tangled
old ''state tracking'' has been resolved and replaced by dedicated
and self-contained diagnostic subclasses, the old dummy BufferProvider
implementation can be detached, using a similar yet very simple
fake implementation.

For context: the `HeapMemBufferStore` is part of the default configuration
and thus automatically used whenever a unit test needs a `BufferProvider`.
This default implementation is not optimised for speed, and actually
never releases any memory, which allows to verify proper handling
of buffer memory allocation.
2026-04-12 01:31:33 +02:00

160 lines
4.7 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
DIAGNOSTIC-BUFFER-PROVIDER.hpp - helper for testing against the BufferProvider interface
Copyright (C)
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
  Free Software Foundation; either version 2 of the License, or (at your
  option) any later version. See the file COPYING for further details.
*/
/** @file diagnostic-buffer-provider.hpp
** A facility for writing unit-tests targeting the BufferProvider interface.
**
** @see buffer-provider-protocol-test.cpp
*/
#ifndef VAULT_MEM_DIAGNOSTIC_BUFFR_PROVIDER_H
#define VAULT_MEM_DIAGNOSTIC_BUFFR_PROVIDER_H
#include "lib/error.hpp"
#include "lib/util.hpp"
#include "vault/mem/type-handler.hpp" ///////////////OOO warum?
#include "vault/mem/naive-buffer-setup.hpp"
#include "lib/iter-adapter-stl.hpp"
#include "lib/result.hpp"
#include "lib/nocopy.hpp"
#include <memory>
#include <vector>
namespace vault {
namespace mem {
namespace err = lumiera::error;
class HeapMemBufferStore; //////////////////////////////OOO fällt dann weg nach dem Umbau
class BufferDiagnostic;
namespace diagn {// state descriptors for diagnostics....
/** represent the status of one allocation */
struct Block
{
HashVal typeKey{0};
HashVal stateKey{0};
size_t buffSize{0};
Buff* storage{nullptr};
Buff* accessMemory() const { return storage; }
Block (metadata::Key, Buff* mem);
operator HashVal() const { return storage? stateKey:typeKey; }
template<typename BU>
BU const& accessAs() const;
};
class StateReg
: util::NonCopyable
{
using Registry = std::vector<Block>;
Registry reg_;
public:
/* ========= Information API ========= */
using Result = lib::Result<Block const&>;
Result operator[] (size_t seqNr) const;
Result byHandle (HashVal handle) const;
bool contains (HashVal handle) const;
auto each() const;
size_t cnt() const;
/* ========= Accounting API ========= */
void record (Block);
};
inline auto
StateReg::each() const
{
return lib::iter_stl::eachElm (reg_);
}
template<typename BU>
inline BU const&
Block::accessAs() const
{
if (not storage)
throw err::Logic ("buffer was never actually locked for access by clients"
, LERR_(LIFECYCLE));
return *reinterpret_cast<BU const*> (storage);
}
}//(End)diagnostic descriptors.
/********************************************************************//**
* Helper for unit tests: Buffer provider that tracks state transitions.
* This is a variant of the _naive_ heap based BufferProvider implementation,
* with additional tracking hooks to record the IDs and further information
* of all allocations encountered at a state transition.
*
* Test code should keep track of the BufferProvider instance used, and may
* attach through a special [diagnostics access](\ref watch(BufferProvider&)),
* to extract the recorded information while or after the allocated buffers
* are used. Since the underlying "naive" implementation does not actually
* discard any allocated memory block, it is possible to look into memory
* contents after invoking the test subject.
*/
class DiagnosticBufferProvider
: public NaiveBufferSetup
{
class InstrumentedStageProxy;
struct BlockTracker;
std::unique_ptr<BlockTracker> tracker_;
public:
~DiagnosticBufferProvider();
DiagnosticBufferProvider();
private:
/// „backdoor“ to watch instrumentation from tests
friend class BufferDiagnostic;
};
/** Accessor-proxy to investigate transactions */
class BufferDiagnostic
: util::MoveOnly
{
DiagnosticBufferProvider& dbp_;
public:
BufferDiagnostic (DiagnosticBufferProvider&);
bool was_created (HashVal);
bool was_emitted (HashVal);
bool was_released (HashVal);
bool is_in_use (HashVal);
bool was_used (HashVal);
Buff* accessMemory(HashVal);
bool all_buffers_released();
diagn::StateReg const& created;
diagn::StateReg const& emitted;
diagn::StateReg const& released;
};
inline BufferDiagnostic
watch (BufferProvider& thePro)
{
return BufferDiagnostic{static_cast<DiagnosticBufferProvider&> (thePro)};
}
}} // namespace vault::mem
#endif