BsFrameAlloc.h 4.0 KB

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