From bfae3931278459f01465787b08e99cd5a24ecc26 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Fri, 13 Feb 2026 15:15:08 -0500 Subject: [PATCH] xo-gc stack: streamline object pointer forwarding --- .../include/xo/alloc2/alloc/RAllocator.hpp | 13 +++++++ xo-facet/include/xo/facet/FacetRegistry.hpp | 39 +++++++++++++++---- xo-facet/include/xo/facet/obj.hpp | 6 +++ xo-gc/idl/GCObject.json5 | 2 +- xo-gc/include/xo/gc/GCObject.hpp | 28 ++++++++++++- xo-gc/include/xo/gc/detail/RCollector.hpp | 10 +++++ 6 files changed, 89 insertions(+), 9 deletions(-) diff --git a/xo-alloc2/include/xo/alloc2/alloc/RAllocator.hpp b/xo-alloc2/include/xo/alloc2/alloc/RAllocator.hpp index ecd80bb7..62552411 100644 --- a/xo-alloc2/include/xo/alloc2/alloc/RAllocator.hpp +++ b/xo-alloc2/include/xo/alloc2/alloc/RAllocator.hpp @@ -36,6 +36,19 @@ namespace xo { return O::iface()->alloc(O::data(), typeseq::id(), sizeof(T)); } + template + T * std_copy_for(const T * src) noexcept { + // TODO: fix alloc_copy(), should take const std::byte * + + T * copy = (T *)O::iface()->alloc_copy(O::data(), (std::byte*)const_cast(src)); + + if (copy) { + *copy = *src; + } + + return copy; + } + typeseq _typeseq() const noexcept { return O::iface()->_typeseq(); } void _drop() const noexcept { O::iface()->_drop(O::data()); } std::string_view name() const noexcept { return O::iface()->name(O::data()); } diff --git a/xo-facet/include/xo/facet/FacetRegistry.hpp b/xo-facet/include/xo/facet/FacetRegistry.hpp index d4b15188..9b7e7ade 100644 --- a/xo-facet/include/xo/facet/FacetRegistry.hpp +++ b/xo-facet/include/xo/facet/FacetRegistry.hpp @@ -159,7 +159,7 @@ namespace xo { * } **/ template - obj try_variant(obj from) { + obj try_variant(obj from) noexcept { return try_variant(from._typeseq(), from.data()); } @@ -173,7 +173,7 @@ namespace xo { * = FacetRegistry::variant(foo._typeseq(), foo.opaque_data()); **/ template - obj try_variant(typeseq repr_id, void * data) { + obj try_variant(typeseq repr_id, void * data) noexcept { const AFacet * iface = this->lookup(repr_id); if (iface) @@ -246,12 +246,37 @@ namespace xo { obj obj::to_facet() { - if constexpr (std::is_same_v) { - // return type has type-erased data - return FacetRegistry::instance().variant(*this); + if (this->data()) { + if constexpr (std::is_same_v) { + // return type has type-erased data + return FacetRegistry::instance().variant(*this); + } else { + // return type has known data + return obj(this->data()); + } } else { - // return type has known data - return obj(this->data()); + return obj(); + } + } + + // Deferred definitioon of obj::to_facet(), + // since implementation requires FacetRegistry + // + template + template + obj + obj::try_to_facet() noexcept + { + if (this->data()) { + if constexpr (std::is_same_v) { + // return type has type-erased data + return FacetRegistry::instance().try_variant(*this); + } else { + // return type has known data + return obj(this->data()); + } + } else { + return obj(); } } diff --git a/xo-facet/include/xo/facet/obj.hpp b/xo-facet/include/xo/facet/obj.hpp index 3619ae3e..ada5c832 100644 --- a/xo-facet/include/xo/facet/obj.hpp +++ b/xo-facet/include/xo/facet/obj.hpp @@ -137,6 +137,12 @@ namespace xo { template obj to_facet(); + /** like to_facet(), + * but on failure return empty obj instead of throwing exception + **/ + template + obj try_to_facet() noexcept; + /** enabled when RRouter provides _preincrement. * Note we don't need this trick for comparison operators, * since return type is fixed. diff --git a/xo-gc/idl/GCObject.json5 b/xo-gc/idl/GCObject.json5 index bf0d78cd..30fc0d3a 100644 --- a/xo-gc/idl/GCObject.json5 +++ b/xo-gc/idl/GCObject.json5 @@ -76,5 +76,5 @@ attributes: [], }, ], - router_facet_explicit_content: [ ], + router_facet_explicit_content: [] } diff --git a/xo-gc/include/xo/gc/GCObject.hpp b/xo-gc/include/xo/gc/GCObject.hpp index 2eede6b3..970d2c31 100644 --- a/xo-gc/include/xo/gc/GCObject.hpp +++ b/xo-gc/include/xo/gc/GCObject.hpp @@ -18,5 +18,31 @@ #include "detail/IGCObject_Xfer.hpp" #include "detail/RGCObject.hpp" +namespace xo { + namespace mm { + /** defined here to avoid #include cycle, since + * template obj awkward to make available there + **/ + template + template + void + RCollector::forward_inplace(xo::facet::obj * p_obj) + { + this->forward_inplace(p_obj->iface(), (void **)&(p_obj->data_)); + } + + template + template + void + RCollector::forward_inplace(DRepr ** p_repr) + { + // fetch static interface for DRepr + auto iface = xo::facet::impl_for(); + + this->forward_inplace(&iface, (void **)p_repr); + } + } +} + +/* end GCObject.hpp */ -/* end GCObject.hpp */ \ No newline at end of file diff --git a/xo-gc/include/xo/gc/detail/RCollector.hpp b/xo-gc/include/xo/gc/detail/RCollector.hpp index 5e3eddb3..9cce4844 100644 --- a/xo-gc/include/xo/gc/detail/RCollector.hpp +++ b/xo-gc/include/xo/gc/detail/RCollector.hpp @@ -23,6 +23,16 @@ namespace xo { RCollector() = default; RCollector(DataPtr data) : Object{std::move(data)} {} + /** forward op in place. Defined in GCObject.hpp to avoid #include cycle **/ + template + void forward_inplace(obj * p_obj); + + /** another convenience template for forwarding. + * Defined in RGCObject.hpp to avoid #include cycle. + **/ + template + void forward_inplace(DRepr ** pp_repr); + int32_t _typeseq() const noexcept { return O::iface()->_typeseq(); } size_type allocated(generation g, role r) const noexcept { return O::iface()->allocated(O::data(), g, r); } size_type reserved(generation g, role r) const noexcept { return O::iface()->reserved(O::data(), g, r); }