#pragma once #include "gp/containers/ring_list.hpp" #include "gp/utils/allocators/allocator.hpp" #include namespace gp { class aggregator : public allocator { using local_container = ring_list; 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 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(gp::forward(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 bool insert(s_allocator&& value) { return contents.insert< std::remove_reference_t< s_allocator > >(gp::forward(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; } }; }