General Purpose library for Freestanding C++ and POSIX systems
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

110 lines
2.1 KiB

#pragma once
#include "gp_config.hpp"
#include "gp/algorithms/min_max.hpp"
#include "gp/algorithms/tmp_manip.hpp"
#include "gp/containers/buffer.hpp"
#include "gp/math/integral.hpp"
#include "gp/utils/allocators/allocator.hpp"
#include <type_traits>
namespace gp {
class arena : public allocator {
gp::optional<gp::reference_wrapper<allocator>> allocator_v;
size_t next;
size_t count;
gp::buffer<char> data;
public:
arena()
: next(0)
, count(0)
, data(gp::buffer<char>(nullptr,nullptr))
{}
arena(allocator& allocator_p, size_t sz)
: allocator_v(allocator_p)
, next(0)
, count(0)
, data(nullptr,nullptr)
{
if(sz != 0)
{
auto v = allocator_v.value().get().allocate(sz);
if(v != nullptr)
{
data=gp::buffer<char>(reinterpret_cast<char*>(v),reinterpret_cast<char*>(v)+sz);
}
}
}
arena(char* pos, size_t sz)
: next(0)
, count(0)
, data(pos,pos+sz)
{}
void reset() {
next = count = 0;
}
virtual void* allocate(size_t sz)
{
size_t align = gp::min((1 << gp::math::log2(sz)), 16);
size_t padding = align - (reinterpret_cast<uintptr_t>(data.begin().data + next)) % align;
auto ret=data.begin()+padding+next;
if(data.contains(ret))
{
count++;
next+=padding+sz;
return ret.data;
}
else
{
return nullptr;
}
}
/**
* @return false whatever happens
*/
virtual bool try_reallocate(void*, size_t) {
return false;
}
/**
* @brief Deallocates the memory if every deallocated block as been deallocated, else marks one deallocation
*
* @param ptr the memory to deallocate
* @return true if either a deallocation or block release happened
* @return false if the pointer was not within the managed area
*/
virtual bool deallocate(void* ptr)
{
if(data.contains((char*)ptr))
{
count--;
if(count==0)
{
for(auto& i : data)
{
i=0;
}
next=0;
}
return true;
}
return false;
}
virtual ~arena()
{
if(allocator_v.has_value())
{
allocator_v.value().get().deallocate(&data[0]);
}
}
};
}