+ docs in xo-alloc2/ + misc improvements
This commit is contained in:
parent
a69158ab32
commit
5964bcf3d5
22 changed files with 763 additions and 121 deletions
|
|
@ -14,52 +14,86 @@ namespace xo {
|
|||
using Copaque = const void *;
|
||||
using Opaque = void *;
|
||||
|
||||
|
||||
/** Abstract facet for allocation
|
||||
/** @class AAllocator
|
||||
* @brief Abstract facet for allocation
|
||||
*
|
||||
* <----------------------------size-------------------------->
|
||||
* <------------committed-----------><-------uncommitted------>
|
||||
* <--allocated-->
|
||||
*
|
||||
* XXXXXXXXXXXXXXX___________________..........................
|
||||
*
|
||||
* allocated: in use
|
||||
* committed: physical memory obtained
|
||||
* uncommitted: mapped in virtual memory, not backed by memory
|
||||
**/
|
||||
struct AAllocator {
|
||||
/** RTTI: unique id# for actual runtime data repr **/
|
||||
/*
|
||||
* <----------------------------size-------------------------->
|
||||
* <------------committed-----------><-------uncommitted------>
|
||||
* <--allocated-->
|
||||
*
|
||||
* XXXXXXXXXXXXXXX___________________..........................
|
||||
*
|
||||
* allocated: in use
|
||||
* committed: physical memory obtained
|
||||
* uncommitted: mapped in virtual memory, not backed by memory
|
||||
*/
|
||||
|
||||
/** @defgroup mm-allocator-methods Allocator methods **/
|
||||
///@{
|
||||
|
||||
/** RTTI: unique id# for actual runtime data representation **/
|
||||
virtual int32_t _typeseq() = 0;
|
||||
/** optional name for this allocator.
|
||||
/** optional name for allocator @p d
|
||||
* Labeling, for diagnostics.
|
||||
**/
|
||||
virtual const std::string & name(Copaque d) = 0;
|
||||
/** allocator size in bytes (up to reserved limit)
|
||||
* includes allocated and uncomitted memory
|
||||
* for allocator @p d.
|
||||
* Includes allocated and uncomitted memory
|
||||
**/
|
||||
virtual std::size_t size(Copaque d) = 0;
|
||||
/** committed size (physical addresses obtained)
|
||||
* for allocator @p d.
|
||||
**/
|
||||
virtual std::size_t committed(Copaque d) = 0;
|
||||
/** true iff pointer @p in range of this allocator
|
||||
/** true iff allocator @p d is responsible for memory at address @p p.
|
||||
**/
|
||||
virtual bool contains(Copaque d, const void * p) = 0;
|
||||
|
||||
/** allocate @p z bytes of memory. **/
|
||||
/** allocate @p z bytes of memory from allocator @p d. **/
|
||||
virtual std::byte * alloc(Opaque d, std::size_t z) = 0;
|
||||
/** reset allocator to empty state **/
|
||||
/** reset allocator @p d to empty state **/
|
||||
virtual void clear(Opaque d) = 0;
|
||||
/** **/
|
||||
/** destruct allocator @p d **/
|
||||
virtual void destruct_data(Opaque d) = 0;
|
||||
};
|
||||
|
||||
///@}
|
||||
}; /*AAllocator*/
|
||||
|
||||
template <typename DRepr>
|
||||
struct IAllocator_Impl;
|
||||
|
||||
template <typename DRepr>
|
||||
using IAllocator_ImplType = IAllocator_Impl<DRepr>::ImplType;
|
||||
|
||||
struct IAllocator_Any : public AAllocator {
|
||||
using Impl = Allocator_ImplType<xo::facet::DVariantPlaceholder>;
|
||||
|
||||
// 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_Impl<DRepr>;
|
||||
using Impl = IAllocator_ImplType<DRepr>;
|
||||
|
||||
static const DRepr & _dcast(Copaque d) { return *(const DRepr *)d; }
|
||||
|
||||
|
|
|
|||
|
|
@ -10,12 +10,17 @@
|
|||
namespace xo {
|
||||
namespace mm {
|
||||
|
||||
/** ArenaConfig
|
||||
/** @class ArenaConfig
|
||||
*
|
||||
* @brief configuration for a @ref DArena instance
|
||||
**/
|
||||
struct ArenaConfig {
|
||||
/** @defgroup mm-arenaconfig-instance-vars ArenaConfig members **/
|
||||
///@{
|
||||
|
||||
/** optional name, for diagnostics **/
|
||||
std::string name_;
|
||||
/** arena size -- hard max = reserved virtual memory **/
|
||||
/** desired arena size -- hard max = reserved virtual memory **/
|
||||
std::size_t size_;
|
||||
/** hugepage size -- using huge pages relieves some TLB pressure
|
||||
* (provided you use their full extent :)
|
||||
|
|
@ -23,31 +28,70 @@ namespace xo {
|
|||
std::size_t hugepage_z_ = 2 * 1024 * 1024;
|
||||
/** true to enable debug logging **/
|
||||
bool debug_flag_ = false;
|
||||
|
||||
///@}
|
||||
};
|
||||
|
||||
/** Arena allocator state
|
||||
/** @class DArena
|
||||
*
|
||||
* <----------------------------size-------------------------->
|
||||
* <------------committed-----------><-------uncommitted------>
|
||||
* <--allocated-->
|
||||
* @brief represent arena allocator state
|
||||
*
|
||||
* XXXXXXXXXXXXXXX___________________..........................
|
||||
*
|
||||
* allocated: in use
|
||||
* committed: physical memory obtained
|
||||
* uncommitted: mapped in virtual memory, not backed by memory
|
||||
* Provides minimal RAII functionality around memory mapping.
|
||||
* For allocation see @ref IAllocator_DArena
|
||||
**/
|
||||
struct DArena {
|
||||
/** [lo, hi) already-mapped address range **/
|
||||
DArena(const ArenaConfig & cfg,
|
||||
std::byte * lo,
|
||||
std::byte * hi);
|
||||
/*
|
||||
* <----------------------------size-------------------------->
|
||||
* <------------committed-----------><-------uncommitted------>
|
||||
* <--allocated-->
|
||||
*
|
||||
* XXXXXXXXXXXXXXX___________________..........................
|
||||
*
|
||||
* [X] allocated: in use
|
||||
* [_] committed: physical memory obtained
|
||||
* [.] uncommitted: mapped in virtual memory, not backed by memory
|
||||
*/
|
||||
|
||||
/** @defgroup mm-arena-traits arena type traits **/
|
||||
///@{
|
||||
|
||||
/** @brief an amount of memory **/
|
||||
using size_type = std::size_t;
|
||||
/** @brief a contiguous memory range **/
|
||||
using range_type = std::pair<std::byte*,std::byte*>;
|
||||
|
||||
///@}
|
||||
|
||||
/** @defgroup mm-arena-ctors arena constructors and destructors **/
|
||||
///@{
|
||||
|
||||
/** create arena per configuration @p cfg. **/
|
||||
static DArena map(const ArenaConfig & cfg);
|
||||
|
||||
/** ctor from already-mapped (but not committed) address range **/
|
||||
DArena(const ArenaConfig & cfg, size_type page_z, std::byte * lo, std::byte * hi);
|
||||
/** DArena is not copyable **/
|
||||
DArena(const DArena & other) = delete;
|
||||
/** move ctor **/
|
||||
DArena(DArena && other);
|
||||
/** dtor releases mapped memory **/
|
||||
~DArena();
|
||||
|
||||
///@}
|
||||
|
||||
/** obtain uncommitted contiguous memory range comprising
|
||||
* a whole multiple of @p hugepage_z bytes, of at least size @p req_z,
|
||||
* aligned on a @p hugepage_z boundary
|
||||
**/
|
||||
static range_type map_aligned_range(size_type req_z, size_type hugepage_z);
|
||||
|
||||
/** @defgroup mm-arena-instance-vars **/
|
||||
///@{
|
||||
|
||||
/** arena configuration **/
|
||||
ArenaConfig config_;
|
||||
|
||||
/** size of a VM page (via getpagesize()). Likely 4k **/
|
||||
/** size of a VM page (obtained automatically via getpagesize()). Likely 4k **/
|
||||
std::size_t page_z_ = 0;
|
||||
|
||||
/** arena owns memory in range [@ref lo_, @ref hi_)
|
||||
|
|
@ -74,6 +118,8 @@ namespace xo {
|
|||
* Memory in range [@ref limit_, @ref hi_) is uncommitted
|
||||
**/
|
||||
std::byte * hi_ = nullptr;
|
||||
|
||||
///@}
|
||||
};
|
||||
|
||||
} /*namespace mm*/
|
||||
|
|
|
|||
|
|
@ -9,12 +9,8 @@
|
|||
namespace xo {
|
||||
namespace mm {
|
||||
|
||||
template <>
|
||||
struct IAllocator_Impl<DArena> {
|
||||
static const std::string & name(const DArena & s) {
|
||||
return s.name_;
|
||||
}
|
||||
|
||||
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);
|
||||
|
|
@ -23,6 +19,10 @@ namespace xo {
|
|||
static void destruct_data(DArena & s);
|
||||
};
|
||||
|
||||
template <>
|
||||
struct IAllocator_Impl<DArena> {
|
||||
using ImplType = IAllocator_DArena;
|
||||
};
|
||||
|
||||
} /*namespace mm*/
|
||||
} /*namespace xo*/
|
||||
|
|
|
|||
38
include/xo/alloc2/RAllocator.hpp
Normal file
38
include/xo/alloc2/RAllocator.hpp
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/** @file RAllocator.hpp
|
||||
*
|
||||
* @author Roland Conybeare, Dec 2025
|
||||
**/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "xo/facet/RRouter.hpp"
|
||||
|
||||
namespace xo {
|
||||
namespace mm {
|
||||
/** @class RAllocator **/
|
||||
template <typename Object>
|
||||
struct RAllocator : public Object {
|
||||
using ObjectType = Object;
|
||||
|
||||
RAllocator() {}
|
||||
RAllocator(Object::DataPtr data) : Object{std::move(data)} {}
|
||||
|
||||
int32_t _typeseq() const { return Object::iface()->_typeseq(); }
|
||||
|
||||
static bool _valid;
|
||||
};
|
||||
|
||||
template <typename Object>
|
||||
bool
|
||||
RAllocator<Object>::_valid = facet::valid_object_router<Object>();
|
||||
}
|
||||
|
||||
namespace facet {
|
||||
template <typename Object>
|
||||
struct RoutingFor<xo::mm::AAllocator, Object> {
|
||||
using RoutingType = xo::mm::RAllocator<Object>;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/* end RAllocator.hpp */
|
||||
Loading…
Add table
Add a link
Reference in a new issue