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.
 
 

87 lines
2.0 KiB

#pragma once
#include "gp/containers/ring_list.hpp"
#include "gp/utils/allocators/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;
}
};
}