temp_allocator.h 2.9 KB

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