From d2cfbb676327ba277c995ac108e178cd141752ef Mon Sep 17 00:00:00 2001 From: CHatingPython Date: Mon, 25 May 2026 14:59:42 +0200 Subject: [PATCH] Add arena to furlang Signed-off-by: CHatingPython --- furc/CMakeLists.txt | 1 + furlang/CMakeLists.txt | 4 ++ furlang/include/furlang/arena.hpp | 48 ++++++++++++++++++++ furlang/src/arena.cpp | 75 +++++++++++++++++++++++++++++++ 4 files changed, 128 insertions(+) create mode 100644 furlang/include/furlang/arena.hpp create mode 100644 furlang/src/arena.cpp diff --git a/furc/CMakeLists.txt b/furc/CMakeLists.txt index ce04753..e89257e 100644 --- a/furc/CMakeLists.txt +++ b/furc/CMakeLists.txt @@ -4,6 +4,7 @@ add_library(libfurc ${FURC_SRCS} ${FURC_HDRS}) target_include_directories(libfurc PUBLIC include/) target_compile_definitions(libfurc PRIVATE LIBFURC) set_target_properties(libfurc PROPERTIES PREFIX "") +target_link_libraries(libfurc PUBLIC furlang) add_executable(furc src/main.cpp) target_link_libraries(furc PRIVATE libfurc) diff --git a/furlang/CMakeLists.txt b/furlang/CMakeLists.txt index e69de29..dd9a48b 100644 --- a/furlang/CMakeLists.txt +++ b/furlang/CMakeLists.txt @@ -0,0 +1,4 @@ +file(GLOB_RECURSE FURLANG_SRCS "src/**.cpp") +file(GLOB_RECURSE FURLANG_HDRS "include/**.hpp") +add_library(furlang STATIC ${FURLANG_SRCS} ${FURLANG_HDRS}) +target_include_directories(furlang PUBLIC include/) \ No newline at end of file diff --git a/furlang/include/furlang/arena.hpp b/furlang/include/furlang/arena.hpp new file mode 100644 index 0000000..857146c --- /dev/null +++ b/furlang/include/furlang/arena.hpp @@ -0,0 +1,48 @@ +#ifndef FURLANG_ARENA_HPP +#define FURLANG_ARENA_HPP + +#include +#include + +namespace furlang { + +class arena { +private: + struct region { + using value_type = std::uintptr_t; + + static region* create(std::size_t capacity); + + region* next; + std::size_t capacity; + std::size_t used; + value_type storage[]; + + std::size_t free() const { return capacity - used; } + }; +public: + arena(std::size_t minCapacity = 4 * 1024ULL); + ~arena(); + + arena(arena&& other) noexcept; + arena(const arena&) = delete; + arena& operator=(arena&& other) noexcept; + arena& operator=(const arena&) = delete; +public: + template + T* allocate(std::size_t count = 1) { + return reinterpret_cast(allocate(sizeof(T), count)); + } + + void reset(); +private: + void* allocate(std::size_t size, std::size_t count); +private: + std::size_t m_minCapacity; + region* m_head = nullptr; + region* m_tail = nullptr; +}; + +} // namespace furlang + +#endif // FURLANG_ARENA_HPP \ No newline at end of file diff --git a/furlang/src/arena.cpp b/furlang/src/arena.cpp new file mode 100644 index 0000000..5863483 --- /dev/null +++ b/furlang/src/arena.cpp @@ -0,0 +1,75 @@ +#include "furlang/arena.hpp" + +#include +#include + +namespace furlang { + +arena::region* arena::region::create(std::size_t capacity) { + arena::region* region = + reinterpret_cast(std::malloc(sizeof(*region) + (sizeof(value_type) * capacity))); // NOLINT + if (region == nullptr) return nullptr; + region->next = nullptr; + region->capacity = capacity; + region->used = 0; + return region; +} + +arena::arena(std::size_t minCapacity) + : m_minCapacity(minCapacity) {} + +arena::~arena() { + region* next = nullptr; + for (region* region = m_head; region != nullptr; region = next) { + next = region->next; + delete region; + } +} + +arena::arena(arena&& other) noexcept + : m_minCapacity(other.m_minCapacity), m_head(other.m_head), m_tail(other.m_tail) { + other.m_minCapacity = 0; + other.m_head = nullptr; + other.m_tail = nullptr; +} + +arena& arena::operator=(arena&& other) noexcept { + if (this == &other) return *this; + m_minCapacity = other.m_minCapacity; + m_head = other.m_head; + m_tail = other.m_tail; + other.m_minCapacity = 0; + other.m_head = nullptr; + other.m_tail = nullptr; + return *this; +} + +void arena::reset() { + for (region* region = m_head; region != nullptr; region = region->next) { + region->used = 0; + } +} + +void* arena::allocate(std::size_t size, std::size_t count) { + std::size_t sizeInBytes = size * count; + std::size_t sizeInWords = (sizeInBytes + sizeof(region::value_type) - 1) / sizeof(region::value_type); + + if (m_head == nullptr) { + m_head = m_tail = region::create(std::min(sizeInWords, m_minCapacity)); + } + + region* region = m_head; + while (region != nullptr && region->free() < sizeInWords) + region = region->next; + + if (region == nullptr) { + region = region::create(std::min(sizeInWords, m_minCapacity)); + m_tail = m_tail->next = region; + } + + uintptr_t* allocated = ®ion->storage[region->used]; + region->used += sizeInWords; + return allocated; +} + +} // namespace furlang \ No newline at end of file