BsFrameAlloc.h 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  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. /**
  16. * @brief A single block of memory within a frame allocator.
  17. */
  18. class MemBlock
  19. {
  20. public:
  21. MemBlock(UINT32 size);
  22. ~MemBlock();
  23. /**
  24. * @brief Allocates a piece of memory within the block. Caller must ensure
  25. * the block has enough empty space.
  26. */
  27. UINT8* alloc(UINT32 amount);
  28. /**
  29. * @brief Releases all allocations within a block but doesn't actually free the memory.
  30. */
  31. void clear();
  32. UINT8* mData;
  33. UINT32 mFreePtr;
  34. UINT32 mSize;
  35. };
  36. public:
  37. FrameAlloc(UINT32 blockSize = 1024 * 1024);
  38. ~FrameAlloc();
  39. /**
  40. * @brief Allocates a new block of memory of the specified size.
  41. *
  42. * @param amount Amount of memory to allocate, in bytes.
  43. *
  44. * @note Not thread safe.
  45. */
  46. UINT8* alloc(UINT32 amount);
  47. /**
  48. * @brief Allocates and constructs a new object.
  49. *
  50. * @note Not thread safe.
  51. */
  52. template<class T, class... Args>
  53. T* alloc(Args &&...args)
  54. {
  55. return new ((T*)alloc(sizeof(T))) T(std::forward<Args>(args)...);
  56. }
  57. /**
  58. * @brief Deallocates a previously allocated block of memory.
  59. *
  60. * @note No deallocation is actually done here. This method is only used for debug purposes
  61. * so it is easier to track down memory leaks and corruption.
  62. *
  63. * Thread safe.
  64. */
  65. void dealloc(UINT8* data);
  66. /**
  67. * @brief Deallocates and destructs a previously allocated object.
  68. *
  69. * @note No deallocation is actually done here. This method is only used to call the destructor
  70. * and for debug purposes so it is easier to track down memory leaks and corruption.
  71. *
  72. * Thread safe.
  73. */
  74. template<class T>
  75. void dealloc(T* obj)
  76. {
  77. if (obj != nullptr)
  78. obj->~T();
  79. dealloc((UINT8*)obj);
  80. }
  81. /**
  82. * @brief Starts a new frame. Next call to ::clear will only clear memory
  83. * allocated past this point.
  84. */
  85. void markFrame();
  86. /**
  87. * @brief Deallocates all allocated memory since the last call to ::markFrame
  88. * (or all the memory if there was no call to ::markFrame).
  89. *
  90. * @note Not thread safe.
  91. */
  92. void clear();
  93. /**
  94. * @brief Changes the frame allocator owner thread. After the owner
  95. * thread has changed only allocations from that thread can be made.
  96. */
  97. void setOwnerThread(BS_THREAD_ID_TYPE thread);
  98. private:
  99. UINT32 mBlockSize;
  100. Vector<MemBlock*> mBlocks;
  101. MemBlock* mFreeBlock;
  102. UINT32 mNextBlockIdx;
  103. std::atomic<UINT32> mTotalAllocBytes;
  104. void* mLastFrame;
  105. #if BS_DEBUG_MODE
  106. BS_THREAD_ID_TYPE mOwnerThread;
  107. #endif
  108. /**
  109. * @brief Allocates a dynamic block of memory of the wanted size. The exact allocation size
  110. * might be slightly higher in order to store block meta data.
  111. */
  112. MemBlock* allocBlock(UINT32 wantedSize);
  113. /**
  114. * @brief Frees a memory block.
  115. */
  116. void deallocBlock(MemBlock* block);
  117. };
  118. /**
  119. * @brief Allocator for the standard library that internally uses a
  120. * frame allocator.
  121. */
  122. template <class T>
  123. class StdFrameAlloc
  124. {
  125. public:
  126. typedef T value_type;
  127. StdFrameAlloc() noexcept
  128. :mFrameAlloc(nullptr)
  129. { }
  130. StdFrameAlloc(FrameAlloc* alloc) noexcept
  131. :mFrameAlloc(alloc)
  132. { }
  133. template<class T> StdFrameAlloc(const StdFrameAlloc<T>& alloc) noexcept
  134. :mFrameAlloc(alloc.mFrameAlloc)
  135. { }
  136. template<class T> bool operator==(const StdFrameAlloc<T>&) const noexcept { return true; }
  137. template<class T> bool operator!=(const StdFrameAlloc<T>&) const noexcept { return false; }
  138. /**
  139. * @brief Allocate but don't initialize number elements of type T.
  140. */
  141. T* allocate(const size_t num) const
  142. {
  143. if (num == 0)
  144. return nullptr;
  145. if (num > static_cast<size_t>(-1) / sizeof(T))
  146. throw std::bad_array_new_length();
  147. void* const pv = mFrameAlloc->alloc((UINT32)(num * sizeof(T)));
  148. if (!pv)
  149. throw std::bad_alloc();
  150. return static_cast<T*>(pv);
  151. }
  152. /**
  153. * @brief Deallocate storage p of deleted elements.
  154. */
  155. void deallocate(T* p, size_t num) const noexcept
  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. }