#pragma once
|
|
|
|
#include "gp/ring_list.hpp"
|
|
#include "gp/allocator/allocator.hpp"
|
|
|
|
#include <stddef.h>
|
|
|
|
namespace gp {
|
|
class aggregator : public allocator {
|
|
using local_container = ring_list<allocator, true>;
|
|
|
|
local_container contents;
|
|
local_container::explorer mark;
|
|
|
|
public:
|
|
/**
|
|
* @brief Construct a new aggregator object from a bootstraping allocator
|
|
*
|
|
* @tparam bootstrapper the type of allocator pushed in
|
|
* @param allocator_v the allocator moved inside the new aggregator
|
|
*/
|
|
template<typename bootstrapper>
|
|
aggregator(bootstrapper&& allocator_v)
|
|
: contents{
|
|
new(allocator_v.allocate(sizeof(local_container::node)))
|
|
local_container::node(
|
|
new(allocator_v.allocate(sizeof(bootstrapper))) std::remove_reference_t<bootstrapper>(gp::forward<bootstrapper&&>(allocator_v))
|
|
),
|
|
*this
|
|
}
|
|
, mark{contents.explore()}
|
|
{}
|
|
|
|
/**
|
|
* @brief inserts a new allocator within the aggregator
|
|
*
|
|
* @tparam s_allocator the type of newly inserted allocator
|
|
* @param value the inserted allocator
|
|
* @return true if the insertion was successful
|
|
* @return false if the insertion failed and the allocator is lost to the abyss of time
|
|
*/
|
|
template<typename s_allocator>
|
|
bool insert(s_allocator&& value) {
|
|
return contents.insert<
|
|
std::remove_reference_t<
|
|
s_allocator
|
|
>
|
|
>(gp::forward<s_allocator>(value));
|
|
}
|
|
|
|
virtual void* allocate(size_t sz) {
|
|
auto cpy = mark;
|
|
do{
|
|
if(auto allocated = (*mark).allocate(sz))
|
|
{
|
|
return allocated;
|
|
}
|
|
++mark;
|
|
}while(cpy != mark);
|
|
return nullptr;
|
|
}
|
|
|
|
virtual bool deallocate(void* ptr) {
|
|
auto cpy = mark;
|
|
do{
|
|
if((*cpy).deallocate(ptr))
|
|
{
|
|
return true;
|
|
}
|
|
--cpy;
|
|
}while(cpy != mark);
|
|
return false;
|
|
}
|
|
|
|
virtual 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;
|
|
}
|
|
};
|
|
}
|