Warning, file /include/oneapi/tbb/concurrent_unordered_map.h was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #ifndef __TBB_concurrent_unordered_map_H
0018 #define __TBB_concurrent_unordered_map_H
0019
0020 #include "detail/_namespace_injection.h"
0021 #include "detail/_concurrent_unordered_base.h"
0022 #include "tbb_allocator.h"
0023 #include <functional>
0024
0025 namespace tbb {
0026 namespace detail {
0027 namespace d1 {
0028
0029 template <typename Key, typename T, typename Hash, typename KeyEqual, typename Allocator, bool AllowMultimapping>
0030 struct concurrent_unordered_map_traits {
0031 using value_type = std::pair<const Key, T>;
0032 using key_type = Key;
0033 using allocator_type = Allocator;
0034 using hash_compare_type = hash_compare<Key, Hash, KeyEqual>;
0035 static constexpr bool allow_multimapping = AllowMultimapping;
0036
0037 static constexpr const key_type& get_key( const value_type& value ) {
0038 return value.first;
0039 }
0040 };
0041
0042 template <typename Key, typename T, typename Hash, typename KeyEqual, typename Allocator>
0043 class concurrent_unordered_multimap;
0044
0045 template <typename Key, typename T, typename Hash = std::hash<Key>, typename KeyEqual = std::equal_to<Key>,
0046 typename Allocator = tbb::tbb_allocator<std::pair<const Key, T>> >
0047 class concurrent_unordered_map
0048 : public concurrent_unordered_base<concurrent_unordered_map_traits<Key, T, Hash, KeyEqual, Allocator, false>>
0049 {
0050 using traits_type = concurrent_unordered_map_traits<Key, T, Hash, KeyEqual, Allocator, false>;
0051 using base_type = concurrent_unordered_base<traits_type>;
0052 public:
0053 using key_type = typename base_type::key_type;
0054 using mapped_type = T;
0055 using value_type = typename base_type::value_type;
0056 using size_type = typename base_type::size_type;
0057 using difference_type = typename base_type::difference_type;
0058 using hasher = typename base_type::hasher;
0059 using key_equal = typename base_type::key_equal;
0060 using allocator_type = typename base_type::allocator_type;
0061 using reference = typename base_type::reference;
0062 using const_reference = typename base_type::const_reference;
0063 using pointer = typename base_type::pointer;
0064 using const_pointer = typename base_type::const_pointer;
0065 using iterator = typename base_type::iterator;
0066 using const_iterator = typename base_type::const_iterator;
0067 using local_iterator = typename base_type::local_iterator;
0068 using const_local_iterator = typename base_type::const_local_iterator;
0069 using node_type = typename base_type::node_type;
0070
0071
0072 using base_type::base_type;
0073
0074
0075 concurrent_unordered_map() = default;
0076 concurrent_unordered_map( const concurrent_unordered_map& ) = default;
0077 concurrent_unordered_map( const concurrent_unordered_map& other, const allocator_type& alloc ) : base_type(other, alloc) {}
0078 concurrent_unordered_map( concurrent_unordered_map&& ) = default;
0079 concurrent_unordered_map( concurrent_unordered_map&& other, const allocator_type& alloc ) : base_type(std::move(other), alloc) {}
0080
0081 concurrent_unordered_map& operator=( const concurrent_unordered_map& ) = default;
0082 concurrent_unordered_map& operator=( concurrent_unordered_map&& ) = default;
0083
0084 concurrent_unordered_map& operator=( std::initializer_list<value_type> il ) {
0085 base_type::operator= (il);
0086 return *this;
0087 }
0088
0089
0090 mapped_type& operator[]( const key_type& key ) {
0091 iterator where = this->find(key);
0092
0093 if (where == this->end()) {
0094 where = this->emplace(std::piecewise_construct, std::forward_as_tuple(key), std::tuple<>()).first;
0095 }
0096 return where->second;
0097 }
0098
0099 mapped_type& operator[]( key_type&& key ) {
0100 iterator where = this->find(key);
0101
0102 if (where == this->end()) {
0103 where = this->emplace(std::piecewise_construct, std::forward_as_tuple(std::move(key)), std::tuple<>()).first;
0104 }
0105 return where->second;
0106 }
0107
0108 mapped_type& at( const key_type& key ) {
0109 iterator where = this->find(key);
0110
0111 if (where == this->end()) {
0112 throw_exception(exception_id::invalid_key);
0113 }
0114 return where->second;
0115 }
0116
0117 const mapped_type& at( const key_type& key ) const {
0118 const_iterator where = this->find(key);
0119
0120 if (where == this->end()) {
0121 throw_exception(exception_id::out_of_range);
0122 }
0123 return where->second;
0124 }
0125
0126 using base_type::insert;
0127
0128 template<typename P>
0129 typename std::enable_if<std::is_constructible<value_type, P&&>::value,
0130 std::pair<iterator, bool>>::type insert( P&& value ) {
0131 return this->emplace(std::forward<P>(value));
0132 }
0133
0134 template<typename P>
0135 typename std::enable_if<std::is_constructible<value_type, P&&>::value,
0136 iterator>::type insert( const_iterator hint, P&& value ) {
0137 return this->emplace_hint(hint, std::forward<P>(value));
0138 }
0139
0140 template <typename OtherHash, typename OtherKeyEqual>
0141 void merge( concurrent_unordered_map<key_type, mapped_type, OtherHash, OtherKeyEqual, allocator_type>& source ) {
0142 this->internal_merge(source);
0143 }
0144
0145 template <typename OtherHash, typename OtherKeyEqual>
0146 void merge( concurrent_unordered_map<key_type, mapped_type, OtherHash, OtherKeyEqual, allocator_type>&& source ) {
0147 this->internal_merge(std::move(source));
0148 }
0149
0150 template <typename OtherHash, typename OtherKeyEqual>
0151 void merge( concurrent_unordered_multimap<key_type, mapped_type, OtherHash, OtherKeyEqual, allocator_type>& source ) {
0152 this->internal_merge(source);
0153 }
0154
0155 template <typename OtherHash, typename OtherKeyEqual>
0156 void merge( concurrent_unordered_multimap<key_type, mapped_type, OtherHash, OtherKeyEqual, allocator_type>&& source ) {
0157 this->internal_merge(std::move(source));
0158 }
0159 };
0160
0161 #if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
0162 template <typename It,
0163 typename Hash = std::hash<iterator_key_t<It>>,
0164 typename KeyEq = std::equal_to<iterator_key_t<It>>,
0165 typename Alloc = tbb::tbb_allocator<iterator_alloc_pair_t<It>>,
0166 typename = std::enable_if_t<is_input_iterator_v<It>>,
0167 typename = std::enable_if_t<is_allocator_v<Alloc>>,
0168 typename = std::enable_if_t<!is_allocator_v<Hash>>,
0169 typename = std::enable_if_t<!is_allocator_v<KeyEq>>,
0170 typename = std::enable_if_t<!std::is_integral_v<Hash>>>
0171 concurrent_unordered_map( It, It, std::size_t = {},
0172 Hash = Hash(), KeyEq = KeyEq(), Alloc = Alloc() )
0173 -> concurrent_unordered_map<iterator_key_t<It>, iterator_mapped_t<It>, Hash, KeyEq, Alloc>;
0174
0175 template <typename Key, typename T,
0176 typename Hash = std::hash<std::remove_const_t<Key>>,
0177 typename KeyEq = std::equal_to<std::remove_const_t<Key>>,
0178 typename Alloc = tbb::tbb_allocator<std::pair<const Key, T>>,
0179 typename = std::enable_if_t<is_allocator_v<Alloc>>,
0180 typename = std::enable_if_t<!is_allocator_v<Hash>>,
0181 typename = std::enable_if_t<!is_allocator_v<KeyEq>>,
0182 typename = std::enable_if_t<!std::is_integral_v<Hash>>>
0183 concurrent_unordered_map( std::initializer_list<std::pair<Key, T>>, std::size_t = {},
0184 Hash = Hash(), KeyEq = KeyEq(), Alloc = Alloc() )
0185 -> concurrent_unordered_map<std::remove_const_t<Key>, T, Hash, KeyEq, Alloc>;
0186
0187 template <typename It, typename Alloc,
0188 typename = std::enable_if_t<is_input_iterator_v<It>>,
0189 typename = std::enable_if_t<is_allocator_v<Alloc>>>
0190 concurrent_unordered_map( It, It, std::size_t, Alloc )
0191 -> concurrent_unordered_map<iterator_key_t<It>, iterator_mapped_t<It>,
0192 std::hash<iterator_key_t<It>>,
0193 std::equal_to<iterator_key_t<It>>, Alloc>;
0194
0195
0196
0197 template <typename It, typename Hash, typename Alloc,
0198 typename = std::enable_if_t<is_input_iterator_v<It>>,
0199 typename = std::enable_if_t<is_allocator_v<Alloc>>,
0200 typename = std::enable_if_t<!is_allocator_v<Hash>>,
0201 typename = std::enable_if_t<!std::is_integral_v<Hash>>>
0202 concurrent_unordered_map( It, It, std::size_t, Hash, Alloc )
0203 -> concurrent_unordered_map<iterator_key_t<It>, iterator_mapped_t<It>,
0204 Hash, std::equal_to<iterator_key_t<It>>, Alloc>;
0205
0206 template <typename Key, typename T, typename Alloc,
0207 typename = std::enable_if_t<is_allocator_v<Alloc>>>
0208 concurrent_unordered_map( std::initializer_list<std::pair<Key, T>>, std::size_t, Alloc )
0209 -> concurrent_unordered_map<std::remove_const_t<Key>, T, std::hash<std::remove_const_t<Key>>,
0210 std::equal_to<std::remove_const_t<Key>>, Alloc>;
0211
0212 template <typename Key, typename T, typename Alloc,
0213 typename = std::enable_if_t<is_allocator_v<Alloc>>>
0214 concurrent_unordered_map( std::initializer_list<std::pair<Key, T>>, Alloc )
0215 -> concurrent_unordered_map<std::remove_const_t<Key>, T, std::hash<std::remove_const_t<Key>>,
0216 std::equal_to<std::remove_const_t<Key>>, Alloc>;
0217
0218 template <typename Key, typename T, typename Hash, typename Alloc,
0219 typename = std::enable_if_t<is_allocator_v<Alloc>>,
0220 typename = std::enable_if_t<!is_allocator_v<Hash>>,
0221 typename = std::enable_if_t<!std::is_integral_v<Hash>>>
0222 concurrent_unordered_map( std::initializer_list<std::pair<Key, T>>, std::size_t, Hash, Alloc )
0223 -> concurrent_unordered_map<std::remove_const_t<Key>, T, Hash,
0224 std::equal_to<std::remove_const_t<Key>>, Alloc>;
0225
0226 #if __APPLE__ && __TBB_CLANG_VERSION == 100000
0227
0228
0229
0230
0231 template <typename Key, typename T, typename Hash, typename KeyEq, typename Alloc>
0232 concurrent_unordered_map( concurrent_unordered_map<Key, T, Hash, KeyEq, Alloc>, Alloc )
0233 -> concurrent_unordered_map<Key, T, Hash, KeyEq, Alloc>;
0234 #endif
0235
0236 #endif
0237
0238 template <typename Key, typename T, typename Hash, typename KeyEqual, typename Allocator>
0239 void swap( concurrent_unordered_map<Key, T, Hash, KeyEqual, Allocator>& lhs,
0240 concurrent_unordered_map<Key, T, Hash, KeyEqual, Allocator>& rhs ) {
0241 lhs.swap(rhs);
0242 }
0243
0244 template <typename Key, typename T, typename Hash = std::hash<Key>, typename KeyEqual = std::equal_to<Key>,
0245 typename Allocator = tbb::tbb_allocator<std::pair<const Key, T>> >
0246 class concurrent_unordered_multimap
0247 : public concurrent_unordered_base<concurrent_unordered_map_traits<Key, T, Hash, KeyEqual, Allocator, true>>
0248 {
0249 using traits_type = concurrent_unordered_map_traits<Key, T, Hash, KeyEqual, Allocator, true>;
0250 using base_type = concurrent_unordered_base<traits_type>;
0251 public:
0252 using key_type = typename base_type::key_type;
0253 using mapped_type = T;
0254 using value_type = typename base_type::value_type;
0255 using size_type = typename base_type::size_type;
0256 using difference_type = typename base_type::difference_type;
0257 using hasher = typename base_type::hasher;
0258 using key_equal = typename base_type::key_equal;
0259 using allocator_type = typename base_type::allocator_type;
0260 using reference = typename base_type::reference;
0261 using const_reference = typename base_type::const_reference;
0262 using pointer = typename base_type::pointer;
0263 using const_pointer = typename base_type::const_pointer;
0264 using iterator = typename base_type::iterator;
0265 using const_iterator = typename base_type::const_iterator;
0266 using local_iterator = typename base_type::local_iterator;
0267 using const_local_iterator = typename base_type::const_local_iterator;
0268 using node_type = typename base_type::node_type;
0269
0270
0271 using base_type::base_type;
0272 using base_type::insert;
0273
0274
0275 concurrent_unordered_multimap() = default;
0276 concurrent_unordered_multimap( const concurrent_unordered_multimap& ) = default;
0277 concurrent_unordered_multimap( const concurrent_unordered_multimap& other, const allocator_type& alloc ) : base_type(other, alloc) {}
0278 concurrent_unordered_multimap( concurrent_unordered_multimap&& ) = default;
0279 concurrent_unordered_multimap( concurrent_unordered_multimap&& other, const allocator_type& alloc ) : base_type(std::move(other), alloc) {}
0280
0281 concurrent_unordered_multimap& operator=( const concurrent_unordered_multimap& ) = default;
0282 concurrent_unordered_multimap& operator=( concurrent_unordered_multimap&& ) = default;
0283
0284 concurrent_unordered_multimap& operator=( std::initializer_list<value_type> il ) {
0285 base_type::operator= (il);
0286 return *this;
0287 }
0288
0289 template <typename P>
0290 typename std::enable_if<std::is_constructible<value_type, P&&>::value,
0291 std::pair<iterator, bool>>::type insert( P&& value ) {
0292 return this->emplace(std::forward<P>(value));
0293 }
0294
0295 template<typename P>
0296 typename std::enable_if<std::is_constructible<value_type, P&&>::value,
0297 iterator>::type insert( const_iterator hint, P&& value ) {
0298 return this->emplace_hint(hint, std::forward<P&&>(value));
0299 }
0300
0301 template <typename OtherHash, typename OtherKeyEqual>
0302 void merge( concurrent_unordered_map<key_type, mapped_type, OtherHash, OtherKeyEqual, allocator_type>& source ) {
0303 this->internal_merge(source);
0304 }
0305
0306 template <typename OtherHash, typename OtherKeyEqual>
0307 void merge( concurrent_unordered_map<key_type, mapped_type, OtherHash, OtherKeyEqual, allocator_type>&& source ) {
0308 this->internal_merge(std::move(source));
0309 }
0310
0311 template <typename OtherHash, typename OtherKeyEqual>
0312 void merge( concurrent_unordered_multimap<key_type, mapped_type, OtherHash, OtherKeyEqual, allocator_type>& source ) {
0313 this->internal_merge(source);
0314 }
0315
0316 template <typename OtherHash, typename OtherKeyEqual>
0317 void merge( concurrent_unordered_multimap<key_type, mapped_type, OtherHash, OtherKeyEqual, allocator_type>&& source ) {
0318 this->internal_merge(std::move(source));
0319 }
0320 };
0321
0322 #if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
0323
0324 template <typename It,
0325 typename Hash = std::hash<iterator_key_t<It>>,
0326 typename KeyEq = std::equal_to<iterator_key_t<It>>,
0327 typename Alloc = tbb::tbb_allocator<iterator_alloc_pair_t<It>>,
0328 typename = std::enable_if_t<is_input_iterator_v<It>>,
0329 typename = std::enable_if_t<is_allocator_v<Alloc>>,
0330 typename = std::enable_if_t<!is_allocator_v<Hash>>,
0331 typename = std::enable_if_t<!is_allocator_v<KeyEq>>,
0332 typename = std::enable_if_t<!std::is_integral_v<Hash>>>
0333 concurrent_unordered_multimap( It, It, std::size_t = {}, Hash = Hash(), KeyEq = KeyEq(), Alloc = Alloc() )
0334 -> concurrent_unordered_multimap<iterator_key_t<It>, iterator_mapped_t<It>, Hash, KeyEq, Alloc>;
0335
0336 template <typename Key, typename T,
0337 typename Hash = std::hash<std::remove_const_t<Key>>,
0338 typename KeyEq = std::equal_to<std::remove_const_t<Key>>,
0339 typename Alloc = tbb::tbb_allocator<std::pair<const Key, T>>,
0340 typename = std::enable_if_t<is_allocator_v<Alloc>>,
0341 typename = std::enable_if_t<!is_allocator_v<Hash>>,
0342 typename = std::enable_if_t<!is_allocator_v<KeyEq>>,
0343 typename = std::enable_if_t<!std::is_integral_v<Hash>>>
0344 concurrent_unordered_multimap( std::initializer_list<std::pair<Key, T>>, std::size_t = {},
0345 Hash = Hash(), KeyEq = KeyEq(), Alloc = Alloc() )
0346 -> concurrent_unordered_multimap<std::remove_const_t<Key>, T, Hash, KeyEq, Alloc>;
0347
0348 template <typename It, typename Alloc,
0349 typename = std::enable_if_t<is_input_iterator_v<It>>,
0350 typename = std::enable_if_t<is_allocator_v<Alloc>>>
0351 concurrent_unordered_multimap( It, It, std::size_t, Alloc )
0352 -> concurrent_unordered_multimap<iterator_key_t<It>, iterator_mapped_t<It>,
0353 std::hash<iterator_key_t<It>>,
0354 std::equal_to<iterator_key_t<It>>, Alloc>;
0355
0356 template <typename It, typename Hash, typename Alloc,
0357 typename = std::enable_if_t<is_input_iterator_v<It>>,
0358 typename = std::enable_if_t<is_allocator_v<Alloc>>,
0359 typename = std::enable_if_t<!is_allocator_v<Hash>>,
0360 typename = std::enable_if_t<!std::is_integral_v<Hash>>>
0361 concurrent_unordered_multimap( It, It, std::size_t, Hash, Alloc )
0362 -> concurrent_unordered_multimap<iterator_key_t<It>, iterator_mapped_t<It>, Hash,
0363 std::equal_to<iterator_key_t<It>>, Alloc>;
0364
0365 template <typename Key, typename T, typename Alloc,
0366 typename = std::enable_if_t<is_allocator_v<Alloc>>>
0367 concurrent_unordered_multimap( std::initializer_list<std::pair<Key, T>>, std::size_t, Alloc )
0368 -> concurrent_unordered_multimap<std::remove_const_t<Key>, T, std::hash<std::remove_const_t<Key>>,
0369 std::equal_to<std::remove_const_t<Key>>, Alloc>;
0370
0371 template <typename Key, typename T, typename Alloc,
0372 typename = std::enable_if_t<is_allocator_v<Alloc>>>
0373 concurrent_unordered_multimap( std::initializer_list<std::pair<Key, T>>, Alloc )
0374 -> concurrent_unordered_multimap<std::remove_const_t<Key>, T, std::hash<std::remove_const_t<Key>>,
0375 std::equal_to<std::remove_const_t<Key>>, Alloc>;
0376
0377 template <typename Key, typename T, typename Hash, typename Alloc,
0378 typename = std::enable_if_t<is_allocator_v<Alloc>>,
0379 typename = std::enable_if_t<!is_allocator_v<Hash>>,
0380 typename = std::enable_if_t<!std::is_integral_v<Hash>>>
0381 concurrent_unordered_multimap( std::initializer_list<std::pair<Key, T>>, std::size_t, Hash, Alloc )
0382 -> concurrent_unordered_multimap<std::remove_const_t<Key>, T, Hash,
0383 std::equal_to<std::remove_const_t<Key>>, Alloc>;
0384
0385 #if __APPLE__ && __TBB_CLANG_VERSION == 100000
0386
0387
0388
0389
0390 template <typename Key, typename T, typename Hash, typename KeyEq, typename Alloc>
0391 concurrent_unordered_multimap( concurrent_unordered_multimap<Key, T, Hash, KeyEq, Alloc>, Alloc )
0392 -> concurrent_unordered_multimap<Key, T, Hash, KeyEq, Alloc>;
0393 #endif
0394 #endif
0395
0396 template <typename Key, typename T, typename Hash, typename KeyEqual, typename Allocator>
0397 void swap( concurrent_unordered_multimap<Key, T, Hash, KeyEqual, Allocator>& lhs,
0398 concurrent_unordered_multimap<Key, T, Hash, KeyEqual, Allocator>& rhs ) {
0399 lhs.swap(rhs);
0400 }
0401
0402 }
0403 }
0404
0405 inline namespace v1 {
0406
0407 using detail::d1::concurrent_unordered_map;
0408 using detail::d1::concurrent_unordered_multimap;
0409 using detail::split;
0410
0411 }
0412 }
0413
0414 #endif