xo-alloc2: work on alloc iteration.

This commit is contained in:
Roland Conybeare 2025-12-18 11:22:36 -05:00
commit d8ed0d6235
17 changed files with 216 additions and 29 deletions

View file

@ -14,9 +14,6 @@ namespace xo {
using Copaque = const void *;
using Opaque = void *;
/** forward decl for obj<AAllocIterator> **/
struct ObjAllocIterator;
/** @class AAllocIterator
* @brief Abstract facet for iterating over allocs
*

View file

@ -16,6 +16,9 @@ namespace xo {
using Copaque = const void *;
using Opaque = void *;
// see DArena.hpp
struct DArena;
/** @class AAllocator
* @brief Abstract facet for allocation
*
@ -81,7 +84,21 @@ namespace xo {
*
* Non-const @p d because may stash error details
**/
virtual AllocInfo alloc_info(Opaque d, value_type mem) const noexcept = 0;
virtual AllocInfo alloc_info(Copaque d, value_type mem) const noexcept = 0;
/** Ideally we want to control allocation for iterator here.
* Awkward to describe to compiler since we don't have vt<AAllocator> yet.
* OTOH iteration over allocs is a niche feature.
* Consider alternatives:
* - put begin/end in separate interface. e.g. extend AAllocator
* - layer of indirection: begin/end return iterator factory.
* Then allocator can be passed to iterator factory separately.
* Helps because factory can be static
* - abandon allocator support in this case. Instead will need to
* reinstate uvt<AAllocIterator> (unique variant), use heap
* - just pass DArena& for alloc-iterator-allocation
**/
//virtual facet::vt<AAllocIterator> begin(Copaque d, DArena & ialloc) const noexcept;
// virtual obj<AAllocIterator> end() const noexcept = 0;
/** expand committed space in arena @p d
* to size at least @p z

View file

@ -6,6 +6,8 @@
#pragma once
#include "AAllocator.hpp"
#include "AllocIterator.hpp"
#include <xo/facet/obj.hpp>
#include <cassert>
namespace xo {
@ -40,9 +42,11 @@ namespace xo {
[[noreturn]] size_type allocated(Copaque) const noexcept override { _fatal(); }
[[noreturn]] bool contains(Copaque, const void *) const noexcept override { _fatal(); }
[[noreturn]] AllocError last_error(Copaque) const noexcept override { _fatal(); }
[[noreturn]] AllocInfo alloc_info(Copaque, value_type) const noexcept override { _fatal(); }
// defn in .cpp - problematic to require compiler know vt<AAllocIterator> defn here
//[[noreturn]] facet::vt<AAllocIterator> begin(Copaque, DArena &) const noexcept override; // { _fatal(); }
// non-const methods
[[noreturn]] AllocInfo alloc_info(Opaque, value_type) const noexcept override { _fatal(); }
[[noreturn]] bool expand(Opaque, std::size_t) const noexcept override { _fatal(); }
[[noreturn]] value_type alloc(Opaque, std::size_t) const override { _fatal(); }
[[noreturn]] value_type super_alloc(Opaque, std::size_t) const override { _fatal(); }

View file

@ -42,7 +42,7 @@ namespace xo {
// non-const methods
AllocInfo alloc_info(Opaque d, value_type mem) const noexcept override {
AllocInfo alloc_info(Copaque d, value_type mem) const noexcept override {
return I::alloc_info(_dcast(d), mem);
}
bool expand(Opaque d,

View file

@ -22,6 +22,10 @@ namespace xo {
RAllocIterator(Object::DataPtr data) : Object{std::move(data)} {}
int32_t _typeseq() const noexcept { return O::iface()->_typeseq(); }
AllocInfo deref() const noexcept { return O::iface()->deref(O::data()); }
cmpresult compare(const obj<AAllocIterator> & other) const noexcept {
return O::iface()->compare(O::data(), other); }
void next() noexcept { O::iface()->next(O::data()); }
static bool _valid;
};
@ -36,6 +40,21 @@ namespace xo {
struct RoutingFor<xo::mm::AAllocIterator, Object> {
using RoutingType = xo::mm::RAllocIterator<Object>;
};
/* also provide comparison */
template <typename DRepr1, typename DRepr2>
inline bool operator==(obj<xo::mm::AAllocIterator, DRepr1> lhs,
obj<xo::mm::AAllocIterator, DRepr2> rhs)
{
return lhs.compare(rhs).is_equal();
}
template <typename DRepr1, typename DRepr2>
inline bool operator!=(obj<xo::mm::AAllocIterator, DRepr1> lhs,
obj<xo::mm::AAllocIterator, DRepr2> rhs)
{
return !lhs.compare(rhs).is_equal();
}
}
} /*namespace xo*/

