OLD | NEW |
---|---|
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_SET_H_ | 5 #ifndef BASE_CONTAINERS_FLAT_SET_H_ |
6 #define BASE_CONTAINERS_FLAT_SET_H_ | 6 #define BASE_CONTAINERS_FLAT_SET_H_ |
7 | 7 |
8 #include "base/containers/flat_tree.h" | 8 #include "base/containers/flat_tree.h" |
9 | 9 |
10 namespace base { | 10 namespace base { |
11 | 11 |
12 // Overview: | 12 // Overview: |
13 // This file implements flat_set container. It is an alternative to standard | 13 // This file implements flat_set container. It is an alternative to standard |
14 // sorted containers that stores it's elements in contiguous memory (current | 14 // sorted containers that stores it's elements in contiguous memory using a |
15 // version uses sorted std::vector). | 15 // std::vector. |
16 // | |
16 // Discussion that preceded introduction of this container can be found here: | 17 // Discussion that preceded introduction of this container can be found here: |
17 // https://groups.google.com/a/chromium.org/forum/#!searchin/chromium-dev/vector $20based/chromium-dev/4uQMma9vj9w/HaQ-WvMOAwAJ | 18 // https://groups.google.com/a/chromium.org/forum/#!searchin/chromium-dev/vector $20based/chromium-dev/4uQMma9vj9w/HaQ-WvMOAwAJ |
18 // | 19 // |
19 // Motivation: | 20 // Motivation: |
20 // Contiguous memory is very beneficial to iteration and copy speed at the cost | 21 // Contiguous memory is very beneficial to iteration and copy speed at the cost |
21 // of worse algorithmic complexity of insertion/erasure operations. They can | 22 // of worse algorithmic complexity of insertion/erasure operations. They can |
22 // be very fast for set operations and for small number of elements. | 23 // be very fast for set operations and for small number of elements. |
23 // | 24 // |
24 // Usage guidance: | 25 // Usage guidance: |
danakj
2017/04/05 21:33:43
Noticing that guidance of some sort like this is c
| |
25 // Prefer base::flat_set for: | 26 // Prefer base::flat_set for: |
26 // * Very small sets, something that is an easy fit for cache. Consider | 27 // * Very small sets, something that is an easy fit for cache. Consider |
27 // "very small" to be under a 100 32bit integers. | 28 // "very small" to be under 100 32bit integers. |
28 // * Sets that are built once (using flat_set::flat_set(first, last)). Consider | 29 // * Sets that are built once (using flat_set::flat_set(first, last)). Consider |
29 // collecting all data in a vector and then building flat_set out of it. | 30 // collecting all data in a vector and then building flat_set out of it. |
30 // TODO(dyaroshev): improve the interface to better support this pattern | 31 // Using the cosntructor that takes a vector rvalue allows you to re-use |
danakj
2017/04/05 21:33:43
no rvalue
brettw
2017/04/07 21:59:03
Done.
| |
31 // (crbug.com/682254). | 32 // storage. |
32 // * Sets where mutating happens in big bulks: to erase multiple elements, use | 33 // * Sets where mutating happens in big bulks: to erase multiple elements, use |
33 // base::EraseIf() rather than repeated single-element removal. Insertion is | 34 // base::EraseIf() rather than repeated single-element removal. Insertion is |
34 // harder - consider set operations or building a new vector. Set operations | 35 // harder - consider set operations or building a new vector. Set operations |
35 // can be slow if one of the sets is considerably bigger. Also be aware that | 36 // can be slow if one of the sets is considerably bigger. Also be aware that |
36 // beating performance of sort + unique (implementation of flat_set's | 37 // beating performance of sort + unique (implementation of flat_set's |
37 // constructor) is hard, clever merge of many sets might not win. Generally | 38 // constructor) is hard, clever merge of many sets might not win. Generally |
38 // avoid inserting into flat set without benchmarks. | 39 // avoid inserting into flat set without benchmarks. |
39 // * Copying and iterating. | 40 // * Copying and iterating. |
40 // * Set operations (union/intersect etc). | 41 // * Set operations (union/intersect etc). |
41 // | 42 // |
42 // Prefer to build a new flat_set from a std::vector (or similar) instead of | 43 // Prefer to build a new flat_set from a std::vector (or similar) instead of |
43 // calling insert() repeatedly, which would have O(size^2) complexity. | 44 // calling insert() repeatedly, which would have O(size^2) complexity. The |
45 // constructor that moves a vector (not required to be sorted) is the most | |
danakj
2017/04/05 21:33:43
receives a vector?
brettw
2017/04/07 21:59:04
Done.
| |
46 // efficient. | |
44 // | 47 // |
45 // TODO(dyaroshev): develop standalone benchmarks to find performance boundaries | 48 // TODO(dyaroshev): develop standalone benchmarks to find performance boundaries |
46 // for different types of sets crbug.com/682215. | 49 // for different types of sets crbug.com/682215. |
47 // | 50 // |
48 // If you do write a benchmark that significantly depends on using sets please | 51 // If you do write a benchmark that significantly depends on using sets please |
49 // share your results at: | 52 // share your results at: |
50 // https://groups.google.com/a/chromium.org/forum/#!searchin/chromium-dev/vector $20based/chromium-dev/4uQMma9vj9w/HaQ-WvMOAwAJ | 53 // https://groups.google.com/a/chromium.org/forum/#!searchin/chromium-dev/vector $20based/chromium-dev/4uQMma9vj9w/HaQ-WvMOAwAJ |
51 // | 54 // |
52 // Important usability aspects: | 55 // Important usability aspects: |
53 // * flat_set implements std::set interface from C++11 where possible. It | 56 // * flat_set implements std::set interface from C++11 where possible. It |
54 // also has reserve(), capacity() and shrink_to_fit() from std::vector. | 57 // also has reserve(), capacity() and shrink_to_fit() from std::vector. |
55 // * iteration invalidation rules differ: | 58 // * iteration invalidation rules differ: |
56 // - all cases of std::vector::iterator invalidation also apply. | 59 // - all cases of std::vector::iterator invalidation also apply. |
57 // - we ask (for now) to assume that move operations invalidate iterators. | 60 // - we ask (for now) to assume that move operations invalidate iterators. |
58 // TODO(dyaroshev): Research the possibility of using a small buffer | 61 // TODO(dyaroshev): Research the possibility of using a small buffer |
59 // optimization crbug.com/682240. | 62 // optimization crbug.com/682240. |
60 // * Constructor sorts elements in a non-stable manner (unlike std::set). So | |
61 // among equivalent (with respect to provided compare) elements passed to | |
62 // the constructor it is unspecified with one will end up in the set. | |
63 // However insert()/emplace() methods are stable with respect to already | |
64 // inserted elements - an element that is already in the set will not be | |
65 // replaced. | |
66 // * allocator support is not implemented. | 63 // * allocator support is not implemented. |
67 // * insert(first, last) and insert(std::initializer_list) are not | 64 // * insert(first, last) and insert(std::initializer_list) are not |
68 // implemented (see Notes section). | 65 // implemented (see Notes section). |
69 // | 66 // |
70 // Notes: | 67 // Notes: |
71 // Current implementation is based on boost::containers::flat_set, | 68 // Current implementation is based on boost::containers::flat_set, |
72 // eastl::vector_set and folly::sorted_vector. All of these implementations do | 69 // eastl::vector_set and folly::sorted_vector. All of these implementations do |
73 // insert(first, last) as insertion one by one (some implementations with hints | 70 // insert(first, last) as insertion one by one (some implementations with hints |
74 // and/or reserve). Boost documentation claims this algorithm to be O(n*log(n)) | 71 // and/or reserve). Boost documentation claims this algorithm to be O(n*log(n)) |
75 // but it seems to be a quadratic algorithm. For now we do not implement this | 72 // but it seems to be a quadratic algorithm. For now we do not implement this |
76 // method. | 73 // method. |
77 // TODO(dyaroshev): research an algorithm for range insertion crbug.com/682249. | 74 // TODO(dyaroshev): research an algorithm for range insertion crbug.com/682249. |
78 | 75 |
79 // QUICK REFERENCE | 76 // QUICK REFERENCE |
80 // | 77 // |
81 // Most of the core functionality is inherited from flat_tree. Please see | 78 // Most of the core functionality is inherited from flat_tree. Please see |
82 // flat_tree.h for more details for most of these functions. As a quick | 79 // flat_tree.h for more details for most of these functions. As a quick |
83 // reference, the functions available are: | 80 // reference, the functions available are: |
84 // | 81 // |
82 // Constructors (inputs need not be sorted, first of duplicates will be kept): | |
danakj
2017/04/05 21:33:42
Like in the map, the comments saying first is kept
brettw
2017/04/07 21:59:04
Done.
| |
83 // flat_set(InputIterator first, InputIterator last, | |
84 // FlatContainerDupes, const Compare& compare = Compare()); | |
85 // flat_set(const flat_set&); | |
86 // flat_set(flat_set&&); | |
87 // flat_set(std::vector<Key>, FlatContainerDupes); // Re-use storage. | |
88 // flat_set(std::initializer_list<value_type> ilist, | |
89 // const Compare& comp = Compare()); | |
90 // | |
85 // Assignment functions: | 91 // Assignment functions: |
86 // flat_set& operator=(const flat_set&); | 92 // flat_set& operator=(const flat_set&); |
87 // flat_set& operator=(flat_set&&); | 93 // flat_set& operator=(flat_set&&); |
88 // flat_set& operator=(initializer_list<Key>); | 94 // flat_set& operator=(initializer_list<Key>); |
89 // | 95 // |
90 // Memory management functions: | 96 // Memory management functions: |
91 // void reserve(size_t); | 97 // void reserve(size_t); |
92 // size_t capacity() const; | 98 // size_t capacity() const; |
93 // void shrink_to_fit(); | 99 // void shrink_to_fit(); |
94 // | 100 // |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
130 // Search functions: | 136 // Search functions: |
131 // size_t count(const Key&) const; | 137 // size_t count(const Key&) const; |
132 // iterator find(const Key&); | 138 // iterator find(const Key&); |
133 // const_iterator find(const Key&) const; | 139 // const_iterator find(const Key&) const; |
134 // pair<iterator, iterator> equal_range(Key&) | 140 // pair<iterator, iterator> equal_range(Key&) |
135 // iterator lower_bound(const Key&); | 141 // iterator lower_bound(const Key&); |
136 // const_iterator lower_bound(const Key&) const; | 142 // const_iterator lower_bound(const Key&) const; |
137 // iterator upper_bound(const Key&); | 143 // iterator upper_bound(const Key&); |
138 // const_iterator upper_bound(const Key&) const; | 144 // const_iterator upper_bound(const Key&) const; |
139 // | 145 // |
140 // General functions | 146 // General functions: |
141 // void swap(flat_set&&) | 147 // void swap(flat_set&&) |
142 // | 148 // |
143 // Non-member operators: | 149 // Non-member operators: |
144 // bool operator==(const flat_set&, const flat_set); | 150 // bool operator==(const flat_set&, const flat_set); |
145 // bool operator!=(const flat_set&, const flat_set); | 151 // bool operator!=(const flat_set&, const flat_set); |
146 // bool operator<(const flat_set&, const flat_set); | 152 // bool operator<(const flat_set&, const flat_set); |
147 // bool operator>(const flat_set&, const flat_set); | 153 // bool operator>(const flat_set&, const flat_set); |
148 // bool operator>=(const flat_set&, const flat_set); | 154 // bool operator>=(const flat_set&, const flat_set); |
149 // bool operator<=(const flat_set&, const flat_set); | 155 // bool operator<=(const flat_set&, const flat_set); |
150 // | 156 // |
151 template <class Key, class Compare = std::less<Key>> | 157 template <class Key, class Compare = std::less<Key>> |
152 using flat_set = typename ::base::internal::flat_tree< | 158 using flat_set = typename ::base::internal::flat_tree< |
153 Key, | 159 Key, |
154 Key, | 160 Key, |
155 ::base::internal::GetKeyFromValueIdentity<Key>, | 161 ::base::internal::GetKeyFromValueIdentity<Key>, |
156 Compare>; | 162 Compare>; |
157 | 163 |
158 } // namespace base | 164 } // namespace base |
159 | 165 |
160 #endif // BASE_CONTAINERS_FLAT_SET_H_ | 166 #endif // BASE_CONTAINERS_FLAT_SET_H_ |
OLD | NEW |