BlockArray.h 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  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. #pragma once
  6. #include <AnKi/Util/MemoryPool.h>
  7. #include <AnKi/Util/Functions.h>
  8. #include <AnKi/Util/BitSet.h>
  9. #include <AnKi/Util/DynamicArray.h>
  10. namespace anki {
  11. /// @addtogroup util_containers
  12. /// @{
  13. /// Config options for a BlockArray.
  14. template<U32 kElementCountPerBlock>
  15. class BlockArrayConfig
  16. {
  17. public:
  18. static constexpr U32 getElementCountPerBlock()
  19. {
  20. return kElementCountPerBlock;
  21. }
  22. };
  23. /// Config options for a BlockArray.
  24. class BlockArrayDefaultConfig : public BlockArrayConfig<64>
  25. {
  26. };
  27. /// BlockArray iterator.
  28. template<typename TValuePointer, typename TValueReference, typename TBlockArrayPtr>
  29. class BlockArrayIterator
  30. {
  31. template<typename, typename, typename>
  32. friend class BlockArray;
  33. template<typename, typename, typename>
  34. friend class BlockArrayIterator;
  35. public:
  36. /// Default constructor.
  37. BlockArrayIterator()
  38. : m_array(nullptr)
  39. , m_elementIdx(kMaxU32)
  40. {
  41. }
  42. /// Copy.
  43. BlockArrayIterator(const BlockArrayIterator& b)
  44. : m_array(b.m_array)
  45. , m_elementIdx(b.m_elementIdx)
  46. {
  47. }
  48. /// Allow conversion from iterator to const iterator.
  49. template<typename YValuePointer, typename YValueReference, typename YBlockArrayPtr>
  50. BlockArrayIterator(const BlockArrayIterator<YValuePointer, YValueReference, YBlockArrayPtr>& b)
  51. : m_array(b.m_array)
  52. , m_elementIdx(b.m_elementIdx)
  53. {
  54. }
  55. BlockArrayIterator(TBlockArrayPtr arr, U32 idx)
  56. : m_array(arr)
  57. , m_elementIdx(idx)
  58. {
  59. }
  60. BlockArrayIterator& operator=(const BlockArrayIterator& b)
  61. {
  62. m_array = b.m_array;
  63. m_elementIdx = b.m_elementIdx;
  64. return *this;
  65. }
  66. TValueReference operator*() const
  67. {
  68. check();
  69. return (*m_array)[m_elementIdx];
  70. }
  71. TValuePointer operator->() const
  72. {
  73. check();
  74. return &(*m_array)[m_elementIdx];
  75. }
  76. BlockArrayIterator& operator++()
  77. {
  78. check();
  79. m_elementIdx = m_array->getNextElementIndex(m_elementIdx);
  80. return *this;
  81. }
  82. BlockArrayIterator operator++(int)
  83. {
  84. check();
  85. BlockArrayIterator out = *this;
  86. ++(*this);
  87. return out;
  88. }
  89. Bool operator==(const BlockArrayIterator& b) const
  90. {
  91. ANKI_ASSERT(m_array == b.m_array);
  92. return m_elementIdx == b.m_elementIdx;
  93. }
  94. Bool operator!=(const BlockArrayIterator& b) const
  95. {
  96. return !(*this == b);
  97. }
  98. /// Returns the imaginary index inside the BlockArray.
  99. U32 getArrayIndex() const
  100. {
  101. check();
  102. return m_elementIdx;
  103. }
  104. private:
  105. TBlockArrayPtr m_array;
  106. U32 m_elementIdx;
  107. void check() const
  108. {
  109. ANKI_ASSERT(m_array);
  110. ANKI_ASSERT(m_array->indexExists(m_elementIdx));
  111. }
  112. };
  113. /// It's a type of dynamic array that unlike DynamicArray doesn't move elements around when it shrinks or grows the storage.
  114. template<typename T, typename TMemoryPool = SingletonMemoryPoolWrapper<DefaultMemoryPool>, typename TConfig = BlockArrayDefaultConfig>
  115. class BlockArray
  116. {
  117. template<typename, typename, typename>
  118. friend class BlockArrayIterator;
  119. public:
  120. // Typedefs
  121. using Config = TConfig;
  122. using Value = T;
  123. using Iterator = BlockArrayIterator<T*, T&, BlockArray*>;
  124. using ConstIterator = BlockArrayIterator<const T*, const T&, const BlockArray*>;
  125. using Reference = Value&;
  126. using ConstReference = const Value&;
  127. static constexpr U32 kElementCountPerBlock = TConfig::getElementCountPerBlock();
  128. BlockArray(const TMemoryPool& pool = TMemoryPool())
  129. : m_blockStorages(pool)
  130. , m_blockMetadatas(pool)
  131. {
  132. }
  133. /// Copy.
  134. BlockArray(const BlockArray& b)
  135. {
  136. *this = b;
  137. }
  138. /// Move.
  139. BlockArray(BlockArray&& b)
  140. {
  141. *this = std::move(b);
  142. }
  143. /// Destroy.
  144. ~BlockArray()
  145. {
  146. destroy();
  147. }
  148. /// Copy.
  149. BlockArray& operator=(const BlockArray& b);
  150. /// Move operator.
  151. BlockArray& operator=(BlockArray&& b)
  152. {
  153. destroy();
  154. m_blockStorages = std::move(b.m_blockStorages);
  155. m_blockMetadatas = std::move(b.m_blockMetadatas);
  156. m_elementCount = b.m_elementCount;
  157. b.m_elementCount = 0;
  158. m_firstIndex = b.m_firstIndex;
  159. b.m_firstIndex = 0;
  160. m_endIndex = b.m_endIndex;
  161. b.m_endIndex = 0;
  162. return *this;
  163. }
  164. ConstReference operator[](U32 idx) const
  165. {
  166. const U32 blockIdx = idx / kElementCountPerBlock;
  167. const U32 localIdx = idx % kElementCountPerBlock;
  168. ANKI_ASSERT(blockIdx < m_blockMetadatas.getSize());
  169. ANKI_ASSERT(m_blockStorages[blockIdx] != nullptr);
  170. ANKI_ASSERT(m_blockMetadatas[blockIdx].m_elementsInUseMask.get(localIdx) == true);
  171. return *reinterpret_cast<Value*>(&m_blockStorages[blockIdx]->m_storage[localIdx * sizeof(Value)]);
  172. }
  173. Reference operator[](U32 idx)
  174. {
  175. const auto& constSelf = *this;
  176. return const_cast<Reference>(constSelf[idx]);
  177. }
  178. /// Get begin.
  179. Iterator getBegin()
  180. {
  181. return Iterator(this, m_firstIndex);
  182. }
  183. /// Get begin.
  184. ConstIterator getBegin() const
  185. {
  186. return ConstIterator(this, m_firstIndex);
  187. }
  188. /// Get end.
  189. Iterator getEnd()
  190. {
  191. return Iterator(this, m_endIndex);
  192. }
  193. /// Get end.
  194. ConstIterator getEnd() const
  195. {
  196. return ConstIterator(this, m_endIndex);
  197. }
  198. /// Get begin.
  199. Iterator begin()
  200. {
  201. return getBegin();
  202. }
  203. /// Get begin.
  204. ConstIterator begin() const
  205. {
  206. return getBegin();
  207. }
  208. /// Get end.
  209. Iterator end()
  210. {
  211. return getEnd();
  212. }
  213. /// Get end.
  214. ConstIterator end() const
  215. {
  216. return getEnd();
  217. }
  218. U32 getSize() const
  219. {
  220. return m_elementCount;
  221. }
  222. Bool isEmpty() const
  223. {
  224. return m_elementCount == 0;
  225. }
  226. /// Destroy the array and free its elements.
  227. void destroy();
  228. /// Emplace somewhere in some block.
  229. template<typename... TArgs>
  230. Iterator emplace(TArgs&&... args);
  231. /// Removes one element.
  232. /// @param at Points to the position of the element to remove.
  233. void erase(Iterator idx);
  234. /// Removes one element.
  235. /// @param at Points to the position of the element to remove.
  236. void erase(U32 index)
  237. {
  238. erase(indexToIterator(index));
  239. }
  240. Iterator indexToIterator(U32 idx)
  241. {
  242. ANKI_ASSERT(indexExists(idx));
  243. return Iterator(this, idx);
  244. }
  245. ConstIterator indexToIterator(U32 idx) const
  246. {
  247. ANKI_ASSERT(indexExists(idx));
  248. return ConstIterator(this, idx);
  249. }
  250. Bool indexExists(U32 idx) const
  251. {
  252. const U32 localIdx = idx % kElementCountPerBlock;
  253. const U32 blockIdx = idx / kElementCountPerBlock;
  254. return blockIdx < m_blockMetadatas.getSize() && m_blockMetadatas[blockIdx].m_elementsInUseMask.get(localIdx) == true;
  255. }
  256. TMemoryPool& getMemoryPool()
  257. {
  258. return m_blockStorages.getMemoryPool();
  259. }
  260. void validate() const;
  261. private:
  262. class alignas(alignof(T)) BlockStorage
  263. {
  264. public:
  265. U8 m_storage[sizeof(T) * kElementCountPerBlock];
  266. };
  267. using Mask = BitSet<kElementCountPerBlock, U64>;
  268. class BlockMetadata
  269. {
  270. public:
  271. Mask m_elementsInUseMask{false};
  272. BlockMetadata() = default;
  273. BlockMetadata(Bool set)
  274. : m_elementsInUseMask(set)
  275. {
  276. }
  277. };
  278. DynamicArray<BlockStorage*, TMemoryPool> m_blockStorages;
  279. DynamicArray<BlockMetadata, TMemoryPool> m_blockMetadatas;
  280. U32 m_elementCount = 0;
  281. U32 m_firstIndex = 0;
  282. U32 m_endIndex = 0; ///< The index after the last.
  283. U32 getFirstElementIndex() const
  284. {
  285. for(U32 blockIdx = 0; blockIdx < m_blockMetadatas.getSize(); ++blockIdx)
  286. {
  287. U32 localIdx;
  288. if((localIdx = m_blockMetadatas[blockIdx].m_elementsInUseMask.getLeastSignificantBit()) != kMaxU32)
  289. {
  290. return localIdx + blockIdx * kElementCountPerBlock;
  291. }
  292. }
  293. ANKI_ASSERT(0);
  294. return 0;
  295. }
  296. U32 getLastElementIndex() const
  297. {
  298. U32 blockIdx = m_blockMetadatas.getSize();
  299. while(blockIdx--)
  300. {
  301. U32 localIdx;
  302. if((localIdx = m_blockMetadatas[blockIdx].m_elementsInUseMask.getMostSignificantBit()) != kMaxU32)
  303. {
  304. return localIdx + blockIdx * kElementCountPerBlock;
  305. }
  306. }
  307. ANKI_ASSERT(0);
  308. return 0;
  309. }
  310. U32 getNextElementIndex(U32 crnt) const;
  311. };
  312. /// @}
  313. } // end namespace anki
  314. #include <AnKi/Util/BlockArray.inl.h>