HashMap.h 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. // Copyright (C) 2009-2021, 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/Allocator.h>
  7. #include <AnKi/Util/Functions.h>
  8. #include <AnKi/Util/SparseArray.h>
  9. namespace anki
  10. {
  11. /// @addtogroup util_containers
  12. /// @{
  13. /// Default hasher.
  14. template<typename TKey>
  15. class DefaultHasher
  16. {
  17. public:
  18. U64 operator()(const TKey& a) const
  19. {
  20. return a.computeHash();
  21. }
  22. };
  23. /// Specialization for U64 keys.
  24. template<>
  25. class DefaultHasher<U64>
  26. {
  27. public:
  28. U64 operator()(const U64 a) const
  29. {
  30. return a;
  31. }
  32. };
  33. /// Specialization for I64 keys.
  34. template<>
  35. class DefaultHasher<I64>
  36. {
  37. public:
  38. U64 operator()(const I64 a) const
  39. {
  40. union
  41. {
  42. U64 u64;
  43. I64 i64;
  44. };
  45. i64 = a;
  46. return u64;
  47. }
  48. };
  49. template<>
  50. class DefaultHasher<U32>
  51. {
  52. public:
  53. U64 operator()(const U32 a) const
  54. {
  55. return computeHash(&a, sizeof(a));
  56. }
  57. };
  58. /// Hash map template.
  59. template<typename TKey, typename TValue, typename THasher = DefaultHasher<TKey>>
  60. class HashMap
  61. {
  62. public:
  63. // Typedefs
  64. using SparseArrayType = SparseArray<TValue, U64>;
  65. using Value = TValue;
  66. using Key = TKey;
  67. using Hasher = THasher;
  68. using Iterator = typename SparseArrayType::Iterator;
  69. using ConstIterator = typename SparseArrayType::ConstIterator;
  70. // Consts
  71. /// @see SparseArray::INITIAL_STORAGE_SIZE
  72. static constexpr U32 INITIAL_STORAGE_SIZE = SparseArrayType::INITIAL_STORAGE_SIZE;
  73. /// @see SparseArray::LINEAR_PROBING_COUNT
  74. static constexpr U32 LINEAR_PROBING_COUNT = SparseArrayType::LINEAR_PROBING_COUNT;
  75. /// @see SparseArray::MAX_LOAD_FACTOR
  76. static constexpr F32 MAX_LOAD_FACTOR = SparseArrayType::MAX_LOAD_FACTOR;
  77. /// Default constructor.
  78. /// @copy doc SparseArray::SparseArray
  79. HashMap(U32 initialStorageSize = INITIAL_STORAGE_SIZE, U32 probeCount = LINEAR_PROBING_COUNT,
  80. F32 maxLoadFactor = MAX_LOAD_FACTOR)
  81. : m_sparseArr(initialStorageSize, probeCount, maxLoadFactor)
  82. {
  83. }
  84. /// Move.
  85. HashMap(HashMap&& b)
  86. {
  87. *this = std::move(b);
  88. }
  89. /// You need to manually destroy the map.
  90. /// @see HashMap::destroy
  91. ~HashMap()
  92. {
  93. }
  94. /// Move.
  95. HashMap& operator=(HashMap&& b)
  96. {
  97. m_sparseArr = std::move(b.m_sparseArr);
  98. return *this;
  99. }
  100. /// Get begin.
  101. Iterator getBegin()
  102. {
  103. return m_sparseArr.getBegin();
  104. }
  105. /// Get begin.
  106. ConstIterator getBegin() const
  107. {
  108. return m_sparseArr.getBegin();
  109. }
  110. /// Get end.
  111. Iterator getEnd()
  112. {
  113. return m_sparseArr.getEnd();
  114. }
  115. /// Get end.
  116. ConstIterator getEnd() const
  117. {
  118. return m_sparseArr.getEnd();
  119. }
  120. /// Get begin.
  121. Iterator begin()
  122. {
  123. return getBegin();
  124. }
  125. /// Get begin.
  126. ConstIterator begin() const
  127. {
  128. return getBegin();
  129. }
  130. /// Get end.
  131. Iterator end()
  132. {
  133. return getEnd();
  134. }
  135. /// Get end.
  136. ConstIterator end() const
  137. {
  138. return getEnd();
  139. }
  140. /// Return true if map is empty.
  141. Bool isEmpty() const
  142. {
  143. return m_sparseArr.isEmpty();
  144. }
  145. PtrSize getSize() const
  146. {
  147. return m_sparseArr.getSize();
  148. }
  149. /// Destroy the list.
  150. template<typename TAllocator>
  151. void destroy(TAllocator alloc)
  152. {
  153. m_sparseArr.destroy(alloc);
  154. }
  155. /// Construct an element inside the map.
  156. template<typename TAllocator, typename... TArgs>
  157. Iterator emplace(TAllocator alloc, const TKey& key, TArgs&&... args)
  158. {
  159. const U64 hash = THasher()(key);
  160. return m_sparseArr.emplace(alloc, hash, std::forward<TArgs>(args)...);
  161. }
  162. /// Erase element.
  163. template<typename TAllocator>
  164. void erase(TAllocator alloc, Iterator it)
  165. {
  166. m_sparseArr.erase(alloc, it);
  167. }
  168. /// Find a value using a key.
  169. Iterator find(const Key& key)
  170. {
  171. const U64 hash = THasher()(key);
  172. return m_sparseArr.find(hash);
  173. }
  174. /// Find a value using a key.
  175. ConstIterator find(const Key& key) const
  176. {
  177. const U64 hash = THasher()(key);
  178. return m_sparseArr.find(hash);
  179. }
  180. protected:
  181. SparseArrayType m_sparseArr;
  182. };
  183. /// Hash map template with automatic cleanup.
  184. template<typename TKey, typename TValue, typename THasher = DefaultHasher<TKey>>
  185. class HashMapAuto : public HashMap<TKey, TValue, THasher>
  186. {
  187. public:
  188. using Base = HashMap<TKey, TValue, THasher>;
  189. /// Default constructor.
  190. /// @copy doc SparseArray::SparseArray
  191. HashMapAuto(const GenericMemoryPoolAllocator<U8>& alloc, U32 initialStorageSize = Base::INITIAL_STORAGE_SIZE,
  192. U32 probeCount = Base::LINEAR_PROBING_COUNT, F32 maxLoadFactor = Base::MAX_LOAD_FACTOR)
  193. : Base(initialStorageSize, probeCount, maxLoadFactor)
  194. , m_alloc(alloc)
  195. {
  196. }
  197. /// Move.
  198. HashMapAuto(HashMapAuto&& b)
  199. {
  200. *this = std::move(b);
  201. }
  202. /// Copy.
  203. HashMapAuto(const HashMapAuto& b)
  204. : Base()
  205. {
  206. copy(b);
  207. }
  208. /// Destructor.
  209. ~HashMapAuto()
  210. {
  211. destroy();
  212. }
  213. /// Move.
  214. HashMapAuto& operator=(HashMapAuto&& b)
  215. {
  216. std::move(*static_cast<HashMapAuto>(this));
  217. m_alloc = std::move(b.m_alloc);
  218. return *this;
  219. }
  220. /// Copy.
  221. HashMapAuto& operator=(const HashMapAuto& b)
  222. {
  223. copy(b);
  224. return *this;
  225. }
  226. /// Construct an element inside the map.
  227. template<typename... TArgs>
  228. typename Base::Iterator emplace(const TKey& key, TArgs&&... args)
  229. {
  230. return Base::emplace(m_alloc, key, std::forward<TArgs>(args)...);
  231. }
  232. /// Erase element.
  233. void erase(typename Base::Iterator it)
  234. {
  235. Base::erase(m_alloc, it);
  236. }
  237. /// Clean up the map.
  238. void destroy()
  239. {
  240. Base::destroy(m_alloc);
  241. }
  242. private:
  243. GenericMemoryPoolAllocator<U8> m_alloc;
  244. void copy(const HashMapAuto& b)
  245. {
  246. destroy();
  247. m_alloc = b.m_alloc;
  248. b.m_sparseArr.clone(m_alloc, Base::m_sparseArr);
  249. }
  250. };
  251. /// @}
  252. } // end namespace anki