pool.hh 1.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. #ifndef RUBY_PARSER_POOL_HH
  2. #define RUBY_PARSER_POOL_HH
  3. #include <type_traits>
  4. #include <utility>
  5. #include <vector>
  6. template<typename T, std::size_t N>
  7. class pool {
  8. public:
  9. pool() : _slab(new(slab)) {}
  10. template <typename... Args>
  11. T *alloc(Args&&... args) {
  12. if (_slab->is_full()) {
  13. push_slab();
  14. }
  15. return _slab->alloc(std::forward<Args>(args)...);
  16. }
  17. ~pool() {
  18. delete _slab;
  19. for (auto &p: _history) {
  20. delete p;
  21. }
  22. }
  23. protected:
  24. class slab {
  25. typename std::aligned_storage<sizeof(T), alignof(T)>::type data[N];
  26. std::size_t _size = 0;
  27. public:
  28. inline bool is_full() const {
  29. return _size >= N;
  30. }
  31. template<typename ...Args>
  32. T *alloc(Args&&... args)
  33. {
  34. assert(!is_full());
  35. T *p = reinterpret_cast<T*>(data+_size);
  36. new(p) T(std::forward<Args>(args)...);
  37. ++_size;
  38. return p;
  39. }
  40. ~slab() {
  41. for (std::size_t pos = 0; pos < _size; ++pos) {
  42. reinterpret_cast<T*>(data+pos)->~T();
  43. }
  44. }
  45. };
  46. using slab_t = slab*;
  47. std::vector<slab *> _history;
  48. slab *_slab;
  49. void push_slab() {
  50. slab *newb = new(slab);
  51. _history.emplace_back(_slab);
  52. _slab = newb;
  53. }
  54. };
  55. #endif