Helios Engine
A modular ECS based data-oriented C++23 game engine framework
Loading...
Searching...
No Matches
fixed_arena_allocator.cpp
Go to the documentation of this file.
1#include <pch.hpp>
2
4
5#include <helios/assert.hpp>
8#include <helios/memory/details/profile.hpp>
9
10#include <algorithm>
11#include <atomic>
12#include <cstddef>
13
14namespace helios::mem {
15
16void FixedArenaAllocator::MoveFrom(FixedArenaAllocator& other) noexcept {
17 capacity_ = std::exchange(other.capacity_, 0);
18 buffer_ = std::exchange(other.buffer_, nullptr);
19 offset_.store(other.offset_.exchange(0, std::memory_order_acq_rel),
20 std::memory_order_release);
21 peak_usage_.store(other.peak_usage_.exchange(0, std::memory_order_relaxed),
22 std::memory_order_relaxed);
23 allocation_count_.store(
24 other.allocation_count_.exchange(0, std::memory_order_relaxed),
25 std::memory_order_relaxed);
26 total_allocations_.store(
27 other.total_allocations_.exchange(0, std::memory_order_relaxed),
28 std::memory_order_relaxed);
29 total_deallocations_.store(
30 other.total_deallocations_.exchange(0, std::memory_order_relaxed),
31 std::memory_order_relaxed);
32 alignment_waste_.store(
33 other.alignment_waste_.exchange(0, std::memory_order_relaxed),
34 std::memory_order_relaxed);
35}
36
37void FixedArenaAllocator::Release() noexcept {
38 if (buffer_ == nullptr) {
39 return;
40 }
41
42 HELIOS_MEMORY_PROFILE_FREE(buffer_, "FixedArenaAllocator");
43 AlignedFree(buffer_, false);
44 buffer_ = nullptr;
45}
46
47void* FixedArenaAllocator::do_allocate(size_t bytes, size_t alignment) {
48 HELIOS_MEMORY_PROFILE_SCOPE_N(
49 "helios::mem::FixedArenaAllocator::do_allocate");
50 HELIOS_MEMORY_PROFILE_ZONE_VALUE(bytes);
51
52 if (bytes == 0) [[unlikely]] {
53 return nullptr;
54 }
55
56 HELIOS_VERIFY(IsPowerOfTwo(alignment),
57 "alignment must be a power of two, got {}!", alignment);
58
59 const size_t effective_alignment = std::max(alignment, kMinAlignment);
60 size_t observed = offset_.load(std::memory_order_relaxed);
61 for (;;) {
62 const size_t padding =
63 CalculatePadding(buffer_ + observed, effective_alignment);
64 const size_t next = SaturatingAdd(observed, SaturatingAdd(padding, bytes));
65 HELIOS_VERIFY(next <= capacity_, "Fixed arena allocator exhausted!");
66 if (offset_.compare_exchange_weak(observed, next, std::memory_order_acq_rel,
67 std::memory_order_relaxed)) {
68 allocation_count_.fetch_add(1, std::memory_order_relaxed);
69 total_allocations_.fetch_add(1, std::memory_order_relaxed);
70 alignment_waste_.fetch_add(padding, std::memory_order_relaxed);
71 size_t peak = peak_usage_.load(std::memory_order_relaxed);
72 while (next > peak && !peak_usage_.compare_exchange_weak(
73 peak, next, std::memory_order_relaxed)) {
74 }
75 return buffer_ + observed + padding;
76 }
77 }
78}
79
80void FixedArenaAllocator::do_deallocate(void* ptr, size_t /*bytes*/,
81 size_t /*alignment*/) {
82 HELIOS_MEMORY_PROFILE_SCOPE_N(
83 "helios::mem::FixedArenaAllocator::do_deallocate");
84
85 if (ptr != nullptr) {
86 HELIOS_ASSERT(Owns(ptr), "ptr does not belong to fixed arena!");
87 total_deallocations_.fetch_add(1, std::memory_order_relaxed);
88 }
89}
90
91} // namespace helios::mem
#define HELIOS_ASSERT(condition,...)
Assertion macro that aborts execution in debug builds.
Definition assert.hpp:259
#define HELIOS_VERIFY(condition,...)
Verify macro that always checks the condition.
Definition assert.hpp:323
PMR arena with fixed runtime capacity.
bool Owns(const void *ptr) const noexcept
Checks whether pointer belongs to this arena's backing buffer.
constexpr bool IsPowerOfTwo(size_t value) noexcept
Checks if a value is a power of two.
Definition common.hpp:215
constexpr size_t kMinAlignment
Minimum alignment used by memory resources.
Definition common.hpp:17
void AlignedFree(void *ptr, bool enable_profile=true) noexcept
Frees memory allocated with AlignedAlloc.
size_t CalculatePadding(const void *ptr, size_t alignment) noexcept
Computes padding required for pointer alignment.
Definition common.hpp:274
constexpr size_t SaturatingAdd(size_t lhs, size_t rhs) noexcept
Saturating add for size_t.
Definition common.hpp:25