temp_allocator.h 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. /*
  2. * Copyright (c) 2012-2014 Daniele Bartolini and individual contributors.
  3. * License: https://github.com/taylor001/crown/blob/master/LICENSE
  4. */
  5. #pragma once
  6. #include "allocator.h"
  7. #include "memory.h"
  8. namespace crown
  9. {
  10. /// Allocates from a fixed-size buffer.
  11. /// When the internal memory is exhausted or the allocation size exceeds
  12. /// the remainig internal storage, the backing allocator is used instead.
  13. /// The memory is automatically freed when the allocator is destroyed.
  14. ///
  15. /// @ingroup Memory
  16. template <size_t SIZE>
  17. class TempAllocator : public Allocator
  18. {
  19. public:
  20. /// Uses the @a backing allocator when internal memory is exahusted
  21. /// or the allocation size exceeds the remaining storage.
  22. TempAllocator(Allocator& backing = default_allocator());
  23. ~TempAllocator();
  24. /// @copydoc Allocator::allocate()
  25. void* allocate(size_t size, size_t align = Allocator::DEFAULT_ALIGN);
  26. /// Does nothing, the memory is automatically freed when the
  27. /// allocator is destroyed.
  28. void deallocate(void* data);
  29. /// @copydoc Allocator::allocated_size()
  30. size_t allocated_size();
  31. private:
  32. Allocator& _backing;
  33. char* _begin;
  34. char* _end;
  35. char* _cur;
  36. size_t _chunk_size;
  37. char _buffer[SIZE];
  38. };
  39. typedef TempAllocator<64> TempAllocator64;
  40. typedef TempAllocator<128> TempAllocator128;
  41. typedef TempAllocator<256> TempAllocator256;
  42. typedef TempAllocator<512> TempAllocator512;
  43. typedef TempAllocator<1024> TempAllocator1024;
  44. typedef TempAllocator<2048> TempAllocator2048;
  45. typedef TempAllocator<4096> TempAllocator4096;
  46. template <size_t SIZE>
  47. inline TempAllocator<SIZE>::TempAllocator(Allocator& backing)
  48. : _backing(backing)
  49. , _begin(&_buffer[0])
  50. , _end(&_buffer[SIZE - 1])
  51. , _cur(&_buffer[0])
  52. , _chunk_size(4 * 1024)
  53. {
  54. *(void**) _begin = 0;
  55. _cur += sizeof(void*);
  56. }
  57. template <size_t SIZE>
  58. inline TempAllocator<SIZE>::~TempAllocator()
  59. {
  60. union { char* as_char; void** as_dvoid; };
  61. as_char = _buffer;
  62. void *p = *(void **)as_dvoid;
  63. while (p)
  64. {
  65. void *next = *(void **)p;
  66. _backing.deallocate(p);
  67. p = next;
  68. }
  69. }
  70. template <size_t SIZE>
  71. inline void* TempAllocator<SIZE>::allocate(size_t size, size_t align)
  72. {
  73. _cur = (char*) memory::align_top(_cur, align);
  74. if (size > size_t(_end - _cur))
  75. {
  76. uint32_t to_allocate = sizeof(void*) + size + align;
  77. if (to_allocate < _chunk_size)
  78. {
  79. to_allocate = _chunk_size;
  80. }
  81. _chunk_size *= 2;
  82. void *p = _backing.allocate(to_allocate);
  83. *(void **)_begin = p;
  84. _cur = _begin = (char*) p;
  85. _end = _begin + to_allocate;
  86. *(void**) _begin = 0;
  87. _cur += sizeof(void*);
  88. memory::align_top(p, align);
  89. }
  90. void *result = _cur;
  91. _cur += size;
  92. return result;
  93. }
  94. template <size_t SIZE>
  95. inline void TempAllocator<SIZE>::deallocate(void* /*data*/)
  96. {
  97. }
  98. template <size_t SIZE>
  99. inline size_t TempAllocator<SIZE>::allocated_size()
  100. {
  101. return 0;
  102. }
  103. } // namespace crown