| 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: |
| 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 |
| 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 |
| 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): |
| 83 // flat_set(InputIterator first, InputIterator last, |
| 84 // const Compare& compare = Compare()); |
| 85 // flat_set(const flat_set&); |
| 86 // flat_set(flat_set&&); |
| 87 // flat_set(std::vector<Key>&&); |
| 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 |