xo-alloc2: ++ plumbing for AAllocator / DArena

This commit is contained in:
Roland Conybeare 2025-12-12 01:02:45 -05:00
commit e0dd9d2a1c
10 changed files with 223 additions and 91 deletions

View file

@ -35,90 +35,61 @@ namespace xo {
///@{
/** RTTI: unique id# for actual runtime data representation **/
virtual int32_t _typeseq() = 0;
virtual int32_t _typeseq() const = 0;
/** optional name for allocator @p d
* Labeling, for diagnostics.
**/
virtual const std::string & name(Copaque d) = 0;
virtual const std::string & name(Copaque d) const = 0;
/** reserved size in bytes for allocator @p d.
* Includes committed + uncommitted memory.
* Cannot be increased.
**/
virtual std::size_t reserved(Copaque d) const = 0;
/** allocator size in bytes (up to reserved limit)
* for allocator @p d.
* Includes allocated and uncomitted memory
* Includes all committed memory.
* Can increase on @ref alloc
**/
virtual std::size_t size(Copaque d) = 0;
virtual std::size_t size(Copaque d) const = 0;
/** committed size (physical addresses obtained)
* for allocator @p d.
**/
virtual std::size_t committed(Copaque d) = 0;
virtual std::size_t committed(Copaque d) const = 0;
/** true iff allocator @p d is responsible for memory at address @p p.
**/
virtual bool contains(Copaque d, const void * p) = 0;
virtual bool contains(Copaque d, const void * p) const = 0;
/** allocate @p z bytes of memory from allocator @p d. **/
virtual std::byte * alloc(Opaque d, std::size_t z) = 0;
virtual std::byte * alloc(Opaque d, std::size_t z) const = 0;
/** reset allocator @p d to empty state **/
virtual void clear(Opaque d) = 0;
virtual void clear(Opaque d) const = 0;
/** destruct allocator @p d **/
virtual void destruct_data(Opaque d) = 0;
virtual void destruct_data(Opaque d) const = 0;
///@}
}; /*AAllocator*/
// implementation IAllocator_DRepr of AAllocator for state DRepr
// should provide a specialization:
//
// template <>
// struct xo::facet::FacetImplementation<AAllocator, DRepr> {
// using ImplType = IAllocator_DRepr;
// };
//
// then IAllocator_ImplType<DRepr> --> IAllocator_DRepr
//
template <typename DRepr>
struct IAllocator_Impl;
using IAllocator_ImplType = xo::facet::FacetImplType<AAllocator, DRepr>;
template <typename DRepr>
using IAllocator_ImplType = IAllocator_Impl<DRepr>::ImplType;
// can't we do this with FacetImplementation<AAllocator, DRepr>
//
// template <typename DRepr>
// struct IAllocator_Impl {};
struct IAllocator_Any : public AAllocator {
using Impl = Allocator_ImplType<xo::facet::DVariantPlaceholder>;
// template <typename DRepr>
// using IAllocator_ImplType = IAllocator_Impl<DRepr>::ImplType;
// from AAllocator
int32_t _typeseq() override { return s_typeseq; }
const std::string & name(Copaque d) override { assert(false); static std::string x; return x; }
std::size_t size(Copaque d) override { assert(false); return 0ul; }
std::size_t committed(Copaque d) override { assert(false); reutrn 0ul; }
bool contains(Copaque d, const void * p) override { assert(false); return false; }
std::byte * alloc(Opaque d, std::size_t z) override { assert(false); return nullptr; }
void clear(Opaque d) override { assert(false); }
void destruct_data(Opaque d) override { assert(false); }
static int32_t s_typeseq;
static bool _valid;
}
/** @class IAllocator_Xfer
**/
template <typename DRepr>
struct IAllocator_Xfer : public AAllocator {
// parallel interface to AAllocator, with specific data type
using Impl = IAllocator_ImplType<DRepr>;
static const DRepr & _dcast(Copaque d) { return *(const DRepr *)d; }
// from AAllocator
int32_t _typeseq() override { return s_typeseq; }
const std::string & name(Copaque d) override { return Impl::name(_dcast(d)); }
std::size_t size(Copaque d) override { return Impl::size(*(DRepr*)d); }
std::size_t committed(Copaque d) override { return Impl::committed(*(DRepr*)d); }
bool contains(Copaque d, const void * p) override { return Impl::contains(*(DRepr*)d, p); }
std::byte * alloc(Opaque d, std::size_t z) override { return Impl::alloc(*(DRepr*)d, z); }
void clear(Opaque d) override { return Impl::clear(*(DRepr*)d); }
void destruct_data(Opaque d) override { return Impl::destruct_data(*(DRepr*)d); }
static int32_t s_typeseq;
static bool _valid;
};
template <typename DRepr>
int32_t
IAllocator_Xfer<DRepr>::s_typeseq = facet::typeseq::id<DRepr>();
template <typename DRepr>
bool
IAllocator_Xfer<DRepr>::_valid = facet::valid_facet_implementation<AAllocator, IAllocator_Xfer>();
} /*namespace mm*/
} /*namespace xo*/

View file

