BsFrameAlloc.h 4.3 KB

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