From 7bca67eafc281abffab33f8e8955164514a2e984 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Fri, 12 Dec 2025 11:50:12 -0500 Subject: [PATCH] xo-alloc2: + Allocator.available() + unit test --- include/xo/alloc2/AAllocator.hpp | 2 ++ include/xo/alloc2/IAllocator_Any.hpp | 8 +++++--- include/xo/alloc2/IAllocator_DArena.hpp | 9 ++++++--- include/xo/alloc2/IAllocator_Xfer.hpp | 15 ++++++++++++--- include/xo/alloc2/RAllocator.hpp | 1 + src/alloc2/IAllocator_DArena.cpp | 13 ++++++++++--- utest/arena.test.cpp | 4 ++++ 7 files changed, 40 insertions(+), 12 deletions(-) diff --git a/include/xo/alloc2/AAllocator.hpp b/include/xo/alloc2/AAllocator.hpp index 7b0558b..bcb75fa 100644 --- a/include/xo/alloc2/AAllocator.hpp +++ b/include/xo/alloc2/AAllocator.hpp @@ -55,6 +55,8 @@ namespace xo { * for allocator @p d. **/ virtual std::size_t committed(Copaque d) const = 0; + /** unallocated (but committed) size in bytes for allocator @p d **/ + virtual std::size_t available(Copaque d) const = 0; /** true iff allocator @p d is responsible for memory at address @p p. **/ virtual bool contains(Copaque d, const void * p) const = 0; diff --git a/include/xo/alloc2/IAllocator_Any.hpp b/include/xo/alloc2/IAllocator_Any.hpp index c53495d..e344403 100644 --- a/include/xo/alloc2/IAllocator_Any.hpp +++ b/include/xo/alloc2/IAllocator_Any.hpp @@ -26,14 +26,16 @@ namespace xo { **/ struct IAllocator_Any : public AAllocator { //using Impl = IAllocator_ImplType; + using size_type = std::size_t; // from AAllocator int32_t _typeseq() const override { return s_typeseq; } [[noreturn]] const std::string & name(Copaque) const override { _fatal(); } - [[noreturn]] std::size_t reserved(Copaque) const override { _fatal(); } - [[noreturn]] std::size_t size(Copaque) const override { _fatal(); } - [[noreturn]] std::size_t committed(Copaque) const override { _fatal(); } + [[noreturn]] size_type reserved(Copaque) const override { _fatal(); } + [[noreturn]] size_type size(Copaque) const override { _fatal(); } + [[noreturn]] size_type committed(Copaque) const override { _fatal(); } + [[noreturn]] size_type available(Copaque) const override { _fatal(); } [[noreturn]] bool contains(Copaque, const void *) const override { _fatal(); } [[noreturn]] bool expand(Opaque, std::size_t) const override { _fatal(); } diff --git a/include/xo/alloc2/IAllocator_DArena.hpp b/include/xo/alloc2/IAllocator_DArena.hpp index b0c7782..2a0a703 100644 --- a/include/xo/alloc2/IAllocator_DArena.hpp +++ b/include/xo/alloc2/IAllocator_DArena.hpp @@ -28,10 +28,13 @@ namespace xo { * RAllocator RAllocator.hpp */ struct IAllocator_DArena { + using size_type = std::size_t; + static const std::string & name(const DArena &); - static std::size_t reserved(const DArena &); - static std::size_t size(const DArena &); - static std::size_t committed(const DArena &); + static size_type reserved(const DArena &); + static size_type size(const DArena &); + static size_type committed(const DArena &); + static size_type available(const DArena &); static bool contains(const DArena &, const void * p); /** expand committed space in arena @p d diff --git a/include/xo/alloc2/IAllocator_Xfer.hpp b/include/xo/alloc2/IAllocator_Xfer.hpp index 872b997..838cc0d 100644 --- a/include/xo/alloc2/IAllocator_Xfer.hpp +++ b/include/xo/alloc2/IAllocator_Xfer.hpp @@ -18,6 +18,7 @@ namespace xo { struct IAllocator_Xfer : public AAllocator { // parallel interface to AAllocator, with specific data type using Impl = IAllocator_DRepr; + using size_type = std::size_t; static const DRepr & _dcast(Copaque d) { return *(const DRepr *)d; } static DRepr & _dcast(Opaque d) { return *(DRepr *)d; } @@ -27,15 +28,19 @@ namespace xo { const std::string & name(Copaque d) const override { return Impl::name(_dcast(d)); } - std::size_t reserved(Copaque d) const override { + size_type reserved(Copaque d) const override { return Impl::reserved(_dcast(d)); } - std::size_t size(Copaque d) const override { + size_type size(Copaque d) const override { return Impl::size(_dcast(d)); } - std::size_t committed(Copaque d) const override { + size_type committed(Copaque d) const override { return Impl::committed(_dcast(d)); } + size_type available(Copaque d) const override { + return I::available(_dcast(d)); + } + bool contains(Copaque d, const void * p) const override { return Impl::contains(_dcast(d), p); } @@ -53,6 +58,10 @@ namespace xo { return Impl::destruct_data(*(DRepr*)d); } + private: + using I = Impl; + + public: static int32_t s_typeseq; static bool _valid; }; diff --git a/include/xo/alloc2/RAllocator.hpp b/include/xo/alloc2/RAllocator.hpp index a825568..a47f482 100644 --- a/include/xo/alloc2/RAllocator.hpp +++ b/include/xo/alloc2/RAllocator.hpp @@ -27,6 +27,7 @@ namespace xo { 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()); } bool contains(const void * p) const { return O::iface()->contains(O::data(), p); } bool expand(size_type z) { return O::iface()->expand(O::data(), z); } std::byte * alloc(size_type z) { return O::iface()->alloc(O::data(), z); } diff --git a/src/alloc2/IAllocator_DArena.cpp b/src/alloc2/IAllocator_DArena.cpp index 83ebd8a..73bce9d 100644 --- a/src/alloc2/IAllocator_DArena.cpp +++ b/src/alloc2/IAllocator_DArena.cpp @@ -11,6 +11,8 @@ #include namespace xo { + using std::size_t; + namespace mm { const std::string & @@ -18,21 +20,26 @@ namespace xo { return s.config_.name_; } - std::size_t + size_t IAllocator_DArena::reserved(const DArena & s) { return s.hi_ - s.lo_; } - std::size_t + size_t IAllocator_DArena::size(const DArena & s) { return s.limit_ - s.lo_; } - std::size_t + size_t IAllocator_DArena::committed(const DArena & s) { return s.committed_z_; } + size_t + IAllocator_DArena::available(const DArena & s) { + return s.limit_ - s.free_; + } + bool IAllocator_DArena::contains(const DArena & s, const void * p) diff --git a/utest/arena.test.cpp b/utest/arena.test.cpp index 72c6b4e..02912fe 100644 --- a/utest/arena.test.cpp +++ b/utest/arena.test.cpp @@ -114,6 +114,8 @@ namespace xo { DArena arena = DArena::map(cfg); obj a1o{&arena}; + REQUIRE(a1o.available() == 0); + size_t z2 = 512; REQUIRE(a1o.expand(z2)); @@ -122,6 +124,8 @@ namespace xo { REQUIRE(a1o.committed() % cfg.hugepage_z_ == 0); /* .size() is synonym for .committed() */ REQUIRE(a1o.size() == a1o.committed()); + REQUIRE(a1o.available() >= z2); + REQUIRE(a1o.available() == a1o.committed()); #ifdef NOPE byte * m = a1o.alloc(1);