HashMap.h 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498
  1. // Copyright (C) 2009-2016, Panagiotis Christopoulos Charitos.
  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/NonCopyable.h>
  9. namespace anki
  10. {
  11. // Forward
  12. template<typename, typename, typename, typename>
  13. class HashMap;
  14. template<typename, typename, typename, typename>
  15. class IntrusiveHashMap;
  16. /// @addtogroup util_containers
  17. /// @{
  18. namespace detail
  19. {
  20. /// HashMap node. It's not a traditional bucket because it doesn't contain more
  21. /// than one values.
  22. /// @internal
  23. template<typename TValue>
  24. class HashMapNode
  25. {
  26. public:
  27. U64 m_hash = 0;
  28. HashMapNode* m_left = nullptr;
  29. HashMapNode* m_right = nullptr;
  30. TValue m_value;
  31. HashMapNode* m_parent = nullptr; ///< Used for iterating.
  32. template<typename... TArgs>
  33. HashMapNode(TArgs&&... args)
  34. : m_value(std::forward<TArgs>(args)...)
  35. {
  36. }
  37. TValue& getValue()
  38. {
  39. return m_value;
  40. }
  41. const TValue& getValue() const
  42. {
  43. return m_value;
  44. }
  45. };
  46. /// HashMap forward-only iterator.
  47. /// @internal
  48. template<typename TNodePointer,
  49. typename TValuePointer,
  50. typename TValueReference>
  51. class HashMapIterator
  52. {
  53. template<typename, typename, typename, typename>
  54. friend class anki::HashMap;
  55. template<typename, typename, typename, typename>
  56. friend class anki::IntrusiveHashMap;
  57. public:
  58. /// Default constructor.
  59. HashMapIterator()
  60. : m_node(nullptr)
  61. {
  62. }
  63. /// Copy.
  64. HashMapIterator(const HashMapIterator& b)
  65. : m_node(b.m_node)
  66. {
  67. }
  68. /// Allow conversion from iterator to const iterator.
  69. template<typename YNodePointer,
  70. typename YValuePointer,
  71. typename YValueReference>
  72. HashMapIterator(
  73. const HashMapIterator<YNodePointer, YValuePointer, YValueReference>& b)
  74. : m_node(b.m_node)
  75. {
  76. }
  77. HashMapIterator(TNodePointer node)
  78. : m_node(node)
  79. {
  80. }
  81. TValueReference operator*() const
  82. {
  83. ANKI_ASSERT(m_node);
  84. return m_node->getValue();
  85. }
  86. TValuePointer operator->() const
  87. {
  88. ANKI_ASSERT(m_node);
  89. return &m_node->getValue();
  90. }
  91. HashMapIterator& operator++()
  92. {
  93. ANKI_ASSERT(m_node);
  94. TNodePointer node = m_node;
  95. if(node->m_left)
  96. {
  97. node = node->m_left;
  98. }
  99. else if(node->m_right)
  100. {
  101. node = node->m_right;
  102. }
  103. else
  104. {
  105. // Node without children
  106. TNodePointer prevNode = node;
  107. node = node->m_parent;
  108. while(node)
  109. {
  110. if(node->m_right && node->m_right != prevNode)
  111. {
  112. node = node->m_right;
  113. break;
  114. }
  115. prevNode = node;
  116. node = node->m_parent;
  117. }
  118. }
  119. m_node = node;
  120. return *this;
  121. }
  122. HashMapIterator operator++(int)
  123. {
  124. ANKI_ASSERT(m_node);
  125. HashMapIterator out = *this;
  126. ++(*this);
  127. return out;
  128. }
  129. HashMapIterator operator+(U n) const
  130. {
  131. HashMapIterator it = *this;
  132. while(n-- != 0)
  133. {
  134. ++it;
  135. }
  136. return it;
  137. }
  138. HashMapIterator& operator+=(U n)
  139. {
  140. while(n-- != 0)
  141. {
  142. ++(*this);
  143. }
  144. return *this;
  145. }
  146. Bool operator==(const HashMapIterator& b) const
  147. {
  148. return m_node == b.m_node;
  149. }
  150. Bool operator!=(const HashMapIterator& b) const
  151. {
  152. return !(*this == b);
  153. }
  154. private:
  155. TNodePointer m_node;
  156. };
  157. /// Hash map base.
  158. /// @tparam TKey The key of the map.
  159. /// @tparam TValue The value of the map.
  160. /// @internal
  161. template<typename TKey,
  162. typename TValue,
  163. typename THasher,
  164. typename TCompare,
  165. typename TNode>
  166. class HashMapBase : public NonCopyable
  167. {
  168. public:
  169. using Key = TKey;
  170. using Value = TValue;
  171. using Reference = Value&;
  172. using ConstReference = const Value&;
  173. using Pointer = Value*;
  174. using ConstPointer = const Value*;
  175. using Iterator = HashMapIterator<TNode*, Pointer, Reference>;
  176. using ConstIterator =
  177. HashMapIterator<const TNode*, ConstPointer, ConstReference>;
  178. /// Default constructor.
  179. HashMapBase()
  180. : m_root(nullptr)
  181. {
  182. }
  183. ~HashMapBase() = default;
  184. /// Get begin.
  185. Iterator getBegin()
  186. {
  187. return Iterator(m_root);
  188. }
  189. /// Get begin.
  190. ConstIterator getBegin() const
  191. {
  192. return ConstIterator(m_root);
  193. }
  194. /// Get end.
  195. Iterator getEnd()
  196. {
  197. return Iterator();
  198. }
  199. /// Get end.
  200. ConstIterator getEnd() const
  201. {
  202. return ConstIterator();
  203. }
  204. /// Get begin.
  205. Iterator begin()
  206. {
  207. return getBegin();
  208. }
  209. /// Get begin.
  210. ConstIterator begin() const
  211. {
  212. return getBegin();
  213. }
  214. /// Get end.
  215. Iterator end()
  216. {
  217. return getEnd();
  218. }
  219. /// Get end.
  220. ConstIterator end() const
  221. {
  222. return getEnd();
  223. }
  224. /// Return true if map is empty.
  225. Bool isEmpty() const
  226. {
  227. return m_root == nullptr;
  228. }
  229. /// Find item.
  230. Iterator find(const Key& key);
  231. protected:
  232. /// @privatesection
  233. TNode* m_root = nullptr;
  234. void move(HashMapBase& b)
  235. {
  236. m_root = b.m_root;
  237. b.m_root = nullptr;
  238. }
  239. /// Add a node in the tree.
  240. void insertNode(TNode* node);
  241. /// Remove a node from the tree.
  242. void removeNode(TNode* node);
  243. };
  244. } // end namespace detail
  245. /// Hash map template.
  246. template<typename TKey, typename TValue, typename THasher, typename TCompare>
  247. class HashMap : public detail::HashMapBase<TKey,
  248. TValue,
  249. THasher,
  250. TCompare,
  251. detail::HashMapNode<TValue>>
  252. {
  253. private:
  254. using Base = detail::HashMapBase<TKey,
  255. TValue,
  256. THasher,
  257. TCompare,
  258. detail::HashMapNode<TValue>>;
  259. using Node = detail::HashMapNode<TValue>;
  260. public:
  261. /// Default constructor.
  262. HashMap()
  263. : Base()
  264. {
  265. }
  266. /// Move.
  267. HashMap(HashMap&& b)
  268. : Base()
  269. {
  270. Base::move(b);
  271. }
  272. /// You need to manually destroy the map.
  273. /// @see HashMap::destroy
  274. ~HashMap()
  275. {
  276. ANKI_ASSERT(Base::m_root == nullptr && "Requires manual destruction");
  277. }
  278. /// Move.
  279. HashMap& operator=(HashMap&& b)
  280. {
  281. Base::move(b);
  282. return *this;
  283. }
  284. /// Destroy the list.
  285. template<typename TAllocator>
  286. void destroy(TAllocator alloc);
  287. /// Copy an element in the map.
  288. template<typename TAllocator>
  289. void pushBack(TAllocator alloc, const TKey& key, const TValue& x)
  290. {
  291. Node* node = alloc.template newInstance<Node>(x);
  292. node->m_hash = THasher()(key);
  293. Base::insertNode(node);
  294. }
  295. /// Construct an element inside the map.
  296. template<typename TAllocator, typename... TArgs>
  297. void emplaceBack(TAllocator alloc, const TKey& key, TArgs&&... args)
  298. {
  299. Node* node =
  300. alloc.template newInstance<Node>(std::forward<TArgs>(args)...);
  301. node->m_hash = THasher()(key);
  302. Base::insertNode(node);
  303. }
  304. /// Erase element.
  305. template<typename TAllocator>
  306. void erase(TAllocator alloc, typename Base::Iterator it)
  307. {
  308. Node* del = it.m_node;
  309. Base::removeNode(del);
  310. alloc.deleteInstance(del);
  311. }
  312. private:
  313. template<typename TAllocator>
  314. void destroyInternal(TAllocator alloc, Node* node);
  315. };
  316. /// The classes that will use the IntrusiveHashMap need to inherit from this
  317. /// one.
  318. template<typename TClass>
  319. class IntrusiveHashMapEnabled : public NonCopyable
  320. {
  321. template<typename TKey,
  322. typename TValue,
  323. typename THasher,
  324. typename TCompare,
  325. typename TNode>
  326. friend class detail::HashMapBase;
  327. template<typename TNodePointer,
  328. typename TValuePointer,
  329. typename TValueReference>
  330. friend class detail::HashMapIterator;
  331. template<typename TKey,
  332. typename TValue,
  333. typename THasher,
  334. typename TCompare>
  335. friend class IntrusiveHashMap;
  336. friend TClass;
  337. public:
  338. /// Default constructor.
  339. IntrusiveHashMapEnabled() = default;
  340. /// Move.
  341. IntrusiveHashMapEnabled(IntrusiveHashMapEnabled&& b)
  342. : m_hash(b.m_hash)
  343. , m_left(b.m_left)
  344. , m_right(b.m_right)
  345. , m_parent(b.m_parent)
  346. {
  347. b.m_hash = 0;
  348. b.m_left = b.m_right = b.m_parent = nullptr;
  349. }
  350. /// Move.
  351. IntrusiveHashMapEnabled& operator=(IntrusiveHashMapEnabled&& b)
  352. {
  353. ANKI_ASSERT(m_hash == 0 && m_left == m_right && m_right == m_parent
  354. && m_parent == nullptr);
  355. m_hash = b.m_hash;
  356. m_left = b.m_left;
  357. m_right = b.m_right;
  358. m_parent = b.m_parent;
  359. b.m_hash = 0;
  360. b.m_left = b.m_right = b.m_parent = nullptr;
  361. return *this;
  362. }
  363. private:
  364. U64 m_hash = 0;
  365. TClass* m_left = nullptr;
  366. TClass* m_right = nullptr;
  367. TClass* m_parent = nullptr; ///< Used for iterating.
  368. TClass& getValue()
  369. {
  370. return *static_cast<TClass*>(this);
  371. }
  372. const TClass& getValue() const
  373. {
  374. return *static_cast<const TClass*>(this);
  375. }
  376. };
  377. /// Hash map that doesn't perform any allocations. To work the TValue nodes will
  378. /// have to inherit from IntrusiveHashMapEnabled.
  379. template<typename TKey, typename TValue, typename THasher, typename TCompare>
  380. class IntrusiveHashMap
  381. : public detail::HashMapBase<TKey, TValue, THasher, TCompare, TValue>
  382. {
  383. private:
  384. using Base = detail::HashMapBase<TKey, TValue, THasher, TCompare, TValue>;
  385. using Node = TValue;
  386. public:
  387. /// Default constructor.
  388. IntrusiveHashMap()
  389. : Base()
  390. {
  391. }
  392. /// Move.
  393. IntrusiveHashMap(IntrusiveHashMap&& b)
  394. : Base()
  395. {
  396. Base::move(b);
  397. }
  398. ~IntrusiveHashMap() = default;
  399. /// Move.
  400. IntrusiveHashMap& operator=(IntrusiveHashMap&& b)
  401. {
  402. Base::move(b);
  403. return *this;
  404. }
  405. /// Add an element to the map.
  406. void pushBack(const TKey& key, TValue* x)
  407. {
  408. ANKI_ASSERT(x);
  409. IntrusiveHashMapEnabled<TValue>* e =
  410. static_cast<IntrusiveHashMapEnabled<TValue>*>(x);
  411. e->m_hash = THasher()(key);
  412. Base::insertNode(x);
  413. }
  414. /// Erase element.
  415. void erase(typename Base::Iterator it)
  416. {
  417. Node* del = it.m_node;
  418. Base::removeNode(del);
  419. }
  420. };
  421. /// @}
  422. } // end namespace anki
  423. #include <anki/util/HashMap.inl.h>