StackAllocator.h 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. //
  2. // Created by Ivan Arkhipov on 29.04.2018.
  3. //
  4. #ifndef XOR_LIST_STACKALLOCATOR_H
  5. #define XOR_LIST_STACKALLOCATOR_H
  6. #include <c++/cstddef>
  7. #include <c++/new>
  8. #include <memory.h>
  9. template<typename T, size_t elements_in_block = 128256>
  10. class StackAllocator {
  11. public:
  12. typedef size_t size_type;
  13. typedef ptrdiff_t difference_type;
  14. typedef T *pointer;
  15. typedef const T *const_pointer;
  16. typedef T &reference;
  17. typedef const T &const_reference;
  18. typedef T value_type;
  19. template<typename T1>
  20. struct rebind {
  21. typedef StackAllocator<T1> other;
  22. };
  23. StackAllocator() : last_block_(nullptr) {}
  24. StackAllocator(const StackAllocator &other) : last_block_(nullptr) {};
  25. template<class U>
  26. explicit StackAllocator(const StackAllocator<U> &other) : last_block_(nullptr) {};
  27. ~StackAllocator() {
  28. for (Block *block = last_block_; block != nullptr;) {
  29. Block *prev_block = block->prev_block_;
  30. delete block;
  31. block = prev_block;
  32. }
  33. }
  34. pointer allocate(size_type n, const void * = nullptr) {
  35. if (!last_block_ || last_block_->end_ + n >= last_block_->block_end_) {
  36. last_block_ = new Block(std::max(n, elements_in_block), last_block_);
  37. }
  38. pointer result = last_block_->end_;
  39. last_block_->end_ += n;
  40. return result;
  41. }
  42. void deallocate(pointer p, size_type n) {
  43. // does nothing
  44. }
  45. template<class U, class... Args>
  46. void construct(U *p, Args &&... args) {
  47. ::new((void *) p) U(std::forward<Args>(args)...);
  48. };
  49. template<class U>
  50. void destroy(U *p) {
  51. p->~U();
  52. }
  53. private:
  54. struct Block {
  55. private:
  56. Block() {}
  57. public:
  58. explicit Block(int els_in_block = elements_in_block, Block *prev_block = nullptr) {
  59. begin_ = reinterpret_cast<pointer>(::operator new(sizeof(value_type) * els_in_block));
  60. end_ = begin_;
  61. block_end_ = begin_ + elements_in_block;
  62. prev_block_ = prev_block;
  63. }
  64. ~Block() {
  65. delete[] begin_;
  66. }
  67. pointer begin_;
  68. pointer end_;
  69. pointer block_end_;
  70. Block *prev_block_;
  71. };
  72. Block *last_block_;
  73. };
  74. #endif //XOR_LIST_STACKALLOCATOR_H