General Purpose library for Freestanding C++ and POSIX systems
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

94 linhas
1.5 KiB

  1. #pragma once
  2. #include "gp_config.hpp"
  3. #include "gp/buffer.hpp"
  4. #include <type_traits>
  5. #include <gp/algorithm/tmp_manip.hpp>
  6. namespace gp{
  7. template<typename page_allocator, size_t align = 1>
  8. class arena{
  9. page_allocator allocator;
  10. fel::buffer<char> data;
  11. size_t last;
  12. size_t count;
  13. public:
  14. arena()
  15. :last(0)
  16. ,count(0)
  17. ,data(fel::buffer<char>(nullptr,nullptr))
  18. {}
  19. template<typename T = typename std::enable_if<fel::has_allocator_interface<page_allocator>::value,int>::type>
  20. arena(size_t sz)
  21. :last(0)
  22. ,count(0)
  23. ,data(nullptr,nullptr)
  24. {
  25. if(sz!=0)
  26. {
  27. auto v=allocator.allocate(sz);
  28. if(v!=nullptr)
  29. {
  30. data=fel::buffer<char>(reinterpret_cast<char*>(v),reinterpret_cast<char*>(v)+sz);
  31. }
  32. }
  33. }
  34. arena(char* pos,size_t sz)
  35. :last(0)
  36. ,count(0)
  37. ,data(pos,pos+sz)
  38. {
  39. }
  40. void* allocate(size_t sz)
  41. {
  42. [[maybe_unused]]
  43. size_t mod = 0;
  44. if constexpr (align != 1)
  45. {
  46. mod = align - ((intptr_t)data.begin())%align;
  47. }
  48. auto ret=data.begin()+last+mod;
  49. if(data.contains(ret))
  50. {
  51. count++;
  52. last+=sz+mod;
  53. return &*(ret);
  54. }
  55. else
  56. {
  57. return nullptr;
  58. }
  59. }
  60. bool deallocate(void* ptr)
  61. {
  62. if(data.contains((char*)ptr))
  63. {
  64. count--;
  65. if(count==0)
  66. {
  67. for(auto& i : data)
  68. {
  69. i=0;
  70. }
  71. last=0;
  72. }
  73. return true;
  74. }
  75. return false;
  76. }
  77. ~arena()
  78. {
  79. if constexpr(fel::has_allocator_interface<page_allocator>::value)
  80. {
  81. allocator.deallocate(&data[0]);
  82. }
  83. }
  84. };
  85. }