24 #ifndef __TBB__concurrent_unordered_impl_H 25 #define __TBB__concurrent_unordered_impl_H 26 #if !defined(__TBB_concurrent_unordered_map_H) && !defined(__TBB_concurrent_unordered_set_H) && !defined(__TBB_concurrent_hash_map_H) 27 #error Do not #include this internal file directly; use public TBB headers instead. 30 #include "../tbb_stddef.h" 37 #include __TBB_STD_SWAP_HEADER 39 #include "../atomic.h" 40 #include "../tbb_exception.h" 41 #include "../tbb_allocator.h" 43 #if __TBB_INITIALIZER_LISTS_PRESENT 44 #include <initializer_list> 51 namespace interface5 {
55 template <
typename T,
typename Allocator>
57 template <
typename Traits>
61 template<
class Solist,
typename Value>
62 class flist_iterator :
public std::iterator<std::forward_iterator_tag, Value>
64 template <
typename T,
typename Allocator>
66 template <
typename Traits>
68 template<
class M,
typename V>
102 template<
typename M,
typename T,
typename U>
104 template<
typename M,
typename T,
typename U>
108 template<
typename Solist,
typename T,
typename U>
112 template<
typename Solist,
typename T,
typename U>
118 template<
class Solist,
typename Value>
123 using base_type::get_node_ptr;
124 template <
typename T,
typename Allocator>
126 template<
class M,
typename V>
128 template<
typename M,
typename T,
typename U>
130 template<
typename M,
typename T,
typename U>
134 solist_iterator(nodeptr_t pnode,
const Solist *plist) : base_type(pnode), my_list_ptr(plist) {}
144 : base_type(other), my_list_ptr(other.my_list_ptr) {}
147 return this->base_type::operator*();
155 do ++(*(base_type *)
this);
170 template<
typename Solist,
typename T,
typename U>
174 template<
typename Solist,
typename T,
typename U>
184 template <
typename T,
typename Allocator>
218 my_order_key = order_key;
233 if (exchange_node == current_node)
241 return exchange_node;
248 return (my_order_key & 0x1) == 0;
259 nodeptr_t pnode = my_node_allocator.allocate(1);
260 pnode->init(order_key);
265 template<
typename Arg>
268 nodeptr_t pnode = my_node_allocator.allocate(1);
272 new(
static_cast<void*
>(&pnode->my_element)) T(tbb::internal::forward<Arg>(t));
273 pnode->init(order_key);
275 my_node_allocator.deallocate(pnode, 1);
283 template<
typename Arg>
286 __TBB_ASSERT(
false,
"This compile-time helper should never get called");
291 template<
typename __TBB_PARAMETER_PACK Args>
293 nodeptr_t pnode = my_node_allocator.allocate(1);
297 new(
static_cast<void*
>(&pnode->my_element)) T(
__TBB_PACK_EXPANSION(tbb::internal::forward<Args>(args)));
299 my_node_allocator.deallocate(pnode, 1);
307 : my_node_allocator(a), my_element_count(0)
311 my_head = create_node(
sokey_t(0));
320 nodeptr_t pnode = my_head;
323 __TBB_ASSERT(pnode != NULL && pnode->my_next == NULL,
"Invalid head list node");
331 return (my_node_allocator);
336 nodeptr_t pnode = my_head;
338 __TBB_ASSERT(my_head != NULL,
"Invalid head list node");
339 pnext = pnode->my_next;
340 pnode->my_next = NULL;
343 while (pnode != NULL)
345 pnext = pnode->my_next;
350 my_element_count = 0;
355 return first_real_iterator(raw_begin());
360 return first_real_iterator(raw_begin());
364 return (iterator(0,
this));
367 const_iterator
end()
const {
368 return (const_iterator(0,
this));
372 return (((
const self_type *)
this)->
begin());
376 return (((
const self_type *)
this)->
end());
381 return (my_element_count == 0);
386 return my_element_count;
391 return my_node_allocator.max_size();
411 return raw_iterator(my_head);
416 return raw_const_iterator(my_head);
420 return raw_iterator(0);
424 return raw_const_iterator(0);
465 while (it != raw_end() && it.
get_node_ptr()->is_dummy())
476 while (it != raw_end() && it.
get_node_ptr()->is_dummy())
484 if (!pnode->is_dummy()) my_node_allocator.destroy(pnode);
485 my_node_allocator.deallocate(pnode, 1);
490 static nodeptr_t
try_insert_atomic(nodeptr_t previous, nodeptr_t new_node, nodeptr_t current_node) {
491 new_node->my_next = current_node;
492 return previous->atomic_set_next(new_node, current_node);
496 std::pair<iterator, bool>
try_insert(raw_iterator it, raw_iterator next, nodeptr_t pnode, size_type *new_count)
500 if (inserted_node == pnode)
503 check_range(it, next);
505 return std::pair<iterator, bool>(iterator(pnode,
this),
true);
509 return std::pair<iterator, bool>(
end(),
false);
516 raw_iterator
last = raw_end();
517 raw_iterator where = it;
524 nodeptr_t dummy_node = create_node(order_key);
532 if (where == last || get_order_key(where) > order_key)
534 __TBB_ASSERT(get_order_key(it) < order_key,
"Invalid node order in the list");
539 if (inserted_node == dummy_node)
542 check_range(it, where);
543 return raw_iterator(dummy_node);
557 else if (get_order_key(where) == order_key)
560 destroy_node(dummy_node);
572 void erase_node(raw_iterator previous, raw_const_iterator& where)
576 __TBB_ASSERT(prevnode->my_next == pnode,
"Erase must take consecutive iterators");
577 prevnode->my_next = pnode->my_next;
583 iterator
erase_node(raw_iterator previous, const_iterator where)
585 raw_const_iterator it = where;
586 erase_node(previous, it);
589 return get_iterator(first_real_iterator(it));
601 nodeptr_t previous_node = my_head;
602 raw_const_iterator begin_iterator = first++;
605 for (raw_const_iterator it = first; it !=
last;)
609 nodeptr_t dummy_node = pnode->is_dummy() ? create_node(pnode->get_order_key()) : create_node(pnode->get_order_key(), pnode->my_element);
610 previous_node = try_insert_atomic(previous_node, dummy_node, NULL);
611 __TBB_ASSERT(previous_node != NULL,
"Insertion must succeed");
612 raw_const_iterator where = it++;
613 source.
erase_node(get_iterator(begin_iterator), where);
621 template <
typename Traits>
628 for (raw_iterator it = first; it !=
last; ++it)
630 raw_iterator next = it;
633 __TBB_ASSERT(next == raw_end() || get_order_key(next) >= get_order_key(it),
"!!! List order inconsistency !!!");
642 check_range( raw_begin(), raw_end() );
651 #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) 652 #pragma warning(push) 653 #pragma warning(disable: 4127) // warning C4127: conditional expression is constant 656 template <
typename Traits>
686 using Traits::my_hash_compare;
687 using Traits::get_key;
688 using Traits::allow_multimapping;
690 static const size_type initial_bucket_number = 8;
693 typedef std::pair<const_iterator, const_iterator>
paircc_t;
695 static size_type
const pointers_per_table =
sizeof(size_type) * 8;
696 static const size_type initial_bucket_load = 4;
711 const hash_compare& hc = hash_compare(),
const allocator_type& a = allocator_type())
712 : Traits(hc), my_solist(a),
713 my_allocator(a), my_maximum_bucket_size((float) initial_bucket_load)
715 if( n_of_buckets == 0) ++n_of_buckets;
716 my_number_of_buckets = size_type(1)<<
__TBB_Log2((uintptr_t)n_of_buckets*2-1);
721 : Traits(right.my_hash_compare), my_solist(a), my_allocator(a)
724 internal_copy(right);
728 : Traits(right.my_hash_compare), my_solist(right.get_allocator()), my_allocator(right.get_allocator())
732 internal_copy(right);
735 #if __TBB_CPP11_RVALUE_REF_PRESENT 737 : Traits(right.my_hash_compare), my_solist(right.get_allocator()), my_allocator(right.get_allocator()),
738 my_maximum_bucket_size(float(initial_bucket_load))
740 my_number_of_buckets = initial_bucket_number;
746 : Traits(right.my_hash_compare), my_solist(a), my_allocator(a)
748 call_internal_clear_on_exit clear_buckets_on_exception(
this);
751 if (a == right.get_allocator()){
752 my_number_of_buckets = initial_bucket_number;
753 my_maximum_bucket_size = float(initial_bucket_load);
756 my_maximum_bucket_size = right.my_maximum_bucket_size;
757 my_number_of_buckets = right.my_number_of_buckets;
758 my_solist.my_element_count = right.my_solist.my_element_count;
760 if (! right.my_solist.empty()){
761 nodeptr_t previous_node = my_solist.my_head;
764 for (raw_const_iterator it = ++(right.my_solist.raw_begin()),
last = right.my_solist.raw_end(); it !=
last; ++it)
766 const nodeptr_t pnode = it.get_node_ptr();
768 if (pnode->is_dummy()) {
769 node = my_solist.create_node(pnode->get_order_key());
770 size_type bucket =
__TBB_ReverseBits(pnode->get_order_key()) % my_number_of_buckets;
771 set_bucket(bucket, node);
773 node = my_solist.create_node(pnode->get_order_key(),
std::move(pnode->my_element));
776 previous_node = my_solist.try_insert_atomic(previous_node, node, NULL);
777 __TBB_ASSERT(previous_node != NULL,
"Insertion of node failed. Concurrent inserts in constructor ?");
779 my_solist.check_range();
783 clear_buckets_on_exception.dismiss();
786 #endif // __TBB_CPP11_RVALUE_REF_PRESENT 790 internal_copy(right);
794 #if __TBB_CPP11_RVALUE_REF_PRESENT 805 swap(this->my_solist.my_node_allocator, other.my_solist.my_node_allocator);
806 swap(this->my_allocator, other.my_allocator);
810 this->
swap(moved_copy);
816 #endif // __TBB_CPP11_RVALUE_REF_PRESENT 818 #if __TBB_INITIALIZER_LISTS_PRESENT 823 this->insert(il.begin(),il.end());
826 #endif // __TBB_INITIALIZER_LISTS_PRESENT 836 return my_solist.get_allocator();
841 return my_solist.empty();
845 return my_solist.size();
849 return my_solist.max_size();
854 return my_solist.begin();
858 return my_solist.begin();
862 return my_solist.end();
865 const_iterator
end()
const {
866 return my_solist.end();
870 return my_solist.cbegin();
874 return my_solist.cend();
892 bool empty()
const {
return my_begin_node == my_end_node;}
896 return my_midpoint_node != my_end_node;
900 my_table(r.my_table), my_end_node(r.my_end_node)
903 __TBB_ASSERT( !empty(),
"Splitting despite the range is not divisible" );
910 my_table(a_table), my_begin_node(a_table.my_solist.
begin()),
911 my_end_node(a_table.my_solist.
end())
922 if( my_begin_node == my_end_node )
923 my_midpoint_node = my_end_node;
925 sokey_t begin_key = solist_t::get_safe_order_key(my_begin_node);
926 sokey_t end_key = solist_t::get_safe_order_key(my_end_node);
935 my_midpoint_node = my_end_node;
939 sokey_t mid_key = solist_t::get_safe_order_key(my_midpoint_node);
940 __TBB_ASSERT( begin_key < mid_key,
"my_begin_node is after my_midpoint_node" );
941 __TBB_ASSERT( mid_key <= end_key,
"my_midpoint_node is after my_end_node" );
943 #endif // TBB_USE_ASSERT 961 return range_type( *
this );
965 return const_range_type( *
this );
975 return insert(value).first;
978 #if __TBB_CPP11_RVALUE_REF_PRESENT 988 #if __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT 989 template<
typename... Args>
990 std::pair<iterator, bool>
emplace(Args&&... args) {
991 nodeptr_t pnode = my_solist.create_node_v(tbb::internal::forward<Args>(args)...);
992 const sokey_t hashed_element_key = (
sokey_t) my_hash_compare(get_key(pnode->my_element));
993 const sokey_t order_key = split_order_key_regular(hashed_element_key);
994 pnode->init(order_key);
999 template<
typename... Args>
1002 return emplace(tbb::internal::forward<Args>(args)...).first;
1005 #endif // __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT 1006 #endif // __TBB_CPP11_RVALUE_REF_PRESENT 1008 template<
class Iterator>
1010 for (Iterator it = first; it !=
last; ++it)
1014 #if __TBB_INITIALIZER_LISTS_PRESENT 1015 void insert(std::initializer_list<value_type> il) {
1017 insert(il.begin(), il.end());
1022 return internal_erase(where);
1026 while (first != last)
1027 unsafe_erase(first++);
1028 return my_solist.get_iterator(first);
1032 pairii_t where = equal_range(key);
1033 size_type item_count = internal_distance(where.first, where.second);
1034 unsafe_erase(where.first, where.second);
1039 if (
this != &right) {
1040 std::swap(my_hash_compare, right.my_hash_compare);
1042 internal_swap_buckets(right);
1050 return my_hash_compare.my_hash_object;
1054 return my_hash_compare.my_key_compare_object;
1066 raw_iterator dummy_node = my_solist.raw_begin();
1067 set_bucket(0, dummy_node);
1072 return internal_find(key);
1076 return const_cast<self_type*
>(
this)->internal_find(key);
1080 if(allow_multimapping) {
1081 paircc_t answer = equal_range(key);
1082 size_type item_count = internal_distance(answer.first, answer.second);
1085 return const_cast<self_type*
>(
this)->internal_find(key) ==
end()?0:1;
1090 return internal_equal_range(key);
1094 return const_cast<self_type*
>(
this)->internal_equal_range(key);
1099 return my_number_of_buckets;
1103 return segment_size(pointers_per_table-1);
1107 size_type item_count = 0;
1108 if (is_initialized(bucket)) {
1109 raw_iterator it = get_bucket(bucket);
1111 for (; it != my_solist.raw_end() && !it.
get_node_ptr()->is_dummy(); ++it)
1118 sokey_t order_key = (
sokey_t) my_hash_compare(key);
1119 size_type bucket = order_key % my_number_of_buckets;
1125 if (!is_initialized(bucket))
1128 raw_iterator it = get_bucket(bucket);
1129 return my_solist.first_real_iterator(it);
1135 if (!is_initialized(bucket))
1138 raw_const_iterator it = get_bucket(bucket);
1139 return my_solist.first_real_iterator(it);
1146 if (!is_initialized(bucket))
1149 raw_iterator it = get_bucket(bucket);
1153 while(it != my_solist.raw_end() && !it.
get_node_ptr()->is_dummy());
1156 return my_solist.first_real_iterator(it);
1163 if (!is_initialized(bucket))
1166 raw_const_iterator it = get_bucket(bucket);
1170 while(it != my_solist.raw_end() && !it.
get_node_ptr()->is_dummy());
1173 return my_solist.first_real_iterator(it);
1177 return ((
const self_type *)
this)->unsafe_begin(bucket);
1181 return ((
const self_type *)
this)->unsafe_end(bucket);
1186 return (
float)
size() / (float) unsafe_bucket_count();
1190 return my_maximum_bucket_size;
1194 if (newmax != newmax || newmax < 0)
1196 my_maximum_bucket_size = newmax;
1203 size_type current_buckets = my_number_of_buckets;
1204 if (current_buckets >= buckets)
1206 my_number_of_buckets = size_type(1)<<
__TBB_Log2((uintptr_t)buckets*2-1);
1214 memset(my_buckets, 0,
sizeof(my_buckets));
1217 raw_iterator dummy_node = my_solist.raw_begin();
1218 set_bucket(0, dummy_node);
1222 for (size_type index = 0; index < pointers_per_table; ++index) {
1223 if (my_buckets[index] != NULL) {
1224 size_type sz = segment_size(index);
1225 for (size_type index2 = 0; index2 < sz; ++index2)
1226 my_allocator.destroy(&my_buckets[index][index2]);
1227 my_allocator.deallocate(my_buckets[index], sz);
1228 my_buckets[index] = 0;
1240 insert(right.
begin(), right.
end());
1251 for (size_type index = 0; index < pointers_per_table; ++index)
1253 raw_iterator * iterator_pointer = my_buckets[index];
1265 for (const_iterator it = first; it !=
last; ++it)
1272 template<
typename AllowCreate,
typename ValueType>
1275 const key_type *pkey = &get_key(value);
1276 sokey_t hash_key = (
sokey_t) my_hash_compare(*pkey);
1277 size_type new_count = 0;
1278 sokey_t order_key = split_order_key_regular(hash_key);
1279 raw_iterator previous = prepare_bucket(hash_key);
1280 raw_iterator
last = my_solist.raw_end();
1284 for (raw_iterator where = previous;;)
1287 if (where == last || solist_t::get_order_key(where) > order_key ||
1289 (allow_multimapping && solist_t::get_order_key(where) == order_key &&
1290 !my_hash_compare(get_key(*where), *pkey)))
1293 pnode = my_solist.create_node(order_key, tbb::internal::forward<ValueType>(value), AllowCreate());
1295 pkey = &get_key(pnode->my_element);
1299 std::pair<iterator, bool> result = my_solist.try_insert(previous, where, pnode, &new_count);
1304 adjust_table_size(new_count, my_number_of_buckets);
1318 else if (!allow_multimapping && solist_t::get_order_key(where) == order_key &&
1319 !my_hash_compare(get_key(*where), *pkey))
1322 my_solist.destroy_node(pnode);
1323 return std::pair<iterator, bool>(my_solist.get_iterator(where),
false);
1333 sokey_t hash_key = (
sokey_t) my_hash_compare(key);
1334 sokey_t order_key = split_order_key_regular(hash_key);
1335 raw_iterator
last = my_solist.raw_end();
1337 for (raw_iterator it = prepare_bucket(hash_key); it !=
last; ++it)
1339 if (solist_t::get_order_key(it) > order_key)
1345 else if (solist_t::get_order_key(it) == order_key)
1350 if (!my_hash_compare(get_key(*it), key))
1351 return my_solist.get_iterator(it);
1361 sokey_t hash_key = (
sokey_t) my_hash_compare(get_key(*it));
1362 raw_iterator previous = prepare_bucket(hash_key);
1363 raw_iterator
last = my_solist.raw_end();
1367 for (raw_iterator where = previous; ; previous = where) {
1371 else if (my_solist.get_iterator(where) == it)
1372 return my_solist.erase_node(previous, it);
1380 sokey_t hash_key = (
sokey_t) my_hash_compare(key);
1381 sokey_t order_key = split_order_key_regular(hash_key);
1382 raw_iterator end_it = my_solist.raw_end();
1384 for (raw_iterator it = prepare_bucket(hash_key); it != end_it; ++it)
1386 if (solist_t::get_order_key(it) > order_key)
1389 return pairii_t(
end(),
end());
1391 else if (solist_t::get_order_key(it) == order_key &&
1392 !my_hash_compare(get_key(*it), key))
1394 iterator
first = my_solist.get_iterator(it);
1396 do ++
last;
while( allow_multimapping && last !=
end() && !my_hash_compare(get_key(*last), key) );
1397 return pairii_t(first, last);
1401 return pairii_t(
end(),
end());
1408 __TBB_ASSERT( bucket != 0,
"The first bucket must always be initialized");
1410 size_type parent_bucket = get_parent(bucket);
1413 if (!is_initialized(parent_bucket))
1414 init_bucket(parent_bucket);
1416 raw_iterator
parent = get_bucket(parent_bucket);
1419 raw_iterator dummy_node = my_solist.insert_dummy(parent, split_order_key_dummy(bucket));
1420 set_bucket(bucket, dummy_node);
1426 if ( ((
float) total_elements / (
float) current_size) > my_maximum_bucket_size )
1429 my_number_of_buckets.compare_and_swap(2u*current_size, current_size);
1438 size_type msb =
__TBB_Log2((uintptr_t)bucket);
1439 return bucket & ~(size_type(1) << msb);
1446 return size_type(
__TBB_Log2( uintptr_t(index|1) ) );
1451 return (size_type(1)<<k & ~size_type(1));
1456 return k? size_type(1)<<k : 2;
1460 size_type segment = segment_index_of(bucket);
1461 bucket -= segment_base(segment);
1462 __TBB_ASSERT( my_buckets[segment],
"bucket must be in an allocated segment" );
1463 return my_buckets[segment][bucket];
1467 size_type bucket = hash_key % my_number_of_buckets;
1468 size_type segment = segment_index_of(bucket);
1469 size_type index = bucket - segment_base(segment);
1470 if (my_buckets[segment] == NULL || my_buckets[segment][index].
get_node_ptr() == NULL)
1471 init_bucket(bucket);
1472 return my_buckets[segment][index];
1476 size_type segment = segment_index_of(bucket);
1477 bucket -= segment_base(segment);
1479 if (my_buckets[segment] == NULL) {
1480 size_type sz = segment_size(segment);
1481 raw_iterator * new_segment = my_allocator.allocate(sz);
1482 std::memset(static_cast<void*>(new_segment), 0, sz*
sizeof(raw_iterator));
1484 if (my_buckets[segment].compare_and_swap( new_segment, NULL) != NULL)
1485 my_allocator.deallocate(new_segment, sz);
1488 my_buckets[segment][bucket] = dummy_head;
1492 size_type segment = segment_index_of(bucket);
1493 bucket -= segment_base(segment);
1495 if (my_buckets[segment] == NULL)
1498 raw_iterator it = my_buckets[segment][bucket];
1521 #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) 1522 #pragma warning(pop) // warning 4127 is back 1529 #endif // __TBB__concurrent_unordered_impl_H void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task __itt_model_task_instance ITT_FORMAT p void ITT_FORMAT p void ITT_FORMAT p void size_t ITT_FORMAT d void ITT_FORMAT p const wchar_t ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s no args void ITT_FORMAT p size_t ITT_FORMAT d no args const wchar_t const wchar_t ITT_FORMAT s __itt_heap_function void size_t int ITT_FORMAT d __itt_heap_function void ITT_FORMAT p __itt_heap_function void void size_t int ITT_FORMAT d no args no args unsigned int ITT_FORMAT u const __itt_domain __itt_id ITT_FORMAT lu const __itt_domain __itt_id __itt_id __itt_string_handle ITT_FORMAT p const __itt_domain __itt_id ITT_FORMAT p const __itt_domain __itt_id __itt_timestamp __itt_timestamp end
iterator find(const key_type &key)
concurrent_unordered_base(const concurrent_unordered_base &right)
pointer operator->() const
static sokey_t get_order_key(const raw_const_iterator &it)
void swap(self_type &other)
concurrent_unordered_base::iterator iterator
void adjust_table_size(size_type total_elements, size_type current_size)
hash_compare::key_equal key_equal
raw_const_iterator raw_begin() const
void init_bucket(size_type bucket)
allocator_type::difference_type difference_type
concurrent_unordered_base::value_type value_type
split_ordered_list< value_type, typename Traits::allocator_type > solist_t
concurrent_unordered_base::const_iterator iterator
iterator internal_find(const key_type &key)
const_iterator const_local_iterator
iterator emplace_hint(const_iterator, Args &&... args)
size_type max_size() const
concurrent_unordered_base * my_instance
tbb::internal::allocator_rebind< allocator_type, raw_iterator >::type my_allocator
iterator erase_node(raw_iterator previous, const_iterator where)
Solist::nodeptr_t nodeptr_t
const_range_type(const_range_type &r, split)
Split range.
solist_t::const_iterator const_iterator
size_type unsafe_max_bucket_count() const
raw_const_iterator my_midpoint_node
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
tbb::internal::allocator_traits< allocator_type >::pointer pointer
Solist::difference_type difference_type
const Solist * my_list_ptr
static sokey_t get_safe_order_key(const raw_const_iterator &it)
size_type my_element_count
const_range_type(const concurrent_unordered_base &a_table)
Init range with container and grainsize specified.
local_iterator unsafe_end(size_type bucket)
auto first(Container &c) -> decltype(begin(c))
Base class for types that should not be assigned.
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task __itt_model_task_instance ITT_FORMAT p void ITT_FORMAT p void ITT_FORMAT p void size_t ITT_FORMAT d void ITT_FORMAT p const wchar_t ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s no args void ITT_FORMAT p size_t ITT_FORMAT d no args const wchar_t const wchar_t ITT_FORMAT s __itt_heap_function void size_t int ITT_FORMAT d __itt_heap_function void ITT_FORMAT p __itt_heap_function void void size_t int ITT_FORMAT d no args no args unsigned int ITT_FORMAT u const __itt_domain __itt_id ITT_FORMAT lu const __itt_domain __itt_id __itt_id __itt_string_handle ITT_FORMAT p const __itt_domain __itt_id ITT_FORMAT p const __itt_domain __itt_id __itt_timestamp begin
allocator_type::const_pointer const_pointer
void suppress_unused_warning(const T1 &)
Utility template function to prevent "unused" warnings by various compilers.
range_type(const concurrent_unordered_base &a_table)
Init range with container and grainsize specified.
static iterator get_iterator(const_iterator it)
const_local_iterator unsafe_begin(size_type bucket) const
void insert(Iterator first, Iterator last)
Traits::hash_compare hash_compare
void swap(concurrent_unordered_base &right)
tbb::internal::allocator_rebind< Allocator, T >::type allocator_type
float max_load_factor() const
const_iterator first_real_iterator(raw_const_iterator it) const
const allocator_type::value_type & const_reference
std::pair< iterator, bool > insert(value_type &&value)
size_type unsafe_bucket_count() const
call_internal_clear_on_exit(concurrent_unordered_base *instance)
iterator internal_erase(const_iterator it)
size_type get_parent(size_type bucket) const
void init(sokey_t order_key)
pairii_t internal_equal_range(const key_type &key)
std::pair< iterator, iterator > pairii_t
void swap(atomic< T > &lhs, atomic< T > &rhs)
pointer operator->() const
Solist::nodeptr_t nodeptr_t
raw_iterator insert_dummy(raw_iterator it, sokey_t order_key)
#define __TBB_PARAMETER_PACK
void move_all(self_type &source)
allocator_type::pointer pointer
void internal_swap_buckets(concurrent_unordered_base &right)
Traits::key_type key_type
tbb::internal::allocator_traits< allocator_type >::const_pointer const_pointer
allocator_type get_allocator() const
concurrent_unordered_base::reference reference
split_ordered_list(allocator_type a=allocator_type())
iterator insert(const_iterator, const value_type &value)
concurrent_unordered_base(const concurrent_unordered_base &right, const allocator_type &a)
std::pair< iterator, bool > insert(const value_type &value)
const concurrent_unordered_base & my_table
const_local_iterator unsafe_cend(size_type bucket) const
const_local_iterator unsafe_cbegin(size_type bucket) const
nodeptr_t get_node_ptr() const
T __TBB_ReverseBits(T src)
allocator_type::value_type value_type
float my_maximum_bucket_size
raw_const_iterator my_begin_node
const_iterator get_iterator(raw_const_iterator it) const
allocator_type get_allocator() const
solist_t::iterator iterator
std::pair< const_iterator, const_iterator > equal_range(const key_type &key) const
Solist::reference reference
void throw_exception(exception_id eid)
Versionless convenience wrapper for throw_exception_v4()
atomic< size_type > my_number_of_buckets
iterator unsafe_erase(const_iterator first, const_iterator last)
flist_iterator(nodeptr_t pnode)
atomic< raw_iterator * > my_buckets[pointers_per_table]
void max_load_factor(float newmax)
tbb::internal::allocator_traits< allocator_type >::value_type value_type
auto last(Container &c) -> decltype(begin(c))
intptr_t __TBB_Log2(uintptr_t x)
const_range_type range() const
tbb::internal::allocator_traits< allocator_type >::difference_type difference_type
concurrent_unordered_base & operator=(const concurrent_unordered_base &right)
concurrent_unordered_base(concurrent_unordered_base &&right, const allocator_type &a)
size_type unsafe_bucket(const key_type &key) const
concurrent_unordered_base & operator=(concurrent_unordered_base &&other)
size_type unsafe_erase(const key_type &key)
solist_t::nodeptr_t nodeptr_t
#define __TBB_FORWARDING_REF(A)
~concurrent_unordered_base()
solist_iterator(const solist_iterator< Solist, typename Solist::value_type > &other)
const_iterator cbegin() const
sokey_t split_order_key_regular(sokey_t order_key) const
raw_const_iterator raw_end() const
size_type unsafe_bucket_size(size_type bucket)
flist_iterator operator++(int)
iterator insert(const_iterator, value_type &&value)
concurrent_unordered_base::difference_type difference_type
void swap(concurrent_hash_map< Key, T, HashCompare, A > &a, concurrent_hash_map< Key, T, HashCompare, A > &b)
friend bool operator!=(const flist_iterator< M, T > &i, const flist_iterator< M, U > &j)
std::pair< iterator, bool > emplace(Args &&... args)
bool empty() const
True if range is empty.
std::pair< iterator, bool > internal_insert(__TBB_FORWARDING_REF(ValueType) value, nodeptr_t pnode=NULL)
solist_iterator< self_type, value_type > iterator
#define __TBB_PACK_EXPANSION(A)
sokey_t get_order_key() const
solist_iterator operator++(int)
flist_iterator< self_type, const value_type > raw_const_iterator
hasher hash_function() const
local_iterator unsafe_begin(size_type bucket)
concurrent_unordered_base(concurrent_unordered_base &&right)
raw_iterator get_iterator(raw_const_iterator it)
flist_iterator< Solist, Value > base_type
const_iterator begin() const
void set_bucket(size_type bucket, raw_iterator dummy_head)
static nodeptr_t try_insert_atomic(nodeptr_t previous, nodeptr_t new_node, nodeptr_t current_node)
void set_midpoint() const
Set my_midpoint_node to point approximately half way between my_begin_node and my_end_node.
static size_type segment_size(size_type k)
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task __itt_model_task_instance ITT_FORMAT p void ITT_FORMAT p void ITT_FORMAT p void size_t ITT_FORMAT d void ITT_FORMAT p const wchar_t ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s no args void ITT_FORMAT p size_t ITT_FORMAT d no args const wchar_t const wchar_t ITT_FORMAT s __itt_heap_function void size_t int ITT_FORMAT d __itt_heap_function void ITT_FORMAT p __itt_heap_function void void size_t int ITT_FORMAT d no args no args unsigned int ITT_FORMAT u const __itt_domain __itt_id ITT_FORMAT lu const __itt_domain __itt_id __itt_id __itt_string_handle ITT_FORMAT p const __itt_domain __itt_id ITT_FORMAT p const __itt_domain __itt_id __itt_timestamp __itt_timestamp ITT_FORMAT lu const __itt_domain __itt_id __itt_id __itt_string_handle ITT_FORMAT p const __itt_domain ITT_FORMAT p const __itt_domain __itt_string_handle unsigned long long value
size_type grainsize() const
The grain size for this range.
solist_iterator & operator++()
const_local_iterator unsafe_end(size_type bucket) const
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task __itt_model_task_instance ITT_FORMAT p void ITT_FORMAT p void ITT_FORMAT p void size_t ITT_FORMAT d void ITT_FORMAT p const wchar_t ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s no args void ITT_FORMAT p size_t ITT_FORMAT d no args const wchar_t const wchar_t ITT_FORMAT s __itt_heap_function void size_t int ITT_FORMAT d __itt_heap_function void ITT_FORMAT p __itt_heap_function void void size_t int ITT_FORMAT d no args no args unsigned int ITT_FORMAT u const __itt_domain __itt_id ITT_FORMAT lu const __itt_domain __itt_id __itt_id parent
friend bool operator==(const flist_iterator< M, T > &i, const flist_iterator< M, U > &j)
raw_iterator get_bucket(size_type bucket) const
float load_factor() const
tbb::internal::allocator_traits< allocator_type >::pointer pointer
Solist::reference reference
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task __itt_model_task_instance ITT_FORMAT p void ITT_FORMAT p void ITT_FORMAT p void size_t ITT_FORMAT d void ITT_FORMAT p const wchar_t ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s no args void ITT_FORMAT p size_t ITT_FORMAT d no args const wchar_t const wchar_t ITT_FORMAT s __itt_heap_function void size_t int ITT_FORMAT d __itt_heap_function void ITT_FORMAT p __itt_heap_function void void size_t int ITT_FORMAT d no args no args unsigned int ITT_FORMAT u const __itt_domain __itt_id ITT_FORMAT lu const __itt_domain __itt_id __itt_id __itt_string_handle ITT_FORMAT p const __itt_domain __itt_id ITT_FORMAT p const __itt_domain __itt_id __itt_timestamp __itt_timestamp ITT_FORMAT lu const __itt_domain __itt_id __itt_id __itt_string_handle ITT_FORMAT p const __itt_domain ITT_FORMAT p const __itt_domain __itt_string_handle unsigned long long ITT_FORMAT lu const __itt_domain __itt_id __itt_string_handle * key
nodeptr_t create_node(sokey_t order_key)
solist_iterator(nodeptr_t pnode, const Solist *plist)
static size_type segment_base(size_type k)
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance * instance
bool is_initialized(size_type bucket) const
flist_iterator(const flist_iterator< Solist, typename Solist::value_type > &other)
tbb::internal::allocator_rebind< allocator_type, node >::type my_node_allocator
const value_type & const_reference
void check_range(raw_iterator first, raw_iterator last)
const_iterator cend() const
allocator_traits< Alloc >::template rebind_alloc< T >::other type
bool is_divisible() const
True if range can be partitioned into two subranges.
tbb::internal::allocator_traits< allocator_type >::size_type size_type
void move(tbb_thread &t1, tbb_thread &t2)
Traits::allocator_type allocator_type
reference operator*() const
const_iterator find(const key_type &key) const
solist_iterator< self_type, const value_type > const_iterator
Traits::value_type value_type
tbb::internal::allocator_traits< allocator_type >::difference_type difference_type
concurrent_unordered_base< Traits > self_type
void destroy_node(nodeptr_t pnode)
split_ordered_list< T, Allocator > self_type
solist_t::raw_const_iterator raw_const_iterator
const_iterator cend() const
nodeptr_t create_node_v(__TBB_FORWARDING_REF(Args) __TBB_PARAMETER_PACK args)
flist_iterator< self_type, value_type > raw_iterator
static size_type segment_index_of(size_type index)
~call_internal_clear_on_exit()
nodeptr_t create_node(sokey_t, __TBB_FORWARDING_REF(Arg), tbb::internal::false_type)
concurrent_unordered_base::size_type size_type
Type for size of a range.
iterator get_iterator(raw_iterator it)
Solist::value_type value_type
tbb::internal::allocator_traits< allocator_type >::size_type size_type
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t size
solist_t::raw_iterator raw_iterator
size_type count(const key_type &key) const
tbb::internal::allocator_traits< allocator_type >::const_pointer const_pointer
std::pair< iterator, bool > try_insert(raw_iterator it, raw_iterator next, nodeptr_t pnode, size_type *new_count)
nodeptr_t atomic_set_next(nodeptr_t new_node, nodeptr_t current_node)
size_type max_size() const
const_iterator end() const
allocator_type::value_type & reference
std::pair< iterator, iterator > equal_range(const key_type &key)
const_iterator begin() const
allocator_type::size_type size_type
range_type(range_type &r, split)
Split range.
iterator unsafe_erase(const_iterator where)
hash_compare my_hash_compare
void internal_copy(const self_type &right)
static size_type internal_distance(const_iterator first, const_iterator last)
concurrent_unordered_base(size_type n_of_buckets=initial_bucket_number, const hash_compare &hc=hash_compare(), const allocator_type &a=allocator_type())
Solist::value_type value_type
raw_const_iterator my_end_node
Dummy type that distinguishes splitting constructor from copy constructor.
hash_compare::hasher hasher
std::pair< const_iterator, const_iterator > paircc_t
nodeptr_t create_node(sokey_t order_key, __TBB_FORWARDING_REF(Arg) t, tbb::internal::true_type=tbb::internal::true_type())
const_iterator cbegin() const
void rehash(size_type buckets)
atomic< T > & as_atomic(T &t)
raw_iterator prepare_bucket(sokey_t hash_key)
const_iterator end() const
iterator first_real_iterator(raw_iterator it)
reference operator*() const
sokey_t split_order_key_dummy(sokey_t order_key) const
flist_iterator & operator++()
Solist::difference_type difference_type
void erase_node(raw_iterator previous, raw_const_iterator &where)