View file

@ -6,6 +6,7 @@
#pragma once
#include "AAllocator.hpp"
#include "AllocIterator.hpp"
#include <xo/facet/RRouter.hpp>
#include <string>

View file

@ -46,7 +46,7 @@ namespace xo {
static AllocError last_error(const DArena &) noexcept;
/** retrieve allocation bookkeeping info for @p mem from arena @p d **/
static AllocInfo alloc_info(DArena &, value_type mem) noexcept;
static AllocInfo alloc_info(const DArena &, value_type mem) noexcept;
/** expand committed space in arena @p d
* to size at least @p z
* In practice will round up to a multiple of @ref page_z_.

View file

@ -46,7 +46,12 @@ namespace xo {
/** print to stream **/
void display(std::ostream & os) const;
bool is_equal() const { return (err_ == comparison::comparable) && (cmp_ == 0); }
bool is_lesser() const {
return (err_ == comparison::comparable) && (cmp_ < 0);
}
bool is_equal() const {
return (err_ == comparison::comparable) && (cmp_ == 0);
}
/* -1 -> invalid (sentinel)
* 0 -> comparable

View file

@ -191,6 +191,9 @@ namespace xo {
/** true iff original alloc has been replaced by a forwarding pointer **/
bool is_forwarding_header(header_type hdr) const noexcept;
/** Retreive bookkeeping info for allocation at @p mem. **/
AllocInfo alloc_info(value_type mem) const noexcept;
// ----- allocation -----
/** simple allocation. new allocs always in gen0 to-space **/
@ -211,8 +214,6 @@ namespace xo {
/** expand gen0 committed size to at least @p z.
**/
bool expand(size_type z) noexcept;
/** Retreive bookkeeping info for allocation at @p mem. **/
AllocInfo alloc_info(value_type mem) noexcept;
// ----- iteration -----

View file

@ -42,6 +42,11 @@ namespace xo {
bool is_valid() const noexcept { return (gc_ != nullptr); }
bool is_invalid() const noexcept { return !is_valid(); }
generation gen_ix() const { return gen_ix_; }
generation gen_hi() const { return gen_hi_; }
DArenaIterator arena_ix() const { return arena_ix_; }
DArenaIterator arena_hi() const { return arena_hi_; }
/** fetch contents at current iterator position **/
AllocInfo deref() const noexcept;
/** compare two iterators. To be comparable,

View file

@ -49,6 +49,8 @@ namespace xo {
static bool contains(const DX1Collector & d, const void * p) noexcept;
/** report last error, if any, for collector @p d **/
static AllocError last_error(const DX1Collector &) noexcept;
/** fetch allocation bookkeeping info **/
static AllocInfo alloc_info(const DX1Collector & d, value_type mem) noexcept;
/** always alloc in gen0 to-space **/
static value_type alloc(DX1Collector & d, size_type z) noexcept;
@ -56,8 +58,6 @@ namespace xo {
static value_type sub_alloc(DX1Collector & d, size_type z, bool complete) noexcept;
/** expand gen0 spaces (both from-space and to-space) **/
static bool expand(DX1Collector & d, size_type z) noexcept;
/** fetch allocation bookkeeping info **/
static AllocInfo alloc_info(DX1Collector & d, value_type mem) noexcept;
/** reset to empty state; clears all generations **/
static void clear(DX1Collector & d);