xo-alloc2: ++ plumbing for AAllocator / DArena
This commit is contained in:
parent
5964bcf3d5
commit
e0dd9d2a1c
10 changed files with 223 additions and 91 deletions
|
|
@ -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*/
|
||||
|
||||
|
|
|
|||
47
include/xo/alloc2/IAllocator_Any.hpp
Normal file
47
include/xo/alloc2/IAllocator_Any.hpp
Normal 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 */
|
||||
|
|
@ -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*/
|
||||
|
|
|
|||
47
include/xo/alloc2/IAllocator_Xfer.hpp
Normal file
47
include/xo/alloc2/IAllocator_Xfer.hpp
Normal 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 */
|
||||
|
|
@ -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;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -3,16 +3,7 @@
|
|||
#include "xo/alloc2/AAllocator.hpp"
|
||||
|
||||
namespace xo {
|
||||
using xo::facet::DVariantPlaceholder;
|
||||
using xo::facet::typeseq;
|
||||
using xo::facet::valid_facet_implementation;
|
||||
|
||||
namespace mm {
|
||||
int32_t
|
||||
IAllocator_Any::s_typeseq = typeseq::id<DVariantPlaceholder>;
|
||||
|
||||
bool
|
||||
IAllocator_Any::_valid = valid_facet_implementation<AAllocator, IAllocator_Any>;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ set(SELF_LIB xo_alloc2)
|
|||
set(SELF_SRCS
|
||||
AAllocator.cpp
|
||||
DArena.cpp
|
||||
IAllocator_Any.cpp
|
||||
IAllocator_DArena.cpp
|
||||
)
|
||||
|
||||
|
|
|
|||
24
src/alloc2/IAllocator_Any.cpp
Normal file
24
src/alloc2/IAllocator_Any.cpp
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
/** @file IAllocator_Any.cpp
|
||||
*
|
||||
* @author Roland Conybeare, Dec 2025
|
||||
**/
|
||||
|
||||
#include "IAllocator_Any.hpp"
|
||||
|
||||
namespace xo {
|
||||
using xo::facet::DVariantPlaceholder;
|
||||
using xo::facet::typeseq;
|
||||
using xo::facet::valid_facet_implementation;
|
||||
|
||||
namespace mm {
|
||||
|
||||
int32_t
|
||||
IAllocator_Any::s_typeseq = typeseq::id<DVariantPlaceholder>();
|
||||
|
||||
bool
|
||||
IAllocator_Any::_valid = valid_facet_implementation<AAllocator, IAllocator_Any>();
|
||||
|
||||
} /*namespace mm*/
|
||||
} /*namespace xo*/
|
||||
|
||||
/* end IAllocator_Any.cpp */
|
||||
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include "IAllocator_DArena.hpp"
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
|
||||
namespace xo {
|
||||
namespace mm {
|
||||
|
|
@ -14,6 +15,11 @@ namespace xo {
|
|||
return s.config_.name_;
|
||||
}
|
||||
|
||||
std::size_t
|
||||
IAllocator_DArena::reserved(const DArena & s) {
|
||||
return s.hi_ - s.lo_;
|
||||
}
|
||||
|
||||
std::size_t
|
||||
IAllocator_DArena::size(const DArena & s) {
|
||||
return s.limit_ - s.lo_;
|
||||
|
|
|
|||
|
|
@ -4,7 +4,9 @@
|
|||
**/
|
||||
|
||||
#include "xo/alloc2/AAllocator.hpp"
|
||||
#include "xo/alloc2/DArena.hpp"
|
||||
#include "xo/alloc2/IAllocator_Any.hpp"
|
||||
#include "xo/alloc2/IAllocator_Xfer.hpp"
|
||||
//#include "xo/alloc2/DArena.hpp"
|
||||
#include "xo/alloc2/IAllocator_DArena.hpp"
|
||||
#include "xo/alloc2/RAllocator.hpp"
|
||||
#include "xo/alloc2/padding.hpp"
|
||||
|
|
@ -13,6 +15,7 @@
|
|||
|
||||
namespace xo {
|
||||
using xo::mm::AAllocator;
|
||||
using xo::mm::IAllocator_DArena;
|
||||
using xo::mm::IAllocator_Xfer;
|
||||
using xo::mm::DArena;
|
||||
using xo::mm::ArenaConfig;
|
||||
|
|
@ -23,9 +26,9 @@ namespace xo {
|
|||
namespace ut {
|
||||
TEST_CASE("IAllocator_Xfer_DArena", "[alloc2]")
|
||||
{
|
||||
IAllocator_Xfer<DArena> xfer;
|
||||
IAllocator_Xfer<DArena, IAllocator_DArena> xfer;
|
||||
|
||||
REQUIRE(IAllocator_Xfer<DArena>::_valid);
|
||||
REQUIRE(IAllocator_Xfer<DArena, IAllocator_DArena>::_valid);
|
||||
}
|
||||
|
||||
TEST_CASE("DArena", "[alloc2][DArena]")
|
||||
|
|
@ -73,18 +76,36 @@ namespace xo {
|
|||
|
||||
TEST_CASE("allocator-any-1", "[alloc2][AAllocator]")
|
||||
{
|
||||
#ifdef NOPE
|
||||
ArenaConfig cfg { .name_ = "testarena",
|
||||
.size_ = 1 };
|
||||
DArena arena = DArena::map(cfg);
|
||||
#endif
|
||||
|
||||
/* empty allocator */
|
||||
obj<AAllocator> alloc1;
|
||||
|
||||
REQUIRE(!alloc1);
|
||||
REQUIRE(alloc1.iface() != nullptr);
|
||||
REQUIRE(alloc1.data() == nullptr);
|
||||
|
||||
ArenaConfig cfg { .name_ = "testarena",
|
||||
.size_ = 1 };
|
||||
DArena arena = DArena::map(cfg);
|
||||
obj<AAllocator, DArena> a1o{&arena};
|
||||
|
||||
REQUIRE(a1o);
|
||||
REQUIRE(a1o.iface() != nullptr);
|
||||
REQUIRE(a1o.data() != nullptr);
|
||||
|
||||
REQUIRE(a1o._typeseq()
|
||||
== xo::facet::FacetImplType<AAllocator, DArena>::s_typeseq);
|
||||
REQUIRE(a1o.name() == cfg.name_);
|
||||
REQUIRE(a1o.reserved() >= cfg.size_);
|
||||
REQUIRE(a1o.reserved() < cfg.size_ + cfg.hugepage_z_);
|
||||
REQUIRE(a1o.reserved() % cfg.hugepage_z_ == 0);
|
||||
REQUIRE(a1o.size() == 0);
|
||||
REQUIRE(a1o.committed() == 0);
|
||||
|
||||
#ifdef NOPE
|
||||
byte * m = a1o.alloc(1);
|
||||
|
||||
REQUIRE(m);
|
||||
#endif
|
||||
}
|
||||
} /*namespace ut*/
|
||||
} /*namespace xo*/
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue