concurrent_unordered_map.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492
  1. /*
  2. Copyright (c) 2005-2020 Intel Corporation
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. /* Container implementations in this header are based on PPL implementations
  14. provided by Microsoft. */
  15. #ifndef __TBB_concurrent_unordered_map_H
  16. #define __TBB_concurrent_unordered_map_H
  17. #define __TBB_concurrent_unordered_map_H_include_area
  18. #include "internal/_warning_suppress_enable_notice.h"
  19. #include "internal/_concurrent_unordered_impl.h"
  20. namespace tbb
  21. {
  22. namespace interface5 {
  23. // Template class for hash map traits
  24. template<typename Key, typename T, typename Hash_compare, typename Allocator, bool Allow_multimapping>
  25. class concurrent_unordered_map_traits
  26. {
  27. protected:
  28. typedef std::pair<const Key, T> value_type;
  29. typedef Key key_type;
  30. typedef Hash_compare hash_compare;
  31. typedef typename tbb::internal::allocator_rebind<Allocator, value_type>::type allocator_type;
  32. #if __TBB_UNORDERED_NODE_HANDLE_PRESENT
  33. typedef tbb::internal::node_handle<key_type, value_type,
  34. typename internal::split_ordered_list<value_type, allocator_type>::node,
  35. allocator_type> node_type;
  36. #endif // __TBB_UNORDERED_NODE_HANDLE_PRESENT
  37. enum { allow_multimapping = Allow_multimapping };
  38. concurrent_unordered_map_traits() : my_hash_compare() {}
  39. concurrent_unordered_map_traits(const hash_compare& hc) : my_hash_compare(hc) {}
  40. template<class Type1, class Type2>
  41. static const Key& get_key(const std::pair<Type1, Type2>& value) {
  42. return (value.first);
  43. }
  44. hash_compare my_hash_compare; // the comparator predicate for keys
  45. };
  46. template<typename Key, typename T, typename Hasher, typename Key_equality, typename Allocator>
  47. class concurrent_unordered_multimap;
  48. template <typename Key, typename T, typename Hasher = tbb::tbb_hash<Key>, typename Key_equality = std::equal_to<Key>,
  49. typename Allocator = tbb::tbb_allocator<std::pair<const Key, T> > >
  50. class concurrent_unordered_map :
  51. public internal::concurrent_unordered_base< concurrent_unordered_map_traits<Key, T,
  52. internal::hash_compare<Key, Hasher, Key_equality>, Allocator, false> >
  53. {
  54. // Base type definitions
  55. typedef internal::hash_compare<Key, Hasher, Key_equality> hash_compare;
  56. typedef concurrent_unordered_map_traits<Key, T, hash_compare, Allocator, false> traits_type;
  57. typedef internal::concurrent_unordered_base< traits_type > base_type;
  58. #if __TBB_EXTRA_DEBUG
  59. public:
  60. #endif
  61. using traits_type::allow_multimapping;
  62. public:
  63. using base_type::end;
  64. using base_type::find;
  65. using base_type::insert;
  66. // Type definitions
  67. typedef Key key_type;
  68. typedef typename base_type::value_type value_type;
  69. typedef T mapped_type;
  70. typedef Hasher hasher;
  71. typedef Key_equality key_equal;
  72. typedef hash_compare key_compare;
  73. typedef typename base_type::allocator_type allocator_type;
  74. typedef typename base_type::pointer pointer;
  75. typedef typename base_type::const_pointer const_pointer;
  76. typedef typename base_type::reference reference;
  77. typedef typename base_type::const_reference const_reference;
  78. typedef typename base_type::size_type size_type;
  79. typedef typename base_type::difference_type difference_type;
  80. typedef typename base_type::iterator iterator;
  81. typedef typename base_type::const_iterator const_iterator;
  82. typedef typename base_type::iterator local_iterator;
  83. typedef typename base_type::const_iterator const_local_iterator;
  84. #if __TBB_UNORDERED_NODE_HANDLE_PRESENT
  85. typedef typename base_type::node_type node_type;
  86. #endif // __TBB_UNORDERED_NODE_HANDLE_PRESENT
  87. // Construction/destruction/copying
  88. explicit concurrent_unordered_map(size_type n_of_buckets = base_type::initial_bucket_number,
  89. const hasher& a_hasher = hasher(), const key_equal& a_keyeq = key_equal(),
  90. const allocator_type& a = allocator_type())
  91. : base_type(n_of_buckets, key_compare(a_hasher, a_keyeq), a)
  92. {}
  93. concurrent_unordered_map(size_type n_of_buckets, const allocator_type& a)
  94. : base_type(n_of_buckets, key_compare(hasher(), key_equal()), a)
  95. {}
  96. concurrent_unordered_map(size_type n_of_buckets, const hasher& a_hasher, const allocator_type& a)
  97. : base_type(n_of_buckets, key_compare(a_hasher, key_equal()), a)
  98. {}
  99. explicit concurrent_unordered_map(const Allocator& a) : base_type(base_type::initial_bucket_number, key_compare(), a)
  100. {}
  101. template <typename Iterator>
  102. concurrent_unordered_map(Iterator first, Iterator last, size_type n_of_buckets = base_type::initial_bucket_number,
  103. const hasher& a_hasher = hasher(), const key_equal& a_keyeq = key_equal(),
  104. const allocator_type& a = allocator_type())
  105. : base_type(n_of_buckets, key_compare(a_hasher, a_keyeq), a)
  106. {
  107. insert(first, last);
  108. }
  109. template <typename Iterator>
  110. concurrent_unordered_map(Iterator first, Iterator last, size_type n_of_buckets, const allocator_type& a)
  111. : base_type(n_of_buckets, key_compare(hasher(), key_equal()), a)
  112. {
  113. insert(first, last);
  114. }
  115. template <typename Iterator>
  116. concurrent_unordered_map(Iterator first, Iterator last, size_type n_of_buckets, const hasher& a_hasher,
  117. const allocator_type& a)
  118. : base_type(n_of_buckets, key_compare(a_hasher, key_equal()), a)
  119. {
  120. insert(first, last);
  121. }
  122. #if __TBB_INITIALIZER_LISTS_PRESENT
  123. //! Constructor from initializer_list
  124. concurrent_unordered_map(std::initializer_list<value_type> il, size_type n_of_buckets = base_type::initial_bucket_number,
  125. const hasher& a_hasher = hasher(), const key_equal& a_keyeq = key_equal(),
  126. const allocator_type& a = allocator_type())
  127. : base_type(n_of_buckets, key_compare(a_hasher, a_keyeq), a)
  128. {
  129. insert(il.begin(),il.end());
  130. }
  131. concurrent_unordered_map(std::initializer_list<value_type> il, size_type n_of_buckets, const allocator_type& a)
  132. : base_type(n_of_buckets, key_compare(hasher(), key_equal()), a)
  133. {
  134. insert(il.begin(), il.end());
  135. }
  136. concurrent_unordered_map(std::initializer_list<value_type> il, size_type n_of_buckets, const hasher& a_hasher,
  137. const allocator_type& a)
  138. : base_type(n_of_buckets, key_compare(a_hasher, key_equal()), a)
  139. {
  140. insert(il.begin(), il.end());
  141. }
  142. #endif //# __TBB_INITIALIZER_LISTS_PRESENT
  143. #if __TBB_CPP11_RVALUE_REF_PRESENT && !__TBB_IMPLICIT_MOVE_PRESENT
  144. concurrent_unordered_map(const concurrent_unordered_map& table)
  145. : base_type(table)
  146. {}
  147. concurrent_unordered_map& operator=(const concurrent_unordered_map& table)
  148. {
  149. return static_cast<concurrent_unordered_map&>(base_type::operator=(table));
  150. }
  151. concurrent_unordered_map(concurrent_unordered_map&& table)
  152. : base_type(std::move(table))
  153. {}
  154. concurrent_unordered_map& operator=(concurrent_unordered_map&& table)
  155. {
  156. return static_cast<concurrent_unordered_map&>(base_type::operator=(std::move(table)));
  157. }
  158. #endif //__TBB_CPP11_RVALUE_REF_PRESENT && !__TBB_IMPLICIT_MOVE_PRESENT
  159. #if __TBB_CPP11_RVALUE_REF_PRESENT
  160. concurrent_unordered_map(concurrent_unordered_map&& table, const Allocator& a) : base_type(std::move(table), a)
  161. {}
  162. #endif /*__TBB_CPP11_RVALUE_REF_PRESENT*/
  163. #if __TBB_UNORDERED_NODE_HANDLE_PRESENT
  164. template<typename Hash, typename Equality>
  165. void merge(concurrent_unordered_map<Key, T, Hash, Equality, Allocator>& source)
  166. { this->internal_merge(source); }
  167. template<typename Hash, typename Equality>
  168. void merge(concurrent_unordered_map<Key, T, Hash, Equality, Allocator>&& source)
  169. { this->internal_merge(source); }
  170. template<typename Hash, typename Equality>
  171. void merge(concurrent_unordered_multimap<Key, T, Hash, Equality, Allocator>& source)
  172. { this->internal_merge(source); }
  173. template<typename Hash, typename Equality>
  174. void merge(concurrent_unordered_multimap<Key, T, Hash, Equality, Allocator>&& source)
  175. { this->internal_merge(source); }
  176. #endif //__TBB_UNORDERED_NODE_HANDLE_PRESENT
  177. concurrent_unordered_map(const concurrent_unordered_map& table, const Allocator& a)
  178. : base_type(table, a)
  179. {}
  180. // Observers
  181. mapped_type& operator[](const key_type& key)
  182. {
  183. iterator where = find(key);
  184. if (where == end())
  185. {
  186. where = insert(std::pair<key_type, mapped_type>(key, mapped_type())).first;
  187. }
  188. return ((*where).second);
  189. }
  190. mapped_type& at(const key_type& key)
  191. {
  192. iterator where = find(key);
  193. if (where == end())
  194. {
  195. tbb::internal::throw_exception(tbb::internal::eid_invalid_key);
  196. }
  197. return ((*where).second);
  198. }
  199. const mapped_type& at(const key_type& key) const
  200. {
  201. const_iterator where = find(key);
  202. if (where == end())
  203. {
  204. tbb::internal::throw_exception(tbb::internal::eid_invalid_key);
  205. }
  206. return ((*where).second);
  207. }
  208. };
  209. #if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
  210. namespace internal {
  211. using namespace tbb::internal;
  212. template<template<typename...> typename Map, typename Key, typename Element, typename... Args>
  213. using cu_map_t = Map<
  214. Key, Element,
  215. std::conditional_t< (sizeof...(Args)>0) && !is_allocator_v< pack_element_t<0, Args...> >,
  216. pack_element_t<0, Args...>, tbb_hash<Key> >,
  217. std::conditional_t< (sizeof...(Args)>1) && !is_allocator_v< pack_element_t<1, Args...> >,
  218. pack_element_t<1, Args...>, std::equal_to<Key> >,
  219. std::conditional_t< (sizeof...(Args)>0) && is_allocator_v< pack_element_t<sizeof...(Args)-1, Args...> >,
  220. pack_element_t<sizeof...(Args)-1, Args...>, tbb_allocator<std::pair<const Key, Element> > >
  221. >;
  222. }
  223. // Deduction guide for the constructor from two iterators
  224. template<typename I>
  225. concurrent_unordered_map (I, I)
  226. -> internal::cu_map_t<concurrent_unordered_map, internal::iterator_key_t<I>, internal::iterator_mapped_t<I>>;
  227. // Deduction guide for the constructor from two iterators and hasher/equality/allocator
  228. template<typename I, typename... Args>
  229. concurrent_unordered_map(I, I, size_t, Args...)
  230. -> internal::cu_map_t<concurrent_unordered_map, internal::iterator_key_t<I>, internal::iterator_mapped_t<I>, Args...>;
  231. // Deduction guide for the constructor from an initializer_list
  232. template<typename Key, typename Element>
  233. concurrent_unordered_map(std::initializer_list<std::pair<const Key, Element>>)
  234. -> internal::cu_map_t<concurrent_unordered_map, Key, Element>;
  235. // Deduction guide for the constructor from an initializer_list and hasher/equality/allocator
  236. template<typename Key, typename Element, typename... Args>
  237. concurrent_unordered_map(std::initializer_list<std::pair<const Key, Element>>, size_t, Args...)
  238. -> internal::cu_map_t<concurrent_unordered_map, Key, Element, Args...>;
  239. #endif /* __TBB_CPP17_DEDUCTION_GUIDES_PRESENT */
  240. template < typename Key, typename T, typename Hasher = tbb::tbb_hash<Key>, typename Key_equality = std::equal_to<Key>,
  241. typename Allocator = tbb::tbb_allocator<std::pair<const Key, T> > >
  242. class concurrent_unordered_multimap :
  243. public internal::concurrent_unordered_base< concurrent_unordered_map_traits< Key, T,
  244. internal::hash_compare<Key, Hasher, Key_equality>, Allocator, true> >
  245. {
  246. // Base type definitions
  247. typedef internal::hash_compare<Key, Hasher, Key_equality> hash_compare;
  248. typedef concurrent_unordered_map_traits<Key, T, hash_compare, Allocator, true> traits_type;
  249. typedef internal::concurrent_unordered_base<traits_type> base_type;
  250. #if __TBB_EXTRA_DEBUG
  251. public:
  252. #endif
  253. using traits_type::allow_multimapping;
  254. public:
  255. using base_type::insert;
  256. // Type definitions
  257. typedef Key key_type;
  258. typedef typename base_type::value_type value_type;
  259. typedef T mapped_type;
  260. typedef Hasher hasher;
  261. typedef Key_equality key_equal;
  262. typedef hash_compare key_compare;
  263. typedef typename base_type::allocator_type allocator_type;
  264. typedef typename base_type::pointer pointer;
  265. typedef typename base_type::const_pointer const_pointer;
  266. typedef typename base_type::reference reference;
  267. typedef typename base_type::const_reference const_reference;
  268. typedef typename base_type::size_type size_type;
  269. typedef typename base_type::difference_type difference_type;
  270. typedef typename base_type::iterator iterator;
  271. typedef typename base_type::const_iterator const_iterator;
  272. typedef typename base_type::iterator local_iterator;
  273. typedef typename base_type::const_iterator const_local_iterator;
  274. #if __TBB_UNORDERED_NODE_HANDLE_PRESENT
  275. typedef typename base_type::node_type node_type;
  276. #endif //__TBB_UNORDERED_NODE_HANDLE_PRESENT
  277. // Construction/destruction/copying
  278. explicit concurrent_unordered_multimap(size_type n_of_buckets = base_type::initial_bucket_number,
  279. const hasher& a_hasher = hasher(), const key_equal& a_keyeq = key_equal(),
  280. const allocator_type& a = allocator_type())
  281. : base_type(n_of_buckets, key_compare(a_hasher, a_keyeq), a)
  282. {}
  283. concurrent_unordered_multimap(size_type n_of_buckets, const allocator_type& a)
  284. : base_type(n_of_buckets, key_compare(hasher(), key_equal()), a)
  285. {}
  286. concurrent_unordered_multimap(size_type n_of_buckets, const hasher& a_hasher, const allocator_type& a)
  287. : base_type(n_of_buckets, key_compare(a_hasher, key_equal()), a)
  288. {}
  289. explicit concurrent_unordered_multimap(const Allocator& a) : base_type(base_type::initial_bucket_number, key_compare(), a)
  290. {}
  291. template <typename Iterator>
  292. concurrent_unordered_multimap(Iterator first, Iterator last, size_type n_of_buckets = base_type::initial_bucket_number,
  293. const hasher& a_hasher = hasher(), const key_equal& a_keyeq = key_equal(),
  294. const allocator_type& a = allocator_type())
  295. : base_type(n_of_buckets,key_compare(a_hasher,a_keyeq), a)
  296. {
  297. insert(first, last);
  298. }
  299. template <typename Iterator>
  300. concurrent_unordered_multimap(Iterator first, Iterator last, size_type n_of_buckets, const allocator_type& a)
  301. : base_type(n_of_buckets, key_compare(hasher(), key_equal()), a)
  302. {
  303. insert(first, last);
  304. }
  305. template <typename Iterator>
  306. concurrent_unordered_multimap(Iterator first, Iterator last, size_type n_of_buckets, const hasher& a_hasher,
  307. const allocator_type& a)
  308. : base_type(n_of_buckets, key_compare(a_hasher, key_equal()), a)
  309. {
  310. insert(first, last);
  311. }
  312. #if __TBB_INITIALIZER_LISTS_PRESENT
  313. //! Constructor from initializer_list
  314. concurrent_unordered_multimap(std::initializer_list<value_type> il, size_type n_of_buckets = base_type::initial_bucket_number,
  315. const hasher& a_hasher = hasher(), const key_equal& a_keyeq = key_equal(),
  316. const allocator_type& a = allocator_type())
  317. : base_type(n_of_buckets, key_compare(a_hasher, a_keyeq), a)
  318. {
  319. insert(il.begin(),il.end());
  320. }
  321. concurrent_unordered_multimap(std::initializer_list<value_type> il, size_type n_of_buckets, const allocator_type& a)
  322. : base_type(n_of_buckets, key_compare(hasher(), key_equal()), a)
  323. {
  324. insert(il.begin(), il.end());
  325. }
  326. concurrent_unordered_multimap(std::initializer_list<value_type> il, size_type n_of_buckets, const hasher& a_hasher,
  327. const allocator_type& a)
  328. : base_type(n_of_buckets, key_compare(a_hasher, key_equal()), a)
  329. {
  330. insert(il.begin(), il.end());
  331. }
  332. #endif //# __TBB_INITIALIZER_LISTS_PRESENT
  333. #if __TBB_CPP11_RVALUE_REF_PRESENT && !__TBB_IMPLICIT_MOVE_PRESENT
  334. concurrent_unordered_multimap(const concurrent_unordered_multimap& table)
  335. : base_type(table)
  336. {}
  337. concurrent_unordered_multimap& operator=(const concurrent_unordered_multimap& table)
  338. {
  339. return static_cast<concurrent_unordered_multimap&>(base_type::operator=(table));
  340. }
  341. concurrent_unordered_multimap(concurrent_unordered_multimap&& table)
  342. : base_type(std::move(table))
  343. {}
  344. concurrent_unordered_multimap& operator=(concurrent_unordered_multimap&& table)
  345. {
  346. return static_cast<concurrent_unordered_multimap&>(base_type::operator=(std::move(table)));
  347. }
  348. #endif //__TBB_CPP11_RVALUE_REF_PRESENT && !__TBB_IMPLICIT_MOVE_PRESENT
  349. #if __TBB_CPP11_RVALUE_REF_PRESENT
  350. concurrent_unordered_multimap(concurrent_unordered_multimap&& table, const Allocator& a) : base_type(std::move(table), a)
  351. {}
  352. #endif /*__TBB_CPP11_RVALUE_REF_PRESENT*/
  353. #if __TBB_UNORDERED_NODE_HANDLE_PRESENT
  354. template<typename Hash, typename Equality>
  355. void merge(concurrent_unordered_map<Key, T, Hash, Equality, Allocator>& source)
  356. { this->internal_merge(source); }
  357. template<typename Hash, typename Equality>
  358. void merge(concurrent_unordered_map<Key, T, Hash, Equality, Allocator>&& source)
  359. { this->internal_merge(source); }
  360. template<typename Hash, typename Equality>
  361. void merge(concurrent_unordered_multimap<Key, T, Hash, Equality, Allocator>& source)
  362. { this->internal_merge(source); }
  363. template<typename Hash, typename Equality>
  364. void merge(concurrent_unordered_multimap<Key, T, Hash, Equality, Allocator>&& source)
  365. { this->internal_merge(source); }
  366. #endif //__TBB_UNORDERED_NODE_HANDLE_PRESENT
  367. concurrent_unordered_multimap(const concurrent_unordered_multimap& table, const Allocator& a)
  368. : base_type(table, a)
  369. {}
  370. };
  371. #if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
  372. // Deduction guide for the constructor from two iterators
  373. template<typename I>
  374. concurrent_unordered_multimap (I, I)
  375. -> internal::cu_map_t<concurrent_unordered_multimap, internal::iterator_key_t<I>, internal::iterator_mapped_t<I>>;
  376. // Deduction guide for the constructor from two iterators and hasher/equality/allocator
  377. template<typename I, typename... Args>
  378. concurrent_unordered_multimap(I, I, size_t, Args...)
  379. -> internal::cu_map_t<concurrent_unordered_multimap, internal::iterator_key_t<I>, internal::iterator_mapped_t<I>, Args...>;
  380. // Deduction guide for the constructor from an initializer_list
  381. template<typename Key, typename Element>
  382. concurrent_unordered_multimap(std::initializer_list<std::pair<const Key, Element>>)
  383. -> internal::cu_map_t<concurrent_unordered_multimap, Key, Element>;
  384. // Deduction guide for the constructor from an initializer_list and hasher/equality/allocator
  385. template<typename Key, typename Element, typename... Args>
  386. concurrent_unordered_multimap(std::initializer_list<std::pair<const Key, Element>>, size_t, Args...)
  387. -> internal::cu_map_t<concurrent_unordered_multimap, Key, Element, Args...>;
  388. #endif /* __TBB_CPP17_DEDUCTION_GUIDES_PRESENT */
  389. } // namespace interface5
  390. using interface5::concurrent_unordered_map;
  391. using interface5::concurrent_unordered_multimap;
  392. } // namespace tbb
  393. #include "internal/_warning_suppress_disable_notice.h"
  394. #undef __TBB_concurrent_unordered_map_H_include_area
  395. #endif// __TBB_concurrent_unordered_map_H