forked from KPGPMC/furlang
Add arena to furlang
Signed-off-by: CHatingPython <chatingpython@gmail.com>
This commit is contained in:
@@ -4,6 +4,7 @@ add_library(libfurc ${FURC_SRCS} ${FURC_HDRS})
|
|||||||
target_include_directories(libfurc PUBLIC include/)
|
target_include_directories(libfurc PUBLIC include/)
|
||||||
target_compile_definitions(libfurc PRIVATE LIBFURC)
|
target_compile_definitions(libfurc PRIVATE LIBFURC)
|
||||||
set_target_properties(libfurc PROPERTIES PREFIX "")
|
set_target_properties(libfurc PROPERTIES PREFIX "")
|
||||||
|
target_link_libraries(libfurc PUBLIC furlang)
|
||||||
add_executable(furc src/main.cpp)
|
add_executable(furc src/main.cpp)
|
||||||
target_link_libraries(furc PRIVATE libfurc)
|
target_link_libraries(furc PRIVATE libfurc)
|
||||||
|
|
||||||
|
|||||||
@@ -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/)
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
#ifndef FURLANG_ARENA_HPP
|
||||||
|
#define FURLANG_ARENA_HPP
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
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 <typename T>
|
||||||
|
T* allocate(std::size_t count = 1) {
|
||||||
|
return reinterpret_cast<T*>(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
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
#include "furlang/arena.hpp"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
namespace furlang {
|
||||||
|
|
||||||
|
arena::region* arena::region::create(std::size_t capacity) {
|
||||||
|
arena::region* region =
|
||||||
|
reinterpret_cast<arena::region*>(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
|
||||||
Reference in New Issue
Block a user