Back to home page

EIC code displayed by LXR

 
 

    


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     Copyright (c) 2005-2022 Intel Corporation
0003 
0004     Licensed under the Apache License, Version 2.0 (the "License");
0005     you may not use this file except in compliance with the License.
0006     You may obtain a copy of the License at
0007 
0008         http://www.apache.org/licenses/LICENSE-2.0
0009 
0010     Unless required by applicable law or agreed to in writing, software
0011     distributed under the License is distributed on an "AS IS" BASIS,
0012     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013     See the License for the specific language governing permissions and
0014     limitations under the License.
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 }; // struct concurrent_unordered_map_traits
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     // Include constructors of base type
0072     using base_type::base_type;
0073 
0074     // Required for implicit deduction guides
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     // Required to respect the rule of 5
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     // Observers
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 }; // class concurrent_unordered_map
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 // TODO: investigate if a deduction guide for concurrent_unordered_map(It, It, Alloc) is needed
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 // An explicit deduction guide is required for copy/move constructor with allocator for APPLE LLVM 10.0.0
0228 // due to an issue with generating an implicit deduction guide for these constructors under several strange surcumstances.
0229 // Currently the issue takes place because the last template parameter for Traits is boolean, it should not affect the deduction guides
0230 // The issue reproduces only on this version of the compiler
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 // __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
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     // Include constructors of base type
0271     using base_type::base_type;
0272     using base_type::insert;
0273 
0274     // Required for implicit deduction guides
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     // Required to respect the rule of 5
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 }; // class concurrent_unordered_multimap
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 // An explicit deduction guide is required for copy/move constructor with allocator for APPLE LLVM 10.0.0
0387 // due to an issue with generating an implicit deduction guide for these constructors under several strange surcumstances.
0388 // Currently the issue takes place because the last template parameter for Traits is boolean, it should not affect the deduction guides
0389 // The issue reproduces only on this version of the compiler
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 // __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
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 } // namespace d1
0403 } // namespace detail
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 } // inline namespace v1
0412 } // namespace tbb
0413 
0414 #endif // __TBB_concurrent_unordered_map_H