diff --git a/include/xo/alloc2/AAllocator.hpp b/include/xo/alloc2/AAllocator.hpp index b0d8234..d2903d9 100644 --- a/include/xo/alloc2/AAllocator.hpp +++ b/include/xo/alloc2/AAllocator.hpp @@ -30,11 +30,15 @@ namespace xo { using value_type = std::byte*; AllocatorError() = default; - explicit AllocatorError(error err) : error_{err} {} + explicit AllocatorError(error err, + uint32_t seq) : error_{err}, + error_seq_{seq} {} AllocatorError(error err, + uint32_t seq, size_type req_z, size_type com_z, size_type rsv_z) : error_{err}, + error_seq_{seq}, request_z_{req_z}, committed_z_{com_z}, reserved_z_{rsv_z} {} @@ -42,6 +46,10 @@ namespace xo { /** error code **/ error error_ = error::none; + /** sequence# of this error. + * Each error event within an allocator gets next sequence number + **/ + uint32_t error_seq_ = 0; /** reqeust size assoc'd with errror **/ size_type request_z_ = 0; /** committed allocator memory at time of error **/ @@ -104,6 +112,9 @@ namespace xo { **/ virtual bool contains(Copaque d, const void * p) const noexcept = 0; + /** report last error **/ + virtual AllocatorError last_error(Copaque d) const noexcept = 0; + /** expand committed space in arena @p d * to size at least @p z * In practice will round up to a multiple of hugepage size (2MB) diff --git a/include/xo/alloc2/IAllocator_Any.hpp b/include/xo/alloc2/IAllocator_Any.hpp index c8735f7..5323188 100644 --- a/include/xo/alloc2/IAllocator_Any.hpp +++ b/include/xo/alloc2/IAllocator_Any.hpp @@ -38,6 +38,7 @@ namespace xo { [[noreturn]] size_type available(Copaque) const noexcept override { _fatal(); } [[noreturn]] size_type allocated(Copaque) const noexcept override { _fatal(); } [[noreturn]] bool contains(Copaque, const void *) const noexcept override { _fatal(); } + [[noreturn]] AllocatorError last_error(Copaque) const noexcept override { _fatal(); } [[noreturn]] bool expand(Opaque, std::size_t) const noexcept override { _fatal(); } [[noreturn]] std::byte * alloc(Opaque, std::size_t) const override { _fatal(); } diff --git a/include/xo/alloc2/IAllocator_DArena.hpp b/include/xo/alloc2/IAllocator_DArena.hpp index 47886f4..fcdf869 100644 --- a/include/xo/alloc2/IAllocator_DArena.hpp +++ b/include/xo/alloc2/IAllocator_DArena.hpp @@ -37,6 +37,7 @@ namespace xo { static size_type available(const DArena &) noexcept; static size_type allocated(const DArena &) noexcept; static bool contains(const DArena &, const void * p) noexcept; + static AllocatorError last_error(const DArena &) noexcept; /** expand committed space in arena @p d * to size at least @p z diff --git a/include/xo/alloc2/IAllocator_Xfer.hpp b/include/xo/alloc2/IAllocator_Xfer.hpp index 4c49890..54a6915 100644 --- a/include/xo/alloc2/IAllocator_Xfer.hpp +++ b/include/xo/alloc2/IAllocator_Xfer.hpp @@ -24,42 +24,29 @@ namespace xo { static DRepr & _dcast(Opaque d) { return *(DRepr *)d; } // from AAllocator + + // const methods + int32_t _typeseq() const noexcept override { return s_typeseq; } - const std::string & name(Copaque d) const noexcept override { - return Impl::name(_dcast(d)); - } - size_type reserved(Copaque d) const noexcept override { - return Impl::reserved(_dcast(d)); - } - size_type size(Copaque d) const noexcept override { - return Impl::size(_dcast(d)); - } - size_type committed(Copaque d) const noexcept override { - return Impl::committed(_dcast(d)); - } - size_type available(Copaque d) const noexcept override { - return I::available(_dcast(d)); - } - size_type allocated(Copaque d) const noexcept override { - return I::allocated(_dcast(d)); - } - + const std::string & name(Copaque d) const noexcept override { return I::name(_dcast(d)); } + size_type reserved(Copaque d) const noexcept override { return I::reserved(_dcast(d)); } + size_type size(Copaque d) const noexcept override { return I::size(_dcast(d)); } + size_type committed(Copaque d) const noexcept override { return I::committed(_dcast(d)); } + size_type available(Copaque d) const noexcept override { return I::available(_dcast(d)); } + size_type allocated(Copaque d) const noexcept override { return I::allocated(_dcast(d)); } bool contains(Copaque d, const void * p) const noexcept override { - return Impl::contains(_dcast(d), p); + return I::contains(_dcast(d), p); } + AllocatorError last_error(Copaque d) const noexcept override { return I::last_error(_dcast(d)); } - bool expand(Opaque d, std::size_t z) const noexcept override { - return Impl::expand(_dcast(d), z); - } - std::byte * alloc(Opaque d, std::size_t z) const override { - return Impl::alloc(*(DRepr*)d, z); - } - void clear(Opaque d) const override { - return Impl::clear(*(DRepr*)d); - } - void destruct_data(Opaque d) const override { - return Impl::destruct_data(*(DRepr*)d); - } + // non-const methods + + bool expand(Opaque d, + std::size_t z) const noexcept override { return I::expand(_dcast(d), z); } + std::byte * alloc(Opaque d, + std::size_t z) const override { return I::alloc(_dcast(d), z); } + void clear(Opaque d) const override { return I::clear(_dcast(d)); } + void destruct_data(Opaque d) const override { return I::destruct_data(_dcast(d)); } private: using I = Impl; diff --git a/src/alloc2/IAllocator_DArena.cpp b/src/alloc2/IAllocator_DArena.cpp index 30ccd1d..bd1ddab 100644 --- a/src/alloc2/IAllocator_DArena.cpp +++ b/src/alloc2/IAllocator_DArena.cpp @@ -52,6 +52,11 @@ namespace xo { return (s.lo_ <= p) && (p < s.hi_); } + AllocatorError + IAllocator_DArena::last_error(const DArena & s) noexcept { + return s.last_error_; + } + bool IAllocator_DArena::expand(DArena & s, size_t target_z) noexcept { @@ -69,6 +74,7 @@ namespace xo { if (s.lo_ + target_z > s.hi_) [[unlikely]] { ++(s.error_count_); s.last_error_ = AllocatorError(error::reserve_exhausted, + s.error_count_, target_z, s.committed_z_, reserved(s)); #ifdef OBSOLETE @@ -116,6 +122,7 @@ namespace xo { if (::mprotect(commit_start, add_commit_z, PROT_READ | PROT_WRITE) != 0) [[unlikely]] { ++(s.error_count_); s.last_error_ = AllocatorError(error::commit_failed, + s.error_count_, add_commit_z, s.committed_z_, reserved(s)); #ifdef OBSOLETE throw std::runtime_error(tostr("ArenaAlloc::expand: commit failure",