SparseArray.inl.h 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  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/SparseArray.h>
  6. namespace anki {
  7. template<typename T, typename TMemoryPool, typename TConfig>
  8. void SparseArray<T, TMemoryPool, TConfig>::destroy()
  9. {
  10. if(m_elements)
  11. {
  12. for(Index i = 0; i < m_capacity; ++i)
  13. {
  14. if(m_metadata[i].m_alive)
  15. {
  16. destroyElement(m_elements[i]);
  17. }
  18. }
  19. m_pool.free(m_elements);
  20. ANKI_ASSERT(m_metadata);
  21. m_pool.free(m_metadata);
  22. }
  23. resetMembers();
  24. invalidateIterators();
  25. }
  26. template<typename T, typename TMemoryPool, typename TConfig>
  27. template<typename... TArgs>
  28. void SparseArray<T, TMemoryPool, TConfig>::emplaceInternal(Index idx, TArgs&&... args)
  29. {
  30. if(m_capacity == 0 || calcLoadFactor() > getMaxLoadFactor())
  31. {
  32. grow();
  33. }
  34. Value tmp(std::forward<TArgs>(args)...);
  35. m_elementCount += insert(idx, tmp);
  36. invalidateIterators();
  37. }
  38. template<typename T, typename TMemoryPool, typename TConfig>
  39. template<typename... TArgs>
  40. typename SparseArray<T, TMemoryPool, TConfig>::Iterator SparseArray<T, TMemoryPool, TConfig>::emplace(Index idx, TArgs&&... args)
  41. {
  42. emplaceInternal(idx, std::forward<TArgs>(args)...);
  43. return Iterator(this, findInternal(idx)
  44. #if ANKI_EXTRA_CHECKS
  45. ,
  46. m_iteratorVer
  47. #endif
  48. );
  49. }
  50. template<typename T, typename TMemoryPool, typename TConfig>
  51. typename TConfig::Index SparseArray<T, TMemoryPool, TConfig>::insert(Index idx, Value& val)
  52. {
  53. while(true)
  54. {
  55. const Index desiredPos = mod(idx);
  56. const Index endPos = mod(desiredPos + getLinearProbingCount());
  57. Index pos = desiredPos;
  58. while(pos != endPos)
  59. {
  60. Metadata& meta = m_metadata[pos];
  61. Value& crntVal = m_elements[pos];
  62. if(!meta.m_alive)
  63. {
  64. // Empty slot was found, construct in-place
  65. meta.m_alive = true;
  66. meta.m_idx = idx;
  67. callConstructor(crntVal, std::move(val));
  68. return 1;
  69. }
  70. else if(meta.m_idx == idx)
  71. {
  72. // Same index was found, replace
  73. meta.m_idx = idx;
  74. destroyElement(crntVal);
  75. callConstructor(crntVal, std::move(val));
  76. return 0;
  77. }
  78. // Do the robin-hood
  79. const Index otherDesiredPos = mod(meta.m_idx);
  80. if(distanceFromDesired(pos, otherDesiredPos) < distanceFromDesired(pos, desiredPos))
  81. {
  82. // Swap
  83. std::swap(val, crntVal);
  84. std::swap(idx, meta.m_idx);
  85. break;
  86. }
  87. pos = mod(pos + 1u);
  88. }
  89. if(pos == endPos)
  90. {
  91. // Didn't found an empty place, need to grow and try again
  92. grow();
  93. }
  94. }
  95. return 0;
  96. }
  97. template<typename T, typename TMemoryPool, typename TConfig>
  98. void SparseArray<T, TMemoryPool, TConfig>::grow()
  99. {
  100. if(m_capacity == 0)
  101. {
  102. ANKI_ASSERT(m_elementCount == 0);
  103. m_capacity = getInitialStorageSize();
  104. m_elements = static_cast<Value*>(m_pool.allocate(m_capacity * sizeof(Value), alignof(Value)));
  105. m_metadata = static_cast<Metadata*>(m_pool.allocate(m_capacity * sizeof(Metadata), alignof(Metadata)));
  106. memset(m_metadata, 0, m_capacity * sizeof(Metadata));
  107. return;
  108. }
  109. // Allocate new storage
  110. Value* const oldElements = m_elements;
  111. Metadata* const oldMetadata = m_metadata;
  112. const Index oldCapacity = m_capacity;
  113. [[maybe_unused]] const Index oldElementCount = m_elementCount;
  114. m_capacity *= 2;
  115. m_elements = static_cast<Value*>(m_pool.allocate(m_capacity * sizeof(Value), alignof(Value)));
  116. m_metadata = static_cast<Metadata*>(m_pool.allocate(m_capacity * sizeof(Metadata), alignof(Metadata)));
  117. memset(m_metadata, 0, m_capacity * sizeof(Metadata));
  118. m_elementCount = 0;
  119. // Find from where we start
  120. Index startPos = ~Index(0);
  121. for(Index i = 0; i < oldCapacity; ++i)
  122. {
  123. if(oldMetadata[i].m_alive)
  124. {
  125. const Index desiredPos = mod(oldMetadata[i].m_idx, oldCapacity);
  126. if(desiredPos <= i)
  127. {
  128. startPos = i;
  129. break;
  130. }
  131. }
  132. }
  133. ANKI_ASSERT(startPos != ~Index(0));
  134. // Start re-inserting
  135. Index count = oldCapacity;
  136. Index pos = startPos;
  137. while(count--)
  138. {
  139. if(oldMetadata[pos].m_alive)
  140. {
  141. Index c = insert(oldMetadata[pos].m_idx, oldElements[pos]);
  142. ANKI_ASSERT(c > 0);
  143. m_elementCount += c;
  144. // The element was moved to a new storage so we need to destroy the original
  145. destroyElement(oldElements[pos]);
  146. }
  147. pos = mod(pos + 1, oldCapacity);
  148. }
  149. ANKI_ASSERT(oldElementCount == m_elementCount);
  150. // Finalize
  151. m_pool.free(oldElements);
  152. m_pool.free(oldMetadata);
  153. }
  154. template<typename T, typename TMemoryPool, typename TConfig>
  155. void SparseArray<T, TMemoryPool, TConfig>::erase(Iterator it)
  156. {
  157. ANKI_ASSERT(it.m_array == this);
  158. ANKI_ASSERT(it.m_elementIdx != getMaxNumericLimit<Index>());
  159. ANKI_ASSERT(it.m_iteratorVer == m_iteratorVer);
  160. ANKI_ASSERT(m_elementCount > 0);
  161. const Index pos = it.m_elementIdx;
  162. ANKI_ASSERT(pos < m_capacity);
  163. ANKI_ASSERT(m_metadata[pos].m_alive);
  164. // Shift elements
  165. Index crntPos; // Also the one that will get deleted
  166. Index nextPos = pos;
  167. while(true)
  168. {
  169. crntPos = nextPos;
  170. nextPos = mod(nextPos + 1);
  171. Metadata& crntMeta = m_metadata[crntPos];
  172. Metadata& nextMeta = m_metadata[nextPos];
  173. Value& crntEl = m_elements[crntPos];
  174. Value& nextEl = m_elements[nextPos];
  175. if(!nextMeta.m_alive)
  176. {
  177. // On gaps, stop
  178. break;
  179. }
  180. const Index nextDesiredPos = mod(nextMeta.m_idx);
  181. if(nextDesiredPos == nextPos)
  182. {
  183. // The element is where it want's to be, stop
  184. break;
  185. }
  186. // Shift left
  187. std::swap(crntEl, nextEl);
  188. crntMeta.m_idx = nextMeta.m_idx;
  189. }
  190. // Delete the element in the given pos
  191. destroyElement(m_elements[crntPos]);
  192. m_metadata[crntPos].m_alive = false;
  193. --m_elementCount;
  194. // If you erased everything destroy the storage
  195. if(m_elementCount == 0)
  196. {
  197. destroy();
  198. }
  199. invalidateIterators();
  200. }
  201. template<typename T, typename TMemoryPool, typename TConfig>
  202. void SparseArray<T, TMemoryPool, TConfig>::validate() const
  203. {
  204. if(m_capacity == 0)
  205. {
  206. ANKI_ASSERT(m_elementCount == 0 && m_elements == nullptr && m_metadata == nullptr);
  207. return;
  208. }
  209. ANKI_ASSERT(m_elementCount < m_capacity);
  210. // Find from where we start
  211. Index startPos = ~Index(0);
  212. for(Index i = 0; i < m_capacity; ++i)
  213. {
  214. if(m_metadata[i].m_alive)
  215. {
  216. const Index desiredPos = mod(m_metadata[i].m_idx);
  217. if(desiredPos <= i)
  218. {
  219. startPos = i;
  220. break;
  221. }
  222. }
  223. }
  224. // Start iterating
  225. [[maybe_unused]] U elementCount = 0;
  226. Index count = m_capacity;
  227. Index pos = startPos;
  228. Index prevPos = ~Index(0);
  229. while(count--)
  230. {
  231. if(m_metadata[pos].m_alive)
  232. {
  233. [[maybe_unused]] const Index myDesiredPos = mod(m_metadata[pos].m_idx);
  234. ANKI_ASSERT(distanceFromDesired(pos, myDesiredPos) < getLinearProbingCount());
  235. if(prevPos != ~Index(0))
  236. {
  237. [[maybe_unused]] Index prevDesiredPos = mod(m_metadata[prevPos].m_idx);
  238. ANKI_ASSERT(myDesiredPos >= prevDesiredPos);
  239. }
  240. ++elementCount;
  241. prevPos = pos;
  242. }
  243. else
  244. {
  245. prevPos = ~Index(0);
  246. }
  247. pos = mod(pos + 1);
  248. }
  249. ANKI_ASSERT(m_elementCount == elementCount);
  250. }
  251. template<typename T, typename TMemoryPool, typename TConfig>
  252. typename TConfig::Index SparseArray<T, TMemoryPool, TConfig>::findInternal(Index idx) const
  253. {
  254. if(m_elementCount == 0) [[unlikely]]
  255. {
  256. return getMaxNumericLimit<Index>();
  257. }
  258. const Index desiredPos = mod(idx);
  259. const Index endPos = mod(desiredPos + getLinearProbingCount());
  260. Index pos = desiredPos;
  261. while(pos != endPos)
  262. {
  263. if(m_metadata[pos].m_alive && m_metadata[pos].m_idx == idx)
  264. {
  265. return pos;
  266. }
  267. pos = mod(pos + 1);
  268. }
  269. return getMaxNumericLimit<Index>();
  270. }
  271. template<typename T, typename TMemoryPool, typename TConfig>
  272. SparseArray<T, TMemoryPool, TConfig>& SparseArray<T, TMemoryPool, TConfig>::operator=(const SparseArray& b)
  273. {
  274. destroy();
  275. m_pool = b.m_pool;
  276. if(b.m_capacity == 0)
  277. {
  278. return *this;
  279. }
  280. // Allocate memory
  281. m_elements = static_cast<Value*>(m_pool.allocate(b.m_capacity * sizeof(Value), alignof(Value)));
  282. m_metadata = static_cast<Metadata*>(m_pool.allocate(b.m_capacity * sizeof(Metadata), alignof(Metadata)));
  283. memcpy(m_metadata, b.m_metadata, b.m_capacity * sizeof(Metadata));
  284. for(U i = 0; i < b.m_capacity; ++i)
  285. {
  286. if(b.m_metadata[i].m_alive)
  287. {
  288. ::new(&m_elements[i]) Value(b.m_elements[i]);
  289. }
  290. }
  291. // Set the rest
  292. m_elementCount = b.m_elementCount;
  293. m_capacity = b.m_capacity;
  294. m_config = b.m_config;
  295. invalidateIterators();
  296. return *this;
  297. }
  298. } // end namespace anki