17 #ifndef __TBB_concurrent_skip_list_H 18 #define __TBB_concurrent_skip_list_H 20 #if !defined(__TBB_concurrent_map_H) && !defined(__TBB_concurrent_set_H) 21 #error Do not #include this internal file directly; use public TBB headers instead. 24 #include "../tbb_config.h" 25 #include "../tbb_stddef.h" 26 #include "../tbb_allocator.h" 27 #include "../spin_mutex.h" 28 #include "../tbb_exception.h" 29 #include "../enumerable_thread_specific.h" 35 #include <initializer_list> 41 #include <type_traits> 47 #pragma warning(disable: 4189) // warning 4189 -- local variable is initialized but not referenced 48 #pragma warning(disable: 4127) // warning 4127 -- while (true) has a constant expression in it 52 namespace interface10 {
55 template <
typename Value,
typename Mutex>
89 return reinterpret_cast<pointer>(&
my_val);
143 template <
typename NodeType,
bool is_const>
151 using pointer =
typename std::conditional<is_const,
typename node_type::const_pointer,
153 using reference =
typename std::conditional<is_const,
typename node_type::const_reference,
194 template <
typename Traits>
202 template <
typename T,
bool M,
bool U>
205 template <
typename T,
bool M,
bool U>
209 template <
typename NodeType,
bool is_const1,
bool is_const2>
214 template <
typename NodeType,
bool is_const1,
bool is_const2>
219 template <
typename Traits>
239 using pointer =
typename allocator_traits_type::pointer;
245 using node_allocator_type =
typename std::allocator_traits<allocator_type>::template rebind_alloc<uint8_t>;
252 using lock_array = std::array<typename list_node_type::lock_type, MAX_LEVEL>;
270 template<
class InputIt>
309 if (alloc == other.get_allocator()) {
314 internal_copy(std::make_move_iterator(other.begin()), std::make_move_iterator(other.end()));
324 if (
this != &other) {
325 using pocca_type =
typename node_allocator_traits::propagate_on_container_copy_assignment;
336 if (
this != &other) {
337 using pocma_type =
typename node_allocator_traits::propagate_on_container_move_assignment;
349 insert(il.begin(),il.end());
371 template<
typename InputIterator>
373 for (InputIterator it =
first; it !=
last; ++it)
377 void insert(std::initializer_list<value_type> init) {
378 insert(init.begin(), init.end());
384 if(insert_result.second) {
387 return insert_result;
389 return std::pair<iterator, bool>(
end(),
false);
397 template<
typename... Args >
398 std::pair<iterator, bool>
emplace(Args&&... args) {
402 template<
typename... Args>
405 return emplace(std::forward<Args>(args)...).first;
410 if(extract_result.first) {
412 return iterator(extract_result.second);
421 template <
typename K,
typename = tbb::
internal::is_transparent<key_compare, K>,
422 typename =
typename std::enable_if<!std::is_convertible<K, iterator>::value &&
423 !std::is_convertible<K, const_iterator>::value>::type>
462 template <
typename K,
typename =
typename tbb::
internal::is_transparent<key_compare, K> >
467 template <
typename K,
typename =
typename tbb::
internal::is_transparent<key_compare, K> >
480 template <
typename K,
typename =
typename tbb::
internal::is_transparent<key_compare, K> >
485 template <
typename K,
typename =
typename tbb::
internal::is_transparent<key_compare, K> >
498 template <
typename K,
typename =
typename tbb::
internal::is_transparent<key_compare, K> >
503 template <
typename K,
typename =
typename tbb::
internal::is_transparent<key_compare, K> >
512 template <
typename K,
typename =
typename tbb::
internal::is_transparent<key_compare, K> >
521 template <
typename K,
typename =
typename tbb::
internal::is_transparent<key_compare, K> >
585 using pocs_type =
typename node_allocator_traits::propagate_on_container_swap;
604 template <
typename K,
typename =
typename tbb::
internal::is_transparent<key_compare, K> >
609 template <
typename K,
typename =
typename tbb::
internal::is_transparent<key_compare, K> >
679 other.dummy_head =
nullptr;
680 other.create_dummy_head();
682 my_size = other.my_size.load();
688 return traits_type::get_key(n->
value());
691 template <
typename K>
697 template <
typename K>
703 template <
typename K>
707 return std::distance(
range.first,
range.second);
721 template <
typename K,
typename po
inter_type,
typename comparator>
723 const comparator& cmp)
const {
724 __TBB_ASSERT(level < prev->height(),
"Wrong level to find position");
725 pointer_type curr = prev->next(level);
730 curr = prev->next(level);
736 template <
typename comparator>
738 const comparator& cmp) {
740 next_nodes.fill(
nullptr);
744 prev_nodes[
h - 1] = prev;
745 next_nodes[
h - 1] = next;
749 template <
typename comparator>
751 const comparator& cmp) {
764 curr = prev->
next(
h - 1);
766 prev_nodes[
h - 1] = prev;
769 std::fill(next_nodes.begin(), next_nodes.begin() + node_height, erase_node);
772 template<
typename... Args>
776 if(!insert_result.second) {
779 return insert_result;
802 return std::pair<iterator, bool>(
iterator(next),
false);
805 "Wrong elements order");
810 return std::pair<iterator, bool>(
iterator(new_node),
true);
826 "Wrong elements order");
829 __TBB_ASSERT(prev_nodes[level]->height() > level, NULL);
830 __TBB_ASSERT(prev_nodes[level]->next(level) == next_nodes[level], NULL);
831 new_node->
set_next(level, next_nodes[level]);
832 prev_nodes[level]->set_next(level, new_node);
843 if (l == 0 || prevs[l] != prevs[l - 1])
844 locks[l] = prevs[l]->acquire();
847 if ( next != next_nodes[l])
return false;
853 template <
typename K,
typename comparator>
866 template <
typename K,
typename comparator>
890 node_ptr erase_node = next_nodes[0];
896 __TBB_ASSERT(prev_nodes[level]->height() > level, NULL);
898 prev_nodes[level]->set_next(level, erase_node->
next(level));
901 return std::pair<node_ptr, node_ptr>(erase_node, next_node);
904 return std::pair<node_ptr, node_ptr>(
nullptr,
nullptr);
908 template<
typename SourceType>
911 using source_iterator =
typename source_type::iterator;
914 for(source_iterator it = source.begin(); it != source.end();) {
915 source_iterator where = it++;
917 std::pair<node_ptr, node_ptr> extract_result = source.internal_extract(where);
921 __TBB_ASSERT(!handle.empty(),
"Extracted handle in merge is empty");
936 template<
typename Iterator>
960 template <
typename... Args>
1005 template <
bool is_dummy = false>
1017 node_allocator_traits::deallocate(
my_node_allocator, reinterpret_cast<uint8_t*>(node), sz);
1039 internal_copy(std::make_move_iterator(other.begin()), std::make_move_iterator(other.end()));
1048 template <
typename K1,
typename K2>
1059 template<
typename OtherTraits>
1065 template <
size_t MAX_LEVEL>
1085 #endif // __TBB_concurrent_skip_list_H
typename traits_type::node_type node_type
const_iterator internal_find(const K &key) const
void delete_node(node_ptr node)
bool_constant< true > true_type
skip_list_node & operator=(const skip_list_node &)=delete
std::pair< iterator, bool > emplace(Args &&... args)
typename node_type::value_type value_type
iterator upper_bound(const key_type &key)
std::atomic< size_type > my_size
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 h
void insert(InputIterator first, InputIterator last)
typename concurrent_skip_list::iterator iterator
static constexpr size_t max_level
pointer_type internal_find_position(size_type level, pointer_type &prev, const K &key, const comparator &cmp) const
void allocator_swap(MyAlloc &my_allocator, OtherAlloc &other_allocator, traits_true_type)
void internal_move(concurrent_skip_list &&other)
bool operator()(const K1 &first, const K2 &second) const
std::reverse_iterator< iterator > reverse_iterator
const_iterator lower_bound(const key_type &key) const
size_type max_size() const
std::ptrdiff_t difference_type
skip_list_iterator(node_type *n)
iterator internal_get_bound(const K &key, const comparator &cmp)
allocator_type get_allocator() const
skip_list_iterator< list_node_type, false > iterator
concurrent_skip_list(const key_compare &comp, const allocator_type &alloc=allocator_type())
typename allocator_traits_type::const_pointer const_pointer
concurrent_skip_list(concurrent_skip_list &&other, const allocator_type &alloc)
iterator lower_bound(const key_type &key)
const_iterator begin() const
std::pair< node_ptr, node_ptr > internal_extract(const_iterator it)
iterator lower_bound(const K &key)
void allocator_move_assignment(MyAlloc &my_allocator, OtherAlloc &other_allocator, traits_true_type)
size_type count(const K &key) const
typename traits_type::value_type value_type
void internal_copy(const concurrent_skip_list &other)
range_type(range_type &r, split)
const_iterator end() const
std::array< node_ptr, MAX_LEVEL > array_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 __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_string_handle unsigned long long ITT_FORMAT lu const __itt_domain __itt_id __itt_string_handle * key
const key_compare & my_less_compare
bool try_lock_nodes(size_type height, array_type &prevs, array_type &next_nodes, lock_array &locks)
Base class for types that should not be assigned.
not_greater_compare(const key_compare &less_compare)
std::pair< iterator, iterator > equal_range(const key_type &key)
skip_list_node< value_type, typename traits_type::mutex_type > list_node_type
skip_list_node(size_type levels)
random_level_generator_type my_rnd_generator
std::pair< iterator, iterator > equal_range(const K &key)
bool fully_linked() const
size_type count(const key_type &key) const
concurrent_skip_list & operator=(concurrent_skip_list &&other)
const_iterator cend() const
bool is_divisible() const
iterator unsafe_erase(const_iterator pos)
std::pair< iterator, bool > insert(value_type &&value)
auto last(Container &c) -> decltype(begin(c))
bool_constant< false > false_type
size_type unsafe_erase(const K &key)
std::forward_iterator_tag iterator_category
bool operator!=(const skip_list_iterator< NodeType, is_const1 > &lhs, const skip_list_iterator< NodeType, is_const2 > &rhs)
skip_list_iterator(const skip_list_iterator< node_type, false > &other)
const_range_type(const concurrent_skip_list &l)
void set_next(size_type level, node_pointer next)
typename traits_type::key_type key_type
concurrent_skip_list & operator=(std::initializer_list< value_type > il)
const_range_type range() const
size_type unsafe_erase(const key_type &key)
const_range_type(const_range_type &r, split)
skip_list_iterator & operator++()
concurrent_skip_list(const concurrent_skip_list &other)
bool contains(const K &key) const
typename std::conditional< is_const, typename node_type::const_pointer, typename node_type::pointer >::type pointer
node_allocator_type my_node_allocator
void allocator_copy_assignment(MyAlloc &my_allocator, OtherAlloc &other_allocator, traits_true_type)
#define __TBB_STATIC_ASSERT(condition, msg)
friend bool operator==(const skip_list_iterator< T, M > &, const skip_list_iterator< T, U > &)
node_type unsafe_extract(const_iterator pos)
skip_list_iterator & operator=(const skip_list_iterator< node_type, false > &other)
const_iterator cbegin() const
bool operator==(const skip_list_iterator< NodeType, is_const1 > &lhs, const skip_list_iterator< NodeType, is_const2 > &rhs)
void deallocate_node(node_ptr node, size_type sz)
friend bool operator!=(const skip_list_iterator< T, M > &, const skip_list_iterator< T, U > &)
concurrent_skip_list & operator=(const concurrent_skip_list &other)
const_iterator upper_bound(const key_type &key) const
skip_list_iterator(const skip_list_iterator< node_type, true > &other)
iterator insert(const_iterator, value_type &&value)
std::unique_lock< mutex_type > lock_type
skip_list_iterator operator++(int)
void internal_copy(Iterator first, Iterator last)
concurrent_skip_list(InputIt first, InputIt last, const key_compare &comp=key_compare(), const allocator_type &alloc=allocator_type())
iterator internal_find(const K &key)
node_pointer next(size_type level) const
concurrent_skip_list(concurrent_skip_list &&other)
std::pair< const_iterator, const_iterator > equal_range(const K &key) const
pointer operator->() const
const_iterator find(const key_type &key) const
The enumerable_thread_specific container.
static size_type calc_node_size(size_type height)
iterator upper_bound(const K &key)
void fill_prev_next_by_ptr(array_type &prev_nodes, array_type &next_nodes, const_iterator it, const key_type &key, const comparator &cmp)
std::array< typename list_node_type::lock_type, MAX_LEVEL > lock_array
std::ptrdiff_t difference_type
tbb::enumerable_thread_specific< std::mt19937_64 > engines
std::allocator_traits< allocator_type > allocator_traits_type
typename allocator_traits_type::pointer pointer
typename concurrent_skip_list::value_type value_type
node_ptr create_node(Args &&... args)
void internal_merge(SourceType &&source)
typename std::allocator_traits< allocator_type >::template rebind_traits< uint8_t > node_allocator_traits
const value_type & const_reference
concurrent_geometric_level_generator()
typename traits_type::value_compare value_compare
atomic_node_pointer & my_next(size_type level)
const value_type * const_pointer
std::pair< iterator, bool > insert(const value_type &value)
Dummy type that distinguishes splitting constructor from copy constructor.
typename traits_type::random_level_generator_type random_level_generator_type
const_iterator internal_get_bound(const K &key, const comparator &cmp) const
std::pair< const_iterator, const_iterator > equal_range(const key_type &key) const
void swap(concurrent_skip_list &other)
iterator emplace_hint(const_iterator, Args &&... args)
concurrent_skip_list(const concurrent_skip_list &other, const allocator_type &alloc)
const_iterator lower_bound(const K &key) const
void internal_move_assign(concurrent_skip_list &&other, std::false_type)
typename traits_type::compare_type key_compare
typename std::conditional< is_const, typename node_type::const_reference, typename node_type::reference >::type reference
iterator find(const key_type &key)
static iterator get_iterator(const_iterator it)
size_type internal_count(const K &key) const
aligned_storage_type my_val
std::atomic< node_pointer > atomic_node_pointer
iterator insert(const_iterator, const_reference value)
auto first(Container &c) -> decltype(begin(c))
typename concurrent_skip_list::size_type size_type
std::atomic_bool my_fullyLinked
std::pair< iterator, bool > internal_insert(Args &&... args)
void insert(std::initializer_list< value_type > init)
void swap(atomic< T > &lhs, atomic< T > &rhs)
iterator unsafe_erase(iterator pos)
static bool const allow_multimapping
void fill_prev_next_arrays(array_type &prev_nodes, array_type &next_nodes, node_ptr prev, const key_type &key, const comparator &cmp)
bool try_insert_node(node_ptr new_node, array_type &prev_nodes, array_type &next_nodes)
iterator insert(const_iterator, node_type &&nh)
std::pair< iterator, bool > insert(node_type &&nh)
typename concurrent_skip_list::const_iterator iterator
bool contains(const key_type &key) const
reference operator *() const
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
const_iterator find(const K &key) const
iterator find(const K &key)
std::pair< iterator, bool > internal_insert_node(node_ptr new_node)
range_type(const concurrent_skip_list &l)
const_iterator upper_bound(const K &key) const
typename std::allocator_traits< allocator_type >::template rebind_alloc< uint8_t > node_allocator_type
std::geometric_distribution< size_t > distribution
value_compare value_comp() const
void internal_move_assign(concurrent_skip_list &&other, std::true_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 __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
key_compare key_comp() 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 __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_string_handle unsigned long long ITT_FORMAT lu const __itt_domain __itt_id __itt_string_handle __itt_metadata_type type
iterator unsafe_erase(const_iterator first, const_iterator last)
node_type unsafe_extract(const key_type &key)
typename traits_type::allocator_type allocator_type
skip_list_iterator< list_node_type, true > const_iterator
typename std::aligned_storage< sizeof(value_type), alignof(value_type)>::type aligned_storage_type
static constexpr size_type MAX_LEVEL
std::reverse_iterator< const_iterator > const_reverse_iterator
const atomic_node_pointer & my_next(size_type level) const
const value_type & const_reference
static const key_type & get_key(node_ptr n)
void move(tbb_thread &t1, tbb_thread &t2)