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.
 
 

102 lines
2.2 KiB

#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;
}
};
}