BlockArray.inl.h 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. // Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include <AnKi/Util/BlockArray.h>
  6. namespace anki {
  7. template<typename T, typename TMemoryPool, typename TConfig>
  8. void BlockArray<T, TMemoryPool, TConfig>::destroy()
  9. {
  10. for(U32 i = 0; i < m_blockStorages.getSize(); ++i)
  11. {
  12. U32 localIdx;
  13. while((localIdx = m_blockMetadatas[i].m_elementsInUseMask.getLeastSignificantBit()) != kMaxU32)
  14. {
  15. reinterpret_cast<T*>(&m_blockStorages[i]->m_storage[localIdx * sizeof(T)])->~T();
  16. m_blockMetadatas[i].m_elementsInUseMask.unset(localIdx);
  17. }
  18. if(m_blockStorages[i])
  19. {
  20. getMemoryPool().free(m_blockStorages[i]);
  21. }
  22. }
  23. m_blockMetadatas.destroy();
  24. m_blockStorages.destroy();
  25. m_elementCount = 0;
  26. m_firstIndex = 0;
  27. m_endIndex = 0;
  28. }
  29. template<typename T, typename TMemoryPool, typename TConfig>
  30. template<typename... TArgs>
  31. typename BlockArray<T, TMemoryPool, TConfig>::Iterator BlockArray<T, TMemoryPool, TConfig>::emplace(TArgs&&... args)
  32. {
  33. U32 localIdx = kMaxU32;
  34. U32 blockIdx = kMaxU32;
  35. // Search for a block with free elements
  36. for(U32 i = 0; i < m_blockStorages.getSize(); ++i)
  37. {
  38. if(m_blockMetadatas[i].m_elementsInUseMask.getSetBitCount() < kElementCountPerBlock)
  39. {
  40. // Found a block, allocate from it
  41. auto unsetBits = ~m_blockMetadatas[i].m_elementsInUseMask;
  42. localIdx = unsetBits.getLeastSignificantBit();
  43. blockIdx = i;
  44. if(m_blockStorages[blockIdx] == nullptr)
  45. {
  46. m_blockStorages[blockIdx] = newInstance<BlockStorage>(getMemoryPool());
  47. }
  48. break;
  49. }
  50. }
  51. // Block not found, crate new
  52. if(blockIdx == kMaxU32)
  53. {
  54. m_blockMetadatas.emplaceBack(false);
  55. m_blockStorages.emplaceBack(newInstance<BlockStorage>(getMemoryPool()));
  56. localIdx = 0;
  57. blockIdx = m_blockMetadatas.getSize() - 1;
  58. }
  59. // Finalize and return
  60. ANKI_ASSERT(localIdx < kElementCountPerBlock);
  61. ::new(&m_blockStorages[blockIdx]->m_storage[localIdx * sizeof(T)]) T(std::forward<TArgs>(args)...);
  62. ANKI_ASSERT(m_blockMetadatas[blockIdx].m_elementsInUseMask.get(localIdx) == false);
  63. m_blockMetadatas[blockIdx].m_elementsInUseMask.set(localIdx);
  64. ++m_elementCount;
  65. const U32 idx = blockIdx * kElementCountPerBlock + localIdx;
  66. m_firstIndex = min(m_firstIndex, idx);
  67. m_endIndex = max(m_endIndex, idx + 1);
  68. return Iterator(this, idx);
  69. }
  70. template<typename T, typename TMemoryPool, typename TConfig>
  71. void BlockArray<T, TMemoryPool, TConfig>::erase(Iterator it)
  72. {
  73. const U32 idx = it.getArrayIndex();
  74. const U32 localIdx = idx % kElementCountPerBlock;
  75. const U32 blockIdx = idx / kElementCountPerBlock;
  76. ANKI_ASSERT(blockIdx < m_blockStorages.getSize());
  77. BlockStorage* block = m_blockStorages[blockIdx];
  78. ANKI_ASSERT(block);
  79. Mask& inUseMask = m_blockMetadatas[blockIdx].m_elementsInUseMask;
  80. ANKI_ASSERT(inUseMask.get(localIdx) == true);
  81. reinterpret_cast<T*>(&block->m_storage[localIdx * sizeof(T)])->~T();
  82. inUseMask.unset(localIdx);
  83. if(inUseMask.getSetBitCount() == 0)
  84. {
  85. // Block is empty, delete it
  86. getMemoryPool().free(block);
  87. m_blockStorages[blockIdx] = nullptr;
  88. }
  89. ANKI_ASSERT(m_elementCount > 0);
  90. --m_elementCount;
  91. if(m_elementCount == 0)
  92. {
  93. m_firstIndex = 0;
  94. m_endIndex = 0;
  95. m_blockStorages.destroy();
  96. m_blockMetadatas.destroy();
  97. }
  98. else
  99. {
  100. if(idx == m_firstIndex)
  101. {
  102. m_firstIndex = getFirstElementIndex();
  103. }
  104. if(idx + 1 == m_endIndex)
  105. {
  106. m_endIndex = getLastElementIndex() + 1;
  107. }
  108. }
  109. }
  110. template<typename T, typename TMemoryPool, typename TConfig>
  111. BlockArray<T, TMemoryPool, TConfig>& BlockArray<T, TMemoryPool, TConfig>::operator=(const BlockArray& b)
  112. {
  113. destroy();
  114. if(b.m_elementCount == 0)
  115. {
  116. return *this;
  117. }
  118. m_elementCount = b.m_elementCount;
  119. m_firstIndex = b.m_firstIndex;
  120. m_endIndex = b.m_endIndex;
  121. m_blockMetadatas = b.m_blockMetadatas;
  122. m_blockStorages.resize(b.m_blockStorages.getSize());
  123. for(U32 blockIdx = 0; blockIdx < b.m_blockMetadatas.getSize(); ++blockIdx)
  124. {
  125. Mask mask = b.m_blockMetadatas[blockIdx].m_elementsInUseMask;
  126. if(mask.getAnySet())
  127. {
  128. m_blockStorages[blockIdx] = newInstance<BlockStorage>(getMemoryPool());
  129. U32 localIdx;
  130. while((localIdx = mask.getLeastSignificantBit()) != kMaxU32)
  131. {
  132. const T& other = b[blockIdx * kElementCountPerBlock + localIdx];
  133. ::new(&m_blockStorages[blockIdx]->m_storage[localIdx * sizeof(T)]) T(other);
  134. mask.unset(localIdx);
  135. }
  136. }
  137. else
  138. {
  139. m_blockStorages[blockIdx] = nullptr;
  140. }
  141. }
  142. return *this;
  143. }
  144. template<typename T, typename TMemoryPool, typename TConfig>
  145. U32 BlockArray<T, TMemoryPool, TConfig>::getNextElementIndex(U32 crnt) const
  146. {
  147. ANKI_ASSERT(crnt < m_endIndex);
  148. ++crnt;
  149. for(; crnt < m_endIndex; ++crnt)
  150. {
  151. const U32 localIdx = crnt % kElementCountPerBlock;
  152. const U32 blockIdx = crnt / kElementCountPerBlock;
  153. if(m_blockMetadatas[blockIdx].m_elementsInUseMask.get(localIdx))
  154. {
  155. return crnt;
  156. }
  157. }
  158. return m_endIndex;
  159. }
  160. template<typename T, typename TMemoryPool, typename TConfig>
  161. void BlockArray<T, TMemoryPool, TConfig>::validate() const
  162. {
  163. ANKI_ASSERT(m_blockStorages.getSize() == m_blockMetadatas.getSize());
  164. [[maybe_unused]] U32 count = 0;
  165. U32 first = 0;
  166. U32 end = 0;
  167. for(U32 i = 0; i < m_blockStorages.getSize(); ++i)
  168. {
  169. const Mask& mask = m_blockMetadatas[i].m_elementsInUseMask;
  170. const U32 lcount = mask.getSetBitCount();
  171. if(lcount == 0)
  172. {
  173. ANKI_ASSERT(m_blockStorages[i] == nullptr);
  174. }
  175. else
  176. {
  177. count += lcount;
  178. first = min(first, mask.getLeastSignificantBit() + i * kElementCountPerBlock);
  179. end = max(end, mask.getMostSignificantBit() + i * kElementCountPerBlock + 1);
  180. }
  181. }
  182. ANKI_ASSERT(count == m_elementCount);
  183. ANKI_ASSERT(first == m_firstIndex);
  184. ANKI_ASSERT(end == m_endIndex);
  185. }
  186. } // end namespace anki