xo-object2: type registration + gc fixes
This commit is contained in:
parent
4af2cd0401
commit
99108b8dbb
16 changed files with 285 additions and 17 deletions
|
|
@ -41,7 +41,7 @@ xo_add_genfacetimpl(
|
|||
|
||||
# must complete definition of expression lib before configuring examples
|
||||
add_subdirectory(src/object2)
|
||||
#add_subdirectory(utest)
|
||||
add_subdirectory(utest)
|
||||
#xo_export_cmake_config(${PROJECT_NAME} ${PROJECT_VERSION} ${PROJECT_NAME}Targets)
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -13,12 +13,24 @@ namespace xo {
|
|||
struct DList {
|
||||
using size_type = std::size_t;
|
||||
using AGCObject = xo::mm::AGCObject;
|
||||
using AAllocator = xo::mm::AAllocator;
|
||||
|
||||
DList(xo::obj<AGCObject> h,
|
||||
DList * r) : head_{h}, rest_{r} {}
|
||||
|
||||
/** sentinel for null list **/
|
||||
static DList * null();
|
||||
|
||||
/** list with one element @p h1, allocated from @p mm **/
|
||||
static DList * list(obj<AAllocator> mm,
|
||||
obj<AGCObject> h1);
|
||||
/** list with two elements @p h1, @p h2, allocated from @p mm **/
|
||||
static DList * list(obj<AAllocator> mm,
|
||||
obj<AGCObject> h1,
|
||||
obj<AGCObject> h2);
|
||||
|
||||
/** DList length is at least 1 **/
|
||||
bool is_empty() const noexcept { return false; };
|
||||
bool is_empty() const noexcept;
|
||||
/** DList models a finite sequence **/
|
||||
bool is_finite() const noexcept { return true; };
|
||||
/** return number of elements in this DList **/
|
||||
|
|
@ -26,7 +38,9 @@ namespace xo {
|
|||
/** return element at 0-based index @p ix **/
|
||||
obj<AGCObject> at(size_type ix) const;
|
||||
|
||||
/** first member of list **/
|
||||
obj<AGCObject> head_;
|
||||
/** remainder of list **/
|
||||
DList * rest_ = nullptr;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -5,13 +5,26 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <xo/alloc2/Allocator.hpp>
|
||||
#include <xo/gc/Collector.hpp>
|
||||
#include <xo/alloc2/alloc/AAllocator.hpp>
|
||||
#include <xo/gc/detail/AGCObject.hpp>
|
||||
#include <xo/gc/detail/IGCObject_Xfer.hpp>
|
||||
#include "DFloat.hpp"
|
||||
|
||||
namespace xo {
|
||||
namespace scm { struct IGCObject_DFloat; }
|
||||
|
||||
namespace facet {
|
||||
template <>
|
||||
struct FacetImplementation<xo::mm::AGCObject,
|
||||
xo::scm::DFloat>
|
||||
{
|
||||
using ImplType = xo::mm::IGCObject_Xfer
|
||||
<xo::scm::DFloat,
|
||||
xo::scm::IGCObject_DFloat>;
|
||||
};
|
||||
}
|
||||
|
||||
namespace scm {
|
||||
/* changes here coordinate with:
|
||||
* IGCObject_Xfer
|
||||
|
|
@ -19,11 +32,12 @@ namespace xo {
|
|||
struct IGCObject_DFloat {
|
||||
public:
|
||||
using AAllocator = xo::mm::AAllocator;
|
||||
using ACollector = xo::mm::ACollector;
|
||||
using size_type = std::size_t;
|
||||
|
||||
static size_type shallow_size(const DFloat & d) noexcept;
|
||||
static DFloat * shallow_copy(const DFloat & d, obj<AAllocator> mm) noexcept;
|
||||
static size_type forward_children(DFloat & d) noexcept;
|
||||
static size_type forward_children(DFloat & d, obj<ACollector> gc) noexcept;
|
||||
};
|
||||
} /*namespace scm*/
|
||||
} /*namespace xo*/
|
||||
|
|
|
|||
|
|
@ -12,6 +12,19 @@
|
|||
#include "DInteger.hpp"
|
||||
|
||||
namespace xo {
|
||||
namespace scm { struct IGCObject_DInteger; }
|
||||
|
||||
namespace facet {
|
||||
template <>
|
||||
struct FacetImplementation<xo::mm::AGCObject,
|
||||
xo::scm::DInteger>
|
||||
{
|
||||
using ImplType = xo::mm::IGCObject_Xfer
|
||||
<xo::scm::DInteger,
|
||||
xo::scm::IGCObject_DInteger>;
|
||||
};
|
||||
}
|
||||
|
||||
namespace scm {
|
||||
/* changes here coordinate with:
|
||||
* IGCObject_Xfer
|
||||
|
|
@ -19,11 +32,12 @@ namespace xo {
|
|||
struct IGCObject_DInteger {
|
||||
public:
|
||||
using AAllocator = xo::mm::AAllocator;
|
||||
using ACollector = xo::mm::ACollector;
|
||||
using size_type = std::size_t;
|
||||
|
||||
static size_type shallow_size(const DInteger & d) noexcept;
|
||||
static DInteger * shallow_copy(const DInteger & d, obj<AAllocator> mm) noexcept;
|
||||
static size_type forward_children(DInteger & d) noexcept;
|
||||
static size_type forward_children(DInteger & d, obj<ACollector> gc) noexcept;
|
||||
};
|
||||
} /*namespace scm*/
|
||||
} /*namespace xo*/
|
||||
|
|
|
|||
|
|
@ -5,8 +5,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <xo/alloc2/alloc/AAllocator.hpp>
|
||||
#include <xo/alloc2/alloc/RAllocator.hpp>
|
||||
#include <xo/alloc2/Allocator.hpp>
|
||||
#include <xo/gc/Collector.hpp>
|
||||
#include <xo/gc/detail/AGCObject.hpp>
|
||||
#include <xo/gc/detail/IGCObject_Xfer.hpp>
|
||||
|
|
|
|||
19
include/xo/object2/object2_register_types.hpp
Normal file
19
include/xo/object2/object2_register_types.hpp
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
/** @file object2_register_types.hpp
|
||||
*
|
||||
* @author Roland Conybeare, Dec 2025
|
||||
**/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <xo/gc/Collector.hpp>
|
||||
|
||||
namespace xo {
|
||||
namespace scm {
|
||||
/** Register all object2/ gc-aware types with @p gc.
|
||||
* Return true iff all types register successfully.
|
||||
**/
|
||||
bool object2_register_types(obj<xo::mm::ACollector> gc);
|
||||
}
|
||||
}
|
||||
|
||||
/* end object2_register_types.hpp */
|
||||
|
|
@ -14,6 +14,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "ASequence.hpp"
|
||||
#include <xo/facet/typeseq.hpp>
|
||||
#include <xo/facet/obj.hpp>
|
||||
|
||||
namespace xo { namespace scm { class ISequence_Any; } }
|
||||
|
|
@ -42,6 +43,7 @@ namespace scm {
|
|||
/** @defgroup scm-sequence-any-type-traits **/
|
||||
///@{
|
||||
|
||||
using typeseq = xo::facet::typeseq;
|
||||
using size_type = ASequence::size_type;
|
||||
using AGCObject = ASequence::AGCObject;
|
||||
|
||||
|
|
@ -54,7 +56,7 @@ namespace scm {
|
|||
// from ASequence
|
||||
|
||||
// const methods
|
||||
int32_t _typeseq() const noexcept override { return s_typeseq; }
|
||||
typeseq _typeseq() const noexcept override { return s_typeseq; }
|
||||
[[noreturn]] bool is_empty(Copaque) const noexcept override { _fatal(); }
|
||||
[[noreturn]] bool is_finite(Copaque) const noexcept override { _fatal(); }
|
||||
[[noreturn]] obj<AGCObject> at(Copaque, size_type) const override { _fatal(); }
|
||||
|
|
@ -75,7 +77,7 @@ namespace scm {
|
|||
/** @defgraoup scm-sequence-any-member-vars **/
|
||||
///@{
|
||||
|
||||
static int32_t s_typeseq;
|
||||
static typeseq s_typeseq;
|
||||
static bool _valid;
|
||||
|
||||
///@}
|
||||
|
|
@ -84,4 +86,4 @@ namespace scm {
|
|||
} /*namespace scm */
|
||||
} /*namespace xo */
|
||||
|
||||
/* ISequence_Any.hpp */
|
||||
/* ISequence_Any.hpp */
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ set(SELF_SRCS
|
|||
ISequence_Any.cpp
|
||||
ISequence_DList.cpp
|
||||
DList.cpp
|
||||
object2_register_types.cpp
|
||||
)
|
||||
|
||||
xo_add_shared_library4(${SELF_LIB} ${PROJECT_NAME}Targets ${PROJECT_VERSION} 1 ${SELF_SRCS})
|
||||
|
|
|
|||
|
|
@ -7,7 +7,42 @@
|
|||
#include <xo/indentlog/print/tag.hpp>
|
||||
|
||||
namespace xo {
|
||||
using xo::mm::AGCObject;
|
||||
|
||||
namespace scm {
|
||||
static DList s_null(obj<AGCObject>(), nullptr);
|
||||
|
||||
DList *
|
||||
DList::null()
|
||||
{
|
||||
return &s_null;
|
||||
}
|
||||
|
||||
DList *
|
||||
DList::list(obj<AAllocator> mm,
|
||||
obj<AGCObject> h1)
|
||||
{
|
||||
void * mem = mm.alloc(sizeof(DList));
|
||||
|
||||
return new (mem) DList(h1, DList::null());
|
||||
}
|
||||
|
||||
DList *
|
||||
DList::list(obj<AAllocator> mm,
|
||||
obj<AGCObject> h1,
|
||||
obj<AGCObject> h2)
|
||||
{
|
||||
void * mem = mm.alloc(sizeof(DList));
|
||||
|
||||
return new (mem) DList(h1, DList::list(mm, h2));
|
||||
}
|
||||
|
||||
bool
|
||||
DList::is_empty() const noexcept
|
||||
{
|
||||
return this != &s_null;
|
||||
}
|
||||
|
||||
auto
|
||||
DList::size() const noexcept -> size_type
|
||||
{
|
||||
|
|
@ -15,7 +50,7 @@ namespace xo {
|
|||
|
||||
size_type z = 0;
|
||||
|
||||
while (l) {
|
||||
while (l && l != &s_null) {
|
||||
++z;
|
||||
l = l->rest_;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,9 +33,10 @@ namespace xo {
|
|||
}
|
||||
|
||||
size_t
|
||||
IGCObject_DFloat::forward_children(DFloat &) noexcept
|
||||
IGCObject_DFloat::forward_children(DFloat & src,
|
||||
obj<ACollector>) noexcept
|
||||
{
|
||||
return sizeof(DFloat);
|
||||
return shallow_size(src);
|
||||
}
|
||||
|
||||
} /*namespace scm*/
|
||||
|
|
|
|||
|
|
@ -33,9 +33,10 @@ namespace xo {
|
|||
}
|
||||
|
||||
size_t
|
||||
IGCObject_DInteger::forward_children(DInteger &) noexcept
|
||||
IGCObject_DInteger::forward_children(DInteger & src,
|
||||
obj<ACollector>) noexcept
|
||||
{
|
||||
return sizeof(DInteger);
|
||||
return shallow_size(src);
|
||||
}
|
||||
|
||||
} /*namespace scm*/
|
||||
|
|
|
|||
|
|
@ -37,8 +37,7 @@ namespace xo {
|
|||
{
|
||||
gc.forward_inplace(src.head_.iface(), (void **)&(src.head_.data_));
|
||||
|
||||
//auto rest = with_facet<AGCObject>::mkobj(src.rest_);
|
||||
xo::facet::FacetImplementation<xo::mm::AGCObject, DList>::ImplType iface;
|
||||
auto iface = xo::facet::impl_for<AGCObject, DList>();
|
||||
gc.forward_inplace(&iface, (void **)(&src.rest_));
|
||||
|
||||
return shallow_size(src);
|
||||
|
|
|
|||
34
src/object2/object2_register_types.cpp
Normal file
34
src/object2/object2_register_types.cpp
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
/** @file object2_register_types.cpp
|
||||
*
|
||||
* @author Roland Conybeare, Dec 2025
|
||||
**/
|
||||
|
||||
#include "object2_register_types.hpp"
|
||||
#include "IGCObject_DList.hpp"
|
||||
#include "IGCObject_DFloat.hpp"
|
||||
#include "IGCObject_DInteger.hpp"
|
||||
|
||||
namespace xo {
|
||||
using xo::mm::ACollector;
|
||||
using xo::mm::AGCObject;
|
||||
using xo::mm::IGCObject_Any;
|
||||
using xo::facet::impl_for;
|
||||
using xo::facet::typeseq;
|
||||
|
||||
namespace scm {
|
||||
|
||||
bool
|
||||
object2_register_types(obj<ACollector> gc)
|
||||
{
|
||||
bool ok = true;
|
||||
|
||||
ok &= gc.install_type(impl_for<AGCObject, DList>());
|
||||
|
||||
ok &= gc.install_type(impl_for<AGCObject, DFloat>());
|
||||
|
||||
return ok;
|
||||
}
|
||||
}
|
||||
} /*namespace xo*/
|
||||
|
||||
/* end object2_register_types.cpp */
|
||||
12
utest/CMakeLists.txt
Normal file
12
utest/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
# built unittest xo-object2/utest
|
||||
|
||||
set(UTEST_EXE utest.object2)
|
||||
set(UTEST_SRCS
|
||||
object2_utest_main.cpp
|
||||
X1Collector.test.cpp
|
||||
)
|
||||
|
||||
xo_add_utest_executable(${UTEST_EXE} ${UTEST_SRCS})
|
||||
xo_self_dependency(${UTEST_EXE} xo_object2)
|
||||
#xo_dependency(${UTEST_EXE} randomgen)
|
||||
xo_external_target_dependency(${UTEST_EXE} Catch2 Catch2::Catch2)
|
||||
117
utest/X1Collector.test.cpp
Normal file
117
utest/X1Collector.test.cpp
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
/** @file X1Collector.test.cpp
|
||||
*
|
||||
* @author Roland Conybeare, Dec 2025
|
||||
**/
|
||||
|
||||
#include <xo/gc/Collector.hpp>
|
||||
#include <xo/gc/DX1Collector.hpp>
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
namespace ut {
|
||||
using xo::mm::DX1Collector;
|
||||
using xo::mm::DArena;
|
||||
using xo::mm::CollectorConfig;
|
||||
using xo::mm::ArenaConfig;
|
||||
using xo::mm::generation;
|
||||
using xo::mm::role;
|
||||
|
||||
namespace {
|
||||
struct testcase_x1 {
|
||||
testcase_x1(std::size_t nz,
|
||||
std::size_t tz,
|
||||
std::size_t n_gct,
|
||||
std::size_t t_gct)
|
||||
: nursery_z_{nz},
|
||||
tenured_z_{tz},
|
||||
incr_gc_threshold_{n_gct},
|
||||
full_gc_threshold_{t_gct} {}
|
||||
|
||||
std::size_t nursery_z_;
|
||||
std::size_t tenured_z_;
|
||||
std::size_t incr_gc_threshold_;
|
||||
std::size_t full_gc_threshold_;
|
||||
};
|
||||
|
||||
std::vector<testcase_x1>
|
||||
s_testcase_v = {
|
||||
// n_gct: nursery gc threshold
|
||||
// t_gct: tenured gc threshold
|
||||
//
|
||||
// nz tz n_gct t_gct
|
||||
testcase_x1(4096, 8192, 1024, 1024)
|
||||
};
|
||||
}
|
||||
|
||||
TEST_CASE("x1", "[gc][x1]")
|
||||
{
|
||||
for (std::size_t i_tc = 0, n_tc = s_testcase_v.size(); i_tc < n_tc; ++i_tc) {
|
||||
try {
|
||||
const testcase_x1 & tc = s_testcase_v[i_tc];
|
||||
|
||||
CollectorConfig cfg{
|
||||
.name_ = "x1_test",
|
||||
.arena_config_ = ArenaConfig{
|
||||
.size_ = tc.tenured_z_,
|
||||
.store_header_flag_ = true},
|
||||
.object_types_z_ = 16384,
|
||||
.gc_trigger_v_{{
|
||||
tc.incr_gc_threshold_,
|
||||
tc.full_gc_threshold_}},
|
||||
};
|
||||
|
||||
DX1Collector gc(cfg);
|
||||
|
||||
{
|
||||
REQUIRE(gc.name() == "x1_test");
|
||||
|
||||
const DArena * otypes = gc.get_object_types();
|
||||
|
||||
REQUIRE(otypes != nullptr);
|
||||
REQUIRE(otypes->reserved() >= cfg.object_types_z_);
|
||||
REQUIRE(otypes->reserved() < cfg.object_types_z_ + otypes->page_z_);
|
||||
|
||||
DArena * from_0 = gc.get_space(role::from_space(), generation{0});
|
||||
|
||||
REQUIRE(from_0 != nullptr);
|
||||
REQUIRE(from_0->reserved() >= tc.tenured_z_);
|
||||
REQUIRE(from_0->reserved() < tc.tenured_z_ + from_0->page_z_);
|
||||
REQUIRE(from_0->reserved() % from_0->page_z_ == 0);
|
||||
|
||||
DArena * from_1 = gc.get_space(role::from_space(), generation{1});
|
||||
|
||||
REQUIRE(from_1 != nullptr);
|
||||
REQUIRE(from_1->reserved() == from_0->reserved());
|
||||
|
||||
DArena * to_0 = gc.get_space(role::to_space(), generation{0});
|
||||
|
||||
REQUIRE(to_0 != nullptr);
|
||||
REQUIRE(to_0->reserved() == from_0->reserved());
|
||||
|
||||
DArena * to_1 = gc.get_space(role::to_space(), generation{1});
|
||||
|
||||
REQUIRE(to_1 != nullptr);
|
||||
REQUIRE(to_1->reserved() == to_0->reserved());
|
||||
|
||||
DArena * from_2 = gc.get_space(role::from_space(), generation{2});
|
||||
|
||||
REQUIRE(from_2 == nullptr);
|
||||
|
||||
DArena * to_2 = gc.get_space(role::to_space(), generation{2});
|
||||
|
||||
REQUIRE(to_2 == nullptr);
|
||||
|
||||
REQUIRE(gc.reserved_total()
|
||||
== otypes->reserved() + 4 * from_0->reserved());
|
||||
}
|
||||
|
||||
/* attempt allocation */
|
||||
|
||||
} catch (std::exception & ex) {
|
||||
std::cerr << "caught exception: " << ex.what() << std::endl;
|
||||
REQUIRE(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* end X1Collector.test.cpp */
|
||||
6
utest/object2_utest_main.cpp
Normal file
6
utest/object2_utest_main.cpp
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
/* file object2_utest_main.cpp */
|
||||
|
||||
#define CATCH_CONFIG_MAIN
|
||||
#include "catch2/catch.hpp"
|
||||
|
||||
/* end object2_utest_main.cpp */
|
||||
Loading…
Add table
Add a link
Reference in a new issue