- #pragma once
-
- #include "gp_config.hpp"
-
- #include "gp/algorithm/min_max.hpp"
- #include "gp/algorithm/tmp_manip.hpp"
- #include "gp/buffer.hpp"
- #include "gp/math/integer_math.hpp"
- #include "gp/allocator/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;
- }
- }
-
- virtual bool try_reallocate(void*, size_t) {
- return false;
- }
-
- 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]);
- }
- }
- };
- }
|