Skip to content

Introducing Memory Manager #426

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Mar 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/Engine-CI.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
on:
push:
branches: [ master, develop ]
branches: [ master, develop, arena-integration ]
pull_request:
branches: [ master, develop ]
branches: [ master, develop, arena-integration ]

jobs:
clang-format:
Expand Down
96 changes: 92 additions & 4 deletions ZEngine/ZEngine/Core/Memory/Allocator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@

namespace ZEngine::Core::Memory
{
ArenaAllocator::~ArenaAllocator() {}

void ArenaAllocator::Initialize(size_t size)
{
memory = (uint8_t*) malloc(size);
Expand Down Expand Up @@ -43,8 +41,6 @@ namespace ZEngine::Core::Memory
return Allocate(size, alignment);
}

void ArenaAllocator::Deallocate(void* pointer) {}

void* ArenaAllocator::Resize(void* old_memory, size_t old_size, size_t new_size, size_t alignment)
{
assert(Helpers::is_power_of_two(alignment) && "Alignment should be power of 2");
Expand Down Expand Up @@ -88,4 +84,96 @@ namespace ZEngine::Core::Memory
current_offset = 0;
}

ArenaTemp BeginTempArena(ArenaAllocator* arena)
{
ArenaTemp temp = {};
temp.Arena = arena;
temp.PreviousOffset = arena->previous_offset;
temp.CurrentOffset = arena->current_offset;
return temp;
}

void EndTempArena(ArenaTemp tmp)
{
auto arena = tmp.Arena;
arena->previous_offset = tmp.PreviousOffset;
arena->current_offset = tmp.CurrentOffset;
}

void PoolAllocator::Initialize(Arena* arena, size_t size, size_t chk_size, size_t alignment)
{
uintptr_t initial_start = (uintptr_t) &arena->memory[arena->current_offset];
uintptr_t start = Helpers::memory_align(initial_start, (uintptr_t) alignment);
size -= (size_t) (start - initial_start);

chk_size = Helpers::memory_align_size_t(chk_size, alignment);

assert(chk_size >= sizeof(PoolFreeNode) && "Chunk size is too small");
assert(size >= chk_size && "Backing buffer length is smaller than the chunk size");

memory = (uint8_t*) arena->Allocate(size, alignment);

assert(memory && "Failed to allocate memory");

total_size = size;
chunk_size = chk_size;
head = nullptr;

Clear();
}

void* PoolAllocator::Allocate()
{
PoolFreeNode* node = head;

if (node == nullptr)
{
return nullptr;
}

head = head->Next;
Helpers::secure_memset(node, 0, chunk_size, chunk_size);

return node;
}

void* PoolAllocator::Allocate(const char* file, int line)
{
return Allocate();
}

void PoolAllocator::Free(void* ptr)
{
if (!ptr)
{
return;
}

auto start = memory;
auto end = &memory[total_size];

if (!(start <= ptr && ptr < end))
{
return;
}

PoolFreeNode* node = (PoolFreeNode*) (ptr);
node->Next = head;
head = node;
}

void PoolAllocator::Clear()
{
auto chunk_count = total_size / chunk_size;
size_t i = 0;

for (i = 0; i < chunk_count; i++)
{
void* ptr = &memory[i * chunk_size];
PoolFreeNode* node = (PoolFreeNode*) ptr;
// Push free node onto thte free list
node->Next = head;
head = node;
}
}
} // namespace ZEngine::Core::Memory
59 changes: 44 additions & 15 deletions ZEngine/ZEngine/Core/Memory/Allocator.h
Original file line number Diff line number Diff line change
@@ -1,31 +1,29 @@
#pragma once
#include <ZEngineDef.h>
#include <stddef.h>
#include <cstdint>

#ifndef DEFAULT_ALIGNMENT
#define DEFAULT_ALIGNMENT (2 * sizeof(void*))
#endif // !DEFAULT_ALIGNMENT

namespace ZEngine::Core::Memory
{
struct Allocator
struct ArenaAllocator;
struct ArenaTemp;

struct ArenaTemp
{
virtual ~Allocator() {}
virtual void* Allocate(size_t size, size_t alignment = DEFAULT_ALIGNMENT) = 0;
virtual void* Allocate(size_t size, size_t alignment, const char* file, int line) = 0;
virtual void Deallocate(void* pointer) = 0;
}; // struct Allocator
ArenaAllocator* Arena = nullptr;
size_t CurrentOffset = 0;
size_t PreviousOffset = 0;
};

