From 9b74d749a32122a5b2ca68ae86f05e03db64741f Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Sun, 14 Dec 2025 13:52:29 -0500 Subject: [PATCH] xo-alloc2 xo-object: bugfix + refactor -> IGCObject_DList builds --- docs/glossary.rst | 5 +- xo-alloc2/include/xo/alloc2/ACollector.hpp | 19 ++++++- xo-alloc2/include/xo/alloc2/AGCObject.hpp | 2 +- .../include/xo/alloc2/IAllocator_Any.hpp | 2 + .../include/xo/alloc2/ICollector_Any.hpp | 51 +++++++++++++++++++ xo-alloc2/include/xo/alloc2/RAllocator.hpp | 29 ++++++----- xo-alloc2/include/xo/alloc2/RCollector.hpp | 51 +++++++++++++++++++ .../include/xo/alloc2/RCollector_Any.hpp | 51 +++++++++++++++++++ xo-alloc2/include/xo/alloc2/RGCObject.hpp | 47 +++++++++++++++++ xo-alloc2/include/xo/alloc2/gc/generation.hpp | 2 + xo-alloc2/src/alloc2/CMakeLists.txt | 2 + xo-alloc2/src/alloc2/ICollector_Any.cpp | 39 ++++++++++++++ xo-facet/include/xo/facet/OObject.hpp | 24 +++++++++ xo-facet/include/xo/facet/RRouter.hpp | 4 ++ xo-object2/include/xo/object2/DInteger.hpp | 4 +- xo-object2/include/xo/object2/DList.hpp | 26 ++++++++++ .../include/xo/object2/IGCObject_DList.hpp | 36 +++++++++++++ xo-object2/src/object2/CMakeLists.txt | 1 + xo-object2/src/object2/IGCObject_DList.cpp | 45 ++++++++++++++++ 19 files changed, 421 insertions(+), 19 deletions(-) create mode 100644 xo-alloc2/include/xo/alloc2/ICollector_Any.hpp create mode 100644 xo-alloc2/include/xo/alloc2/RCollector.hpp create mode 100644 xo-alloc2/include/xo/alloc2/RCollector_Any.hpp create mode 100644 xo-alloc2/include/xo/alloc2/RGCObject.hpp create mode 100644 xo-alloc2/src/alloc2/ICollector_Any.cpp create mode 100644 xo-object2/include/xo/object2/DList.hpp create mode 100644 xo-object2/include/xo/object2/IGCObject_DList.hpp create mode 100644 xo-object2/src/object2/IGCObject_DList.cpp diff --git a/docs/glossary.rst b/docs/glossary.rst index 682583cc..a30b992e 100644 --- a/docs/glossary.rst +++ b/docs/glossary.rst @@ -4,9 +4,12 @@ Glossary -------- .. glossary:: - b/c + b/c | abbreviation for ``because`` + dwim + | abbreviation for ``do what I mean`` + iff | abbreviation for ``if, and only if`` diff --git a/xo-alloc2/include/xo/alloc2/ACollector.hpp b/xo-alloc2/include/xo/alloc2/ACollector.hpp index 1b4cf4c0..c88a3404 100644 --- a/xo-alloc2/include/xo/alloc2/ACollector.hpp +++ b/xo-alloc2/include/xo/alloc2/ACollector.hpp @@ -3,6 +3,14 @@ * @author Roland Conybeare, Dec 2025 **/ +#pragma once + +#include "IGCObject_Any.hpp" + +#include +#include +#include + #include "gc/generation.hpp" #include "gc/role.hpp" @@ -14,6 +22,8 @@ namespace xo { using Copaque = const void *; using Opaque = void *; + struct IGCObject_Any; // see IGCObject_Any.hpp + /** @class ACollector * @brief Abstract facet for the XO garbage collector * @@ -37,8 +47,13 @@ namespace xo { * in which case calls through @c std::launder(&iface) * will properly act on @c DFoo. **/ - virtual void install_type(Opaque d, int32_t tseq, AGCObject_Any & iface); - virtual void add_gc_root(Opaque d, int32_t tid, Opaque * root) = 0; + virtual void install_type(Opaque d, int32_t tseq, IGCObject_Any & iface); + virtual void add_gc_root(Opaque d, int32_t tseq, Opaque * root) = 0; + + /** evacuate @p *lhs to to-space and replace with forwarding pointer + * Require: gc in progress + **/ + virtual void forward_inplace(Opaque d, obj * lhs) = 0; }; } diff --git a/xo-alloc2/include/xo/alloc2/AGCObject.hpp b/xo-alloc2/include/xo/alloc2/AGCObject.hpp index fc9c016d..c5586244 100644 --- a/xo-alloc2/include/xo/alloc2/AGCObject.hpp +++ b/xo-alloc2/include/xo/alloc2/AGCObject.hpp @@ -9,7 +9,7 @@ #include "RAllocator.hpp" #include "xo/facet/facet_implementation.hpp" #include "xo/facet/typeseq.hpp" -#include "xo/facet/obj.hpp" +#include "xo/facet/obj.hpp" // for obj in shallow_copy #include #include diff --git a/xo-alloc2/include/xo/alloc2/IAllocator_Any.hpp b/xo-alloc2/include/xo/alloc2/IAllocator_Any.hpp index c58a19d8..24414fb9 100644 --- a/xo-alloc2/include/xo/alloc2/IAllocator_Any.hpp +++ b/xo-alloc2/include/xo/alloc2/IAllocator_Any.hpp @@ -31,6 +31,7 @@ namespace xo { // from AAllocator int32_t _typeseq() const noexcept override { return s_typeseq; } + // const methods [[noreturn]] std::string_view name(Copaque) const noexcept override { _fatal(); } [[noreturn]] size_type reserved(Copaque) const noexcept override { _fatal(); } [[noreturn]] size_type size(Copaque) const noexcept override { _fatal(); } @@ -40,6 +41,7 @@ namespace xo { [[noreturn]] bool contains(Copaque, const void *) const noexcept override { _fatal(); } [[noreturn]] AllocatorError last_error(Copaque) const noexcept override { _fatal(); } + // non-const methods [[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(); } diff --git a/xo-alloc2/include/xo/alloc2/ICollector_Any.hpp b/xo-alloc2/include/xo/alloc2/ICollector_Any.hpp new file mode 100644 index 00000000..9e5d9980 --- /dev/null +++ b/xo-alloc2/include/xo/alloc2/ICollector_Any.hpp @@ -0,0 +1,51 @@ +/** @file ICollector_Any.hpp + * + * @author Roland Conybeare, Dec 2025 + **/ + +#pragma once + +#include "ACollector.hpp" +//#include + +namespace xo { + namespace mm { struct ICollector_Any; } + + namespace facet { + template <> + struct FacetImplementation { + using ImplType = xo::mm::ICollector_Any; + }; + } + + namespace mm { + /** @class ICollector_Any + * @brief Stub Collector Implementation for empty variant instance + **/ + struct ICollector_Any : public ACollector { + using size_type = std::size_t; + + // from ACollector + int32_t _typeseq() const noexcept override { return s_typeseq; } + + // const methods + [[noreturn]] size_type allocated(Copaque, generation, role) const noexcept { _fatal(); } + [[noreturn]] size_type reserved(Copaque, generation, role) const noexcept { _fatal(); } + [[noreturn]] size_type committed(Copaque, generation, role) const noexcept { _fatal(); } + + // non-const methods + [[noreturn]] void install_type(Opaque, int32_t, IGCObject_Any &) noexcept { _fatal(); } + [[noreturn]] void add_gc_root(Opaque, int32_t, Opaque *) { _fatal(); } + [[noreturn]] void forward_inplace(Opaque, obj *) { _fatal(); } + + private: + [[noreturn]] static void _fatal(); + + public: + static int32_t s_typeseq; + static bool _valid; + }; + } /*namespace mm*/ +} /*namespace xo*/ + +/* end ICollector_Any.hpp */ diff --git a/xo-alloc2/include/xo/alloc2/RAllocator.hpp b/xo-alloc2/include/xo/alloc2/RAllocator.hpp index 012c7c2b..6d0b4a5e 100644 --- a/xo-alloc2/include/xo/alloc2/RAllocator.hpp +++ b/xo-alloc2/include/xo/alloc2/RAllocator.hpp @@ -6,7 +6,7 @@ #pragma once #include "AAllocator.hpp" -#include "xo/facet/RRouter.hpp" +#include #include namespace xo { @@ -18,28 +18,29 @@ namespace xo { using O = Object; public: using ObjectType = Object; + using DataPtr = Object::DataPtr; using size_type = std::size_t; using value_type = std::byte *; RAllocator() {} RAllocator(Object::DataPtr data) : Object{std::move(data)} {} - int32_t _typeseq() const { return O::iface()->_typeseq(); } - std::string_view 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()); } - size_type available() const { return O::iface()->available(O::data()); } - size_type allocated() const { return O::iface()->allocated(O::data()); } - bool contains(const void * p) const { return O::iface()->contains(O::data(), p); } - AllocatorError last_error() const { return O::iface()->last_error(O::data()); } + int32_t _typeseq() const noexcept { return O::iface()->_typeseq(); } + std::string_view name() const noexcept { return O::iface()->name(O::data()); } + size_type reserved() const noexcept { return O::iface()->reserved(O::data()); } + size_type size() const noexcept { return O::iface()->size(O::data()); } + size_type committed() const noexcept { return O::iface()->committed(O::data()); } + size_type available() const noexcept { return O::iface()->available(O::data()); } + size_type allocated() const noexcept { return O::iface()->allocated(O::data()); } + bool contains(const void * p) const noexcept { return O::iface()->contains(O::data(), p); } + AllocatorError last_error() const noexcept { return O::iface()->last_error(O::data()); } bool expand(size_type z) { return O::iface()->expand(O::data(), z); } - value_type alloc(size_type z) { return O::iface()->alloc(O::data(), z); } - value_type super_alloc(size_type z) { return O::iface()->super_alloc(O::data(), z); } + value_type alloc(size_type z) noexcept { return O::iface()->alloc(O::data(), z); } + value_type super_alloc(size_type z) noexcept { return O::iface()->super_alloc(O::data(), z); } value_type sub_alloc(size_type z, - bool complete_flag) { return O::iface()->sub_alloc(O::data(), - z, complete_flag); } + bool complete_flag) noexcept { return O::iface()->sub_alloc(O::data(), + z, complete_flag); } static bool _valid; }; diff --git a/xo-alloc2/include/xo/alloc2/RCollector.hpp b/xo-alloc2/include/xo/alloc2/RCollector.hpp new file mode 100644 index 00000000..5da5b30c --- /dev/null +++ b/xo-alloc2/include/xo/alloc2/RCollector.hpp @@ -0,0 +1,51 @@ +/** @file RCollector.hpp + * + * @author Roland Conybeare, Dec 2025 + **/ + +#include "ACollector.hpp" +#include + +namespace xo { + namespace mm { + /** @class RCollector **/ + template + struct RCollector : public Object { + private: + using O = Object; + public: + using ObjectType = Object; + using DataPtr = Object::DataPtr; + using size_type = std::size_t; + //using value_type = std::byte *; + + RCollector() = default; + RCollector(DataPtr data) : Object{std::move(data)} {} + + int32_t _typeseq() const noexcept { return O::iface()->_typeseq(); } + size_type allocated(generation g, role r) const noexcept { return O::iface()->allocated(O::data()); } + size_type reserved(generation g, role r) const noexcept { return O::iface()->reserved(O::data()); } + size_type committed(generation g, role r) const noexcept { return O::iface()->committed(O::data()); } + + void install_type(int32_t tseq, IGCObject_Any & iface) { return O::iface()->install_type(O::data()); } + void add_gc_root(int32_t tseq, Opaque * root) { O::iface()->add_gc_root(O::data()); } + + void forward_inplace(obj * lhs) { O::iface()->forward_inplace(O::data(), lhs); } + + static bool _valid; + }; + + template + bool + RCollector::_valid = facet::valid_object_router(); + } /*namespace mm*/ + + namespace facet { + template + struct RoutingFor { + using RoutingType = xo::mm::RCollector; + }; + } +} /*namespace xo*/ + +/* end RCollector.hpp */ diff --git a/xo-alloc2/include/xo/alloc2/RCollector_Any.hpp b/xo-alloc2/include/xo/alloc2/RCollector_Any.hpp new file mode 100644 index 00000000..5799aa6f --- /dev/null +++ b/xo-alloc2/include/xo/alloc2/RCollector_Any.hpp @@ -0,0 +1,51 @@ +/** @file RCollector_Any.hpp + * + * @author Roland Conybeare, Dec 2025 + **/ + +#pragma once + +#include "ACollector.hpp" +//#include + +namespace xo { + namespace mm { struct ICollector_Any; } + + namespace facet { + template <> + struct FacetImplementation { + using ImplType = xo::mm::ICollector_Any; + }; + } + + namespace mm { + /** @class ICollector_Any + * @brief Stub Collector Implementation for empty variant instance + **/ + struct ICollector_Any : public ACollector { + using size_type = std::size_t; + + // from ACollector + int32_t _typeseq() const noexcept override { return s_typeseq; } + + // const methods + [[noreturn]] size_type allocated(Copaque, generation, role) const noexcept { _fatal(); } + [[noreturn]] size_type reserved(Copaque, generation, role) const noexcept { _fatal(); } + [[noreturn]] size_type committed(Copaque, generation, role) const noexcept { _fatal(); } + + // non-const methods + [[noreturn]] void install_type(Opaque, int32_t, IGCObject_Any &) noexcept { _fatal(); } + [[noreturn]] void add_gc_root(Opaque, int32_t, Opaque *) { _fatal(); } + [[noreturn]] void forward_inplace(Opaque, Opaque **) { _fatail(); } + + private: + [[noreturn]] static void _fatal(); + + public: + static int32_t s_typeseq; + static bool _valid; + }; + } /*namespace mm*/ +} /*namespace xo*/ + +/* end RCollector_Any.hpp */ diff --git a/xo-alloc2/include/xo/alloc2/RGCObject.hpp b/xo-alloc2/include/xo/alloc2/RGCObject.hpp new file mode 100644 index 00000000..054b995e --- /dev/null +++ b/xo-alloc2/include/xo/alloc2/RGCObject.hpp @@ -0,0 +1,47 @@ +/** @file RGCObject.hpp + * + * @author Roland Conybeare, Dec 2025 + **/ + +#pragma once + +#include "AGCObject.hpp" +#include + +namespace xo { + namespace mm { + /** @class RGCObject **/ + template + struct RGCObject : public Object { + private: + using O = Object; + public: + using ObjectType = Object; + using DataPtr = Object::DataPtr; + using size_type = std::size_t; + + RGCObject() = default; + RGCObject(Object::DataPtr data) : Object{std::move(data)} {} + + int32_t _typeseq() const noexcept { return O::iface()->_typeseq(); } + size_type shallow_size() const noexcept { O::iface()->shallow_size(O::data()); } + Opaque * shallow_copy(obj mm) const noexcept { O::iface()->shallow_copy(O::data(), mm); } + size_type forward_children() noexcept { O::iface()->forward_children(O::data()); } + + static bool _valid; + }; + + template + bool + RGCObject::_valid = facet::valid_object_router(); + } /*namespace mm*/ + + namespace facet { + template + struct RoutingFor { + using RoutingType = xo::mm::RGCObject; + }; + } +} /*namespace xo*/ + +/* end RGCObject.hpp */ diff --git a/xo-alloc2/include/xo/alloc2/gc/generation.hpp b/xo-alloc2/include/xo/alloc2/gc/generation.hpp index e7a39eea..96a69a2f 100644 --- a/xo-alloc2/include/xo/alloc2/gc/generation.hpp +++ b/xo-alloc2/include/xo/alloc2/gc/generation.hpp @@ -3,6 +3,8 @@ * @author Roland Conybeare, Dec 2025 **/ +#pragma once + #include #include diff --git a/xo-alloc2/src/alloc2/CMakeLists.txt b/xo-alloc2/src/alloc2/CMakeLists.txt index 77d29762..28f8c202 100644 --- a/xo-alloc2/src/alloc2/CMakeLists.txt +++ b/xo-alloc2/src/alloc2/CMakeLists.txt @@ -8,6 +8,8 @@ set(SELF_SRCS IAllocator_Any.cpp IAllocator_DArena.cpp + ICollector_Any.cpp + IGCObject_Any.cpp ) diff --git a/xo-alloc2/src/alloc2/ICollector_Any.cpp b/xo-alloc2/src/alloc2/ICollector_Any.cpp new file mode 100644 index 00000000..8f0069b9 --- /dev/null +++ b/xo-alloc2/src/alloc2/ICollector_Any.cpp @@ -0,0 +1,39 @@ +/** @file ICollector_Any.cpp + * + * @author Roland Conybeare, Dec 2025 + **/ + +#include "ICollector_Any.hpp" +#include + +namespace xo { + using xo::facet::DVariantPlaceholder; + using xo::facet::typeseq; + using xo::facet::valid_facet_implementation; + + namespace mm { + + void + ICollector_Any::_fatal() { + /* control here on uninitialized ICollector_Any. + * Initialized instance will have specific implementation type + * e.g. ICollector_Xfer + */ + + std::cerr << "fatal" + << ": attempt to call uninitialized" + << " ICollector_Any method" + << std::endl; + std::terminate(); + } + + int32_t + ICollector_Any::s_typeseq = typeseq::id(); + + bool + ICollector_Any::_valid = valid_facet_implementation(); + + } /*namespace mm*/ +} /*namespace xo*/ + +/** end ICollector_Any.cpp */ diff --git a/xo-facet/include/xo/facet/OObject.hpp b/xo-facet/include/xo/facet/OObject.hpp index 7c87a66f..1f46fad2 100644 --- a/xo-facet/include/xo/facet/OObject.hpp +++ b/xo-facet/include/xo/facet/OObject.hpp @@ -72,6 +72,8 @@ namespace xo { /** OObject is truthy **/ operator bool() const { return data_ != nullptr; } + // ----- iface() for variant fat pointer ----- + /** interface pointer for variant OObject instances. * These instance support runtime polymorphism. **/ @@ -88,6 +90,18 @@ namespace xo { return std::launder(&iface_); } + /** non-const verison. Technically all interface methods are const. + * But counterintuitive to have to mark interface methods const + * that are dedicated to mutable data. + **/ + FacetType * iface() + requires std::is_same_v + { + return std::launder(&iface_); + } + + // ----- iface() for typed fat pointer ----- + /** interface pointer for OObject instance with representation * known at compile time. * @@ -102,6 +116,16 @@ namespace xo { return &iface_; } + /** non-const verison. Technically all interface methods are const. + * But counterintuitive to have to mark interface methods const + * that are dedicated to mutable data. + **/ + FacetType * iface() + requires(!std::is_same_v) + { + return &iface_; + } + DataPtr data() const { return data_; } void reset() { data_ = nullptr; } diff --git a/xo-facet/include/xo/facet/RRouter.hpp b/xo-facet/include/xo/facet/RRouter.hpp index daa7887c..56e521d3 100644 --- a/xo-facet/include/xo/facet/RRouter.hpp +++ b/xo-facet/include/xo/facet/RRouter.hpp @@ -12,6 +12,10 @@ namespace xo { template consteval bool valid_object_router() { + static_assert(sizeof(RRouter) >= sizeof(RRouter::ObjectType), + "Router type must inherit Router::ObjectType"); + static_assert(std::is_convertible_v, + "Router type must inherit Router::ObjectType"); static_assert(requires { typename RRouter::ObjectType; }, "Router type must provide typename Router::ObjectType"); static_assert(valid_object_traits, diff --git a/xo-object2/include/xo/object2/DInteger.hpp b/xo-object2/include/xo/object2/DInteger.hpp index ded9e805..3457af79 100644 --- a/xo-object2/include/xo/object2/DInteger.hpp +++ b/xo-object2/include/xo/object2/DInteger.hpp @@ -5,9 +5,11 @@ #pragma once +#include + namespace xo { namespace scm { - using DInteger = double; + using DInteger = std::int64_t; } /*nmaespace obj*/ } /*namespace xo*/ diff --git a/xo-object2/include/xo/object2/DList.hpp b/xo-object2/include/xo/object2/DList.hpp new file mode 100644 index 00000000..f0be1cf4 --- /dev/null +++ b/xo-object2/include/xo/object2/DList.hpp @@ -0,0 +1,26 @@ +/** @file DList.hpp + * + * @author Roland Conybeare, Dec 2025 + **/ + +#include "xo/alloc2/RGCObject.hpp" +#include "xo/alloc2/IGCObject_Any.hpp" +#include "xo/facet/obj.hpp" + +namespace xo { + namespace scm { + + struct DList { + using AGCObject = xo::mm::AGCObject; + + DList(xo::obj h, + xo::obj r) : head_{h}, rest_{r} {} + + obj head_; + obj rest_; + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DList.hpp */ diff --git a/xo-object2/include/xo/object2/IGCObject_DList.hpp b/xo-object2/include/xo/object2/IGCObject_DList.hpp new file mode 100644 index 00000000..890fdd33 --- /dev/null +++ b/xo-object2/include/xo/object2/IGCObject_DList.hpp @@ -0,0 +1,36 @@ +/** @file IGCObject_DList.hpp + * + * @author Roland Conybeare, Dec 2025 + **/ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include "DList.hpp" + +namespace xo { + namespace scm { + /* changes here coordinate with: + * IGCObject_XFer + */ + struct IGCObject_DList { + public: + using AAllocator = xo::mm::AAllocator; + using ACollector = xo::mm::ACollector; + using size_type = std::size_t; + + static size_type shallow_size(const DList & d) noexcept; + static DList * shallow_copy(const DList & d, obj mm) noexcept; + static size_type forward_children(DList & d, obj gc) noexcept; + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IGCObject_DList.hpp */ diff --git a/xo-object2/src/object2/CMakeLists.txt b/xo-object2/src/object2/CMakeLists.txt index 25b46ba1..f3c1382a 100644 --- a/xo-object2/src/object2/CMakeLists.txt +++ b/xo-object2/src/object2/CMakeLists.txt @@ -4,6 +4,7 @@ set(SELF_LIB xo_object2) set(SELF_SRCS IGCObject_DFloat.cpp IGCObject_DInteger.cpp + IGCObject_DList.cpp ) xo_add_shared_library4(${SELF_LIB} ${PROJECT_NAME}Targets ${PROJECT_VERSION} 1 ${SELF_SRCS}) diff --git a/xo-object2/src/object2/IGCObject_DList.cpp b/xo-object2/src/object2/IGCObject_DList.cpp new file mode 100644 index 00000000..104358e8 --- /dev/null +++ b/xo-object2/src/object2/IGCObject_DList.cpp @@ -0,0 +1,45 @@ +/** @file IGCObject_DList.cpp + * + * @author Roland Conybeare, Dec 2025 + **/ + +#include "IGCObject_DList.hpp" + +namespace xo { + using xo::mm::AAllocator; + using xo::facet::obj; + using std::size_t; + + namespace scm { + size_t + IGCObject_DList::shallow_size(const DList &) noexcept + { + return sizeof(DList); + } + + DList * + IGCObject_DList::shallow_copy(const DList & src, + obj mm) noexcept + { + DList * copy = (DList *)mm.alloc(sizeof(DList)); + + if (copy) + *copy = src; + + return copy; + } + + size_t + IGCObject_DList::forward_children(DList & src, + obj gc) noexcept + { + gc.forward_inplace(&src.head_); + gc.forward_inplace(&src.rest_); + + return shallow_size(src); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IGCObject_DList.cpp */