1
0

Arena.h 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. #ifndef MANDEL_ARENA_H
  2. #define MANDEL_ARENA_H
  3. #include <vector>
  4. #include <array>
  5. #include <utility>
  6. #include <memory>
  7. namespace mnd
  8. {
  9. namespace util
  10. {
  11. template <typename T, int chunkSize = 32>
  12. class Arena
  13. {
  14. struct Chunk
  15. {
  16. char data[sizeof(T) * chunkSize];
  17. int used = 0;
  18. bool full(void) const { return used == chunkSize; }
  19. template<typename... Args>
  20. T* allocate(Args&&... args)
  21. {
  22. return new(reinterpret_cast<T*>(&data[(used++) * sizeof(T)])) T(std::forward<Args>(args)...);
  23. }
  24. ~Chunk(void)
  25. {
  26. for (int i = used - 1; i >= 0; i--) {
  27. reinterpret_cast<T*>(&data[i * sizeof(T)])->~T();
  28. }
  29. }
  30. };
  31. std::vector<std::unique_ptr<Chunk>> chunks;
  32. public:
  33. Arena(void) = default;
  34. Arena(const Arena&) = delete;
  35. Arena(Arena&&) = default;
  36. ~Arena(void)
  37. {
  38. for (auto it = chunks.rbegin(); it != chunks.rend(); ++it) {
  39. *it = nullptr;
  40. }
  41. }
  42. Arena& operator=(const Arena&) = delete;
  43. Arena& operator=(Arena&&) = default;
  44. Chunk& lastChunk(void) { return *chunks[chunks.size() - 1]; }
  45. template<typename... Args>
  46. T* allocate(Args&&... args)
  47. {
  48. if (chunks.empty() || lastChunk().full()) {
  49. chunks.push_back(std::make_unique<Chunk>());
  50. }
  51. return lastChunk().allocate(std::forward<Args>(args)...);
  52. }
  53. };
  54. }
  55. }
  56. #endif // MANDEL_ARENA_H