struct ArenaAllocator : public Allocator
struct ArenaAllocator
{
virtual ~ArenaAllocator();
~ArenaAllocator() {};

void Initialize(size_t size);
void Shutdown();

void* Allocate(size_t size, size_t alignment = DEFAULT_ALIGNMENT) override;
void* Allocate(size_t size, size_t alignment, const char* file, int line) override;
void Deallocate(void* pointer) override;
void* Allocate(size_t size, size_t alignment = DEFAULT_ALIGNMENT);
void* Allocate(size_t size, size_t alignment, const char* file, int line);

void* Resize(void* old_memory, size_t old_size, size_t new_size, size_t alignment = DEFAULT_ALIGNMENT);
void Clear();
Expand All @@ -35,4 +33,35 @@ namespace ZEngine::Core::Memory
size_t current_offset = 0;
size_t previous_offset = 0;
}; // struct ArenaAllocator

struct PoolFreeNode
{
PoolFreeNode* Next = nullptr;
};

struct PoolAllocator
{
using Arena = ArenaAllocator;

~PoolAllocator() {};

void Initialize(Arena* arena, size_t size, size_t chunk_size, size_t alignment = DEFAULT_ALIGNMENT);

void* Allocate();
void* Allocate(const char* file, int line);

void Free(void* ptr);
void Clear();

uint8_t* memory = nullptr;
PoolFreeNode* head = nullptr;
size_t total_size = 0;
size_t chunk_size = 0;
};

ArenaTemp BeginTempArena(ArenaAllocator* arena);
void EndTempArena(ArenaTemp arena);
} // namespace ZEngine::Core::Memory

#define ZGetScratch(arena) ZEngine::Core::Memory::BeginTempArena(arena)
#define ZReleaseScratch(scratch) ZEngine::Core::Memory::EndTempArena(scratch)
25 changes: 25 additions & 0 deletions ZEngine/ZEngine/Core/Memory/MemoryManager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#pragma once
#include <Allocator.h>

namespace ZEngine::Core::Memory
{
struct MemoryConfiguration
{
size_t DefaultSize = ZGiga(2ull);
};

struct MemoryManager
{
void Initialize(const MemoryConfiguration& config)
{
this->ArenaAllocator.Initialize(config.DefaultSize);
}

void Shutdowm()
{
ArenaAllocator.Shutdown();
}

ArenaAllocator ArenaAllocator = {};
};
} // namespace ZEngine::Core::Memory
16 changes: 16 additions & 0 deletions ZEngine/ZEngine/Helpers/MemoryOperations.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,4 +159,20 @@ namespace ZEngine::Helpers
return p;
}

inline size_t memory_align_size_t(size_t ptr, size_t align)
{
size_t p, a, mod;

assert(is_power_of_two((uintptr_t) align) && "Alignment should be power of two");

p = ptr;
a = align;
mod = p & (a - 1);
if (mod != 0)
{
p += a - mod;
}
return p;
}

} // namespace ZEngine::Helpers
19 changes: 19 additions & 0 deletions ZEngine/ZEngine/ZEngineDef.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,22 @@
#define SINGLE_ARG(...) __VA_ARGS__

#define MAX_FILE_PATH_COUNT 256

/*
* Allocator and Memory Macros
*/
#ifndef DEFAULT_ALIGNMENT
#define DEFAULT_ALIGNMENT (2 * sizeof(void*))
#endif // !DEFAULT_ALIGNMENT

#define ZKilo(size) (size * 1024)
#define ZMega(size) (ZKilo(size) * 1024)
#define ZGiga(size) (ZMega(size) * 1024)

#define ZPush(allocator, type, size) ((type*) (allocator)->Allocate(size, DEFAULT_ALIGNMENT, __FILE__, __LINE__))

#define ZPushArray(arena, type, count) ZPush(arena, type, (sizeof(type) * count))
#define ZPushString(arena, count) ZPushArray(arena, char, count)
#define ZPushStruct(arena, type) ZPushArray(arena, type, 1)

#define ZPushDynamicArray(pool, type) ((type*) (pool)->Allocate(__FILE__, __LINE__))
1 change: 1 addition & 0 deletions ZEngine/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ set (TEST_SOURCES
ThreadPool_test.cpp
handleManager_test.cpp
allocator_test.cpp
../ZEngine/Core/Memory/Allocator.cpp
)

add_executable(ZEngineTests ${TEST_SOURCES})
Expand Down
Loading