filesystem: Add memory arena allocator

I wanted a fast and predictable memory allocator before I start working on the virtual filesystem.
Functions like malloc and realloc will not be used anymore, instead, the allocator will
need to be passed as a function parameter when doing any kind of heap allocation. For example

    char* create_string(Memory::Arena *allocator);
    int* create_int_array(Memory::Arena *allocator, int size);

The definition MEMORY_CAPACITY in arena.h sets the amount of memory the arena can use.
The number can be increased as needed.

Signed-off-by: Ronald Caesar <github43132@proton.me>
This commit is contained in:
Ronald Caesar 2025-07-07 00:05:18 -04:00
parent d00414da58
commit d3c97317ef
2 changed files with 144 additions and 0 deletions

33
core/memory/arena.cpp Normal file
View file

@ -0,0 +1,33 @@
#include "arena.h"
#include "Base/Assert.h"
Memory::Arena Memory::arena_init() {
// TODO(GloriousTaco): The line below is stupidly unsafe. Replace malloc with mmap() and check the return value.
auto data =
static_cast<uint8_t*>(malloc(sizeof(uint8_t) * MEMORY_CAPACITY));
Memory::Arena arena = {
.capacity = MEMORY_CAPACITY,
.size = 0,
.data = data,
};
return arena;
}
const uint8_t* Memory::arena_allocate(Memory::Arena* arena,
const std::size_t size) {
ASSERT(arena != nullptr);
ASSERT(arena->size + size < arena->capacity);
const uint8_t* const data = &(arena->data[arena->size]);
arena->size += size;
return data;
}
void Memory::arena_reset(Memory::Arena* arena) {
ASSERT(arena != nullptr);
arena->size = 0;
}
void Memory::arena_free(Memory::Arena* arena) {
ASSERT(arena != nullptr);
arena->capacity = 0;
arena->size = 0;
// TODO(GloriousTaco): Replace free with a memory safe alternative.
free(arena->data);
}

111
core/memory/arena.h Normal file
View file

@ -0,0 +1,111 @@
#ifndef POUND_ARENA_H
#define POUND_ARENA_H
#include <cstddef>
#include <cstdint>
#include <cstdlib>
namespace Memory {
/* Defines the default size (in bytes) for memory arenas created via arena_init() */
#define MEMORY_CAPACITY 20480 // 20 KB
/*
* NAME
* Arena - Memory management structure for efficient allocation and de-allocation.
*
* SYNOPSIS
* typedef struct {
* std::size_t capacity; Total number of bytes allocated.
* std::size_t size; The current number of bytes consumed.
* uint8_t* data; A pointer to the base address of the allocated memory buffer.
* } Arena;
*
* DESCRIPTION
* The arena struct handles allocating and managing contiguous memory blocks.
*
* RATIONALE
* A memory arena offers a safer alternative to malloc/realloc by
* maintaining a single contiguous block eliminates heap fragmentation
* that occurs with frequent small allocations.
*/
typedef struct {
std::size_t capacity;
std::size_t size;
uint8_t* data;
} Arena;
/*
* NAME
* arena_init - Initialize a memory arena with default capacity.
*
* SYNOPSIS
* Arena Memory::arena_init();
*
* DESCRIPTION
* The function creates and returns a new memory arena instance with a
* pre-allocated capacity. See the definition MEMORY_CAPACITY to change the
* default capacity.
*
* RETURN VALUE
* Returns a valid Arena object on success.
*/
extern Arena arena_init();
/*
* NAME
* arena_allocate - Allocate memory from a pre-initialized arena.
*
* SYNOPSIS
* const uint8_t Memory::arena_allocate(Memory::Arena* arena, std::size_t size);
*
* DESCRIPTION
* The function allocates size bytes from the specified arena. It assumes
* the arena has sufficient capacity and returns a pointer to the allocated
* memory region.
*
* RETURN VALUE
* Returns a pointer to the first byte of the allocated memory. The returned
* pointer is valid until the arena is reset or destroyed.
*
* NOTES
* Requires Arena to be initialized with arena_init() or similar.
*/
const uint8_t* arena_allocate(Arena* arena, std::size_t size);
/*
* NAME
* arena_reset - Reset a memory arena's allocation size to zero.
*
* SYNOPSIS
* void Memory::arena_reset(Memory::Arena* arena);
*
* DESCRIPTION
* The function resets the allocation size of a pre-initialized Arena to zero.
* This effectively "frees" all memory allocated from the arena without
* deallocating the underlying buffer, allowing reuse of the capacity for
* future allocations.
*
* NOTES
* Resets arena->size to 0 while preserving arena->capacity.
* Does not free the underlying memory buffer.
* Useful for reusing arenas without reallocation.
*/
void arena_reset(Arena* arena);
/**
* NAME
* arena_free - Free the memory allocated by an arena
*
* SYNOPSIS
* void Memory::arena_free(Memory::Arena* arena);
*
* DESCRIPTION
* The function releases the memory buffer associated with a Arena and
* resets its capacity and size to zero. This marks the arena as invalid for
* future allocation unless reinitialized.
*/
void arena_free(Memory::Arena* arena);
} // namespace Memory
#endif //POUND_ARENA_H