temp_allocator.h 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  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. uint32_t allocated_size(const void* /*ptr*/) { return SIZE_NOT_TRACKED; }
  31. /// @copydoc Allocator::total_allocated()
  32. uint32_t total_allocated() { return SIZE_NOT_TRACKED; }
  33. private:
  34. Allocator& _backing;
  35. char* _begin;
  36. char* _end;
  37. char* _cur;
  38. size_t _chunk_size;
  39. char _buffer[SIZE];
  40. };
  41. typedef TempAllocator<64> TempAllocator64;
  42. typedef TempAllocator<128> TempAllocator128;
  43. typedef TempAllocator<256> TempAllocator256;
  44. typedef TempAllocator<512> TempAllocator512;
  45. typedef TempAllocator<1024> TempAllocator1024;
  46. typedef TempAllocator<2048> TempAllocator2048;
  47. typedef TempAllocator<4096> TempAllocator4096;
  48. template <size_t SIZE>
  49. inline TempAllocator<SIZE>::TempAllocator(Allocator& backing)
  50. : _backing(backing)
  51. , _begin(&_buffer[0])
  52. , _end(&_buffer[SIZE - 1])
  53. , _cur(&_buffer[0])
  54. , _chunk_size(4 * 1024)
  55. {
  56. *(void**) _begin = 0;
  57. _cur += sizeof(void*);
  58. }
  59. template <size_t SIZE>
  60. inline TempAllocator<SIZE>::~TempAllocator()
  61. {
  62. union { char* as_char; void** as_dvoid; };
  63. as_char = _buffer;
  64. void *p = *(void **)as_dvoid;
  65. while (p)
  66. {
  67. void *next = *(void **)p;
  68. _backing.deallocate(p);
  69. p = next;
  70. }
  71. }
  72. template <size_t SIZE>
  73. inline void* TempAllocator<SIZE>::allocate(size_t size, size_t align)
  74. {
  75. _cur = (char*) memory::align_top(_cur, align);
  76. if (size > size_t(_end - _cur))
  77. {
  78. uint32_t to_allocate = sizeof(void*) + size + align;
  79. if (to_allocate < _chunk_size)
  80. {
  81. to_allocate = _chunk_size;
  82. }
  83. _chunk_size *= 2;
  84. void *p = _backing.allocate(to_allocate);
  85. *(void **)_begin = p;
  86. _cur = _begin = (char*) p;
  87. _end = _begin + to_allocate;
  88. *(void**) _begin = 0;
  89. _cur += sizeof(void*);
  90. memory::align_top(p, align);
  91. }
  92. void *result = _cur;
  93. _cur += size;
  94. return result;
  95. }
  96. } // namespace crown