HashMap.h 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500
  1. // Copyright (C) 2009-2016, 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/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. /// @tparam THasher Functor to hash type of TKey.
  161. /// @tparam TCompare Functor to compare TKey.
  162. /// @internal
  163. template<typename TKey,
  164. typename TValue,
  165. typename THasher,
  166. typename TCompare,
  167. typename TNode>
  168. class HashMapBase : public NonCopyable
  169. {
  170. public:
  171. using Key = TKey;
  172. using Value = TValue;
  173. using Reference = Value&;
  174. using ConstReference = const Value&;
  175. using Pointer = Value*;
  176. using ConstPointer = const Value*;
  177. using Iterator = HashMapIterator<TNode*, Pointer, Reference>;
  178. using ConstIterator =
  179. HashMapIterator<const TNode*, ConstPointer, ConstReference>;
  180. /// Default constructor.
  181. HashMapBase()
  182. : m_root(nullptr)
  183. {
  184. }
  185. ~HashMapBase() = default;
  186. /// Get begin.
  187. Iterator getBegin()
  188. {
  189. return Iterator(m_root);
  190. }
  191. /// Get begin.
  192. ConstIterator getBegin() const
  193. {
  194. return ConstIterator(m_root);
  195. }
  196. /// Get end.
  197. Iterator getEnd()
  198. {
  199. return Iterator();
  200. }
  201. /// Get end.
  202. ConstIterator getEnd() const
  203. {
  204. return ConstIterator();
  205. }
  206. /// Get begin.
  207. Iterator begin()
  208. {
  209. return getBegin();
  210. }
  211. /// Get begin.
  212. ConstIterator begin() const
  213. {
  214. return getBegin();
  215. }
  216. /// Get end.
  217. Iterator end()
  218. {
  219. return getEnd();
  220. }
  221. /// Get end.
  222. ConstIterator end() const
  223. {
  224. return getEnd();
  225. }
  226. /// Return true if map is empty.
  227. Bool isEmpty() const
  228. {
  229. return m_root == nullptr;
  230. }
  231. /// Find item.
  232. Iterator find(const Key& key);
  233. protected:
  234. /// @privatesection
  235. TNode* m_root = nullptr;
  236. void move(HashMapBase& b)
  237. {
  238. m_root = b.m_root;
  239. b.m_root = nullptr;
  240. }
  241. /// Add a node in the tree.
  242. void insertNode(TNode* node);
  243. /// Remove a node from the tree.
  244. void removeNode(TNode* node);
  245. };
  246. } // end namespace detail
  247. /// Hash map template.
  248. template<typename TKey, typename TValue, typename THasher, typename TCompare>
  249. class HashMap : public detail::HashMapBase<TKey,
  250. TValue,
  251. THasher,
  252. TCompare,
  253. detail::HashMapNode<TValue>>
  254. {
  255. private:
  256. using Base = detail::HashMapBase<TKey,
  257. TValue,
  258. THasher,
  259. TCompare,
  260. detail::HashMapNode<TValue>>;
  261. using Node = detail::HashMapNode<TValue>;
  262. public:
  263. /// Default constructor.
  264. HashMap()
  265. : Base()
  266. {
  267. }
  268. /// Move.
  269. HashMap(HashMap&& b)
  270. : Base()
  271. {
  272. Base::move(b);
  273. }
  274. /// You need to manually destroy the map.
  275. /// @see HashMap::destroy
  276. ~HashMap()
  277. {
  278. ANKI_ASSERT(Base::m_root == nullptr && "Requires manual destruction");
  279. }
  280. /// Move.
  281. HashMap& operator=(HashMap&& b)
  282. {
  283. Base::move(b);
  284. return *this;
  285. }
  286. /// Destroy the list.
  287. template<typename TAllocator>
  288. void destroy(TAllocator alloc);
  289. /// Copy an element in the map.
  290. template<typename TAllocator>
  291. void pushBack(TAllocator alloc, const TKey& key, const TValue& x)
  292. {
  293. Node* node = alloc.template newInstance<Node>(x);
  294. node->m_hash = THasher()(key);
  295. Base::insertNode(node);
  296. }
  297. /// Construct an element inside the map.
  298. template<typename TAllocator, typename... TArgs>
  299. void emplaceBack(TAllocator alloc, const TKey& key, TArgs&&... args)
  300. {
  301. Node* node =
  302. alloc.template newInstance<Node>(std::forward<TArgs>(args)...);
  303. node->m_hash = THasher()(key);
  304. Base::insertNode(node);
  305. }
  306. /// Erase element.
  307. template<typename TAllocator>
  308. void erase(TAllocator alloc, typename Base::Iterator it)
  309. {
  310. Node* del = it.m_node;
  311. Base::removeNode(del);
  312. alloc.deleteInstance(del);
  313. }
  314. private:
  315. template<typename TAllocator>
  316. void destroyInternal(TAllocator alloc, Node* node);
  317. };
  318. /// The classes that will use the IntrusiveHashMap need to inherit from this
  319. /// one.
  320. template<typename TClass>
  321. class IntrusiveHashMapEnabled : public NonCopyable
  322. {
  323. template<typename TKey,
  324. typename TValue,
  325. typename THasher,
  326. typename TCompare,
  327. typename TNode>
  328. friend class detail::HashMapBase;
  329. template<typename TNodePointer,
  330. typename TValuePointer,
  331. typename TValueReference>
  332. friend class detail::HashMapIterator;
  333. template<typename TKey,
  334. typename TValue,
  335. typename THasher,
  336. typename TCompare>
  337. friend class IntrusiveHashMap;
  338. friend TClass;
  339. public:
  340. /// Default constructor.
  341. IntrusiveHashMapEnabled() = default;
  342. /// Move.
  343. IntrusiveHashMapEnabled(IntrusiveHashMapEnabled&& b)
  344. : m_hash(b.m_hash)
  345. , m_left(b.m_left)
  346. , m_right(b.m_right)
  347. , m_parent(b.m_parent)
  348. {
  349. b.m_hash = 0;
  350. b.m_left = b.m_right = b.m_parent = nullptr;
  351. }
  352. /// Move.
  353. IntrusiveHashMapEnabled& operator=(IntrusiveHashMapEnabled&& b)
  354. {
  355. ANKI_ASSERT(m_hash == 0 && m_left == m_right && m_right == m_parent
  356. && m_parent == nullptr);
  357. m_hash = b.m_hash;
  358. m_left = b.m_left;
  359. m_right = b.m_right;
  360. m_parent = b.m_parent;
  361. b.m_hash = 0;
  362. b.m_left = b.m_right = b.m_parent = nullptr;
  363. return *this;
  364. }
  365. private:
  366. U64 m_hash = 0;
  367. TClass* m_left = nullptr;
  368. TClass* m_right = nullptr;
  369. TClass* m_parent = nullptr; ///< Used for iterating.
  370. TClass& getValue()
  371. {
  372. return *static_cast<TClass*>(this);
  373. }
  374. const TClass& getValue() const
  375. {
  376. return *static_cast<const TClass*>(this);
  377. }
  378. };
  379. /// Hash map that doesn't perform any allocations. To work the TValue nodes will
  380. /// have to inherit from IntrusiveHashMapEnabled.
  381. template<typename TKey, typename TValue, typename THasher, typename TCompare>
  382. class IntrusiveHashMap
  383. : public detail::HashMapBase<TKey, TValue, THasher, TCompare, TValue>
  384. {
  385. private:
  386. using Base = detail::HashMapBase<TKey, TValue, THasher, TCompare, TValue>;
  387. using Node = TValue;
  388. public:
  389. /// Default constructor.
  390. IntrusiveHashMap()
  391. : Base()
  392. {
  393. }
  394. /// Move.
  395. IntrusiveHashMap(IntrusiveHashMap&& b)
  396. : Base()
  397. {
  398. Base::move(b);
  399. }
  400. ~IntrusiveHashMap() = default;
  401. /// Move.
  402. IntrusiveHashMap& operator=(IntrusiveHashMap&& b)
  403. {
  404. Base::move(b);
  405. return *this;
  406. }
  407. /// Add an element to the map.
  408. void pushBack(const TKey& key, TValue* x)
  409. {
  410. ANKI_ASSERT(x);
  411. IntrusiveHashMapEnabled<TValue>* e =
  412. static_cast<IntrusiveHashMapEnabled<TValue>*>(x);
  413. e->m_hash = THasher()(key);
  414. Base::insertNode(x);
  415. }
  416. /// Erase element.
  417. void erase(typename Base::Iterator it)
  418. {
  419. Node* del = it.m_node;
  420. Base::removeNode(del);
  421. }
  422. };
  423. /// @}
  424. } // end namespace anki
  425. #include <anki/util/HashMap.inl.h>