diff --git a/xo-alloc2/include/xo/alloc2/alloc/AAllocator.hpp b/xo-alloc2/include/xo/alloc2/alloc/AAllocator.hpp index 6c191c5a..26056fb4 100644 --- a/xo-alloc2/include/xo/alloc2/alloc/AAllocator.hpp +++ b/xo-alloc2/include/xo/alloc2/alloc/AAllocator.hpp @@ -117,20 +117,22 @@ namespace xo { **/ virtual bool expand(Opaque d, std::size_t z) const noexcept = 0; /** attempt to allocate @p z bytes of memory from allocator @p d. + * for object with type @p t. + * (DX1collector cares about @p t, DArena does not) * If allocation fails returns nullptr. In this case error details may be retrieved * using last error **/ - virtual value_type alloc(Opaque d, size_type z) const = 0; + virtual value_type alloc(Opaque d, typeseq t, size_type z) const = 0; /** like @ref alloc, but follow with one or more consecutive * @ref sub_alloc() calls. This sequence of allocs will share * the initial allocation header. **/ - virtual value_type super_alloc(Opaque d, size_type z) const = 0; + virtual value_type super_alloc(Opaque d, typeseq t, size_type z) const = 0; /** follow a preceding @ref super_alloc call with additional * subsidiary allocs that share the same object header. * Must finish sequence with exactly one sub_alloc call * with @p complete_flag set. This sub_alloc call may have - * zero @p z + * zero @p z. **/ virtual value_type sub_alloc(Opaque d, size_type z, bool complete_flag) const = 0; /** reset allocator @p d to empty state. **/ diff --git a/xo-alloc2/include/xo/alloc2/alloc/IAllocator_Any.hpp b/xo-alloc2/include/xo/alloc2/alloc/IAllocator_Any.hpp index 60b174ef..df3d18e5 100644 --- a/xo-alloc2/include/xo/alloc2/alloc/IAllocator_Any.hpp +++ b/xo-alloc2/include/xo/alloc2/alloc/IAllocator_Any.hpp @@ -26,6 +26,7 @@ namespace xo { **/ struct IAllocator_Any : public AAllocator { //using Impl = IAllocator_ImplType; + using typeseq = xo::facet::typeseq; using size_type = std::size_t; const AAllocator * iface() const { return std::launder(this); } @@ -49,8 +50,8 @@ namespace xo { // 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(); } + [[noreturn]] value_type alloc(Opaque, typeseq, std::size_t) const override { _fatal(); } + [[noreturn]] value_type super_alloc(Opaque, typeseq, std::size_t) const override { _fatal(); } [[noreturn]] value_type sub_alloc(Opaque, std::size_t, bool) const override { _fatal(); } [[noreturn]] void clear(Opaque) const override { _fatal(); } [[noreturn]] void destruct_data(Opaque) const override { _fatal(); } diff --git a/xo-alloc2/include/xo/alloc2/alloc/IAllocator_Xfer.hpp b/xo-alloc2/include/xo/alloc2/alloc/IAllocator_Xfer.hpp index 796549bc..7d23f2d6 100644 --- a/xo-alloc2/include/xo/alloc2/alloc/IAllocator_Xfer.hpp +++ b/xo-alloc2/include/xo/alloc2/alloc/IAllocator_Xfer.hpp @@ -60,9 +60,11 @@ namespace xo { bool expand(Opaque d, std::size_t z) const noexcept override { return I::expand(_dcast(d), z); } value_type alloc(Opaque d, - std::size_t z) const override { return I::alloc(_dcast(d), z); } + typeseq t, + std::size_t z) const override { return I::alloc(_dcast(d), t, z); } value_type super_alloc(Opaque d, - std::size_t z) const override { return I::super_alloc(_dcast(d), z); } + typeseq t, + std::size_t z) const override { return I::super_alloc(_dcast(d), t, z); } value_type sub_alloc(Opaque d, std::size_t z, bool complete_flag) const override { diff --git a/xo-alloc2/include/xo/alloc2/alloc/RAllocator.hpp b/xo-alloc2/include/xo/alloc2/alloc/RAllocator.hpp index 005dc44e..e39afe8b 100644 --- a/xo-alloc2/include/xo/alloc2/alloc/RAllocator.hpp +++ b/xo-alloc2/include/xo/alloc2/alloc/RAllocator.hpp @@ -40,8 +40,8 @@ namespace xo { AllocInfo alloc_info(value_type mem) const noexcept { return O::iface()->alloc_info(O::data(), mem); } range_type alloc_range(DArena & mm) const noexcept { return O::iface()->alloc_range(O::data(), mm); } - 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 alloc(typeseq t, size_type z) noexcept { return O::iface()->alloc(O::data(), t, z); } + value_type super_alloc(typeseq t, size_type z) noexcept { return O::iface()->super_alloc(O::data(), t, z); } value_type sub_alloc(size_type z, bool complete_flag) noexcept { return O::iface()->sub_alloc(O::data(), z, complete_flag); } diff --git a/xo-alloc2/include/xo/alloc2/arena/DArena.hpp b/xo-alloc2/include/xo/alloc2/arena/DArena.hpp index 696dbae3..efaf768b 100644 --- a/xo-alloc2/include/xo/alloc2/arena/DArena.hpp +++ b/xo-alloc2/include/xo/alloc2/arena/DArena.hpp @@ -8,6 +8,7 @@ #include "ArenaConfig.hpp" #include "AllocError.hpp" #include "AllocInfo.hpp" +#include namespace xo { namespace mm { @@ -43,7 +44,9 @@ namespace xo { /** @brief a contiguous memory range **/ using range_type = std::pair; /** @brief type for allocation header (if enabled) **/ - using header_type = AllocHeader; //std::uint64_t; + using header_type = AllocHeader; + /** integer identifying a type (see xo::facet::typeid()) **/ + using typeseq = xo::facet::typeseq; /** @brief mode argument for @ref _alloc **/ enum class alloc_mode : uint8_t { @@ -169,14 +172,14 @@ namespace xo { * May expand committed memory, as long as resulting committed size * is no larger than reserved size **/ - value_type alloc(size_type z); + value_type alloc(typeseq t, size_type z); /** when store_header_flag enabled: * like alloc(), but combine memory consumed by this alloc * plus following consecutive sub_alloc()'s into a single header. * otherwise equivalent to alloc() **/ - value_type super_alloc(size_type z); + value_type super_alloc(typeseq t, size_type z); /** when store_header_flag enabled: * follow preceding super_alloc() by one or more sub_allocs(). @@ -271,7 +274,10 @@ namespace xo { static T * construct_with(DArena & ialloc, Args&&... args) { - std::byte * mem = ialloc.alloc(sizeof(T)); + using xo::facet::typeseq; + + typeseq t = typeseq::id(); + std::byte * mem = ialloc.alloc(t, sizeof(T)); if (mem) return new (mem) T(std::forward(args)...); diff --git a/xo-alloc2/include/xo/alloc2/arena/IAllocator_DArena.hpp b/xo-alloc2/include/xo/alloc2/arena/IAllocator_DArena.hpp index 85ef4122..d7d5c587 100644 --- a/xo-alloc2/include/xo/alloc2/arena/IAllocator_DArena.hpp +++ b/xo-alloc2/include/xo/alloc2/arena/IAllocator_DArena.hpp @@ -29,6 +29,7 @@ namespace xo { * IAllocator_Xfer IAllocator_Xfer.hpp * RAllocator RAllocator.hpp */ + using typeseq = xo::facet::typeseq; using size_type = std::size_t; using value_type = std::byte *; using range_type = AAllocator::range_type; @@ -54,13 +55,13 @@ namespace xo { **/ static bool expand(DArena & d, size_type z) noexcept; - static value_type alloc(DArena &, size_type z); + static value_type alloc(DArena &, typeseq t, size_type z); /** when store_header_flag enabled: * like alloc(), but combine memory consumed by this alloc * plus following consecutive sub_alloc()'s into a single header. * otherwise equivalent to alloc() **/ - static value_type super_alloc(DArena &, size_type z); + static value_type super_alloc(DArena &, typeseq t, size_type z); /** when store_header_flag enabled: * follow preceding super_alloc() by one or more sub_allocs(). * accumulate total allocated size (including padding) into diff --git a/xo-alloc2/src/alloc2/DArena.cpp b/xo-alloc2/src/alloc2/DArena.cpp index af4892a6..62dce150 100644 --- a/xo-alloc2/src/alloc2/DArena.cpp +++ b/xo-alloc2/src/alloc2/DArena.cpp @@ -15,6 +15,7 @@ #include // for ::memset() namespace xo { + using xo::facet::typeseq; using std::byte; using std::size_t; @@ -313,18 +314,20 @@ namespace xo { } std::byte * - DArena::alloc(std::size_t req_z) + DArena::alloc(typeseq t, std::size_t req_z) { /* - primary allocation path: * exactly 1 header per alloc() call. * - store_header_flag follows configuration */ + (void)t; + return _alloc(req_z, alloc_mode::standard); } std::byte * - DArena::super_alloc(std::size_t req_z) + DArena::super_alloc(typeseq t, std::size_t req_z) { /* - (uncommon) pattern for parent alloc immediately followed by * zero-or-more susidiary allocs, all sharing a single header. @@ -332,6 +335,8 @@ namespace xo { * ArenaConfig.store_header_flag_ disabled */ + (void)t; + return _alloc(req_z, alloc_mode::super); } diff --git a/xo-alloc2/src/alloc2/IAllocator_DArena.cpp b/xo-alloc2/src/alloc2/IAllocator_DArena.cpp index b5362271..12a4a401 100644 --- a/xo-alloc2/src/alloc2/IAllocator_DArena.cpp +++ b/xo-alloc2/src/alloc2/IAllocator_DArena.cpp @@ -111,16 +111,18 @@ namespace xo { std::byte * IAllocator_DArena::alloc(DArena & s, + typeseq t, std::size_t req_z) { - return s.alloc(req_z); + return s.alloc(t, req_z); } std::byte * IAllocator_DArena::super_alloc(DArena & s, + typeseq t, std::size_t req_z) { - return s.super_alloc(req_z); + return s.super_alloc(t, req_z); } std::byte * diff --git a/xo-alloc2/utest/DArenaIterator.test.cpp b/xo-alloc2/utest/DArenaIterator.test.cpp index ce526758..8eb1614a 100644 --- a/xo-alloc2/utest/DArenaIterator.test.cpp +++ b/xo-alloc2/utest/DArenaIterator.test.cpp @@ -169,7 +169,7 @@ namespace xo { /* arbitrary alloc size */ size_t req_z = 13; - byte * mem = a1o.alloc(req_z); + byte * mem = a1o.alloc(typeseq::anon(), req_z); REQUIRE(arena.error_count_ == 0); REQUIRE(mem != nullptr); diff --git a/xo-alloc2/utest/arena.test.cpp b/xo-alloc2/utest/arena.test.cpp index 09e5e4be..6c3278ba 100644 --- a/xo-alloc2/utest/arena.test.cpp +++ b/xo-alloc2/utest/arena.test.cpp @@ -26,6 +26,7 @@ namespace xo { using xo::mm::padding; using xo::mm::error; using xo::facet::obj; + using xo::facet::typeseq; using xo::scope; using std::byte; using std::size_t; @@ -199,7 +200,7 @@ namespace xo { REQUIRE(a1o.allocated() == 0); size_t z0 = 1; - byte * m0 = a1o.alloc(1); + byte * m0 = a1o.alloc(typeseq::anon(), 1); REQUIRE(m0); REQUIRE(a1o.last_error().error_ == error::ok); @@ -211,7 +212,7 @@ namespace xo { REQUIRE(a1o.committed() <= a1o.reserved()); size_t z1 = 16; - byte * m1 = a1o.alloc(z1); + byte * m1 = a1o.alloc(typeseq::anon(), z1); REQUIRE(m1); REQUIRE(a1o.last_error().error_ == error::ok); @@ -248,7 +249,7 @@ namespace xo { REQUIRE(a1o.allocated() == 0); size_t z0 = 1; - byte * m0 = a1o.alloc(1); + byte * m0 = a1o.alloc(typeseq::anon(), 1); REQUIRE(m0); @@ -291,7 +292,7 @@ namespace xo { REQUIRE(a1o.allocated() == 0); size_t z0 = 1; - byte * m0 = a1o.alloc(1); + byte * m0 = a1o.alloc(typeseq::anon(), 1); REQUIRE(m0); @@ -343,7 +344,7 @@ namespace xo { REQUIRE(a1o.allocated() == 0); size_t z0 = cfg.hugepage_z_ + 1; - byte * m0 = a1o.alloc(z0); + byte * m0 = a1o.alloc(typeseq::anon(), z0); REQUIRE(!m0); diff --git a/xo-alloc2/utest/random_allocs.cpp b/xo-alloc2/utest/random_allocs.cpp index 40315342..654c6c9a 100644 --- a/xo-alloc2/utest/random_allocs.cpp +++ b/xo-alloc2/utest/random_allocs.cpp @@ -43,6 +43,8 @@ namespace utest { xoshiro256ss * p_rgen, obj mm) { + using xo::facet::typeseq; + scope log(XO_DEBUG(catch_flag), xtag("n-alloc", n_alloc)); /* track allocs. verify: @@ -65,7 +67,7 @@ namespace utest { bool ok_flag = true; - std::byte * mem = mm.alloc(z); + std::byte * mem = mm.alloc(typeseq::anon(), z); log && log(xtag("i_alloc", i_alloc), xtag("si", si), diff --git a/xo-facet/include/xo/facet/typeseq.hpp b/xo-facet/include/xo/facet/typeseq.hpp index b1088745..ab85821c 100644 --- a/xo-facet/include/xo/facet/typeseq.hpp +++ b/xo-facet/include/xo/facet/typeseq.hpp @@ -44,6 +44,13 @@ namespace xo { } + /** 'anonymous' sentinel type. + * Niche uses for this, e.g. untyped allocator + **/ + static typeseq_impl anon() { + return typeseq_impl(-1); + } + int32_t seqno() const { return seqno_; } private: diff --git a/xo-gc/include/xo/gc/DX1Collector.hpp b/xo-gc/include/xo/gc/DX1Collector.hpp index c5b84839..bd9d5a65 100644 --- a/xo-gc/include/xo/gc/DX1Collector.hpp +++ b/xo-gc/include/xo/gc/DX1Collector.hpp @@ -155,6 +155,7 @@ namespace xo { // ----- DX1Collector ----- struct DX1Collector { + using typeseq = xo::facet::typeseq; using size_type = DArena::size_type; using value_type = DArena::value_type; using header_type = DArena::header_type; @@ -216,9 +217,14 @@ namespace xo { // ----- allocation ----- - /** simple allocation. new allocs always in gen0 to-space **/ - value_type alloc(size_type z) noexcept; - /** compound allocation. To be followed immediately by: + /** simple allocation. allocate @p z bytes of memory + * for an object of type @p t. + * New allocs always in gen0 to-space + **/ + value_type alloc(typeseq t, size_type z) noexcept; + /** compound allocation. Allocate @p z bytes of memory + * for an object of type @p t. + * To be followed immediately by: * 1. zero or more calls to sub_alloc(zi, complete=false), then * 2. exactly one call to sub_alloc(zi, complete=true) * all the allocs in a compound allocation share the same @@ -226,7 +232,7 @@ namespace xo { * allocation with size z + sum(zi). * New allocs always in gen0 to-space **/ - value_type super_alloc(size_type z) noexcept; + value_type super_alloc(typeseq t, size_type z) noexcept; /** sub-allocation with preceding compound allocation. * New allocs always in gen0 to-space **/ diff --git a/xo-gc/include/xo/gc/detail/IAllocator_DX1Collector.hpp b/xo-gc/include/xo/gc/detail/IAllocator_DX1Collector.hpp index c525dadb..6ba79b59 100644 --- a/xo-gc/include/xo/gc/detail/IAllocator_DX1Collector.hpp +++ b/xo-gc/include/xo/gc/detail/IAllocator_DX1Collector.hpp @@ -29,6 +29,7 @@ namespace xo { * RAllocator RCollector.hpp */ struct IAllocator_DX1Collector { + using typeseq = xo::facet::typeseq; using size_type = std::size_t; using value_type = std::byte *; using range_type = AAllocator::range_type; @@ -58,8 +59,8 @@ namespace xo { static range_type alloc_range(const DX1Collector & d, DArena & ialloc) noexcept; /** always alloc in gen0 to-space **/ - static value_type alloc(DX1Collector & d, size_type z) noexcept; - static value_type super_alloc(DX1Collector & d, size_type z) noexcept; + static value_type alloc(DX1Collector & d, typeseq t, size_type z) noexcept; + static value_type super_alloc(DX1Collector & d, typeseq t, size_type z) noexcept; 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; diff --git a/xo-gc/src/gc/DX1Collector.cpp b/xo-gc/src/gc/DX1Collector.cpp index de747764..26223b92 100644 --- a/xo-gc/src/gc/DX1Collector.cpp +++ b/xo-gc/src/gc/DX1Collector.cpp @@ -216,14 +216,14 @@ namespace xo { } auto - DX1Collector::alloc(size_type z) noexcept -> value_type + DX1Collector::alloc(typeseq t, size_type z) noexcept -> value_type { - return with_facet::mkobj(new_space()).alloc(z); + return with_facet::mkobj(new_space()).alloc(t, z); } auto - DX1Collector::super_alloc(size_type z) noexcept -> value_type { - return with_facet::mkobj(new_space()).super_alloc(z); + DX1Collector::super_alloc(typeseq t, size_type z) noexcept -> value_type { + return with_facet::mkobj(new_space()).super_alloc(t, z); } auto diff --git a/xo-gc/src/gc/IAllocator_DX1Collector.cpp b/xo-gc/src/gc/IAllocator_DX1Collector.cpp index d3e172fc..b5b26b5e 100644 --- a/xo-gc/src/gc/IAllocator_DX1Collector.cpp +++ b/xo-gc/src/gc/IAllocator_DX1Collector.cpp @@ -12,6 +12,7 @@ namespace xo { using xo::facet::with_facet; + using xo::facet::typeseq; using std::size_t; using std::byte; @@ -80,15 +81,19 @@ namespace xo { } auto - IAllocator_DX1Collector::alloc(DX1Collector & d, size_type z) noexcept -> value_type + IAllocator_DX1Collector::alloc(DX1Collector & d, + typeseq t, + size_type z) noexcept -> value_type { - return d.alloc(z); + return d.alloc(t, z); } auto - IAllocator_DX1Collector::super_alloc(DX1Collector & d, size_type z) noexcept -> value_type + IAllocator_DX1Collector::super_alloc(DX1Collector & d, + typeseq t, + size_type z) noexcept -> value_type { - return d.super_alloc(z); + return d.super_alloc(t, z); } auto diff --git a/xo-gc/utest/DX1CollectorIterator.test.cpp b/xo-gc/utest/DX1CollectorIterator.test.cpp index ba3ba09c..58a498c5 100644 --- a/xo-gc/utest/DX1CollectorIterator.test.cpp +++ b/xo-gc/utest/DX1CollectorIterator.test.cpp @@ -30,6 +30,7 @@ namespace xo { using xo::mm::cmpresult; using xo::mm::padding; using xo::facet::with_facet; + using xo::facet::typeseq; using std::byte; namespace ut { @@ -109,7 +110,7 @@ namespace xo { REQUIRE(a1o.allocated() == 0); size_t req_z = 13; - byte * mem = gc.alloc(req_z); + byte * mem = gc.alloc(typeseq::anon(), req_z); REQUIRE(mem != nullptr); diff --git a/xo-gc/utest/random_allocs.cpp b/xo-gc/utest/random_allocs.cpp index 40315342..654c6c9a 100644 --- a/xo-gc/utest/random_allocs.cpp +++ b/xo-gc/utest/random_allocs.cpp @@ -43,6 +43,8 @@ namespace utest { xoshiro256ss * p_rgen, obj mm) { + using xo::facet::typeseq; + scope log(XO_DEBUG(catch_flag), xtag("n-alloc", n_alloc)); /* track allocs. verify: @@ -65,7 +67,7 @@ namespace utest { bool ok_flag = true; - std::byte * mem = mm.alloc(z); + std::byte * mem = mm.alloc(typeseq::anon(), z); log && log(xtag("i_alloc", i_alloc), xtag("si", si), diff --git a/xo-object2/src/object2/DList.cpp b/xo-object2/src/object2/DList.cpp index 99469d1a..d95f0bd0 100644 --- a/xo-object2/src/object2/DList.cpp +++ b/xo-object2/src/object2/DList.cpp @@ -8,6 +8,7 @@ namespace xo { using xo::mm::AGCObject; + using xo::facet::typeseq; namespace scm { static DList s_null(obj(), nullptr); @@ -22,7 +23,7 @@ namespace xo { DList::list(obj mm, obj h1) { - void * mem = mm.alloc(sizeof(DList)); + void * mem = mm.alloc(typeseq::id(), sizeof(DList)); return new (mem) DList(h1, DList::null()); } @@ -32,7 +33,7 @@ namespace xo { obj h1, obj h2) { - void * mem = mm.alloc(sizeof(DList)); + void * mem = mm.alloc(typeseq::id(), sizeof(DList)); return new (mem) DList(h1, DList::list(mm, h2)); } diff --git a/xo-object2/src/object2/IGCObject_DFloat.cpp b/xo-object2/src/object2/IGCObject_DFloat.cpp index a56175f1..9d9a65de 100644 --- a/xo-object2/src/object2/IGCObject_DFloat.cpp +++ b/xo-object2/src/object2/IGCObject_DFloat.cpp @@ -11,6 +11,7 @@ namespace xo { using xo::mm::AAllocator; using xo::facet::obj; + using xo::facet::typeseq; using std::size_t; namespace scm { @@ -24,7 +25,8 @@ namespace xo { IGCObject_DFloat::shallow_copy(const DFloat & src, obj mm) noexcept { - DFloat * copy = (DFloat *)mm.alloc(sizeof(DFloat)); + DFloat * copy = (DFloat *)mm.alloc(typeseq::id(), + sizeof(DFloat)); if (copy) *copy = src; diff --git a/xo-object2/src/object2/IGCObject_DInteger.cpp b/xo-object2/src/object2/IGCObject_DInteger.cpp index 706ab093..d6c80bb6 100644 --- a/xo-object2/src/object2/IGCObject_DInteger.cpp +++ b/xo-object2/src/object2/IGCObject_DInteger.cpp @@ -11,6 +11,7 @@ namespace xo { using xo::mm::AAllocator; using xo::facet::obj; + using xo::facet::typeseq; using std::size_t; namespace scm { @@ -24,7 +25,8 @@ namespace xo { IGCObject_DInteger::shallow_copy(const DInteger & src, obj mm) noexcept { - DInteger * copy = (DInteger *)mm.alloc(sizeof(DInteger)); + DInteger * copy = (DInteger *)mm.alloc(typeseq::id(), + sizeof(DInteger)); if (copy) *copy = src; diff --git a/xo-object2/src/object2/IGCObject_DList.cpp b/xo-object2/src/object2/IGCObject_DList.cpp index 19188dfd..a30f2c6a 100644 --- a/xo-object2/src/object2/IGCObject_DList.cpp +++ b/xo-object2/src/object2/IGCObject_DList.cpp @@ -8,8 +8,9 @@ namespace xo { using xo::mm::AGCObject; using xo::mm::AAllocator; - using xo::facet::with_facet; + //using xo::facet::with_facet; using xo::facet::obj; + using xo::facet::typeseq; using std::size_t; namespace scm { @@ -23,7 +24,8 @@ namespace xo { IGCObject_DList::shallow_copy(const DList & src, obj mm) noexcept { - DList * copy = (DList *)mm.alloc(sizeof(DList)); + /* FIXME: need to supply object age here */ + DList * copy = (DList *)mm.alloc(typeseq::id(), sizeof(DList)); if (copy) *copy = src;