@ -0,0 +1,47 @@
/** @file IAllocator_Any.hpp
*
* @author Roland Conybeare, Dec 2025
**/
#pragma once
#include "AAllocator.hpp"
#include <cassert>
namespace xo {
namespace mm {
struct IAllocator_Any;
}
namespace facet {
template <>
struct FacetImplementation<xo::mm::AAllocator, DVariantPlaceholder> {
using ImplType = xo::mm::IAllocator_Any;
};
}
namespace mm {
struct IAllocator_Any : public AAllocator {
//using Impl = IAllocator_ImplType<xo::facet::DVariantPlaceholder>;
// from AAllocator
int32_t _typeseq() const override { return s_typeseq; }
const std::string & name(Copaque) const override { assert(false); static std::string * x; return *x; }
std::size_t reserved(Copaque) const override { assert(false); return 0ul; }
std::size_t size(Copaque) const override { assert(false); return 0ul; }
std::size_t committed(Copaque) const override { assert(false); return 0ul; }
bool contains(Copaque, const void *) const override { assert(false); return false; }
std::byte * alloc(Opaque, std::size_t) const override { assert(false); return nullptr; }
void clear(Opaque) const override { assert(false); }
void destruct_data(Opaque) const override { assert(false); }
static int32_t s_typeseq;
static bool _valid;
};
}
}
/* end IAllocator_Any.hpp */

View file

@ -4,25 +4,38 @@
**/
#include "AAllocator.hpp"
#include "IAllocator_Xfer.hpp"
#include "DArena.hpp"
namespace xo {
namespace mm {
struct IAllocator_DArena;
}
struct IAllocator_DArena {
static const std::string & name(const DArena & s);
static std::size_t size(const DArena & s);
static std::size_t committed(const DArena & s);
static bool contains(const DArena & s, const void * p);
static std::byte * alloc(const DArena & s, std::size_t z);
static void clear(DArena & s);
static void destruct_data(DArena & s);
};
namespace facet {
template <>
struct IAllocator_Impl<DArena> {
using ImplType = IAllocator_DArena;
struct FacetImplementation<xo::mm::AAllocator, xo::mm::DArena> {
using ImplType = xo::mm::IAllocator_Xfer<xo::mm::DArena,
xo::mm::IAllocator_DArena>;
};
}
namespace mm {
struct IAllocator_DArena {
static const std::string & name(const DArena &);
static std::size_t reserved(const DArena &);
static std::size_t size(const DArena &);
static std::size_t committed(const DArena &);
static bool contains(const DArena &, const void * p);
static std::byte * alloc(const DArena &, std::size_t z);
static void clear(DArena &);
static void destruct_data(DArena &);
};
// template <>
// struct IAllocator_Impl<DArena> {
// using ImplType = IAllocator_DArena;
// };
} /*namespace mm*/
} /*namespace xo*/

View file

@ -0,0 +1,47 @@
/** @file IAllocator_Xfer.hpp
*
* @author Roland Conybeare, Dec 2025
**/
#pragma once
#include "AAllocator.hpp"
namespace xo {
namespace mm {
/** @class IAllocator_Xfer
**/
template <typename DRepr, typename IAllocator_DRepr>
struct IAllocator_Xfer : public AAllocator {
// parallel interface to AAllocator, with specific data type
using Impl = IAllocator_DRepr;
static const DRepr & _dcast(Copaque d) { return *(const DRepr *)d; }
// from AAllocator
int32_t _typeseq() const override { return s_typeseq; }
const std::string & name(Copaque d) const override { return Impl::name(_dcast(d)); }
std::size_t reserved(Copaque d) const override { return Impl::reserved(*(DRepr*)d); }
std::size_t size(Copaque d) const override { return Impl::size(*(DRepr*)d); }
std::size_t committed(Copaque d) const override { return Impl::committed(*(DRepr*)d); }
bool contains(Copaque d, const void * p) const override { return Impl::contains(*(DRepr*)d, p); }
std::byte * alloc(Opaque d, std::size_t z) const override { return Impl::alloc(*(DRepr*)d, z); }
void clear(Opaque d) const override { return Impl::clear(*(DRepr*)d); }
void destruct_data(Opaque d) const override { return Impl::destruct_data(*(DRepr*)d); }
static int32_t s_typeseq;
static bool _valid;
};
template <typename DRepr, typename IAllocator_DRepr>
int32_t
IAllocator_Xfer<DRepr, IAllocator_DRepr>::s_typeseq = facet::typeseq::id<DRepr>();
template <typename DRepr, typename IAllocator_DRepr>
bool
IAllocator_Xfer<DRepr, IAllocator_DRepr>::_valid = facet::valid_facet_implementation<AAllocator, IAllocator_Xfer>();
} /*namespace mm*/
} /*namespace xo*/
/* end IAllocator_Xfer.hpp */

View file

@ -6,18 +6,29 @@
#pragma once
#include "xo/facet/RRouter.hpp"
#include <string>
namespace xo {
namespace mm {
/** @class RAllocator **/
template <typename Object>
struct RAllocator : public Object {
private:
using O = Object;
public:
using ObjectType = Object;
using size_type = std::size_t;
RAllocator() {}
RAllocator(Object::DataPtr data) : Object{std::move(data)} {}
int32_t _typeseq() const { return Object::iface()->_typeseq(); }
int32_t _typeseq() const { return O::iface()->_typeseq(); }
const std::string & name() const { return O::iface()->name(O::data()); }
size_type reserved() const { return O::iface()->reserved(O::data()); }
size_type size() const { return O::iface()->size(O::data()); }
size_type committed() const { return O::iface()->committed(O::data()); }
bool contains(const void * p) const { return O::iface()->contains(O::data(), p); }
std::byte * alloc(size_type z) { return O::iface()->alloc(O::data(), z); }
static bool _valid;
};