#pragma once
|
|
#include <stddef.h>
|
|
#include "gp/ring_list.hpp"
|
|
|
|
namespace gp {
|
|
class aggregator {
|
|
struct virtual_allocator
|
|
{
|
|
virtual ~virtual_allocator() = default;
|
|
virtual void* allocate(size_t) = 0;
|
|
virtual bool deallocate(void*) = 0;
|
|
virtual bool try_reallocate(void*, size_t) = 0;
|
|
};
|
|
|
|
template<typename alloc>
|
|
class abstract_allocator final : public virtual_allocator{
|
|
alloc internal_representation;
|
|
public:
|
|
abstract_allocator(abstract_allocator& v)
|
|
: internal_representation{v.internal_representation}
|
|
{}
|
|
|
|
abstract_allocator(alloc& v)
|
|
: internal_representation{v}
|
|
{}
|
|
|
|
virtual ~abstract_allocator() override = default;
|
|
virtual void* allocate(size_t sz) override {
|
|
return internal_representation.allocate(sz);
|
|
}
|
|
virtual bool deallocate(void* ptr) override {
|
|
return internal_representation.deallocate(ptr);
|
|
}
|
|
virtual bool try_reallocate(void* ptr, size_t sz) override {
|
|
return internal_representation.try_reallocate(ptr, sz);
|
|
}
|
|
};
|
|
using local_container = ring_list<virtual_allocator, aggregator, false, true>;
|
|
|
|
local_container contents;
|
|
local_container::explorer mark;
|
|
|
|
public:
|
|
template<typename bootstrapper>
|
|
aggregator(bootstrapper&& allocator)
|
|
: contents{
|
|
new(allocator.allocate(sizeof(local_container::node)))
|
|
local_container::node(
|
|
new(allocator.allocate(sizeof(bootstrapper))) abstract_allocator(allocator)
|
|
),
|
|
*this
|
|
}
|
|
, mark{contents.explore()}
|
|
{}
|
|
|
|
template<typename allocator>
|
|
bool insert(allocator&& value) {
|
|
return contents.insert<
|
|
abstract_allocator<
|
|
std::remove_reference_t<
|
|
allocator
|
|
>
|
|
>
|
|
>(abstract_allocator(value));
|
|
}
|
|
|
|
|
|
void* allocate(size_t sz) {
|
|
auto cpy = mark;
|
|
do{
|
|
if(auto allocated = (*mark).allocate(sz))
|
|
{
|
|
return allocated;
|
|
}
|
|
++mark;
|
|
}while(cpy != mark);
|
|
return nullptr;
|
|
}
|
|
bool deallocate(void* ptr) {
|
|
auto cpy = mark;
|
|
do{
|
|
if((*cpy).deallocate(ptr))
|
|
{
|
|
return true;
|
|
}
|
|
--cpy;
|
|
}while(cpy != mark);
|
|
return false;
|
|
}
|
|
bool try_reallocate(void* ptr, size_t sz) {
|
|
auto cpy = mark;
|
|
do{
|
|
if((*cpy).try_reallocate(ptr, sz))
|
|
{
|
|
return true;
|
|
}
|
|
--cpy;
|
|
}while(cpy != mark);
|
|
return false;
|
|
}
|
|
};
|
|
}
|