Skip to content

Commit 8bed2d3

Browse files
committed
[libc++] Optimize multi{map,set}::insert
1 parent 37fe7a9 commit 8bed2d3

File tree

3 files changed

+35
-7
lines changed

3 files changed

+35
-7
lines changed

libcxx/include/__tree

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -970,6 +970,36 @@ public:
970970
__emplace_hint_multi(__p, std::move(__value));
971971
}
972972

973+
template <class _InIter, class _Sent>
974+
_LIBCPP_HIDE_FROM_ABI void __insert_range_multi(_InIter __first, _Sent __last) {
975+
if (__first == __last)
976+
return;
977+
978+
if (__root() == nullptr) { // Make sure we always have a root node
979+
__node_holder __node = __construct_node(*__first);
980+
__insert_node_at(__end_node(), __end_node()->__left_, static_cast<__node_base_pointer>(__node.release()));
981+
++__first;
982+
}
983+
984+
auto __max_node = static_cast<__node_pointer>(std::__tree_max(static_cast<__node_base_pointer>(__root())));
985+
__node_pointer __last_insertion = __root();
986+
987+
for (; __first != __last; ++__first) {
988+
__node_holder __node = __construct_node(*__first);
989+
if (!value_comp()(__node->__get_value(), __max_node->__get_value())) { // __node >= __max_val
990+
__insert_node_at(static_cast<__end_node_pointer>(__max_node),
991+
__max_node->__right_,
992+
static_cast<__node_base_pointer>(__node.get()));
993+
__max_node = __node.release();
994+
} else {
995+
__end_node_pointer __parent;
996+
__node_base_pointer& __child = __find_leaf(++iterator(__last_insertion), __parent, __node->__value_);
997+
__last_insertion = __node.get();
998+
__insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__node.release()));
999+
}
1000+
}
1001+
}
1002+
9731003
_LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __node_assign_unique(const value_type& __v, __node_pointer __dest);
9741004

9751005
_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)