Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(302)

Side by Side Diff: base/containers/flat_tree.h

Issue 2854353002: Flat Tree Perftest
Patch Set: New Algo Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/containers/flat_set_perftest.cc ('k') | base/containers/flat_tree_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef BASE_CONTAINERS_FLAT_TREE_H_ 5 #ifndef BASE_CONTAINERS_FLAT_TREE_H_
6 #define BASE_CONTAINERS_FLAT_TREE_H_ 6 #define BASE_CONTAINERS_FLAT_TREE_H_
7 7
8 #include <algorithm> 8 #include <algorithm>
9 #include <vector> 9 #include <vector>
10 10
11 #include "base/memory/ptr_util.h"
12
11 namespace base { 13 namespace base {
12 14
13 enum FlatContainerDupes { 15 enum FlatContainerDupes {
14 KEEP_FIRST_OF_DUPES, 16 KEEP_FIRST_OF_DUPES,
15 KEEP_LAST_OF_DUPES, 17 KEEP_LAST_OF_DUPES,
16 }; 18 };
17 19
20 enum RangeInsertMethod {
21 ONE_BY_ONE,
22 STABLE_SORT_ALL,
23 STABLE_SORT_SMART,
24 STABLE_SORT_SMARTER,
25 };
26
18 namespace internal { 27 namespace internal {
19 28
20 // This algorithm is like unique() from the standard library except it 29 // This algorithm is like unique() from the standard library except it
21 // selects only the last of consecutive values instead of the first. 30 // selects only the last of consecutive values instead of the first.
22 template <class Iterator, class BinaryPredicate> 31 template <class Iterator, class BinaryPredicate>
23 Iterator LastUnique(Iterator first, Iterator last, BinaryPredicate compare) { 32 Iterator LastUnique(Iterator first, Iterator last, BinaryPredicate compare) {
24 Iterator replacable = std::adjacent_find(first, last, compare); 33 Iterator replacable = std::adjacent_find(first, last, compare);
25 34
26 // No duplicate elements found. 35 // No duplicate elements found.
27 if (replacable == last) 36 if (replacable == last)
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
193 // 202 //
194 // NOTE: Prefer to build a new flat_tree from a std::vector (or similar) 203 // NOTE: Prefer to build a new flat_tree from a std::vector (or similar)
195 // instead of calling insert() repeatedly. 204 // instead of calling insert() repeatedly.
196 205
197 std::pair<iterator, bool> insert(const value_type& val); 206 std::pair<iterator, bool> insert(const value_type& val);
198 std::pair<iterator, bool> insert(value_type&& val); 207 std::pair<iterator, bool> insert(value_type&& val);
199 208
200 iterator insert(const_iterator position_hint, const value_type& x); 209 iterator insert(const_iterator position_hint, const value_type& x);
201 iterator insert(const_iterator position_hint, value_type&& x); 210 iterator insert(const_iterator position_hint, value_type&& x);
202 211
212 template <class InputIterator>
213 void insert(InputIterator first,
214 InputIterator last,
215 RangeInsertMethod method);
216
203 template <class... Args> 217 template <class... Args>
204 std::pair<iterator, bool> emplace(Args&&... args); 218 std::pair<iterator, bool> emplace(Args&&... args);
205 219
206 template <class... Args> 220 template <class... Args>
207 iterator emplace_hint(const_iterator position_hint, Args&&... args); 221 iterator emplace_hint(const_iterator position_hint, Args&&... args);
208 222
209 // -------------------------------------------------------------------------- 223 // --------------------------------------------------------------------------
210 // Erase operations. 224 // Erase operations.
211 // 225 //
212 // Assume that every operation invalidates iterators and references. 226 // Assume that every operation invalidates iterators and references.
(...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after
549 // 563 //
550 // Currently we use position_hint the same way as eastl or boost: 564 // Currently we use position_hint the same way as eastl or boost:
551 // https://github.com/electronicarts/EASTL/blob/master/include/EASTL/vector_set. h#L493 565 // https://github.com/electronicarts/EASTL/blob/master/include/EASTL/vector_set. h#L493
552 // 566 //
553 // We duplicate code between copy and move version so that we can avoid 567 // We duplicate code between copy and move version so that we can avoid
554 // creating a temporary value. 568 // creating a temporary value.
555 569
556 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> 570 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
557 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::insert( 571 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::insert(
558 const value_type& val) -> std::pair<iterator, bool> { 572 const value_type& val) -> std::pair<iterator, bool> {
559 auto position = lower_bound(val); 573 GetKeyFromValue extractor;
574 auto position = lower_bound(extractor(val));
560 575
561 if (position == end() || impl_.get_value_comp()(val, *position)) 576 if (position == end() || impl_.get_value_comp()(val, *position))
562 return {impl_.body_.insert(position, val), true}; 577 return {impl_.body_.insert(position, val), true};
563 578
564 return {position, false}; 579 return {position, false};
565 } 580 }
566 581
567 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> 582 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
568 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::insert( 583 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::insert(
569 value_type&& val) -> std::pair<iterator, bool> { 584 value_type&& val) -> std::pair<iterator, bool> {
(...skipping 26 matching lines...) Expand all
596 if (position_hint == end() || impl_.get_value_comp()(val, *position_hint)) { 611 if (position_hint == end() || impl_.get_value_comp()(val, *position_hint)) {
597 if (position_hint == begin() || 612 if (position_hint == begin() ||
598 impl_.get_value_comp()(*(position_hint - 1), val)) 613 impl_.get_value_comp()(*(position_hint - 1), val))
599 // We have to cast away const because of crbug.com/677044. 614 // We have to cast away const because of crbug.com/677044.
600 return impl_.body_.insert(const_cast_it(position_hint), std::move(val)); 615 return impl_.body_.insert(const_cast_it(position_hint), std::move(val));
601 } 616 }
602 return insert(std::move(val)).first; 617 return insert(std::move(val)).first;
603 } 618 }
604 619
605 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> 620 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
621 template <class InputIterator>
622 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::insert(
623 InputIterator first,
624 InputIterator last,
625 RangeInsertMethod method) -> void {
626 switch (method) {
627 case ONE_BY_ONE:
628 for (; first != last; ++first) {
629 insert(*first);
630 }
631 return;
632
633 case STABLE_SORT_ALL:
634 impl_.body_.insert(impl_.body_.end(), first, last);
635 sort_and_unique(KEEP_FIRST_OF_DUPES);
636 return;
637
638 case STABLE_SORT_SMART: {
639 const size_type prev_size = size();
640 impl_.body_.insert(impl_.body_.end(), first, last);
641 std::stable_sort(std::next(begin(), prev_size), end(), value_comp());
642 std::inplace_merge(begin(), std::next(begin(), prev_size), end(),
643 value_comp());
644 erase(std::unique(begin(), end(),
645 [this](const value_type& lhs, const value_type& rhs) {
646 // lhs is already <= rhs due to sort, therefore
647 // !(lhs < rhs) <=> lhs == rhs.
648 return !value_comp()(lhs, rhs);
649 }),
650 end());
651 }
652
653 case STABLE_SORT_SMARTER: {
654 size_type prev_size = size();
655 std::copy_if(first, last, std::back_inserter(impl_.body_),
656 [this, prev_size](const value_type& val) {
657 return !std::binary_search(begin(),
658 std::next(begin(), prev_size),
659 val, value_comp());
660 });
661
662 iterator prev_end = begin() + prev_size;
663 std::stable_sort(prev_end, end(), value_comp());
664 erase(std::unique(prev_end, end(),
665 [this](const value_type& lhs, const value_type& rhs) {
666 // lhs is already <= rhs due to sort, therefore
667 // !(lhs < rhs) <=> lhs == rhs.
668 return !value_comp()(lhs, rhs);
669 }),
670 end());
671
672 if (prev_end != end()) {
673 std::inplace_merge(
674 std::lower_bound(begin(), prev_end, *prev_end, value_comp()),
675 prev_end, end(), value_comp());
676 }
677 }
678 }
679 }
680
681 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
606 template <class... Args> 682 template <class... Args>
607 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::emplace(Args&&... args) 683 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::emplace(Args&&... args)
608 -> std::pair<iterator, bool> { 684 -> std::pair<iterator, bool> {
609 return insert(value_type(std::forward<Args>(args)...)); 685 return insert(value_type(std::forward<Args>(args)...));
610 } 686 }
611 687
612 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> 688 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
613 template <class... Args> 689 template <class... Args>
614 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::emplace_hint( 690 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::emplace_hint(
615 const_iterator position_hint, 691 const_iterator position_hint,
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
768 void EraseIf(base::internal::flat_tree<Key, Value, GetKeyFromValue, KeyCompare>& 844 void EraseIf(base::internal::flat_tree<Key, Value, GetKeyFromValue, KeyCompare>&
769 container, 845 container,
770 Predicate pred) { 846 Predicate pred) {
771 container.erase(std::remove_if(container.begin(), container.end(), pred), 847 container.erase(std::remove_if(container.begin(), container.end(), pred),
772 container.end()); 848 container.end());
773 } 849 }
774 850
775 } // namespace base 851 } // namespace base
776 852
777 #endif // BASE_CONTAINERS_FLAT_TREE_H_ 853 #endif // BASE_CONTAINERS_FLAT_TREE_H_
OLDNEW
« no previous file with comments | « base/containers/flat_set_perftest.cc ('k') | base/containers/flat_tree_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698