BsFrameAlloc.h 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. #pragma once
  2. #include "BsPrerequisitesUtil.h"
  3. namespace BansheeEngine
  4. {
  5. /**
  6. * @brief Frame allocator. Performs very fast allocations but can only free all of its memory at once.
  7. * Perfect for allocations that last just a single frame.
  8. *
  9. * @note Not thread safe with an exception. "alloc" and "clear" methods need to be called from the same thread.
  10. * "dealloc" is thread safe and can be called from any thread.
  11. */
  12. class BS_UTILITY_EXPORT FrameAlloc
  13. {
  14. private:
  15. class MemBlock
  16. {
  17. public:
  18. MemBlock(UINT32 size);
  19. ~MemBlock();
  20. UINT8* alloc(UINT8 amount);
  21. void clear();
  22. UINT8* mData;
  23. UINT32 mFreePtr;
  24. UINT32 mSize;
  25. };
  26. public:
  27. FrameAlloc(UINT32 blockSize = 1024 * 1024);
  28. ~FrameAlloc();
  29. /**
  30. * @brief Allocates a new block of memory of the specified size.
  31. *
  32. * @param amount Amount of memory to allocate, in bytes.
  33. *
  34. * @note Not thread safe.
  35. */
  36. UINT8* alloc(UINT32 amount);
  37. /**
  38. * @brief Deallocates a previously allocated block of memory.
  39. *
  40. * @note No deallocation is actually done here. This method is only used for debug purposes
  41. * so it is easier to track down memory leaks and corruption.
  42. *
  43. * Thread safe.
  44. */
  45. void dealloc(UINT8* data);
  46. /**
  47. * @brief Deallocates all allocated memory.
  48. *
  49. * @note Not thread safe.
  50. */
  51. void clear();
  52. private:
  53. UINT32 mBlockSize;
  54. Vector<MemBlock*> mBlocks;
  55. MemBlock* mFreeBlock;
  56. std::atomic<UINT32> mTotalAllocBytes;
  57. #if BS_DEBUG_MODE
  58. UINT32 mAllocId;
  59. Set<UINT32> mActiveAllocs;
  60. #endif
  61. MemBlock* allocBlock(UINT32 wantedSize);
  62. void deallocBlock(MemBlock* block);
  63. };
  64. /**
  65. * @brief Allocator for the standard library that internally uses a
  66. * frame allocator.
  67. */
  68. template <class T>
  69. class StdFrameAlloc
  70. {
  71. public:
  72. // Type definitions
  73. typedef T value_type;
  74. typedef T* pointer;
  75. typedef const T* const_pointer;
  76. typedef T& reference;
  77. typedef const T& const_reference;
  78. typedef std::size_t size_type;
  79. typedef std::ptrdiff_t difference_type;
  80. /**
  81. * @brief Rebind allocator to type U
  82. */
  83. template <class U>
  84. struct rebind
  85. {
  86. typedef StdFrameAlloc<U> other;
  87. };
  88. StdFrameAlloc() throw()
  89. :mFrameAlloc(nullptr)
  90. { }
  91. StdFrameAlloc(FrameAlloc* frameAlloc) throw()
  92. :mFrameAlloc(frameAlloc)
  93. { }
  94. StdFrameAlloc(const StdFrameAlloc& alloc) throw()
  95. :mFrameAlloc(alloc.mFrameAlloc)
  96. { }
  97. template <class U>
  98. StdFrameAlloc(const StdFrameAlloc<U>& alloc) throw()
  99. :mFrameAlloc(alloc.mFrameAlloc)
  100. { }
  101. ~StdFrameAlloc() throw()
  102. { }
  103. /**
  104. * @brief Return address of value.
  105. */
  106. pointer address(reference value) const
  107. {
  108. return &value;
  109. }
  110. /**
  111. * @brief Return address of value.
  112. */
  113. const_pointer address(const_reference value) const
  114. {
  115. return &value;
  116. }
  117. /**
  118. * @brief Return maximum number of elements that can be allocated.
  119. */
  120. size_type max_size() const throw()
  121. {
  122. return std::numeric_limits<std::size_t>::max() / sizeof(T);
  123. }
  124. /**
  125. * @brief Allocate but don't initialize number elements of type T.
  126. */
  127. pointer allocate(size_type num, const void* = 0)
  128. {
  129. pointer ret = (pointer)(mFrameAlloc->alloc((UINT32)num*sizeof(T)));
  130. return ret;
  131. }
  132. /**
  133. * @brief Initialize elements of allocated storage p with value "value".
  134. */
  135. void construct(pointer p, const T& value)
  136. {
  137. new((void*)p)T(value);
  138. }
  139. /**
  140. * @brief Destroy elements of initialized storage p.
  141. */
  142. void destroy(pointer p)
  143. {
  144. p->~T();
  145. }
  146. /**
  147. * @brief Deallocate storage p of deleted elements.
  148. */
  149. void deallocate(pointer p, size_type num)
  150. {
  151. mFrameAlloc->dealloc((UINT8*)p);
  152. }
  153. FrameAlloc* mFrameAlloc;
  154. };
  155. /**
  156. * @brief Return that all specializations of this allocator are interchangeable.
  157. */
  158. template <class T1, class T2>
  159. bool operator== (const StdFrameAlloc<T1>&,
  160. const StdFrameAlloc<T2>&) throw() {
  161. return true;
  162. }
  163. /**
  164. * @brief Return that all specializations of this allocator are interchangeable.
  165. */
  166. template <class T1, class T2>
  167. bool operator!= (const StdFrameAlloc<T1>&,
  168. const StdFrameAlloc<T2>&) throw() {
  169. return false;
  170. }
  171. }