HashMap.h 5.3 KB

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