BsFrameAlloc.h 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  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(UINT32 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. /**
  53. * @brief Changes the frame allocator owner thread. After the owner
  54. * thread has changed only allocations from that thread can be made.
  55. */
  56. void setOwnerThread(BS_THREAD_ID_TYPE thread) { mOwnerThread = thread; }
  57. private:
  58. UINT32 mBlockSize;
  59. Vector<MemBlock*> mBlocks;
  60. MemBlock* mFreeBlock;
  61. std::atomic<UINT32> mTotalAllocBytes;
  62. #if BS_DEBUG_MODE
  63. UINT32 mAllocId;
  64. Set<UINT32> mActiveAllocs;
  65. BS_THREAD_ID_TYPE mOwnerThread;
  66. #endif
  67. MemBlock* allocBlock(UINT32 wantedSize);
  68. void deallocBlock(MemBlock* block);
  69. };
  70. /**
  71. * @brief Allocator for the standard library that internally uses a
  72. * frame allocator.
  73. */
  74. template <class T>
  75. class StdFrameAlloc
  76. {
  77. public:
  78. // Type definitions
  79. typedef T value_type;
  80. typedef T* pointer;
  81. typedef const T* const_pointer;
  82. typedef T& reference;
  83. typedef const T& const_reference;
  84. typedef std::size_t size_type;
  85. typedef std::ptrdiff_t difference_type;
  86. /**
  87. * @brief Rebind allocator to type U
  88. */
  89. template <class U>
  90. struct rebind
  91. {
  92. typedef StdFrameAlloc<U> other;
  93. };
  94. StdFrameAlloc() throw()
  95. :mFrameAlloc(nullptr)
  96. { }
  97. StdFrameAlloc(FrameAlloc* frameAlloc) throw()
  98. :mFrameAlloc(frameAlloc)
  99. { }
  100. StdFrameAlloc(const StdFrameAlloc& alloc) throw()
  101. :mFrameAlloc(alloc.mFrameAlloc)
  102. { }
  103. template <class U>
  104. StdFrameAlloc(const StdFrameAlloc<U>& alloc) throw()
  105. :mFrameAlloc(alloc.mFrameAlloc)
  106. { }
  107. ~StdFrameAlloc() throw()
  108. { }
  109. /**
  110. * @brief Return address of value.
  111. */
  112. pointer address(reference value) const
  113. {
  114. return &value;
  115. }
  116. /**
  117. * @brief Return address of value.
  118. */
  119. const_pointer address(const_reference value) const
  120. {
  121. return &value;
  122. }
  123. /**
  124. * @brief Return maximum number of elements that can be allocated.
  125. */
  126. size_type max_size() const throw()
  127. {
  128. return std::numeric_limits<std::size_t>::max() / sizeof(T);
  129. }
  130. /**
  131. * @brief Allocate but don't initialize number elements of type T.
  132. */
  133. pointer allocate(size_type num, const void* = 0)
  134. {
  135. pointer ret = (pointer)(mFrameAlloc->alloc((UINT32)num*sizeof(T)));
  136. return ret;
  137. }
  138. /**
  139. * @brief Initialize elements of allocated storage p with value "value".
  140. */
  141. void construct(pointer p, const T& value)
  142. {
  143. new((void*)p)T(value);
  144. }
  145. /**
  146. * @brief Destroy elements of initialized storage p.
  147. */
  148. void destroy(pointer p)
  149. {
  150. p->~T();
  151. }
  152. /**
  153. * @brief Deallocate storage p of deleted elements.
  154. */
  155. void deallocate(pointer p, size_type num)
  156. {
  157. mFrameAlloc->dealloc((UINT8*)p);
  158. }
  159. FrameAlloc* mFrameAlloc;
  160. };
  161. /**
  162. * @brief Return that all specializations of this allocator are interchangeable.
  163. */
  164. template <class T1, class T2>
  165. bool operator== (const StdFrameAlloc<T1>&,
  166. const StdFrameAlloc<T2>&) throw() {
  167. return true;
  168. }
  169. /**
  170. * @brief Return that all specializations of this allocator are interchangeable.
  171. */
  172. template <class T1, class T2>
  173. bool operator!= (const StdFrameAlloc<T1>&,
  174. const StdFrameAlloc<T2>&) throw() {
  175. return false;
  176. }
  177. }