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