From 85e68c9abbab6091f56bbe50a6e0955f237668fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20L=C3=BCke?= Date: Sun, 5 Jan 2025 20:19:54 +0100 Subject: [PATCH] new arena implementation using std::align() --- src/internal/mana_arena.h | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/src/internal/mana_arena.h b/src/internal/mana_arena.h index a51843b..00203d2 100644 --- a/src/internal/mana_arena.h +++ b/src/internal/mana_arena.h @@ -13,6 +13,11 @@ namespace mesytec::mnode::mana { +template inline bool is_aligned(const T *ptr, size_t alignment = alignof(T)) +{ + return (((uintptr_t)ptr) % alignment) == 0; +} + class Arena { public: @@ -26,16 +31,11 @@ class Arena Arena(Arena &&other) = default; Arena &operator=(Arena &&other) = default; - // pushes at least the required amount of memory onto the arena. - // 'required' is rounded up to the nearest multiple of 'default_align_to' to make - // subsequent allocations aligned. + // Pushes at least the required amount of memory onto the arena. The memory is aligned to + // 'default_align_to' and zeroed u8 *push_size(size_t required) { - size_t padded = round_up(required, default_align_to); - size_t pad_waste = padded - required; - required = padded; - - if (!segment_ || segment_->free() < required) + if (!segment_) { if (segment_count() < max_segments()) { @@ -52,12 +52,20 @@ class Arena assert(segment_ && segment_->free() >= required); - auto result = segment_->cur(); - std::memset(result, 0, required); - segment_->used += required; - ++allocations_; + void *ptr = segment_->cur(); + size_t space = segment_->free(); + if (!std::align(default_align_to, required, ptr, space)) + throw std::bad_alloc(); + + assert(is_aligned(ptr, default_align_to)); + + size_t pad_waste = segment_->free() - space; + segment_->used += required + pad_waste; pad_waste_ += pad_waste; - return result; + ++allocations_; + + std::memset(ptr, 0, required); + return reinterpret_cast(ptr); } template T *push_t(size_t count = 1)