General Purpose library for Freestanding C++ and POSIX systems
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

110 行
2.0 KiB

  1. #pragma once
  2. #include "gp_config.hpp"
  3. #include "gp/algorithm/min_max.hpp"
  4. #include "gp/algorithm/tmp_manip.hpp"
  5. #include "gp/buffer.hpp"
  6. #include "gp/math/integer_math.hpp"
  7. #include "gp/allocator/allocator.hpp"
  8. #include <type_traits>
  9. namespace gp {
  10. class arena : public allocator {
  11. gp::optional<gp::reference_wrapper<allocator>> allocator_v;
  12. size_t next;
  13. size_t count;
  14. gp::buffer<char> data;
  15. public:
  16. arena()
  17. : next(0)
  18. , count(0)
  19. , data(gp::buffer<char>(nullptr,nullptr))
  20. {}
  21. arena(allocator& allocator_p, size_t sz)
  22. : allocator_v(allocator_p)
  23. , next(0)
  24. , count(0)
  25. , data(nullptr,nullptr)
  26. {
  27. if(sz != 0)
  28. {
  29. auto v = allocator_v.value().get().allocate(sz);
  30. if(v != nullptr)
  31. {
  32. data=gp::buffer<char>(reinterpret_cast<char*>(v),reinterpret_cast<char*>(v)+sz);
  33. }
  34. }
  35. }
  36. arena(char* pos, size_t sz)
  37. : next(0)
  38. , count(0)
  39. , data(pos,pos+sz)
  40. {}
  41. void reset() {
  42. next = count = 0;
  43. }
  44. virtual void* allocate(size_t sz)
  45. {
  46. size_t align = gp::min((1 << gp::math::log2(sz)), 16);
  47. size_t padding = align - (reinterpret_cast<uintptr_t>(data.begin().data + next)) % align;
  48. auto ret=data.begin()+padding+next;
  49. if(data.contains(ret))
  50. {
  51. count++;
  52. next+=padding+sz;
  53. return ret.data;
  54. }
  55. else
  56. {
  57. return nullptr;
  58. }
  59. }
  60. /**
  61. * @return false whatever happens
  62. */
  63. virtual bool try_reallocate(void*, size_t) {
  64. return false;
  65. }
  66. /**
  67. * @brief Deallocates the memory if every deallocated block as been deallocated, else marks one deallocation
  68. *
  69. * @param ptr the memory to deallocate
  70. * @return true if either a deallocation or block release happened
  71. * @return false if the pointer was not within the managed area
  72. */
  73. virtual bool deallocate(void* ptr)
  74. {
  75. if(data.contains((char*)ptr))
  76. {
  77. count--;
  78. if(count==0)
  79. {
  80. for(auto& i : data)
  81. {
  82. i=0;
  83. }
  84. next=0;
  85. }
  86. return true;
  87. }
  88. return false;
  89. }
  90. virtual ~arena()
  91. {
  92. if(allocator_v.has_value())
  93. {
  94. allocator_v.value().get().deallocate(&data[0]);
  95. }
  96. }
  97. };
  98. }