lumiera_documentation/src/vault/out/output-buffer-proxy.hpp
Ichthyostega 2ee6bb3b04 OutputSlot: look for alternative ways to implement the proxy
After a lot of pondering over various solution schemes,
it seems that `BufferProxyAdaptor` is too rigid for the task at hand.
It could be retained as a technology demonstration, and used as blueprint
for a custom-made implementation. In a nutshell, we need a `BufferStore`
that directly delegates to the respective `Connection` — which also implies
to use the `OutputSlot::AllocState` as an intermediate to hendle that delegation.
2026-03-19 00:32:02 +01:00

173 lines
5.3 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.

/*
OUTPUT-BUFFER-PROXY.hpp - Adaptor to access existing allocation via buffer handling protocol
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 output-buffer-proxy.hpp
** Adapter to expose some buffer memory through a BuffHandle as front-end.
** This implementation building-block allows to integrate the output buffers
** managed by a specific output mechanism with the generic implementation of
** OutputSlote, so that only a BuffHandle needs to be exposed to the client.
** @see output-proxy-provider-test.cpp
** @see output-buffer-proxy.hpp
** @see output-slot.hpp
*/
#ifndef VAULT_OUT_OUTPUT_BUFFER_PROXY_H
#define VAULT_OUT_OUTPUT_BUFFER_PROXY_H
#include "lib/error.hpp"
#include "lib/nocopy.hpp"
#include "lib/symbol.hpp"
#include "lib/meta/util.hpp"
#include "vault/mem/buffer-provider.hpp"
#include "vault/mem/buffer-provider-setup.hpp"
#include "vault/mem/heap-mem-buffer-store.hpp"
#include "vault/mem/simple-buffer-state-registry.hpp"
#include <functional>
#include <utility>
namespace vault{
namespace out {
using std::move;
using lib::Literal;
using lib::HashVal;
using vault::mem::Buff;
using vault::mem::LocalTag;
using vault::mem::BuffAlloc;
using vault::mem::BuffDescr;
using vault::mem::BuffHandle;
using vault::mem::TypeHandler; ///////////////////////////OOO Rly?
using vault::mem::BufferProviderSetup;
/**
* Adapter to expose controlled access to some memory resource
* through a [»Buffer Type«](\ref BuffDescr) and a BuffHandle as front-end,
* in accordance with the BufferProvider protocol.
*
* This template is an implementation building block and needs to be instantiated
* with a policy or configuration to define the flexible parts of the behaviour
* - what a Buffer Type means
* - is there only one resource or is this setup statefull?
* - callback functors for the lifecycle stages related to the client's access
* @todo 3/2026 this is prototyping code and was retained for demonstration purposes.
*/
template<class CONF>
class OutputBufferProxy
: util::NonCopyable
{
class ProxyBufferStore
: public BufferProviderSetup::Store
, private CONF
{
Buff*
asBuffer (LocalTag targetMarker)
{
void* buffMem{targetMarker};
return static_cast<Buff*> (buffMem);
}
uint
prepareBuffers (HashVal,uint,size_t) override
{
WARN (engine, "Announce invoked on a Proxy Buffer Provider; "
"Implies misuse as generic BufferProvider");
return 1;
}
BuffAlloc
provideBuffer (HashVal,size_t siz,LocalTag targetMarker) override
{
BuffAlloc storageSlot{asBuffer(targetMarker), siz, targetMarker};
CONF::on_lock (storageSlot);
return storageSlot;
}
void
mark_emitted (HashVal, BuffAlloc storageSlot) override
{
CONF::on_emit (storageSlot);
}
void
detachBuffer (HashVal, BuffAlloc storageSlot) override
{
CONF::on_release (storageSlot);
}
public:
ProxyBufferStore (CONF policy)
: CONF{move(policy)}
{ }
};
struct Setup
: CONF
{
auto buildStage() { return std::make_unique<vault::mem::SimpleBufferStateRegistry>("OutputBufferProxy"); }
auto buildStore() { return std::make_unique<ProxyBufferStore> (move(*this)); }
}; // Note: possible since Setup does not use CONF
class PassThroughBufferProvider
: public BufferProviderSetup
{
public:
PassThroughBufferProvider (Setup setup)
: BufferProviderSetup{setup}
{ }
BuffDescr
registerBuffer (void* buff, size_t siz)
{
REQUIRE (siz);
REQUIRE (buff);
auto& typeKey = bufferStage_->defineBufferType (siz, TypeHandler::RAW, LocalTag(buff));
return buildDescriptor (typeKey);
}
};
PassThroughBufferProvider proxyProvider_;
public:
OutputBufferProxy(CONF policy)
: proxyProvider_{Setup{move(policy)}}
{ }
template<typename TAR>
BuffDescr
getDescriptorFor (TAR& dataBlock)
{
return proxyProvider_.registerBuffer(&dataBlock, sizeof(TAR));
}
template<typename TAR>
BuffHandle
lockBuffer (TAR& dataBlock)
{
BuffDescr buffType = getDescriptorFor<TAR> (dataBlock);
ENSURE (buffType.isValid());
return buffType.lockBuffer();
}
};
}} // namespace vault::out
#endif /*VAULT_OUT_OUTPUT_BUFFER_PROXY_H*/