From a05e4c88a1e21a177b6dad948f6c9f5369ce9cea Mon Sep 17 00:00:00 2001 From: Sinan Date: Sun, 10 Aug 2025 08:54:02 +0200 Subject: [PATCH] Feat: added support for std::allocator (#65) * feat(memory): added arena_allocator for STL data types support * fix(memory): fixed arena_allocate offset compute --- core/memory/arena.cpp | 4 +-- core/memory/arena_allocator.h | 68 +++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 2 deletions(-) create mode 100644 core/memory/arena_allocator.h diff --git a/core/memory/arena.cpp b/core/memory/arena.cpp index 2ea2bcf..46e7025 100644 --- a/core/memory/arena.cpp +++ b/core/memory/arena.cpp @@ -31,8 +31,8 @@ memory::arena_t memory::arena_init(size_t capacity) const void* memory::arena_allocate(memory::arena_t* arena, const std::size_t size) { ASSERT(arena != nullptr); - ASSERT(arena->size + size < arena->capacity); - const void* const data = &arena->data + arena->size; + ASSERT(arena->size + size <= arena->capacity); + const void* const data = static_cast(arena->data) + arena->size; arena->size += size; return data; } diff --git a/core/memory/arena_allocator.h b/core/memory/arena_allocator.h new file mode 100644 index 0000000..a4a3f3c --- /dev/null +++ b/core/memory/arena_allocator.h @@ -0,0 +1,68 @@ +#ifndef POUND_ARENA_ALLOCATOR_H +#define POUND_ARENA_ALLOCATOR_H + +#include +#include +#include "arena.h" + +namespace memory +{ + /** + @brief An STL-compatible allocator that uses a custom arena for memory management. + + This allocator allows STL containers (such as std::vector) to allocate memory from a user-provided arena, + enabling efficient bulk allocation and deallocation patterns. The arena must provide an `arena_allocate` function. + + @tparam T Type of object to allocate. + + @code + memory::arena_t my_arena = memory::arena_init(4096); + memory::arena_allocator alloc(&my_arena); + + std::vector> vec(alloc); + vec.push_back(42); + // ... + memory::arena_reset(&my_arena); // Frees all allocations in the arena + @endcode + + @note The deallocate function is a no-op; memory is managed by the arena. + + @see arena_t + @see arena_allocate + */ + template + struct arena_allocator { + using value_type = T; + + arena_t* arena; + + arena_allocator(arena_t* a) noexcept : arena(a) {} + + template + arena_allocator(const arena_allocator& other) noexcept : arena(other.arena) {} + + T* allocate(std::size_t n) { + return static_cast(const_cast(arena_allocate(arena, n * sizeof(T)))); + } + + void deallocate(T*, std::size_t) noexcept { + // noop since memory should be freed by arena + } + + template + struct rebind { using other = arena_allocator; }; + }; + + template + inline bool operator==(const arena_allocator& a, const arena_allocator& b) { + return a.arena == b.arena; + } + + template + inline bool operator!=(const arena_allocator& a, const arena_allocator& b) { + return a.arena != b.arena; + } + +} + +#endif // POUND_ARENA_ALLOCATOR_H \ No newline at end of file