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.

97 lines
1.6 KiB

4 years ago
4 years ago
4 years ago
  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 <type_traits>
  8. namespace gp {
  9. template<typename page_allocator = int>
  10. class arena {
  11. page_allocator allocator;
  12. gp::buffer<char> data;
  13. size_t next;
  14. size_t count;
  15. public:
  16. arena()
  17. : next(0)
  18. , count(0)
  19. , data(gp::buffer<char>(nullptr,nullptr))
  20. {}
  21. arena(size_t sz)
  22. : next(0)
  23. , count(0)
  24. , data(nullptr,nullptr)
  25. {
  26. if constexpr (gp::has_allocator_interface<page_allocator>::value)
  27. {
  28. if(sz!=0)
  29. {
  30. auto v=allocator.allocate(sz);
  31. if(v!=nullptr)
  32. {
  33. data=gp::buffer<char>(reinterpret_cast<char*>(v),reinterpret_cast<char*>(v)+sz);
  34. }
  35. }
  36. }
  37. }
  38. arena(char* pos,size_t sz)
  39. : next(0)
  40. , count(0)
  41. , data(pos,pos+sz)
  42. {}
  43. void* allocate(size_t sz)
  44. {
  45. size_t align = gp::min((1 << gp::math::log2(sz)), 16);
  46. size_t padding = align - (reinterpret_cast<uintptr_t>(data.begin().data + next)) % align;
  47. auto ret=data.begin()+padding+next;
  48. if(data.contains(ret))
  49. {
  50. count++;
  51. next+=padding+sz;
  52. return ret.data;
  53. }
  54. else
  55. {
  56. return nullptr;
  57. }
  58. }
  59. constexpr bool try_reallocate(void*, size_t) {
  60. return false;
  61. }
  62. bool deallocate(void* ptr)
  63. {
  64. if(data.contains((char*)ptr))
  65. {
  66. count--;
  67. if(count==0)
  68. {
  69. for(auto& i : data)
  70. {
  71. i=0;
  72. }
  73. next=0;
  74. }
  75. return true;
  76. }
  77. return false;
  78. }
  79. ~arena()
  80. {
  81. if constexpr(gp::has_allocator_interface<page_allocator>::value)
  82. {
  83. allocator.deallocate(&data[0]);
  84. }
  85. }
  86. };
  87. }