BsGroupAlloc.h 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #pragma once
  4. #include "BsPrerequisitesUtil.h"
  5. namespace bs
  6. {
  7. /** @addtogroup Internal-Utility
  8. * @{
  9. */
  10. /** @addtogroup Memory-Internal
  11. * @{
  12. */
  13. /**
  14. * Provides an easy way to group multiple allocations under a single (actual) allocation. Requires the user to first
  15. * call reserve() methods for all requested data elements, followed by init(), after which allocation/deallocation
  16. * can follow using construct/destruct or alloc/free methods.
  17. */
  18. class GroupAlloc : INonCopyable
  19. {
  20. public:
  21. GroupAlloc()
  22. : mData(nullptr), mDataPtr(nullptr), mNumBytes(0)
  23. { }
  24. GroupAlloc(GroupAlloc&& other) noexcept
  25. : mData(other.mData), mDataPtr(other.mDataPtr), mNumBytes(other.mNumBytes)
  26. {
  27. other.mData = nullptr;
  28. other.mDataPtr = nullptr;
  29. other.mNumBytes = 0;
  30. }
  31. ~GroupAlloc()
  32. {
  33. if (mNumBytes > 0)
  34. bs_free(mData);
  35. }
  36. GroupAlloc& operator=(GroupAlloc&& other) noexcept
  37. {
  38. if (this == &other)
  39. return *this;
  40. if (mNumBytes > 0)
  41. bs_free(mData);
  42. mData = other.mData;
  43. mDataPtr = other.mDataPtr;
  44. mNumBytes = other.mNumBytes;
  45. other.mData = nullptr;
  46. other.mDataPtr = nullptr;
  47. other.mNumBytes = 0;
  48. return *this;
  49. }
  50. /**
  51. * Allocates internal memory as reserved by previous calls to reserve(). Must be called before any calls to
  52. * construct or alloc.
  53. */
  54. void init()
  55. {
  56. assert(mData == nullptr);
  57. if (mNumBytes > 0)
  58. mData = (UINT8*)bs_alloc(mNumBytes);
  59. mDataPtr = mData;
  60. }
  61. /**
  62. * Reserves the specified amount of bytes to allocate. Multiple calls to reserve() are cumulative. After all needed
  63. * memory is reserved, call init(), followed by actual allocation via construct() or alloc() methods.
  64. */
  65. GroupAlloc& reserve(UINT32 amount)
  66. {
  67. assert(mData == nullptr);
  68. mNumBytes += amount;
  69. return *this;
  70. }
  71. /**
  72. * Reserves the specified amount of bytes to allocate. Multiple calls to reserve() are cumulative. After all needed
  73. * memory is reserved, call init(), followed by actual allocation via construct() or alloc() methods.
  74. */
  75. template<class T>
  76. GroupAlloc& reserve(UINT32 count = 1)
  77. {
  78. assert(mData == nullptr);
  79. mNumBytes += sizeof(T) * count;
  80. return *this;
  81. }
  82. /**
  83. * Allocates a new piece of memory of the specified size.
  84. *
  85. * @param[in] amount Amount of memory to allocate, in bytes.
  86. */
  87. UINT8* alloc(UINT32 amount)
  88. {
  89. assert(mDataPtr + amount <= (mData + mNumBytes));
  90. UINT8* output = mDataPtr;
  91. mDataPtr += amount;
  92. return output;
  93. }
  94. /**
  95. * Allocates enough memory to hold @p count elements of the specified type.
  96. *
  97. * @param[in] count Number of elements to allocate.
  98. */
  99. template<class T>
  100. T* alloc(UINT32 count = 1)
  101. {
  102. return (T*)alloc(sizeof(T) * count);
  103. }
  104. /** Deallocates a previously allocated piece of memory. */
  105. void free(void* data)
  106. {
  107. // Do nothing
  108. }
  109. /**
  110. * Allocates enough memory to hold the object(s) of specified type using the static allocator, and constructs them.
  111. */
  112. template<class T>
  113. T* construct(UINT32 count = 1)
  114. {
  115. T* data = (T*)alloc(sizeof(T) * count);
  116. for(unsigned int i = 0; i < count; i++)
  117. new ((void*)&data[i]) T;
  118. return data;
  119. }
  120. /**
  121. * Allocates enough memory to hold the object(s) of specified type using the static allocator, and constructs them.
  122. */
  123. template<class T, class... Args>
  124. T* construct(Args &&...args, UINT32 count = 1)
  125. {
  126. T* data = (T*)alloc(sizeof(T) * count);
  127. for(unsigned int i = 0; i < count; i++)
  128. new ((void*)&data[i]) T(std::forward<Args>(args)...);
  129. return data;
  130. }
  131. /** Destructs and deallocates an object allocated with the static allocator. */
  132. template<class T>
  133. void destruct(T* data)
  134. {
  135. data->~T();
  136. free(data);
  137. }
  138. /** Destructs and deallocates an array of objects allocated with the static frame allocator. */
  139. template<class T>
  140. void destruct(T* data, UINT32 count)
  141. {
  142. for(unsigned int i = 0; i < count; i++)
  143. data[i].~T();
  144. free(data);
  145. }
  146. private:
  147. UINT8* mData;
  148. UINT8* mDataPtr;
  149. UINT32 mNumBytes;
  150. };
  151. /** @} */
  152. /** @} */
  153. }