Skip to content

Commit 2f03769

Browse files
committed
[libc++] Optimize multi{map,set}::insert
1 parent 900d20d commit 2f03769

File tree

3 files changed

+33
-7
lines changed

3 files changed

+33
-7
lines changed

libcxx/include/__tree

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -995,6 +995,34 @@ public:
995995
__emplace_hint_multi(__p, std::move(__value));
996996
}
997997

998+
template <class _InIter, class _Sent>
999+
_LIBCPP_HIDE_FROM_ABI void __insert_range_multi(_InIter __first, _Sent __last) {
1000+
if (__first == __last)
1001+
return;
1002+
1003+
if (__root() == nullptr) { // Make sure we always have a root node
1004+
__node_holder __node = __construct_node(*__first);
1005+
__insert_node_at(__end_node(), __end_node()->__left_, static_cast<__node_base_pointer>(__node.release()));
1006+
++__first;
1007+
}
1008+
1009+
auto __max_node = static_cast<__node_pointer>(std::__tree_max(static_cast<__node_base_pointer>(__root())));
1010+
__node_pointer __last_insertion = __root();
1011+
1012+
for (; __first != __last; ++__first) {
1013+
__node_holder __node = __construct_node(*__first);
1014+
if (!value_comp()(__node->__get_value(), __max_node->__get_value())) { // __node >= __max_val
1015+
__insert_node_at(__max_node, __max_node->__right_, __node.get());
1016+
__max_node = __node.release();
1017+
} else {
1018+
__end_node_pointer __parent;
1019+
__node_base_pointer& __child = __find_leaf(++iterator(__last_insertion), __parent, __node->__value_);
1020+
__last_insertion = __node.get();
1021+
__insert_node_at(__parent, __child, __node.release());
1022+
}
1023+
}
1024+
}
1025+
9981026
_LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __node_assign_unique(const value_type& __v, __node_pointer __dest);
9991027

10001028
_LIBCPP_HIDE_FROM_ABI iterator __node_insert_multi(__node_pointer __nd);

libcxx/include/map

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -593,6 +593,7 @@ erase_if(multimap<Key, T, Compare, Allocator>& c, Predicate pred); // C++20
593593
# include <__memory/unique_ptr.h>
594594
# include <__memory_resource/polymorphic_allocator.h>
595595
# include <__node_handle>
596+
# include <__ranges/access.h>
596597
# include <__ranges/concepts.h>
597598
# include <__ranges/container_compatible_range.h>
598599
# include <__ranges/from_range.h>

libcxx/include/set

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -530,6 +530,7 @@ erase_if(multiset<Key, Compare, Allocator>& c, Predicate pred); // C++20
530530
# include <__memory/allocator_traits.h>
531531
# include <__memory_resource/polymorphic_allocator.h>
532532
# include <__node_handle>
533+
# include <__ranges/access.h>
533534
# include <__ranges/concepts.h>
534535
# include <__ranges/container_compatible_range.h>
535536
# include <__ranges/from_range.h>
@@ -1205,18 +1206,14 @@ public:
12051206
}
12061207

12071208
template <class _InputIterator>
1208-
_LIBCPP_HIDE_FROM_ABI void insert(_InputIterator __f, _InputIterator __l) {
1209-
for (const_iterator __e = cend(); __f != __l; ++__f)
1210-
__tree_.__emplace_hint_multi(__e, *__f);
1209+
_LIBCPP_HIDE_FROM_ABI void insert(_InputIterator __first, _InputIterator __last) {
1210+
__tree_.__insert_range_multi(__first, __last);
12111211
}
12121212

12131213
# if _LIBCPP_STD_VER >= 23
12141214
template <_ContainerCompatibleRange<value_type> _Range>
12151215
_LIBCPP_HIDE_FROM_ABI void insert_range(_Range&& __range) {
1216-
const_iterator __end = cend();
1217-
for (auto&& __element : __range) {
1218-
__tree_.__emplace_hint_multi(__end, std::forward<decltype(__element)>(__element));
1219-
}
1216+
__tree_.__insert_range_multi(ranges::begin(__range), ranges::end(__range));
12201217
}
12211218
# endif
12221219

0 commit comments

Comments
 (0)