#pragma once #include "gp_config.hpp" #include "gp/buffer.hpp" #include #include namespace gp{ template class arena{ page_allocator allocator; gp::buffer data; size_t last; size_t count; public: arena() :last(0) ,count(0) ,data(gp::buffer(nullptr,nullptr)) {} arena(size_t sz) :last(0) ,count(0) ,data(nullptr,nullptr) { if constexpr (gp::has_allocator_interface::value) { if(sz!=0) { auto v=allocator.allocate(sz); if(v!=nullptr) { data=gp::buffer(reinterpret_cast(v),reinterpret_cast(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::value) { allocator.deallocate(&data[0]); } } }; }