xo-alloc2 xo-gc: assorted utest-guided cleanup ++ coverage

This commit is contained in:
Roland Conybeare 2026-05-10 18:19:41 -04:00
commit 9b84ef8a7f
12 changed files with 111 additions and 11 deletions

View file

@ -0,0 +1,15 @@
/** @file ArenaIterator.hpp
*
* @author Roland Conybeare, May 2026
**/
#pragma once
// reminder: we can't put this AAllocIterator support in xo-arena
// because xo-arena is a dependency of xo-facet, which we're relying
// on here
#include <xo/arena/DArenaIterator.hpp>
#include "arena/IAllocIterator_DArenaIterator.hpp"
/* end ArenaIterator.hpp */

View file

@ -72,8 +72,6 @@ namespace xo {
* @p complete_flag to true.
**/
static value_type sub_alloc(DArena &, size_type z, bool complete_flag);
/** allocate copy of @p src in arena @p d. **/
static value_type alloc_copy(DArena & d, value_type src);
static void clear(DArena &);
/** perform assignment {*lhs_iface, *lhs_data} = {*rhs_iface, rhs_data} **/
static void barrier_assign_aux(DArena &,

View file

@ -30,6 +30,8 @@ namespace xo {
operator value_type() const { return role_; }
Role next() const { return Role(role_ + 1); }
value_type role_ = 0;
};
} /*namespace mm*/

View file

@ -15,7 +15,8 @@ namespace xo {
namespace mm {
void
IAllocator_Any::_fatal() {
IAllocator_Any::_fatal()
{
/* control here on uninitialized IAllocator_Any.
* Initialized instance will have specific implementation type
* e.g. IAllocator_Xfer<DArena>

View file

@ -141,13 +141,6 @@ namespace xo {
return s.sub_alloc(req_z, complete_flag);
}
std::byte *
IAllocator_DArena::alloc_copy(DArena &s,
value_type src)
{
return s.alloc_copy(src);
}
void
IAllocator_DArena::clear(DArena & s)
{

View file

@ -5,6 +5,7 @@
#include "SetupAlloc2.hpp"
#include <xo/alloc2/Arena.hpp>
#include <xo/alloc2/ArenaIterator.hpp>
#include <xo/facet/FacetRegistry.hpp>
#include <xo/indentlog/scope.hpp>
@ -21,8 +22,13 @@ namespace xo {
scope log(XO_DEBUG(true));
FacetRegistry::register_impl<AAllocator, DArena>();
FacetRegistry::register_impl<AAllocIterator, DArenaIterator>();
log && log(xtag("DArena.tseq", typeseq::id<DArena>()));
log && log(xtag("DArenaIterator.tseq", typeseq::id<DArenaIterator>()));
log && log(xtag("AAllocator.tseq", typeseq::id<AAllocator>()));
log && log(xtag("AAllocIterator.tseq", typeseq::id<AAllocIterator>()));
return true;
}

View file

@ -10,6 +10,7 @@ set(UTEST_SRCS
# Collector.test.cpp
# DX1CollectorIterator.test.cpp
Generation.test.cpp
Role.test.cpp
VisitReason.test.cpp
dp.test.cpp
random_allocs.cpp

View file

@ -39,4 +39,4 @@ namespace xo {
} /*namespace ut*/
} /*namespace xo*/
/* end Generation.hpp */
/* end Generation.test.cpp */

46
utest/Role.test.cpp Normal file
View file

@ -0,0 +1,46 @@
/** @file Role.test.cpp
*
* @author Roland Conybeare, May 2026
**/
#include "role.hpp"
#include <catch2/catch.hpp>
namespace xo {
using xo::mm::Role;
namespace ut {
TEST_CASE("Role-1", "[Role]")
{
/* 1. there are two distinct valid roles, 'to' and 'from',
* 2. valid roles fall in interval [begin, end)
*/
REQUIRE(Role::to_space() == Role::to_space());
REQUIRE(Role::from_space() == Role::from_space());
REQUIRE(Role::to_space() != Role::from_space());
Role x0 = Role::begin();
{
bool ok = (x0 == Role::to_space() || x0 == Role::from_space());
REQUIRE(ok);
}
REQUIRE(x0 != Role::end());
Role x1 = x0.next();
REQUIRE(x1 != x0);
{
bool ok = (x1 == Role::to_space() || x1 == Role::from_space());
REQUIRE(ok);
}
REQUIRE(x1 != Role::end());
Role x2 = x1.next();
REQUIRE(x2 == Role::end());
}
}
} /*namespace xo*/
/* end Role.test.cpp */

View file

@ -20,6 +20,7 @@ namespace xo {
using xo::mm::AllocHeaderConfig;
using xo::mm::ArenaConfig;
using xo::mm::AllocHeader;
using xo::mm::AllocInfo;
using xo::mm::padding;
using xo::mm::error;
using xo::facet::with_facet;
@ -223,6 +224,39 @@ namespace xo {
REQUIRE(a1o.allocated() <= a1o.committed());
REQUIRE(a1o.allocated() + a1o.available() == a1o.committed());
REQUIRE(a1o.committed() <= a1o.reserved());
auto committed0_z = a1o.committed();
// also test alloc info
AllocInfo m0_info = a1o.alloc_info(m0);
{
REQUIRE(m0_info.size() >= z0);
// {tseq, age}: feature disabled must be zero
REQUIRE(m0_info.tseq() == 0);
REQUIRE(m0_info.age() == 0);
REQUIRE(m0_info.payload().first == m0);
REQUIRE(m0_info.payload().second >= m0 + z0);
REQUIRE(m0_info.guard_z() == cfg.header_.guard_z_);
REQUIRE((uint32_t)m0_info.guard_byte() == (uint32_t)cfg.header_.guard_byte_);
}
a1o.clear();
// allocated size got reset
REQUIRE(a1o.allocated() == 0);
// committed size unchanged
REQUIRE(a1o.committed() == committed0_z);
REQUIRE(a1o.last_error().error_ == error::ok);
REQUIRE(a1o.last_error().error_seq_ == 0);
// allocator no longer contains m0 (now points to unallocated but committed memory
// (not exposed via AAllocator!
// REQUIRE(a1o.contains_allocated(m0) == false);
REQUIRE(a1o.contains(m0));
}
TEST_CASE("allocator-alloc-3", "[alloc2][Allocator]")

View file

@ -39,6 +39,7 @@ namespace utest {
bool
AllocUtil::random_allocs(uint32_t n_alloc,
uint32_t max_alloc_z,
bool catch_flag,
xoshiro256ss * p_rgen,
obj<AAllocator> mm)
@ -64,6 +65,8 @@ namespace utest {
double si = ngen(*p_rgen);
double zi = ::pow(2.0, si);
std::size_t z = ::ceil(zi);
if (z > max_alloc_z)
z = max_alloc_z;
bool ok_flag = true;

View file

@ -36,6 +36,7 @@ namespace utest {
* verify allocator behavior
**/
static bool random_allocs(std::uint32_t n_alloc,
std::uint32_t max_alloc_z,
bool catch_flag,
xo::rng::xoshiro256ss * p_rgen,
xo::facet::obj<AAllocator> alloc);