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> 50 namespace interface5 {
54 template <
typename T,
typename Allocator>
56 template <
typename Traits>
60 template<
class Solist,
typename Value>
61 class flist_iterator :
public std::iterator<std::forward_iterator_tag, Value>
63 template <
typename T,
typename Allocator>
65 template <
typename Traits>
67 template<
class M,
typename V>
101 template<
typename M,
typename T,
typename U>
103 template<
typename M,
typename T,
typename U>
107 template<
typename Solist,
typename T,
typename U>
111 template<
typename Solist,
typename T,
typename U>
117 template<
class Solist,
typename Value>
123 template <
typename T,
typename Allocator>
125 template<
class M,
typename V>
127 template<
typename M,
typename T,
typename U>
129 template<
typename M,
typename T,
typename U>
169 template<
typename Solist,
typename T,
typename U>
173 template<
typename Solist,
typename T,
typename U>
183 template <
typename T,
typename Allocator>
194 typedef typename allocator_type::pointer
pointer;
229 if (exchange_node == current_node)
237 return exchange_node;
256 pnode->init(order_key);
261 template<
typename Arg>
268 new(static_cast<void*>(&pnode->my_element)) T(tbb::internal::forward<Arg>(t));
269 pnode->init(order_key);
279 template<
typename Arg>
282 __TBB_ASSERT(
false,
"This compile-time helper should never get called");
287 template<
typename __TBB_PARAMETER_PACK Args>
293 new(static_cast<void*>(&pnode->my_element)) T(
__TBB_PACK_EXPANSION(tbb::internal::forward<Args>(args)));
319 __TBB_ASSERT(pnode != NULL && pnode->my_next == NULL,
"Invalid head list node");
335 pnext = pnode->my_next;
336 pnode->my_next = NULL;
339 while (pnode != NULL)
341 pnext = pnode->my_next;
487 new_node->
my_next = current_node;
496 if (inserted_node == pnode)
501 return std::pair<iterator, bool>(
iterator(pnode,
this),
true);
505 return std::pair<iterator, bool>(
end(),
false);
535 if (inserted_node == dummy_node)
570 nodeptr_t pnode = (where++).get_node_ptr();
572 __TBB_ASSERT(prevnode->my_next == pnode,
"Erase must take consecutive iterators");
573 prevnode->my_next = pnode->my_next;
607 __TBB_ASSERT(previous_node != NULL,
"Insertion must succeed");
617 template <
typename Traits>
647 #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) 648 #pragma warning(push) 649 #pragma warning(disable: 4127) // warning C4127: conditional expression is constant 652 template <
typename Traits>
664 typedef typename allocator_type::pointer
pointer;
679 using Traits::my_hash_compare;
680 using Traits::get_key;
681 using Traits::allow_multimapping;
686 typedef std::pair<const_iterator, const_iterator>
paircc_t;
708 if( n_of_buckets == 0) ++n_of_buckets;
728 #if __TBB_CPP11_RVALUE_REF_PRESENT 741 call_internal_clear_on_exit clear_buckets_on_exception(
this);
744 if (a == right.get_allocator()){
753 if (! right.my_solist.empty()){
759 const nodeptr_t pnode = it.get_node_ptr();
761 if (pnode->is_dummy()) {
770 __TBB_ASSERT(previous_node != NULL,
"Insertion of node failed. Concurrent inserts in constructor ?");
776 clear_buckets_on_exception.dismiss();
779 #endif // __TBB_CPP11_RVALUE_REF_PRESENT 787 #if __TBB_CPP11_RVALUE_REF_PRESENT 803 this->
swap(moved_copy);
809 #endif // __TBB_CPP11_RVALUE_REF_PRESENT 811 #if __TBB_INITIALIZER_LISTS_PRESENT 816 this->
insert(il.begin(),il.end());
819 #endif // __TBB_INITIALIZER_LISTS_PRESENT 933 __TBB_ASSERT( begin_key < mid_key,
"my_begin_node is after my_midpoint_node" );
934 __TBB_ASSERT( mid_key <= end_key,
"my_midpoint_node is after my_end_node" );
936 #endif // TBB_USE_ASSERT 954 return range_type( *
this );
958 return const_range_type( *
this );
971 #if __TBB_CPP11_RVALUE_REF_PRESENT 981 #if __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT 982 template<
typename... Args>
983 std::pair<iterator, bool>
emplace(Args&&... args) {
985 const sokey_t hashed_element_key = (
sokey_t) my_hash_compare(get_key(pnode->my_element));
987 pnode->init(order_key);
992 template<
typename... Args>
995 return emplace(tbb::internal::forward<Args>(args)...).first;
998 #endif // __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT 999 #endif // __TBB_CPP11_RVALUE_REF_PRESENT 1001 template<
class Iterator>
1003 for (Iterator it =
first; it !=
last; ++it)
1007 #if __TBB_INITIALIZER_LISTS_PRESENT 1008 void insert(std::initializer_list<value_type> il) {
1010 insert(il.begin(), il.end());
1032 if (
this != &right) {
1033 std::swap(my_hash_compare, right.my_hash_compare);
1043 return my_hash_compare.my_hash_object;
1047 return my_hash_compare.my_key_compare_object;
1069 return const_cast<self_type*>(
this)->internal_find(
key);
1073 if(allow_multimapping) {
1078 return const_cast<self_type*>(
this)->internal_find(
key) ==
end()?0:1;
1087 return const_cast<self_type*>(
this)->internal_equal_range(
key);
1170 return ((
const self_type *)
this)->unsafe_begin(bucket);
1174 return ((
const self_type *)
this)->unsafe_end(bucket);
1187 if (newmax != newmax || newmax < 0)
1197 if (current_buckets >= buckets)
1218 for (
size_type index2 = 0; index2 < sz; ++index2)
1265 template<
typename AllowCreate,
typename ValueType>
1283 !my_hash_compare(get_key(*where), *pkey)))
1288 pkey = &get_key(pnode->my_element);
1292 std::pair<iterator, bool> result =
my_solist.
try_insert(previous, where, pnode, &new_count);
1312 !my_hash_compare(get_key(*where), *pkey))
1343 if (!my_hash_compare(get_key(*it),
key))
1360 for (
raw_iterator where = previous; ; previous = where) {
1385 !my_hash_compare(get_key(*it),
key))
1389 do ++
last;
while( allow_multimapping &&
last !=
end() && !my_hash_compare(get_key(*
last),
key) );
1401 __TBB_ASSERT( bucket != 0,
"The first bucket must always be initialized");
1475 std::memset(static_cast<void*>(new_segment), 0, sz*
sizeof(
raw_iterator));
1477 if (
my_buckets[segment].compare_and_swap( new_segment, NULL) != NULL)
1510 typename allocator_type::template rebind<raw_iterator>::other
my_allocator;
1514 #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) 1515 #pragma warning(pop) // warning 4127 is back 1522 #endif // __TBB__concurrent_unordered_impl_H
Allocator::template rebind< T >::other allocator_type
std::pair< iterator, iterator > equal_range(const key_type &key)
intptr_t __TBB_Log2(uintptr_t x)
static size_type segment_base(size_type k)
void swap(concurrent_unordered_base &right)
size_type my_element_count
concurrent_unordered_base(size_type n_of_buckets=initial_bucket_number, const hash_compare &hc=hash_compare(), const allocator_type &a=allocator_type())
solist_iterator< self_type, const value_type > const_iterator
concurrent_unordered_base * my_instance
const concurrent_unordered_base & my_table
raw_const_iterator my_begin_node
iterator erase_node(raw_iterator previous, const_iterator where)
size_type max_size() const
concurrent_unordered_base(const concurrent_unordered_base &right)
static const size_type initial_bucket_load
const_iterator begin() const
const_iterator cend() const
Traits::allocator_type allocator_type
allocator_type::const_pointer const_pointer
hash_compare::key_equal key_equal
iterator internal_erase(const_iterator it)
const_iterator const_local_iterator
void init(sokey_t order_key)
allocator_type get_allocator() const
raw_const_iterator raw_begin() const
iterator first_real_iterator(raw_iterator it)
allocator_type::template rebind< node >::other my_node_allocator
Traits::key_type key_type
concurrent_unordered_base::value_type value_type
allocator_type::template rebind< raw_iterator >::other my_allocator
atomic< T > & as_atomic(T &t)
concurrent_unordered_base< Traits > self_type
const_iterator end() const
flist_iterator(const flist_iterator< Solist, typename Solist::value_type > &other)
atomic< size_type > my_number_of_buckets
range_type(const concurrent_unordered_base &a_table)
Init range with container and grainsize specified.
flist_iterator(nodeptr_t pnode)
const_range_type(const_range_type &r, split)
Split range.
nodeptr_t atomic_set_next(nodeptr_t new_node, nodeptr_t current_node)
raw_iterator get_bucket(size_type bucket) const
solist_iterator< self_type, value_type > iterator
raw_iterator insert_dummy(raw_iterator it, sokey_t order_key)
Dummy type that distinguishes splitting constructor from copy constructor.
concurrent_unordered_base & operator=(concurrent_unordered_base &&other)
iterator find(const key_type &key)
raw_const_iterator my_end_node
void check_range(raw_iterator first, raw_iterator last)
concurrent_unordered_base::size_type size_type
Type for size of a range.
auto last(Container &c) -> decltype(begin(c))
flist_iterator< Solist, Value > base_type
size_type count(const key_type &key) const
allocator_type::const_reference const_reference
std::pair< iterator, bool > try_insert(raw_iterator it, raw_iterator next, nodeptr_t pnode, size_type *new_count)
reference operator *() const
Solist::difference_type difference_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 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
call_internal_clear_on_exit(concurrent_unordered_base *instance)
static size_type const pointers_per_table
const_iterator get_iterator(raw_const_iterator it) const
#define __TBB_FORWARDING_REF(A)
Solist::value_type value_type
std::pair< const_iterator, const_iterator > equal_range(const key_type &key) const
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
auto first(Container &c) -> decltype(begin(c))
hash_compare::hasher hasher
flist_iterator< self_type, const value_type > raw_const_iterator
void internal_copy(const self_type &right)
const_iterator first_real_iterator(raw_const_iterator it) const
Solist::difference_type difference_type
size_type grainsize() const
The grain size for this range.
concurrent_unordered_base::reference reference
raw_const_iterator raw_end() const
allocator_type::reference reference
concurrent_unordered_base::const_iterator iterator
const_iterator cend() const
bool empty() const
True if range is empty.
Base class for types that should not be assigned.
~concurrent_unordered_base()
Allocator::template rebind< value_type >::other allocator_type
Solist::nodeptr_t nodeptr_t
void init_bucket(size_type bucket)
local_iterator unsafe_end(size_type bucket)
solist_iterator operator++(int)
#define __TBB_PARAMETER_PACK
hash_compare my_hash_compare
hasher hash_function() const
const_local_iterator unsafe_cbegin(size_type bucket) const
raw_iterator get_iterator(raw_const_iterator it)
void rehash(size_type buckets)
nodeptr_t create_node(sokey_t, __TBB_FORWARDING_REF(Arg), tbb::internal::false_type)
allocator_type::const_pointer const_pointer
allocator_type::pointer pointer
Solist::nodeptr_t nodeptr_t
const_local_iterator unsafe_end(size_type bucket) const
allocator_type::const_reference const_reference
static sokey_t get_order_key(const raw_const_iterator &it)
nodeptr_t create_node(sokey_t order_key, __TBB_FORWARDING_REF(Arg) t, tbb::internal::true_type=tbb::internal::true_type())
bool is_initialized(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 * instance
void swap(self_type &other)
nodeptr_t create_node_v(__TBB_FORWARDING_REF(Args) __TBB_PARAMETER_PACK args)
size_type unsafe_bucket_count() const
internal::hash_compare< Key, Hasher, Key_equality > hash_compare
std::pair< iterator, bool > internal_insert(__TBB_FORWARDING_REF(ValueType) value, nodeptr_t pnode=NULL)
std::pair< const_iterator, const_iterator > paircc_t
const_iterator cbegin() const
allocator_type::size_type size_type
void move(tbb_thread &t1, tbb_thread &t2)
split_ordered_list(allocator_type a=allocator_type())
size_type unsafe_bucket_size(size_type bucket)
local_iterator unsafe_begin(size_type bucket)
solist_iterator(nodeptr_t pnode, const Solist *plist)
solist_t::iterator iterator
flist_iterator & operator++()
std::pair< iterator, bool > insert(value_type &&value)
iterator insert(const_iterator, value_type &&value)
iterator emplace_hint(const_iterator, Args &&... args)
bool is_divisible() const
True if range can be partitioned into two subranges.
const Solist * my_list_ptr
Traits::value_type value_type
static sokey_t get_safe_order_key(const raw_const_iterator &it)
concurrent_unordered_base & operator=(const concurrent_unordered_base &right)
static nodeptr_t try_insert_atomic(nodeptr_t previous, nodeptr_t new_node, nodeptr_t current_node)
sokey_t get_order_key() const
friend bool operator==(const flist_iterator< M, T > &i, const flist_iterator< M, U > &j)
allocator_type::size_type size_type
solist_iterator & operator++()
allocator_type get_allocator() const
friend bool operator==(const solist_iterator< M, T > &i, const solist_iterator< M, U > &j)
const_range_type(const concurrent_unordered_base &a_table)
Init range with container and grainsize specified.
concurrent_unordered_base(const concurrent_unordered_base &right, const allocator_type &a)
value_type compare_and_swap(value_type value, value_type comparand)
solist_t::nodeptr_t nodeptr_t
void destroy_node(nodeptr_t pnode)
allocator_type::value_type value_type
static size_type internal_distance(const_iterator first, const_iterator last)
static size_type segment_size(size_type k)
bool operator!=(const hash_map_iterator< Container, T > &i, const hash_map_iterator< Container, U > &j)
nodeptr_t create_node(sokey_t order_key)
flist_iterator< self_type, value_type > raw_iterator
friend bool operator!=(const solist_iterator< M, T > &i, const solist_iterator< M, U > &j)
void set_bucket(size_type bucket, raw_iterator dummy_head)
size_type unsafe_max_bucket_count() const
const_iterator cbegin() const
allocator_type::reference reference
const_iterator begin() const
const_range_type range() const
void erase_node(raw_iterator previous, raw_const_iterator &where)
iterator unsafe_erase(const_iterator first, const_iterator last)
raw_iterator prepare_bucket(sokey_t hash_key)
pairii_t internal_equal_range(const key_type &key)
static const size_type initial_bucket_number
size_type get_parent(size_type bucket) const
static iterator get_iterator(const_iterator it)
iterator unsafe_erase(const_iterator where)
concurrent_unordered_base::iterator iterator
void move_all(self_type &source)
void adjust_table_size(size_type total_elements, size_type current_size)
sokey_t split_order_key_dummy(sokey_t order_key) const
#define __TBB_PACK_EXPANSION(A)
friend bool operator!=(const flist_iterator< M, T > &i, const flist_iterator< M, U > &j)
concurrent_unordered_base(concurrent_unordered_base &&right, const allocator_type &a)
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
range_type(range_type &r, split)
Split range.
Traits::hash_compare hash_compare
atomic< raw_iterator * > my_buckets[pointers_per_table]
std::pair< const Key, T > value_type
void internal_swap_buckets(concurrent_unordered_base &right)
void insert(Iterator first, Iterator last)
solist_t::const_iterator const_iterator
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
bool operator==(const hash_map_iterator< Container, T > &i, const hash_map_iterator< Container, U > &j)
concurrent_unordered_base(concurrent_unordered_base &&right)
concurrent_unordered_base::difference_type difference_type
void suppress_unused_warning(const T1 &)
Utility template function to prevent "unused" warnings by various compilers.
std::pair< iterator, iterator > pairii_t
pointer operator->() const
float load_factor() const
T __TBB_ReverseBits(T src)
size_type max_size() const
float my_maximum_bucket_size
float max_load_factor() const
Solist::reference reference
const_local_iterator unsafe_cend(size_type bucket) const
split_ordered_list< T, Allocator > self_type
iterator internal_find(const key_type &key)
allocator_type::difference_type difference_type
~call_internal_clear_on_exit()
static size_type segment_index_of(size_type index)
solist_t::raw_iterator raw_iterator
void swap(atomic< T > &lhs, atomic< T > &rhs)
pointer operator->() const
void set_midpoint() const
Set my_midpoint_node to point approximately half way between my_begin_node and my_end_node.
const_iterator end() const
reference operator *() const
allocator_type::difference_type difference_type
Solist::value_type value_type
size_type unsafe_bucket(const key_type &key) const
const_iterator find(const key_type &key) const
Solist::reference reference
std::pair< iterator, bool > insert(const value_type &value)
iterator insert(const_iterator, const value_type &value)
raw_const_iterator my_midpoint_node
std::pair< iterator, bool > emplace(Args &&... args)
solist_iterator(const solist_iterator< Solist, typename Solist::value_type > &other)
nodeptr_t get_node_ptr() const
sokey_t split_order_key_regular(sokey_t order_key) const
iterator get_iterator(raw_iterator it)
allocator_type::pointer pointer
void throw_exception(exception_id eid)
Versionless convenience wrapper for throw_exception_v4()
solist_t::raw_const_iterator raw_const_iterator
const_local_iterator unsafe_begin(size_type bucket) const
size_type unsafe_erase(const key_type &key)
flist_iterator operator++(int)
split_ordered_list< value_type, typename Traits::allocator_type > solist_t
void max_load_factor(float newmax)