#pragma once
|
|
#include "gp_config.hpp"
|
|
#include "gp/buffer.hpp"
|
|
#include <type_traits>
|
|
#include <gp/algorithm/tmp_manip.hpp>
|
|
|
|
namespace gp {
|
|
template<typename page_allocator = int, size_t align = 1>
|
|
class arena {
|
|
page_allocator allocator;
|
|
gp::buffer<char> data;
|
|
size_t last;
|
|
size_t count;
|
|
public:
|
|
arena()
|
|
: last(0)
|
|
, count(0)
|
|
, data(gp::buffer<char>(nullptr,nullptr))
|
|
{}
|
|
|
|
arena(size_t sz)
|
|
: last(0)
|
|
, count(0)
|
|
, data(nullptr,nullptr)
|
|
{
|
|
if constexpr (gp::has_allocator_interface<page_allocator>::value)
|
|
{
|
|
if(sz!=0)
|
|
{
|
|
auto v=allocator.allocate(sz);
|
|
if(v!=nullptr)
|
|
{
|
|
data=gp::buffer<char>(reinterpret_cast<char*>(v),reinterpret_cast<char*>(v)+sz);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
arena(char* pos,size_t sz)
|
|
: last(0)
|
|
, count(0)
|
|
, data(pos,pos+sz)
|
|
{}
|
|
|
|
void* allocate(size_t sz)
|
|
{
|
|
[[maybe_unused]]
|
|
size_t mod = 0;
|
|
|
|
if constexpr (align != 1)
|
|
{
|
|
mod = align - ((intptr_t)data.begin())%align;
|
|
}
|
|
|
|
auto ret=data.begin()+last+mod;
|
|
if(data.contains(ret))
|
|
{
|
|
count++;
|
|
last+=sz+mod;
|
|
return &*(ret);
|
|
}
|
|
else
|
|
{
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
constexpr bool try_reallocate(void*, size_t) {
|
|
return false;
|
|
}
|
|
|
|
bool deallocate(void* ptr)
|
|
{
|
|
if(data.contains((char*)ptr))
|
|
{
|
|
count--;
|
|
if(count==0)
|
|
{
|
|
for(auto& i : data)
|
|
{
|
|
i=0;
|
|
}
|
|
last=0;
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
~arena()
|
|
{
|
|
if constexpr(gp::has_allocator_interface<page_allocator>::value)
|
|
{
|
|
allocator.deallocate(&data[0]);
|
|
}
|
|
}
|
|
};
|
|
}
|