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.

101 lines
2.2 KiB

  1. #pragma once
  2. #include <stddef.h>
  3. #include "gp/ring_list.hpp"
  4. namespace gp {
  5. class aggregator {
  6. struct virtual_allocator
  7. {
  8. virtual ~virtual_allocator() = default;
  9. virtual void* allocate(size_t) = 0;
  10. virtual bool deallocate(void*) = 0;
  11. virtual bool try_reallocate(void*, size_t) = 0;
  12. };
  13. template<typename alloc>
  14. class abstract_allocator final : public virtual_allocator{
  15. alloc internal_representation;
  16. public:
  17. abstract_allocator(abstract_allocator& v)
  18. : internal_representation{v.internal_representation}
  19. {}
  20. abstract_allocator(alloc& v)
  21. : internal_representation{v}
  22. {}
  23. virtual ~abstract_allocator() override = default;
  24. virtual void* allocate(size_t sz) override {
  25. return internal_representation.allocate(sz);
  26. }
  27. virtual bool deallocate(void* ptr) override {
  28. return internal_representation.deallocate(ptr);
  29. }
  30. virtual bool try_reallocate(void* ptr, size_t sz) override {
  31. return internal_representation.try_reallocate(ptr, sz);
  32. }
  33. };
  34. using local_container = ring_list<virtual_allocator, aggregator, false, true>;
  35. local_container contents;
  36. local_container::explorer mark;
  37. public:
  38. template<typename bootstrapper>
  39. aggregator(bootstrapper&& allocator)
  40. : contents{
  41. new(allocator.allocate(sizeof(local_container::node)))
  42. local_container::node(
  43. new(allocator.allocate(sizeof(bootstrapper))) abstract_allocator(allocator)
  44. ),
  45. *this
  46. }
  47. , mark{contents.explore()}
  48. {}
  49. template<typename allocator>
  50. bool insert(allocator&& value) {
  51. return contents.insert<
  52. abstract_allocator<
  53. std::remove_reference_t<
  54. allocator
  55. >
  56. >
  57. >(abstract_allocator(value));
  58. }
  59. void* allocate(size_t sz) {
  60. auto cpy = mark;
  61. do{
  62. if(auto allocated = (*mark).allocate(sz))
  63. {
  64. return allocated;
  65. }
  66. ++mark;
  67. }while(cpy != mark);
  68. return nullptr;
  69. }
  70. bool deallocate(void* ptr) {
  71. auto cpy = mark;
  72. do{
  73. if((*cpy).deallocate(ptr))
  74. {
  75. return true;
  76. }
  77. --cpy;
  78. }while(cpy != mark);
  79. return false;
  80. }
  81. bool try_reallocate(void* ptr, size_t sz) {
  82. auto cpy = mark;
  83. do{
  84. if((*cpy).try_reallocate(ptr, sz))
  85. {
  86. return true;
  87. }
  88. --cpy;
  89. }while(cpy != mark);
  90. return false;
  91. }
  92. };
  93. }