1 // Copyright 2018 The Abseil Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // A btree implementation of the STL set and map interfaces. A btree is smaller 16 // and generally also faster than STL set/map (refer to the benchmarks below). 17 // The red-black tree implementation of STL set/map has an overhead of 3 18 // pointers (left, right and parent) plus the node color information for each 19 // stored value. So a set<int32_t> consumes 40 bytes for each value stored in 20 // 64-bit mode. This btree implementation stores multiple values on fixed 21 // size nodes (usually 256 bytes) and doesn't store child pointers for leaf 22 // nodes. The result is that a btree_set<int32_t> may use much less memory per 23 // stored value. For the random insertion benchmark in btree_bench.cc, a 24 // btree_set<int32_t> with node-size of 256 uses 5.1 bytes per stored value. 25 // 26 // The packing of multiple values on to each node of a btree has another effect 27 // besides better space utilization: better cache locality due to fewer cache 28 // lines being accessed. Better cache locality translates into faster 29 // operations. 30 // 31 // CAVEATS 32 // 33 // Insertions and deletions on a btree can cause splitting, merging or 34 // rebalancing of btree nodes. And even without these operations, insertions 35 // and deletions on a btree will move values around within a node. In both 36 // cases, the result is that insertions and deletions can invalidate iterators 37 // pointing to values other than the one being inserted/deleted. Therefore, this 38 // container does not provide pointer stability. This is notably different from 39 // STL set/map which takes care to not invalidate iterators on insert/erase 40 // except, of course, for iterators pointing to the value being erased. A 41 // partial workaround when erasing is available: erase() returns an iterator 42 // pointing to the item just after the one that was erased (or end() if none 43 // exists). 44 45 #ifndef ABSL_CONTAINER_INTERNAL_BTREE_H_ 46 #define ABSL_CONTAINER_INTERNAL_BTREE_H_ 47 48 #include <algorithm> 49 #include <cassert> 50 #include <cstddef> 51 #include <cstdint> 52 #include <cstring> 53 #include <functional> 54 #include <iterator> 55 #include <limits> 56 #include <new> 57 #include <string> 58 #include <type_traits> 59 #include <utility> 60 61 #include "absl/base/macros.h" 62 #include "absl/container/internal/common.h" 63 #include "absl/container/internal/compressed_tuple.h" 64 #include "absl/container/internal/container_memory.h" 65 #include "absl/container/internal/layout.h" 66 #include "absl/memory/memory.h" 67 #include "absl/meta/type_traits.h" 68 #include "absl/strings/string_view.h" 69 #include "absl/types/compare.h" 70 #include "absl/utility/utility.h" 71 72 namespace absl { 73 ABSL_NAMESPACE_BEGIN 74 namespace container_internal { 75 76 // A helper class that indicates if the Compare parameter is a key-compare-to 77 // comparator. 78 template <typename Compare, typename T> 79 using btree_is_key_compare_to = 80 std::is_convertible<absl::result_of_t<Compare(const T &, const T &)>, 81 absl::weak_ordering>; 82 83 struct StringBtreeDefaultLess { 84 using is_transparent = void; 85 86 StringBtreeDefaultLess() = default; 87 88 // Compatibility constructor. StringBtreeDefaultLessStringBtreeDefaultLess89 StringBtreeDefaultLess(std::less<std::string>) {} // NOLINT StringBtreeDefaultLessStringBtreeDefaultLess90 StringBtreeDefaultLess(std::less<string_view>) {} // NOLINT 91 operatorStringBtreeDefaultLess92 absl::weak_ordering operator()(absl::string_view lhs, 93 absl::string_view rhs) const { 94 return compare_internal::compare_result_as_ordering(lhs.compare(rhs)); 95 } 96 }; 97 98 struct StringBtreeDefaultGreater { 99 using is_transparent = void; 100 101 StringBtreeDefaultGreater() = default; 102 StringBtreeDefaultGreaterStringBtreeDefaultGreater103 StringBtreeDefaultGreater(std::greater<std::string>) {} // NOLINT StringBtreeDefaultGreaterStringBtreeDefaultGreater104 StringBtreeDefaultGreater(std::greater<string_view>) {} // NOLINT 105 operatorStringBtreeDefaultGreater106 absl::weak_ordering operator()(absl::string_view lhs, 107 absl::string_view rhs) const { 108 return compare_internal::compare_result_as_ordering(rhs.compare(lhs)); 109 } 110 }; 111 112 // A helper class to convert a boolean comparison into a three-way "compare-to" 113 // comparison that returns a negative value to indicate less-than, zero to 114 // indicate equality and a positive value to indicate greater-than. This helper 115 // class is specialized for less<std::string>, greater<std::string>, 116 // less<string_view>, and greater<string_view>. 117 // 118 // key_compare_to_adapter is provided so that btree users 119 // automatically get the more efficient compare-to code when using common 120 // google string types with common comparison functors. 121 // These string-like specializations also turn on heterogeneous lookup by 122 // default. 123 template <typename Compare> 124 struct key_compare_to_adapter { 125 using type = Compare; 126 }; 127 128 template <> 129 struct key_compare_to_adapter<std::less<std::string>> { 130 using type = StringBtreeDefaultLess; 131 }; 132 133 template <> 134 struct key_compare_to_adapter<std::greater<std::string>> { 135 using type = StringBtreeDefaultGreater; 136 }; 137 138 template <> 139 struct key_compare_to_adapter<std::less<absl::string_view>> { 140 using type = StringBtreeDefaultLess; 141 }; 142 143 template <> 144 struct key_compare_to_adapter<std::greater<absl::string_view>> { 145 using type = StringBtreeDefaultGreater; 146 }; 147 148 template <typename Key, typename Compare, typename Alloc, int TargetNodeSize, 149 bool Multi, typename SlotPolicy> 150 struct common_params { 151 // If Compare is a common comparator for a std::string-like type, then we adapt it 152 // to use heterogeneous lookup and to be a key-compare-to comparator. 153 using key_compare = typename key_compare_to_adapter<Compare>::type; 154 // A type which indicates if we have a key-compare-to functor or a plain old 155 // key-compare functor. 156 using is_key_compare_to = btree_is_key_compare_to<key_compare, Key>; 157 158 using allocator_type = Alloc; 159 using key_type = Key; 160 using size_type = std::make_signed<size_t>::type; 161 using difference_type = ptrdiff_t; 162 163 // True if this is a multiset or multimap. 164 using is_multi_container = std::integral_constant<bool, Multi>; 165 166 using slot_policy = SlotPolicy; 167 using slot_type = typename slot_policy::slot_type; 168 using value_type = typename slot_policy::value_type; 169 using init_type = typename slot_policy::mutable_value_type; 170 using pointer = value_type *; 171 using const_pointer = const value_type *; 172 using reference = value_type &; 173 using const_reference = const value_type &; 174 175 enum { 176 kTargetNodeSize = TargetNodeSize, 177 178 // Upper bound for the available space for values. This is largest for leaf 179 // nodes, which have overhead of at least a pointer + 4 bytes (for storing 180 // 3 field_types and an enum). 181 kNodeValueSpace = 182 TargetNodeSize - /*minimum overhead=*/(sizeof(void *) + 4), 183 }; 184 185 // This is an integral type large enough to hold as many 186 // ValueSize-values as will fit a node of TargetNodeSize bytes. 187 using node_count_type = 188 absl::conditional_t<(kNodeValueSpace / sizeof(value_type) > 189 (std::numeric_limits<uint8_t>::max)()), 190 uint16_t, uint8_t>; // NOLINT 191 192 // The following methods are necessary for passing this struct as PolicyTraits 193 // for node_handle and/or are used within btree. 194 static value_type &element(slot_type *slot) { 195 return slot_policy::element(slot); 196 } 197 static const value_type &element(const slot_type *slot) { 198 return slot_policy::element(slot); 199 } 200 template <class... Args> 201 static void construct(Alloc *alloc, slot_type *slot, Args &&... args) { 202 slot_policy::construct(alloc, slot, std::forward<Args>(args)...); 203 } 204 static void construct(Alloc *alloc, slot_type *slot, slot_type *other) { 205 slot_policy::construct(alloc, slot, other); 206 } 207 static void destroy(Alloc *alloc, slot_type *slot) { 208 slot_policy::destroy(alloc, slot); 209 } 210 static void transfer(Alloc *alloc, slot_type *new_slot, slot_type *old_slot) { 211 construct(alloc, new_slot, old_slot); 212 destroy(alloc, old_slot); 213 } 214 static void swap(Alloc *alloc, slot_type *a, slot_type *b) { 215 slot_policy::swap(alloc, a, b); 216 } 217 static void move(Alloc *alloc, slot_type *src, slot_type *dest) { 218 slot_policy::move(alloc, src, dest); 219 } 220 static void move(Alloc *alloc, slot_type *first, slot_type *last, 221 slot_type *result) { 222 slot_policy::move(alloc, first, last, result); 223 } 224 }; 225 226 // A parameters structure for holding the type parameters for a btree_map. 227 // Compare and Alloc should be nothrow copy-constructible. 228 template <typename Key, typename Data, typename Compare, typename Alloc, 229 int TargetNodeSize, bool Multi> 230 struct map_params : common_params<Key, Compare, Alloc, TargetNodeSize, Multi, 231 map_slot_policy<Key, Data>> { 232 using super_type = typename map_params::common_params; 233 using mapped_type = Data; 234 // This type allows us to move keys when it is safe to do so. It is safe 235 // for maps in which value_type and mutable_value_type are layout compatible. 236 using slot_policy = typename super_type::slot_policy; 237 using slot_type = typename super_type::slot_type; 238 using value_type = typename super_type::value_type; 239 using init_type = typename super_type::init_type; 240 241 using key_compare = typename super_type::key_compare; 242 // Inherit from key_compare for empty base class optimization. 243 struct value_compare : private key_compare { 244 value_compare() = default; 245 explicit value_compare(const key_compare &cmp) : key_compare(cmp) {} 246 247 template <typename T, typename U> 248 auto operator()(const T &left, const U &right) const 249 -> decltype(std::declval<key_compare>()(left.first, right.first)) { 250 return key_compare::operator()(left.first, right.first); 251 } 252 }; 253 using is_map_container = std::true_type; 254 255 static const Key &key(const value_type &x) { return x.first; } 256 static const Key &key(const init_type &x) { return x.first; } 257 static const Key &key(const slot_type *x) { return slot_policy::key(x); } 258 static mapped_type &value(value_type *value) { return value->second; } 259 }; 260 261 // This type implements the necessary functions from the 262 // absl::container_internal::slot_type interface. 263 template <typename Key> 264 struct set_slot_policy { 265 using slot_type = Key; 266 using value_type = Key; 267 using mutable_value_type = Key; 268 269 static value_type &element(slot_type *slot) { return *slot; } 270 static const value_type &element(const slot_type *slot) { return *slot; } 271 272 template <typename Alloc, class... Args> 273 static void construct(Alloc *alloc, slot_type *slot, Args &&... args) { 274 absl::allocator_traits<Alloc>::construct(*alloc, slot, 275 std::forward<Args>(args)...); 276 } 277 278 template <typename Alloc> 279 static void construct(Alloc *alloc, slot_type *slot, slot_type *other) { 280 absl::allocator_traits<Alloc>::construct(*alloc, slot, std::move(*other)); 281 } 282 283 template <typename Alloc> 284 static void destroy(Alloc *alloc, slot_type *slot) { 285 absl::allocator_traits<Alloc>::destroy(*alloc, slot); 286 } 287 288 template <typename Alloc> 289 static void swap(Alloc * /*alloc*/, slot_type *a, slot_type *b) { 290 using std::swap; 291 swap(*a, *b); 292 } 293 294 template <typename Alloc> 295 static void move(Alloc * /*alloc*/, slot_type *src, slot_type *dest) { 296 *dest = std::move(*src); 297 } 298 299 template <typename Alloc> 300 static void move(Alloc *alloc, slot_type *first, slot_type *last, 301 slot_type *result) { 302 for (slot_type *src = first, *dest = result; src != last; ++src, ++dest) 303 move(alloc, src, dest); 304 } 305 }; 306 307 // A parameters structure for holding the type parameters for a btree_set. 308 // Compare and Alloc should be nothrow copy-constructible. 309 template <typename Key, typename Compare, typename Alloc, int TargetNodeSize, 310 bool Multi> 311 struct set_params : common_params<Key, Compare, Alloc, TargetNodeSize, Multi, 312 set_slot_policy<Key>> { 313 using value_type = Key; 314 using slot_type = typename set_params::common_params::slot_type; 315 using value_compare = typename set_params::common_params::key_compare; 316 using is_map_container = std::false_type; 317 318 static const Key &key(const value_type &x) { return x; } 319 static const Key &key(const slot_type *x) { return *x; } 320 }; 321 322 // An adapter class that converts a lower-bound compare into an upper-bound 323 // compare. Note: there is no need to make a version of this adapter specialized 324 // for key-compare-to functors because the upper-bound (the first value greater 325 // than the input) is never an exact match. 326 template <typename Compare> 327 struct upper_bound_adapter { 328 explicit upper_bound_adapter(const Compare &c) : comp(c) {} 329 template <typename K, typename LK> 330 bool operator()(const K &a, const LK &b) const { 331 // Returns true when a is not greater than b. 332 return !compare_internal::compare_result_as_less_than(comp(b, a)); 333 } 334 335 private: 336 Compare comp; 337 }; 338 339 enum class MatchKind : uint8_t { kEq, kNe }; 340 341 template <typename V, bool IsCompareTo> 342 struct SearchResult { 343 V value; 344 MatchKind match; 345 346 static constexpr bool HasMatch() { return true; } 347 bool IsEq() const { return match == MatchKind::kEq; } 348 }; 349 350 // When we don't use CompareTo, `match` is not present. 351 // This ensures that callers can't use it accidentally when it provides no 352 // useful information. 353 template <typename V> 354 struct SearchResult<V, false> { 355 V value; 356 357 static constexpr bool HasMatch() { return false; } 358 static constexpr bool IsEq() { return false; } 359 }; 360 361 // A node in the btree holding. The same node type is used for both internal 362 // and leaf nodes in the btree, though the nodes are allocated in such a way 363 // that the children array is only valid in internal nodes. 364 template <typename Params> 365 class btree_node { 366 using is_key_compare_to = typename Params::is_key_compare_to; 367 using is_multi_container = typename Params::is_multi_container; 368 using field_type = typename Params::node_count_type; 369 using allocator_type = typename Params::allocator_type; 370 using slot_type = typename Params::slot_type; 371 372 public: 373 using params_type = Params; 374 using key_type = typename Params::key_type; 375 using value_type = typename Params::value_type; 376 using pointer = typename Params::pointer; 377 using const_pointer = typename Params::const_pointer; 378 using reference = typename Params::reference; 379 using const_reference = typename Params::const_reference; 380 using key_compare = typename Params::key_compare; 381 using size_type = typename Params::size_type; 382 using difference_type = typename Params::difference_type; 383 384 // Btree decides whether to use linear node search as follows: 385 // - If the key is arithmetic and the comparator is std::less or 386 // std::greater, choose linear. 387 // - Otherwise, choose binary. 388 // TODO(ezb): Might make sense to add condition(s) based on node-size. 389 using use_linear_search = std::integral_constant< 390 bool, 391 std::is_arithmetic<key_type>::value && 392 (std::is_same<std::less<key_type>, key_compare>::value || 393 std::is_same<std::greater<key_type>, key_compare>::value)>; 394 395 // This class is organized by gtl::Layout as if it had the following 396 // structure: 397 // // A pointer to the node's parent. 398 // btree_node *parent; 399 // 400 // // The position of the node in the node's parent. 401 // field_type position; 402 // // The index of the first populated value in `values`. 403 // // TODO(ezb): right now, `start` is always 0. Update insertion/merge 404 // // logic to allow for floating storage within nodes. 405 // field_type start; 406 // // The index after the last populated value in `values`. Currently, this 407 // // is the same as the count of values. 408 // field_type finish; 409 // // The maximum number of values the node can hold. This is an integer in 410 // // [1, kNodeValues] for root leaf nodes, kNodeValues for non-root leaf 411 // // nodes, and kInternalNodeMaxCount (as a sentinel value) for internal 412 // // nodes (even though there are still kNodeValues values in the node). 413 // // TODO(ezb): make max_count use only 4 bits and record log2(capacity) 414 // // to free extra bits for is_root, etc. 415 // field_type max_count; 416 // 417 // // The array of values. The capacity is `max_count` for leaf nodes and 418 // // kNodeValues for internal nodes. Only the values in 419 // // [start, finish) have been initialized and are valid. 420 // slot_type values[max_count]; 421 // 422 // // The array of child pointers. The keys in children[i] are all less 423 // // than key(i). The keys in children[i + 1] are all greater than key(i). 424 // // There are 0 children for leaf nodes and kNodeValues + 1 children for 425 // // internal nodes. 426 // btree_node *children[kNodeValues + 1]; 427 // 428 // This class is only constructed by EmptyNodeType. Normally, pointers to the 429 // layout above are allocated, cast to btree_node*, and de-allocated within 430 // the btree implementation. 431 ~btree_node() = default; 432 btree_node(btree_node const &) = delete; 433 btree_node &operator=(btree_node const &) = delete; 434 435 // Public for EmptyNodeType. 436 constexpr static size_type Alignment() { 437 static_assert(LeafLayout(1).Alignment() == InternalLayout().Alignment(), 438 "Alignment of all nodes must be equal."); 439 return InternalLayout().Alignment(); 440 } 441 442 protected: 443 btree_node() = default; 444 445 private: 446 using layout_type = absl::container_internal::Layout<btree_node *, field_type, 447 slot_type, btree_node *>; 448 constexpr static size_type SizeWithNValues(size_type n) { 449 return layout_type(/*parent*/ 1, 450 /*position, start, finish, max_count*/ 4, 451 /*values*/ n, 452 /*children*/ 0) 453 .AllocSize(); 454 } 455 // A lower bound for the overhead of fields other than values in a leaf node. 456 constexpr static size_type MinimumOverhead() { 457 return SizeWithNValues(1) - sizeof(value_type); 458 } 459 460 // Compute how many values we can fit onto a leaf node taking into account 461 // padding. 462 constexpr static size_type NodeTargetValues(const int begin, const int end) { 463 return begin == end ? begin 464 : SizeWithNValues((begin + end) / 2 + 1) > 465 params_type::kTargetNodeSize 466 ? NodeTargetValues(begin, (begin + end) / 2) 467 : NodeTargetValues((begin + end) / 2 + 1, end); 468 } 469 470 enum { 471 kTargetNodeSize = params_type::kTargetNodeSize, 472 kNodeTargetValues = NodeTargetValues(0, params_type::kTargetNodeSize), 473 474 // We need a minimum of 3 values per internal node in order to perform 475 // splitting (1 value for the two nodes involved in the split and 1 value 476 // propagated to the parent as the delimiter for the split). 477 kNodeValues = kNodeTargetValues >= 3 ? kNodeTargetValues : 3, 478 479 // The node is internal (i.e. is not a leaf node) if and only if `max_count` 480 // has this value. 481 kInternalNodeMaxCount = 0, 482 }; 483 484 // Leaves can have less than kNodeValues values. 485 constexpr static layout_type LeafLayout(const int max_values = kNodeValues) { 486 return layout_type(/*parent*/ 1, 487 /*position, start, finish, max_count*/ 4, 488 /*values*/ max_values, 489 /*children*/ 0); 490 } 491 constexpr static layout_type InternalLayout() { 492 return layout_type(/*parent*/ 1, 493 /*position, start, finish, max_count*/ 4, 494 /*values*/ kNodeValues, 495 /*children*/ kNodeValues + 1); 496 } 497 constexpr static size_type LeafSize(const int max_values = kNodeValues) { 498 return LeafLayout(max_values).AllocSize(); 499 } 500 constexpr static size_type InternalSize() { 501 return InternalLayout().AllocSize(); 502 } 503 504 // N is the index of the type in the Layout definition. 505 // ElementType<N> is the Nth type in the Layout definition. 506 template <size_type N> 507 inline typename layout_type::template ElementType<N> *GetField() { 508 // We assert that we don't read from values that aren't there. 509 assert(N < 3 || !leaf()); 510 return InternalLayout().template Pointer<N>(reinterpret_cast<char *>(this)); 511 } 512 template <size_type N> 513 inline const typename layout_type::template ElementType<N> *GetField() const { 514 assert(N < 3 || !leaf()); 515 return InternalLayout().template Pointer<N>( 516 reinterpret_cast<const char *>(this)); 517 } 518 void set_parent(btree_node *p) { *GetField<0>() = p; } 519 field_type &mutable_finish() { return GetField<1>()[2]; } 520 slot_type *slot(int i) { return &GetField<2>()[i]; } 521 slot_type *start_slot() { return slot(start()); } 522 slot_type *finish_slot() { return slot(finish()); } 523 const slot_type *slot(int i) const { return &GetField<2>()[i]; } 524 void set_position(field_type v) { GetField<1>()[0] = v; } 525 void set_start(field_type v) { GetField<1>()[1] = v; } 526 void set_finish(field_type v) { GetField<1>()[2] = v; } 527 // This method is only called by the node init methods. 528 void set_max_count(field_type v) { GetField<1>()[3] = v; } 529 530 public: 531 // Whether this is a leaf node or not. This value doesn't change after the 532 // node is created. 533 bool leaf() const { return GetField<1>()[3] != kInternalNodeMaxCount; } 534 535 // Getter for the position of this node in its parent. 536 field_type position() const { return GetField<1>()[0]; } 537 538 // Getter for the offset of the first value in the `values` array. 539 field_type start() const { 540 // TODO(ezb): when floating storage is implemented, return GetField<1>()[1]; 541 assert(GetField<1>()[1] == 0); 542 return 0; 543 } 544 545 // Getter for the offset after the last value in the `values` array. 546 field_type finish() const { return GetField<1>()[2]; } 547 548 // Getters for the number of values stored in this node. 549 field_type count() const { 550 assert(finish() >= start()); 551 return finish() - start(); 552 } 553 field_type max_count() const { 554 // Internal nodes have max_count==kInternalNodeMaxCount. 555 // Leaf nodes have max_count in [1, kNodeValues]. 556 const field_type max_count = GetField<1>()[3]; 557 return max_count == field_type{kInternalNodeMaxCount} 558 ? field_type{kNodeValues} 559 : max_count; 560 } 561 562 // Getter for the parent of this node. 563 btree_node *parent() const { return *GetField<0>(); } 564 // Getter for whether the node is the root of the tree. The parent of the 565 // root of the tree is the leftmost node in the tree which is guaranteed to 566 // be a leaf. 567 bool is_root() const { return parent()->leaf(); } 568 void make_root() { 569 assert(parent()->is_root()); 570 set_parent(parent()->parent()); 571 } 572 573 // Getters for the key/value at position i in the node. 574 const key_type &key(int i) const { return params_type::key(slot(i)); } 575 reference value(int i) { return params_type::element(slot(i)); } 576 const_reference value(int i) const { return params_type::element(slot(i)); } 577 578 // Getters/setter for the child at position i in the node. 579 btree_node *child(int i) const { return GetField<3>()[i]; } 580 btree_node *start_child() const { return child(start()); } 581 btree_node *&mutable_child(int i) { return GetField<3>()[i]; } 582 void clear_child(int i) { 583 absl::container_internal::SanitizerPoisonObject(&mutable_child(i)); 584 } 585 void set_child(int i, btree_node *c) { 586 absl::container_internal::SanitizerUnpoisonObject(&mutable_child(i)); 587 mutable_child(i) = c; 588 c->set_position(i); 589 } 590 void init_child(int i, btree_node *c) { 591 set_child(i, c); 592 c->set_parent(this); 593 } 594 595 // Returns the position of the first value whose key is not less than k. 596 template <typename K> 597 SearchResult<int, is_key_compare_to::value> lower_bound( 598 const K &k, const key_compare &comp) const { 599 return use_linear_search::value ? linear_search(k, comp) 600 : binary_search(k, comp); 601 } 602 // Returns the position of the first value whose key is greater than k. 603 template <typename K> 604 int upper_bound(const K &k, const key_compare &comp) const { 605 auto upper_compare = upper_bound_adapter<key_compare>(comp); 606 return use_linear_search::value ? linear_search(k, upper_compare).value 607 : binary_search(k, upper_compare).value; 608 } 609 610 template <typename K, typename Compare> 611 SearchResult<int, btree_is_key_compare_to<Compare, key_type>::value> 612 linear_search(const K &k, const Compare &comp) const { 613 return linear_search_impl(k, start(), finish(), comp, 614 btree_is_key_compare_to<Compare, key_type>()); 615 } 616 617 template <typename K, typename Compare> 618 SearchResult<int, btree_is_key_compare_to<Compare, key_type>::value> 619 binary_search(const K &k, const Compare &comp) const { 620 return binary_search_impl(k, start(), finish(), comp, 621 btree_is_key_compare_to<Compare, key_type>()); 622 } 623 624 // Returns the position of the first value whose key is not less than k using 625 // linear search performed using plain compare. 626 template <typename K, typename Compare> 627 SearchResult<int, false> linear_search_impl( 628 const K &k, int s, const int e, const Compare &comp, 629 std::false_type /* IsCompareTo */) const { 630 while (s < e) { 631 if (!comp(key(s), k)) { 632 break; 633 } 634 ++s; 635 } 636 return {s}; 637 } 638 639 // Returns the position of the first value whose key is not less than k using 640 // linear search performed using compare-to. 641 template <typename K, typename Compare> 642 SearchResult<int, true> linear_search_impl( 643 const K &k, int s, const int e, const Compare &comp, 644 std::true_type /* IsCompareTo */) const { 645 while (s < e) { 646 const absl::weak_ordering c = comp(key(s), k); 647 if (c == 0) { 648 return {s, MatchKind::kEq}; 649 } else if (c > 0) { 650 break; 651 } 652 ++s; 653 } 654 return {s, MatchKind::kNe}; 655 } 656 657 // Returns the position of the first value whose key is not less than k using 658 // binary search performed using plain compare. 659 template <typename K, typename Compare> 660 SearchResult<int, false> binary_search_impl( 661 const K &k, int s, int e, const Compare &comp, 662 std::false_type /* IsCompareTo */) const { 663 while (s != e) { 664 const int mid = (s + e) >> 1; 665 if (comp(key(mid), k)) { 666 s = mid + 1; 667 } else { 668 e = mid; 669 } 670 } 671 return {s}; 672 } 673 674 // Returns the position of the first value whose key is not less than k using 675 // binary search performed using compare-to. 676 template <typename K, typename CompareTo> 677 SearchResult<int, true> binary_search_impl( 678 const K &k, int s, int e, const CompareTo &comp, 679 std::true_type /* IsCompareTo */) const { 680 if (is_multi_container::value) { 681 MatchKind exact_match = MatchKind::kNe; 682 while (s != e) { 683 const int mid = (s + e) >> 1; 684 const absl::weak_ordering c = comp(key(mid), k); 685 if (c < 0) { 686 s = mid + 1; 687 } else { 688 e = mid; 689 if (c == 0) { 690 // Need to return the first value whose key is not less than k, 691 // which requires continuing the binary search if this is a 692 // multi-container. 693 exact_match = MatchKind::kEq; 694 } 695 } 696 } 697 return {s, exact_match}; 698 } else { // Not a multi-container. 699 while (s != e) { 700 const int mid = (s + e) >> 1; 701 const absl::weak_ordering c = comp(key(mid), k); 702 if (c < 0) { 703 s = mid + 1; 704 } else if (c > 0) { 705 e = mid; 706 } else { 707 return {mid, MatchKind::kEq}; 708 } 709 } 710 return {s, MatchKind::kNe}; 711 } 712 } 713 714 // Emplaces a value at position i, shifting all existing values and 715 // children at positions >= i to the right by 1. 716 template <typename... Args> 717 void emplace_value(size_type i, allocator_type *alloc, Args &&... args); 718 719 // Removes the value at position i, shifting all existing values and children 720 // at positions > i to the left by 1. 721 void remove_value(int i, allocator_type *alloc); 722 723 // Removes the values at positions [i, i + to_erase), shifting all values 724 // after that range to the left by to_erase. Does not change children at all. 725 void remove_values_ignore_children(int i, int to_erase, 726 allocator_type *alloc); 727 728 // Rebalances a node with its right sibling. 729 void rebalance_right_to_left(int to_move, btree_node *right, 730 allocator_type *alloc); 731 void rebalance_left_to_right(int to_move, btree_node *right, 732 allocator_type *alloc); 733 734 // Splits a node, moving a portion of the node's values to its right sibling. 735 void split(int insert_position, btree_node *dest, allocator_type *alloc); 736 737 // Merges a node with its right sibling, moving all of the values and the 738 // delimiting key in the parent node onto itself. 739 void merge(btree_node *sibling, allocator_type *alloc); 740 741 // Swap the contents of "this" and "src". 742 void swap(btree_node *src, allocator_type *alloc); 743 744 // Node allocation/deletion routines. 745 static btree_node *init_leaf(btree_node *n, btree_node *parent, 746 int max_count) { 747 n->set_parent(parent); 748 n->set_position(0); 749 n->set_start(0); 750 n->set_finish(0); 751 n->set_max_count(max_count); 752 absl::container_internal::SanitizerPoisonMemoryRegion( 753 n->start_slot(), max_count * sizeof(slot_type)); 754 return n; 755 } 756 static btree_node *init_internal(btree_node *n, btree_node *parent) { 757 init_leaf(n, parent, kNodeValues); 758 // Set `max_count` to a sentinel value to indicate that this node is 759 // internal. 760 n->set_max_count(kInternalNodeMaxCount); 761 absl::container_internal::SanitizerPoisonMemoryRegion( 762 &n->mutable_child(n->start()), 763 (kNodeValues + 1) * sizeof(btree_node *)); 764 return n; 765 } 766 void destroy(allocator_type *alloc) { 767 for (int i = start(); i < finish(); ++i) { 768 value_destroy(i, alloc); 769 } 770 } 771 772 public: 773 // Exposed only for tests. 774 static bool testonly_uses_linear_node_search() { 775 return use_linear_search::value; 776 } 777 778 private: 779 template <typename... Args> 780 void value_init(const size_type i, allocator_type *alloc, Args &&... args) { 781 absl::container_internal::SanitizerUnpoisonObject(slot(i)); 782 params_type::construct(alloc, slot(i), std::forward<Args>(args)...); 783 } 784 void value_destroy(const size_type i, allocator_type *alloc) { 785 params_type::destroy(alloc, slot(i)); 786 absl::container_internal::SanitizerPoisonObject(slot(i)); 787 } 788 789 // Move n values starting at value i in this node into the values starting at 790 // value j in node x. 791 void uninitialized_move_n(const size_type n, const size_type i, 792 const size_type j, btree_node *x, 793 allocator_type *alloc) { 794 absl::container_internal::SanitizerUnpoisonMemoryRegion( 795 x->slot(j), n * sizeof(slot_type)); 796 for (slot_type *src = slot(i), *end = src + n, *dest = x->slot(j); 797 src != end; ++src, ++dest) { 798 params_type::construct(alloc, dest, src); 799 } 800 } 801 802 // Destroys a range of n values, starting at index i. 803 void value_destroy_n(const size_type i, const size_type n, 804 allocator_type *alloc) { 805 for (int j = 0; j < n; ++j) { 806 value_destroy(i + j, alloc); 807 } 808 } 809 810 template <typename P> 811 friend class btree; 812 template <typename N, typename R, typename P> 813 friend struct btree_iterator; 814 friend class BtreeNodePeer; 815 }; 816 817 template <typename Node, typename Reference, typename Pointer> 818 struct btree_iterator { 819 private: 820 using key_type = typename Node::key_type; 821 using size_type = typename Node::size_type; 822 using params_type = typename Node::params_type; 823 824 using node_type = Node; 825 using normal_node = typename std::remove_const<Node>::type; 826 using const_node = const Node; 827 using normal_pointer = typename params_type::pointer; 828 using normal_reference = typename params_type::reference; 829 using const_pointer = typename params_type::const_pointer; 830 using const_reference = typename params_type::const_reference; 831 using slot_type = typename params_type::slot_type; 832 833 using iterator = 834 btree_iterator<normal_node, normal_reference, normal_pointer>; 835 using const_iterator = 836 btree_iterator<const_node, const_reference, const_pointer>; 837 838 public: 839 // These aliases are public for std::iterator_traits. 840 using difference_type = typename Node::difference_type; 841 using value_type = typename params_type::value_type; 842 using pointer = Pointer; 843 using reference = Reference; 844 using iterator_category = std::bidirectional_iterator_tag; 845 846 btree_iterator() : node(nullptr), position(-1) {} 847 explicit btree_iterator(Node *n) : node(n), position(n->start()) {} 848 btree_iterator(Node *n, int p) : node(n), position(p) {} 849 850 // NOTE: this SFINAE allows for implicit conversions from iterator to 851 // const_iterator, but it specifically avoids defining copy constructors so 852 // that btree_iterator can be trivially copyable. This is for performance and 853 // binary size reasons. 854 template <typename N, typename R, typename P, 855 absl::enable_if_t< 856 std::is_same<btree_iterator<N, R, P>, iterator>::value && 857 std::is_same<btree_iterator, const_iterator>::value, 858 int> = 0> 859 btree_iterator(const btree_iterator<N, R, P> &x) // NOLINT 860 : node(x.node), position(x.position) {} 861 862 private: 863 // This SFINAE allows explicit conversions from const_iterator to 864 // iterator, but also avoids defining a copy constructor. 865 // NOTE: the const_cast is safe because this constructor is only called by 866 // non-const methods and the container owns the nodes. 867 template <typename N, typename R, typename P, 868 absl::enable_if_t< 869 std::is_same<btree_iterator<N, R, P>, const_iterator>::value && 870 std::is_same<btree_iterator, iterator>::value, 871 int> = 0> 872 explicit btree_iterator(const btree_iterator<N, R, P> &x) 873 : node(const_cast<node_type *>(x.node)), position(x.position) {} 874 875 // Increment/decrement the iterator. 876 void increment() { 877 if (node->leaf() && ++position < node->finish()) { 878 return; 879 } 880 increment_slow(); 881 } 882 void increment_slow(); 883 884 void decrement() { 885 if (node->leaf() && --position >= node->start()) { 886 return; 887 } 888 decrement_slow(); 889 } 890 void decrement_slow(); 891 892 public: 893 bool operator==(const const_iterator &x) const { 894 return node == x.node && position == x.position; 895 } 896 bool operator!=(const const_iterator &x) const { 897 return node != x.node || position != x.position; 898 } 899 900 // Accessors for the key/value the iterator is pointing at. 901 reference operator*() const { return node->value(position); } 902 pointer operator->() const { return &node->value(position); } 903 904 btree_iterator &operator++() { 905 increment(); 906 return *this; 907 } 908 btree_iterator &operator--() { 909 decrement(); 910 return *this; 911 } 912 btree_iterator operator++(int) { 913 btree_iterator tmp = *this; 914 ++*this; 915 return tmp; 916 } 917 btree_iterator operator--(int) { 918 btree_iterator tmp = *this; 919 --*this; 920 return tmp; 921 } 922 923 private: 924 template <typename Params> 925 friend class btree; 926 template <typename Tree> 927 friend class btree_container; 928 template <typename Tree> 929 friend class btree_set_container; 930 template <typename Tree> 931 friend class btree_map_container; 932 template <typename Tree> 933 friend class btree_multiset_container; 934 template <typename N, typename R, typename P> 935 friend struct btree_iterator; 936 template <typename TreeType, typename CheckerType> 937 friend class base_checker; 938 939 const key_type &key() const { return node->key(position); } 940 slot_type *slot() { return node->slot(position); } 941 942 // The node in the tree the iterator is pointing at. 943 Node *node; 944 // The position within the node of the tree the iterator is pointing at. 945 // TODO(ezb): make this a field_type 946 int position; 947 }; 948 949 template <typename Params> 950 class btree { 951 using node_type = btree_node<Params>; 952 using is_key_compare_to = typename Params::is_key_compare_to; 953 954 // We use a static empty node for the root/leftmost/rightmost of empty btrees 955 // in order to avoid branching in begin()/end(). 956 struct alignas(node_type::Alignment()) EmptyNodeType : node_type { 957 using field_type = typename node_type::field_type; 958 node_type *parent; 959 field_type position = 0; 960 field_type start = 0; 961 field_type finish = 0; 962 // max_count must be != kInternalNodeMaxCount (so that this node is regarded 963 // as a leaf node). max_count() is never called when the tree is empty. 964 field_type max_count = node_type::kInternalNodeMaxCount + 1; 965 966 #ifdef _MSC_VER 967 // MSVC has constexpr code generations bugs here. 968 EmptyNodeType() : parent(this) {} 969 #else 970 constexpr EmptyNodeType(node_type *p) : parent(p) {} 971 #endif 972 }; 973 974 static node_type *EmptyNode() { 975 #ifdef _MSC_VER 976 static EmptyNodeType *empty_node = new EmptyNodeType; 977 // This assert fails on some other construction methods. 978 assert(empty_node->parent == empty_node); 979 return empty_node; 980 #else 981 static constexpr EmptyNodeType empty_node( 982 const_cast<EmptyNodeType *>(&empty_node)); 983 return const_cast<EmptyNodeType *>(&empty_node); 984 #endif 985 } 986 987 enum { 988 kNodeValues = node_type::kNodeValues, 989 kMinNodeValues = kNodeValues / 2, 990 }; 991 992 struct node_stats { 993 using size_type = typename Params::size_type; 994 995 node_stats(size_type l, size_type i) : leaf_nodes(l), internal_nodes(i) {} 996 997 node_stats &operator+=(const node_stats &x) { 998 leaf_nodes += x.leaf_nodes; 999 internal_nodes += x.internal_nodes; 1000 return *this; 1001 } 1002 1003 size_type leaf_nodes; 1004 size_type internal_nodes; 1005 }; 1006 1007 public: 1008 using key_type = typename Params::key_type; 1009 using value_type = typename Params::value_type; 1010 using size_type = typename Params::size_type; 1011 using difference_type = typename Params::difference_type; 1012 using key_compare = typename Params::key_compare; 1013 using value_compare = typename Params::value_compare; 1014 using allocator_type = typename Params::allocator_type; 1015 using reference = typename Params::reference; 1016 using const_reference = typename Params::const_reference; 1017 using pointer = typename Params::pointer; 1018 using const_pointer = typename Params::const_pointer; 1019 using iterator = btree_iterator<node_type, reference, pointer>; 1020 using const_iterator = typename iterator::const_iterator; 1021 using reverse_iterator = std::reverse_iterator<iterator>; 1022 using const_reverse_iterator = std::reverse_iterator<const_iterator>; 1023 using node_handle_type = node_handle<Params, Params, allocator_type>; 1024 1025 // Internal types made public for use by btree_container types. 1026 using params_type = Params; 1027 using slot_type = typename Params::slot_type; 1028 1029 private: 1030 // For use in copy_or_move_values_in_order. 1031 const value_type &maybe_move_from_iterator(const_iterator x) { return *x; } 1032 value_type &&maybe_move_from_iterator(iterator x) { return std::move(*x); } 1033 1034 // Copies or moves (depending on the template parameter) the values in 1035 // x into this btree in their order in x. This btree must be empty before this 1036 // method is called. This method is used in copy construction, copy 1037 // assignment, and move assignment. 1038 template <typename Btree> 1039 void copy_or_move_values_in_order(Btree *x); 1040 1041 // Validates that various assumptions/requirements are true at compile time. 1042 constexpr static bool static_assert_validation(); 1043 1044 public: 1045 btree(const key_compare &comp, const allocator_type &alloc); 1046 1047 btree(const btree &x); 1048 btree(btree &&x) noexcept 1049 : root_(std::move(x.root_)), 1050 rightmost_(absl::exchange(x.rightmost_, EmptyNode())), 1051 size_(absl::exchange(x.size_, 0)) { 1052 x.mutable_root() = EmptyNode(); 1053 } 1054 1055 ~btree() { 1056 // Put static_asserts in destructor to avoid triggering them before the type 1057 // is complete. 1058 static_assert(static_assert_validation(), "This call must be elided."); 1059 clear(); 1060 } 1061 1062 // Assign the contents of x to *this. 1063 btree &operator=(const btree &x); 1064 btree &operator=(btree &&x) noexcept; 1065 1066 iterator begin() { return iterator(leftmost()); } 1067 const_iterator begin() const { return const_iterator(leftmost()); } 1068 iterator end() { return iterator(rightmost_, rightmost_->finish()); } 1069 const_iterator end() const { 1070 return const_iterator(rightmost_, rightmost_->finish()); 1071 } 1072 reverse_iterator rbegin() { return reverse_iterator(end()); } 1073 const_reverse_iterator rbegin() const { 1074 return const_reverse_iterator(end()); 1075 } 1076 reverse_iterator rend() { return reverse_iterator(begin()); } 1077 const_reverse_iterator rend() const { 1078 return const_reverse_iterator(begin()); 1079 } 1080 1081 // Finds the first element whose key is not less than key. 1082 template <typename K> 1083 iterator lower_bound(const K &key) { 1084 return internal_end(internal_lower_bound(key)); 1085 } 1086 template <typename K> 1087 const_iterator lower_bound(const K &key) const { 1088 return internal_end(internal_lower_bound(key)); 1089 } 1090 1091 // Finds the first element whose key is greater than key. 1092 template <typename K> 1093 iterator upper_bound(const K &key) { 1094 return internal_end(internal_upper_bound(key)); 1095 } 1096 template <typename K> 1097 const_iterator upper_bound(const K &key) const { 1098 return internal_end(internal_upper_bound(key)); 1099 } 1100 1101 // Finds the range of values which compare equal to key. The first member of 1102 // the returned pair is equal to lower_bound(key). The second member pair of 1103 // the pair is equal to upper_bound(key). 1104 template <typename K> 1105 std::pair<iterator, iterator> equal_range(const K &key) { 1106 return {lower_bound(key), upper_bound(key)}; 1107 } 1108 template <typename K> 1109 std::pair<const_iterator, const_iterator> equal_range(const K &key) const { 1110 return {lower_bound(key), upper_bound(key)}; 1111 } 1112 1113 // Inserts a value into the btree only if it does not already exist. The 1114 // boolean return value indicates whether insertion succeeded or failed. 1115 // Requirement: if `key` already exists in the btree, does not consume `args`. 1116 // Requirement: `key` is never referenced after consuming `args`. 1117 template <typename... Args> 1118 std::pair<iterator, bool> insert_unique(const key_type &key, Args &&... args); 1119 1120 // Inserts with hint. Checks to see if the value should be placed immediately 1121 // before `position` in the tree. If so, then the insertion will take 1122 // amortized constant time. If not, the insertion will take amortized 1123 // logarithmic time as if a call to insert_unique() were made. 1124 // Requirement: if `key` already exists in the btree, does not consume `args`. 1125 // Requirement: `key` is never referenced after consuming `args`. 1126 template <typename... Args> 1127 std::pair<iterator, bool> insert_hint_unique(iterator position, 1128 const key_type &key, 1129 Args &&... args); 1130 1131 // Insert a range of values into the btree. 1132 template <typename InputIterator> 1133 void insert_iterator_unique(InputIterator b, InputIterator e); 1134 1135 // Inserts a value into the btree. 1136 template <typename ValueType> 1137 iterator insert_multi(const key_type &key, ValueType &&v); 1138 1139 // Inserts a value into the btree. 1140 template <typename ValueType> 1141 iterator insert_multi(ValueType &&v) { 1142 return insert_multi(params_type::key(v), std::forward<ValueType>(v)); 1143 } 1144 1145 // Insert with hint. Check to see if the value should be placed immediately 1146 // before position in the tree. If it does, then the insertion will take 1147 // amortized constant time. If not, the insertion will take amortized 1148 // logarithmic time as if a call to insert_multi(v) were made. 1149 template <typename ValueType> 1150 iterator insert_hint_multi(iterator position, ValueType &&v); 1151 1152 // Insert a range of values into the btree. 1153 template <typename InputIterator> 1154 void insert_iterator_multi(InputIterator b, InputIterator e); 1155 1156 // Erase the specified iterator from the btree. The iterator must be valid 1157 // (i.e. not equal to end()). Return an iterator pointing to the node after 1158 // the one that was erased (or end() if none exists). 1159 // Requirement: does not read the value at `*iter`. 1160 iterator erase(iterator iter); 1161 1162 // Erases range. Returns the number of keys erased and an iterator pointing 1163 // to the element after the last erased element. 1164 std::pair<size_type, iterator> erase_range(iterator begin, iterator end); 1165 1166 // Erases the specified key from the btree. Returns 1 if an element was 1167 // erased and 0 otherwise. 1168 template <typename K> 1169 size_type erase_unique(const K &key); 1170 1171 // Erases all of the entries matching the specified key from the 1172 // btree. Returns the number of elements erased. 1173 template <typename K> 1174 size_type erase_multi(const K &key); 1175 1176 // Finds the iterator corresponding to a key or returns end() if the key is 1177 // not present. 1178 template <typename K> 1179 iterator find(const K &key) { 1180 return internal_end(internal_find(key)); 1181 } 1182 template <typename K> 1183 const_iterator find(const K &key) const { 1184 return internal_end(internal_find(key)); 1185 } 1186 1187 // Returns a count of the number of times the key appears in the btree. 1188 template <typename K> 1189 size_type count_unique(const K &key) const { 1190 const iterator begin = internal_find(key); 1191 if (begin.node == nullptr) { 1192 // The key doesn't exist in the tree. 1193 return 0; 1194 } 1195 return 1; 1196 } 1197 // Returns a count of the number of times the key appears in the btree. 1198 template <typename K> 1199 size_type count_multi(const K &key) const { 1200 const auto range = equal_range(key); 1201 return std::distance(range.first, range.second); 1202 } 1203 1204 // Clear the btree, deleting all of the values it contains. 1205 void clear(); 1206 1207 // Swap the contents of *this and x. 1208 void swap(btree &x); 1209 1210 const key_compare &key_comp() const noexcept { 1211 return root_.template get<0>(); 1212 } 1213 template <typename K, typename LK> 1214 bool compare_keys(const K &x, const LK &y) const { 1215 return compare_internal::compare_result_as_less_than(key_comp()(x, y)); 1216 } 1217 1218 value_compare value_comp() const { return value_compare(key_comp()); } 1219 1220 // Verifies the structure of the btree. 1221 void verify() const; 1222 1223 // Size routines. 1224 size_type size() const { return size_; } 1225 size_type max_size() const { return (std::numeric_limits<size_type>::max)(); } 1226 bool empty() const { return size_ == 0; } 1227 1228 // The height of the btree. An empty tree will have height 0. 1229 size_type height() const { 1230 size_type h = 0; 1231 if (!empty()) { 1232 // Count the length of the chain from the leftmost node up to the 1233 // root. We actually count from the root back around to the level below 1234 // the root, but the calculation is the same because of the circularity 1235 // of that traversal. 1236 const node_type *n = root(); 1237 do { 1238 ++h; 1239 n = n->parent(); 1240 } while (n != root()); 1241 } 1242 return h; 1243 } 1244 1245 // The number of internal, leaf and total nodes used by the btree. 1246 size_type leaf_nodes() const { return internal_stats(root()).leaf_nodes; } 1247 size_type internal_nodes() const { 1248 return internal_stats(root()).internal_nodes; 1249 } 1250 size_type nodes() const { 1251 node_stats stats = internal_stats(root()); 1252 return stats.leaf_nodes + stats.internal_nodes; 1253 } 1254 1255 // The total number of bytes used by the btree. 1256 size_type bytes_used() const { 1257 node_stats stats = internal_stats(root()); 1258 if (stats.leaf_nodes == 1 && stats.internal_nodes == 0) { 1259 return sizeof(*this) + node_type::LeafSize(root()->max_count()); 1260 } else { 1261 return sizeof(*this) + stats.leaf_nodes * node_type::LeafSize() + 1262 stats.internal_nodes * node_type::InternalSize(); 1263 } 1264 } 1265 1266 // The average number of bytes used per value stored in the btree. 1267 static double average_bytes_per_value() { 1268 // Returns the number of bytes per value on a leaf node that is 75% 1269 // full. Experimentally, this matches up nicely with the computed number of 1270 // bytes per value in trees that had their values inserted in random order. 1271 return node_type::LeafSize() / (kNodeValues * 0.75); 1272 } 1273 1274 // The fullness of the btree. Computed as the number of elements in the btree 1275 // divided by the maximum number of elements a tree with the current number 1276 // of nodes could hold. A value of 1 indicates perfect space 1277 // utilization. Smaller values indicate space wastage. 1278 // Returns 0 for empty trees. 1279 double fullness() const { 1280 if (empty()) return 0.0; 1281 return static_cast<double>(size()) / (nodes() * kNodeValues); 1282 } 1283 // The overhead of the btree structure in bytes per node. Computed as the 1284 // total number of bytes used by the btree minus the number of bytes used for 1285 // storing elements divided by the number of elements. 1286 // Returns 0 for empty trees. 1287 double overhead() const { 1288 if (empty()) return 0.0; 1289 return (bytes_used() - size() * sizeof(value_type)) / 1290 static_cast<double>(size()); 1291 } 1292 1293 // The allocator used by the btree. 1294 allocator_type get_allocator() const { return allocator(); } 1295 1296 private: 1297 // Internal accessor routines. 1298 node_type *root() { return root_.template get<2>(); } 1299 const node_type *root() const { return root_.template get<2>(); } 1300 node_type *&mutable_root() noexcept { return root_.template get<2>(); } 1301 key_compare *mutable_key_comp() noexcept { return &root_.template get<0>(); } 1302 1303 // The leftmost node is stored as the parent of the root node. 1304 node_type *leftmost() { return root()->parent(); } 1305 const node_type *leftmost() const { return root()->parent(); } 1306 1307 // Allocator routines. 1308 allocator_type *mutable_allocator() noexcept { 1309 return &root_.template get<1>(); 1310 } 1311 const allocator_type &allocator() const noexcept { 1312 return root_.template get<1>(); 1313 } 1314 1315 // Allocates a correctly aligned node of at least size bytes using the 1316 // allocator. 1317 node_type *allocate(const size_type size) { 1318 return reinterpret_cast<node_type *>( 1319 absl::container_internal::Allocate<node_type::Alignment()>( 1320 mutable_allocator(), size)); 1321 } 1322 1323 // Node creation/deletion routines. 1324 node_type *new_internal_node(node_type *parent) { 1325 node_type *p = allocate(node_type::InternalSize()); 1326 return node_type::init_internal(p, parent); 1327 } 1328 node_type *new_leaf_node(node_type *parent) { 1329 node_type *p = allocate(node_type::LeafSize()); 1330 return node_type::init_leaf(p, parent, kNodeValues); 1331 } 1332 node_type *new_leaf_root_node(const int max_count) { 1333 node_type *p = allocate(node_type::LeafSize(max_count)); 1334 return node_type::init_leaf(p, p, max_count); 1335 } 1336 1337 // Deletion helper routines. 1338 void erase_same_node(iterator begin, iterator end); 1339 iterator erase_from_leaf_node(iterator begin, size_type to_erase); 1340 iterator rebalance_after_delete(iterator iter); 1341 1342 // Deallocates a node of a certain size in bytes using the allocator. 1343 void deallocate(const size_type size, node_type *node) { 1344 absl::container_internal::Deallocate<node_type::Alignment()>( 1345 mutable_allocator(), node, size); 1346 } 1347 1348 void delete_internal_node(node_type *node) { 1349 node->destroy(mutable_allocator()); 1350 deallocate(node_type::InternalSize(), node); 1351 } 1352 void delete_leaf_node(node_type *node) { 1353 node->destroy(mutable_allocator()); 1354 deallocate(node_type::LeafSize(node->max_count()), node); 1355 } 1356 1357 // Rebalances or splits the node iter points to. 1358 void rebalance_or_split(iterator *iter); 1359 1360 // Merges the values of left, right and the delimiting key on their parent 1361 // onto left, removing the delimiting key and deleting right. 1362 void merge_nodes(node_type *left, node_type *right); 1363 1364 // Tries to merge node with its left or right sibling, and failing that, 1365 // rebalance with its left or right sibling. Returns true if a merge 1366 // occurred, at which point it is no longer valid to access node. Returns 1367 // false if no merging took place. 1368 bool try_merge_or_rebalance(iterator *iter); 1369 1370 // Tries to shrink the height of the tree by 1. 1371 void try_shrink(); 1372 1373 iterator internal_end(iterator iter) { 1374 return iter.node != nullptr ? iter : end(); 1375 } 1376 const_iterator internal_end(const_iterator iter) const { 1377 return iter.node != nullptr ? iter : end(); 1378 } 1379 1380 // Emplaces a value into the btree immediately before iter. Requires that 1381 // key(v) <= iter.key() and (--iter).key() <= key(v). 1382 template <typename... Args> 1383 iterator internal_emplace(iterator iter, Args &&... args); 1384 1385 // Returns an iterator pointing to the first value >= the value "iter" is 1386 // pointing at. Note that "iter" might be pointing to an invalid location such 1387 // as iter.position == iter.node->finish(). This routine simply moves iter up 1388 // in the tree to a valid location. 1389 // Requires: iter.node is non-null. 1390 template <typename IterType> 1391 static IterType internal_last(IterType iter); 1392 1393 // Returns an iterator pointing to the leaf position at which key would 1394 // reside in the tree. We provide 2 versions of internal_locate. The first 1395 // version uses a less-than comparator and is incapable of distinguishing when 1396 // there is an exact match. The second version is for the key-compare-to 1397 // specialization and distinguishes exact matches. The key-compare-to 1398 // specialization allows the caller to avoid a subsequent comparison to 1399 // determine if an exact match was made, which is important for keys with 1400 // expensive comparison, such as strings. 1401 template <typename K> 1402 SearchResult<iterator, is_key_compare_to::value> internal_locate( 1403 const K &key) const; 1404 1405 template <typename K> 1406 SearchResult<iterator, false> internal_locate_impl( 1407 const K &key, std::false_type /* IsCompareTo */) const; 1408 1409 template <typename K> 1410 SearchResult<iterator, true> internal_locate_impl( 1411 const K &key, std::true_type /* IsCompareTo */) const; 1412 1413 // Internal routine which implements lower_bound(). 1414 template <typename K> 1415 iterator internal_lower_bound(const K &key) const; 1416 1417 // Internal routine which implements upper_bound(). 1418 template <typename K> 1419 iterator internal_upper_bound(const K &key) const; 1420 1421 // Internal routine which implements find(). 1422 template <typename K> 1423 iterator internal_find(const K &key) const; 1424 1425 // Deletes a node and all of its children. 1426 void internal_clear(node_type *node); 1427 1428 // Verifies the tree structure of node. 1429 int internal_verify(const node_type *node, const key_type *lo, 1430 const key_type *hi) const; 1431 1432 node_stats internal_stats(const node_type *node) const { 1433 // The root can be a static empty node. 1434 if (node == nullptr || (node == root() && empty())) { 1435 return node_stats(0, 0); 1436 } 1437 if (node->leaf()) { 1438 return node_stats(1, 0); 1439 } 1440 node_stats res(0, 1); 1441 for (int i = node->start(); i <= node->finish(); ++i) { 1442 res += internal_stats(node->child(i)); 1443 } 1444 return res; 1445 } 1446 1447 public: 1448 // Exposed only for tests. 1449 static bool testonly_uses_linear_node_search() { 1450 return node_type::testonly_uses_linear_node_search(); 1451 } 1452 1453 private: 1454 // We use compressed tuple in order to save space because key_compare and 1455 // allocator_type are usually empty. 1456 absl::container_internal::CompressedTuple<key_compare, allocator_type, 1457 node_type *> 1458 root_; 1459 1460 // A pointer to the rightmost node. Note that the leftmost node is stored as 1461 // the root's parent. 1462 node_type *rightmost_; 1463 1464 // Number of values. 1465 size_type size_; 1466 }; 1467 1468 //// 1469 // btree_node methods 1470 template <typename P> 1471 template <typename... Args> 1472 inline void btree_node<P>::emplace_value(const size_type i, 1473 allocator_type *alloc, 1474 Args &&... args) { 1475 assert(i >= start()); 1476 assert(i <= finish()); 1477 // Shift old values to create space for new value and then construct it in 1478 // place. 1479 if (i < finish()) { 1480 value_init(finish(), alloc, slot(finish() - 1)); 1481 for (size_type j = finish() - 1; j > i; --j) 1482 params_type::move(alloc, slot(j - 1), slot(j)); 1483 value_destroy(i, alloc); 1484 } 1485 value_init(i, alloc, std::forward<Args>(args)...); 1486 set_finish(finish() + 1); 1487 1488 if (!leaf() && finish() > i + 1) { 1489 for (int j = finish(); j > i + 1; --j) { 1490 set_child(j, child(j - 1)); 1491 } 1492 clear_child(i + 1); 1493 } 1494 } 1495 1496 template <typename P> 1497 inline void btree_node<P>::remove_value(const int i, allocator_type *alloc) { 1498 if (!leaf() && finish() > i + 1) { 1499 assert(child(i + 1)->count() == 0); 1500 for (size_type j = i + 1; j < finish(); ++j) { 1501 set_child(j, child(j + 1)); 1502 } 1503 clear_child(finish()); 1504 } 1505 1506 remove_values_ignore_children(i, /*to_erase=*/1, alloc); 1507 } 1508 1509 template <typename P> 1510 inline void btree_node<P>::remove_values_ignore_children( 1511 const int i, const int to_erase, allocator_type *alloc) { 1512 params_type::move(alloc, slot(i + to_erase), finish_slot(), slot(i)); 1513 value_destroy_n(finish() - to_erase, to_erase, alloc); 1514 set_finish(finish() - to_erase); 1515 } 1516 1517 template <typename P> 1518 void btree_node<P>::rebalance_right_to_left(const int to_move, 1519 btree_node *right, 1520 allocator_type *alloc) { 1521 assert(parent() == right->parent()); 1522 assert(position() + 1 == right->position()); 1523 assert(right->count() >= count()); 1524 assert(to_move >= 1); 1525 assert(to_move <= right->count()); 1526 1527 // 1) Move the delimiting value in the parent to the left node. 1528 value_init(finish(), alloc, parent()->slot(position())); 1529 1530 // 2) Move the (to_move - 1) values from the right node to the left node. 1531 right->uninitialized_move_n(to_move - 1, right->start(), finish() + 1, this, 1532 alloc); 1533 1534 // 3) Move the new delimiting value to the parent from the right node. 1535 params_type::move(alloc, right->slot(to_move - 1), 1536 parent()->slot(position())); 1537 1538 // 4) Shift the values in the right node to their correct position. 1539 params_type::move(alloc, right->slot(to_move), right->finish_slot(), 1540 right->start_slot()); 1541 1542 // 5) Destroy the now-empty to_move entries in the right node. 1543 right->value_destroy_n(right->finish() - to_move, to_move, alloc); 1544 1545 if (!leaf()) { 1546 // Move the child pointers from the right to the left node. 1547 for (int i = 0; i < to_move; ++i) { 1548 init_child(finish() + i + 1, right->child(i)); 1549 } 1550 for (int i = right->start(); i <= right->finish() - to_move; ++i) { 1551 assert(i + to_move <= right->max_count()); 1552 right->init_child(i, right->child(i + to_move)); 1553 right->clear_child(i + to_move); 1554 } 1555 } 1556 1557 // Fixup `finish` on the left and right nodes. 1558 set_finish(finish() + to_move); 1559 right->set_finish(right->finish() - to_move); 1560 } 1561 1562 template <typename P> 1563 void btree_node<P>::rebalance_left_to_right(const int to_move, 1564 btree_node *right, 1565 allocator_type *alloc) { 1566 assert(parent() == right->parent()); 1567 assert(position() + 1 == right->position()); 1568 assert(count() >= right->count()); 1569 assert(to_move >= 1); 1570 assert(to_move <= count()); 1571 1572 // Values in the right node are shifted to the right to make room for the 1573 // new to_move values. Then, the delimiting value in the parent and the 1574 // other (to_move - 1) values in the left node are moved into the right node. 1575 // Lastly, a new delimiting value is moved from the left node into the 1576 // parent, and the remaining empty left node entries are destroyed. 1577 1578 if (right->count() >= to_move) { 1579 // The original location of the right->count() values are sufficient to hold 1580 // the new to_move entries from the parent and left node. 1581 1582 // 1) Shift existing values in the right node to their correct positions. 1583 right->uninitialized_move_n(to_move, right->finish() - to_move, 1584 right->finish(), right, alloc); 1585 for (slot_type *src = right->slot(right->finish() - to_move - 1), 1586 *dest = right->slot(right->finish() - 1), 1587 *end = right->start_slot(); 1588 src >= end; --src, --dest) { 1589 params_type::move(alloc, src, dest); 1590 } 1591 1592 // 2) Move the delimiting value in the parent to the right node. 1593 params_type::move(alloc, parent()->slot(position()), 1594 right->slot(to_move - 1)); 1595 1596 // 3) Move the (to_move - 1) values from the left node to the right node. 1597 params_type::move(alloc, slot(finish() - (to_move - 1)), finish_slot(), 1598 right->start_slot()); 1599 } else { 1600 // The right node does not have enough initialized space to hold the new 1601 // to_move entries, so part of them will move to uninitialized space. 1602 1603 // 1) Shift existing values in the right node to their correct positions. 1604 right->uninitialized_move_n(right->count(), right->start(), 1605 right->start() + to_move, right, alloc); 1606 1607 // 2) Move the delimiting value in the parent to the right node. 1608 right->value_init(to_move - 1, alloc, parent()->slot(position())); 1609 1610 // 3) Move the (to_move - 1) values from the left node to the right node. 1611 const size_type uninitialized_remaining = to_move - right->count() - 1; 1612 uninitialized_move_n(uninitialized_remaining, 1613 finish() - uninitialized_remaining, right->finish(), 1614 right, alloc); 1615 params_type::move(alloc, slot(finish() - (to_move - 1)), 1616 slot(finish() - uninitialized_remaining), 1617 right->start_slot()); 1618 } 1619 1620 // 4) Move the new delimiting value to the parent from the left node. 1621 params_type::move(alloc, slot(finish() - to_move), 1622 parent()->slot(position())); 1623 1624 // 5) Destroy the now-empty to_move entries in the left node. 1625 value_destroy_n(finish() - to_move, to_move, alloc); 1626 1627 if (!leaf()) { 1628 // Move the child pointers from the left to the right node. 1629 for (int i = right->finish(); i >= right->start(); --i) { 1630 right->init_child(i + to_move, right->child(i)); 1631 right->clear_child(i); 1632 } 1633 for (int i = 1; i <= to_move; ++i) { 1634 right->init_child(i - 1, child(finish() - to_move + i)); 1635 clear_child(finish() - to_move + i); 1636 } 1637 } 1638 1639 // Fixup the counts on the left and right nodes. 1640 set_finish(finish() - to_move); 1641 right->set_finish(right->finish() + to_move); 1642 } 1643 1644 template <typename P> 1645 void btree_node<P>::split(const int insert_position, btree_node *dest, 1646 allocator_type *alloc) { 1647 assert(dest->count() == 0); 1648 assert(max_count() == kNodeValues); 1649 1650 // We bias the split based on the position being inserted. If we're 1651 // inserting at the beginning of the left node then bias the split to put 1652 // more values on the right node. If we're inserting at the end of the 1653 // right node then bias the split to put more values on the left node. 1654 if (insert_position == start()) { 1655 dest->set_finish(dest->start() + finish() - 1); 1656 } else if (insert_position == kNodeValues) { 1657 dest->set_finish(dest->start()); 1658 } else { 1659 dest->set_finish(dest->start() + count() / 2); 1660 } 1661 set_finish(finish() - dest->count()); 1662 assert(count() >= 1); 1663 1664 // Move values from the left sibling to the right sibling. 1665 uninitialized_move_n(dest->count(), finish(), dest->start(), dest, alloc); 1666 1667 // Destroy the now-empty entries in the left node. 1668 value_destroy_n(finish(), dest->count(), alloc); 1669 1670 // The split key is the largest value in the left sibling. 1671 --mutable_finish(); 1672 parent()->emplace_value(position(), alloc, finish_slot()); 1673 value_destroy(finish(), alloc); 1674 parent()->init_child(position() + 1, dest); 1675 1676 if (!leaf()) { 1677 for (int i = dest->start(), j = finish() + 1; i <= dest->finish(); 1678 ++i, ++j) { 1679 assert(child(j) != nullptr); 1680 dest->init_child(i, child(j)); 1681 clear_child(j); 1682 } 1683 } 1684 } 1685 1686 template <typename P> 1687 void btree_node<P>::merge(btree_node *src, allocator_type *alloc) { 1688 assert(parent() == src->parent()); 1689 assert(position() + 1 == src->position()); 1690 1691 // Move the delimiting value to the left node. 1692 value_init(finish(), alloc, parent()->slot(position())); 1693 1694 // Move the values from the right to the left node. 1695 src->uninitialized_move_n(src->count(), src->start(), finish() + 1, this, 1696 alloc); 1697 1698 // Destroy the now-empty entries in the right node. 1699 src->value_destroy_n(src->start(), src->count(), alloc); 1700 1701 if (!leaf()) { 1702 // Move the child pointers from the right to the left node. 1703 for (int i = src->start(), j = finish() + 1; i <= src->finish(); ++i, ++j) { 1704 init_child(j, src->child(i)); 1705 src->clear_child(i); 1706 } 1707 } 1708 1709 // Fixup `finish` on the src and dest nodes. 1710 set_finish(start() + 1 + count() + src->count()); 1711 src->set_finish(src->start()); 1712 1713 // Remove the value on the parent node. 1714 parent()->remove_value(position(), alloc); 1715 } 1716 1717 template <typename P> 1718 void btree_node<P>::swap(btree_node *x, allocator_type *alloc) { 1719 using std::swap; 1720 assert(leaf() == x->leaf()); 1721 1722 // Determine which is the smaller/larger node. 1723 btree_node *smaller = this, *larger = x; 1724 if (smaller->count() > larger->count()) { 1725 swap(smaller, larger); 1726 } 1727 1728 // Swap the values. 1729 for (slot_type *a = smaller->start_slot(), *b = larger->start_slot(), 1730 *end = smaller->finish_slot(); 1731 a != end; ++a, ++b) { 1732 params_type::swap(alloc, a, b); 1733 } 1734 1735 // Move values that can't be swapped. 1736 const size_type to_move = larger->count() - smaller->count(); 1737 larger->uninitialized_move_n(to_move, smaller->finish(), smaller->finish(), 1738 smaller, alloc); 1739 larger->value_destroy_n(smaller->finish(), to_move, alloc); 1740 1741 if (!leaf()) { 1742 // Swap the child pointers. 1743 std::swap_ranges(&smaller->mutable_child(smaller->start()), 1744 &smaller->mutable_child(smaller->finish() + 1), 1745 &larger->mutable_child(larger->start())); 1746 // Update swapped children's parent pointers. 1747 int i = smaller->start(); 1748 int j = larger->start(); 1749 for (; i <= smaller->finish(); ++i, ++j) { 1750 smaller->child(i)->set_parent(smaller); 1751 larger->child(j)->set_parent(larger); 1752 } 1753 // Move the child pointers that couldn't be swapped. 1754 for (; j <= larger->finish(); ++i, ++j) { 1755 smaller->init_child(i, larger->child(j)); 1756 larger->clear_child(j); 1757 } 1758 } 1759 1760 // Swap the `finish`s. 1761 // TODO(ezb): with floating storage, will also need to swap starts. 1762 swap(mutable_finish(), x->mutable_finish()); 1763 } 1764 1765 //// 1766 // btree_iterator methods 1767 template <typename N, typename R, typename P> 1768 void btree_iterator<N, R, P>::increment_slow() { 1769 if (node->leaf()) { 1770 assert(position >= node->finish()); 1771 btree_iterator save(*this); 1772 while (position == node->finish() && !node->is_root()) { 1773 assert(node->parent()->child(node->position()) == node); 1774 position = node->position(); 1775 node = node->parent(); 1776 } 1777 if (position == node->finish()) { 1778 *this = save; 1779 } 1780 } else { 1781 assert(position < node->finish()); 1782 node = node->child(position + 1); 1783 while (!node->leaf()) { 1784 node = node->start_child(); 1785 } 1786 position = node->start(); 1787 } 1788 } 1789 1790 template <typename N, typename R, typename P> 1791 void btree_iterator<N, R, P>::decrement_slow() { 1792 if (node->leaf()) { 1793 assert(position <= -1); 1794 btree_iterator save(*this); 1795 while (position < node->start() && !node->is_root()) { 1796 assert(node->parent()->child(node->position()) == node); 1797 position = node->position() - 1; 1798 node = node->parent(); 1799 } 1800 if (position < node->start()) { 1801 *this = save; 1802 } 1803 } else { 1804 assert(position >= node->start()); 1805 node = node->child(position); 1806 while (!node->leaf()) { 1807 node = node->child(node->finish()); 1808 } 1809 position = node->finish() - 1; 1810 } 1811 } 1812 1813 //// 1814 // btree methods 1815 template <typename P> 1816 template <typename Btree> 1817 void btree<P>::copy_or_move_values_in_order(Btree *x) { 1818 static_assert(std::is_same<btree, Btree>::value || 1819 std::is_same<const btree, Btree>::value, 1820 "Btree type must be same or const."); 1821 assert(empty()); 1822 1823 // We can avoid key comparisons because we know the order of the 1824 // values is the same order we'll store them in. 1825 auto iter = x->begin(); 1826 if (iter == x->end()) return; 1827 insert_multi(maybe_move_from_iterator(iter)); 1828 ++iter; 1829 for (; iter != x->end(); ++iter) { 1830 // If the btree is not empty, we can just insert the new value at the end 1831 // of the tree. 1832 internal_emplace(end(), maybe_move_from_iterator(iter)); 1833 } 1834 } 1835 1836 template <typename P> 1837 constexpr bool btree<P>::static_assert_validation() { 1838 static_assert(std::is_nothrow_copy_constructible<key_compare>::value, 1839 "Key comparison must be nothrow copy constructible"); 1840 static_assert(std::is_nothrow_copy_constructible<allocator_type>::value, 1841 "Allocator must be nothrow copy constructible"); 1842 static_assert(type_traits_internal::is_trivially_copyable<iterator>::value, 1843 "iterator not trivially copyable."); 1844 1845 // Note: We assert that kTargetValues, which is computed from 1846 // Params::kTargetNodeSize, must fit the node_type::field_type. 1847 static_assert( 1848 kNodeValues < (1 << (8 * sizeof(typename node_type::field_type))), 1849 "target node size too large"); 1850 1851 // Verify that key_compare returns an absl::{weak,strong}_ordering or bool. 1852 using compare_result_type = 1853 absl::result_of_t<key_compare(key_type, key_type)>; 1854 static_assert( 1855 std::is_same<compare_result_type, bool>::value || 1856 std::is_convertible<compare_result_type, absl::weak_ordering>::value, 1857 "key comparison function must return absl::{weak,strong}_ordering or " 1858 "bool."); 1859 1860 // Test the assumption made in setting kNodeValueSpace. 1861 static_assert(node_type::MinimumOverhead() >= sizeof(void *) + 4, 1862 "node space assumption incorrect"); 1863 1864 return true; 1865 } 1866 1867 template <typename P> 1868 btree<P>::btree(const key_compare &comp, const allocator_type &alloc) 1869 : root_(comp, alloc, EmptyNode()), rightmost_(EmptyNode()), size_(0) {} 1870 1871 template <typename P> 1872 btree<P>::btree(const btree &x) : btree(x.key_comp(), x.allocator()) { 1873 copy_or_move_values_in_order(&x); 1874 } 1875 1876 template <typename P> 1877 template <typename... Args> 1878 auto btree<P>::insert_unique(const key_type &key, Args &&... args) 1879 -> std::pair<iterator, bool> { 1880 if (empty()) { 1881 mutable_root() = rightmost_ = new_leaf_root_node(1); 1882 } 1883 1884 auto res = internal_locate(key); 1885 iterator &iter = res.value; 1886 1887 if (res.HasMatch()) { 1888 if (res.IsEq()) { 1889 // The key already exists in the tree, do nothing. 1890 return {iter, false}; 1891 } 1892 } else { 1893 iterator last = internal_last(iter); 1894 if (last.node && !compare_keys(key, last.key())) { 1895 // The key already exists in the tree, do nothing. 1896 return {last, false}; 1897 } 1898 } 1899 return {internal_emplace(iter, std::forward<Args>(args)...), true}; 1900 } 1901 1902 template <typename P> 1903 template <typename... Args> 1904 inline auto btree<P>::insert_hint_unique(iterator position, const key_type &key, 1905 Args &&... args) 1906 -> std::pair<iterator, bool> { 1907 if (!empty()) { 1908 if (position == end() || compare_keys(key, position.key())) { 1909 if (position == begin() || compare_keys(std::prev(position).key(), key)) { 1910 // prev.key() < key < position.key() 1911 return {internal_emplace(position, std::forward<Args>(args)...), true}; 1912 } 1913 } else if (compare_keys(position.key(), key)) { 1914 ++position; 1915 if (position == end() || compare_keys(key, position.key())) { 1916 // {original `position`}.key() < key < {current `position`}.key() 1917 return {internal_emplace(position, std::forward<Args>(args)...), true}; 1918 } 1919 } else { 1920 // position.key() == key 1921 return {position, false}; 1922 } 1923 } 1924 return insert_unique(key, std::forward<Args>(args)...); 1925 } 1926 1927 template <typename P> 1928 template <typename InputIterator> 1929 void btree<P>::insert_iterator_unique(InputIterator b, InputIterator e) { 1930 for (; b != e; ++b) { 1931 insert_hint_unique(end(), params_type::key(*b), *b); 1932 } 1933 } 1934 1935 template <typename P> 1936 template <typename ValueType> 1937 auto btree<P>::insert_multi(const key_type &key, ValueType &&v) -> iterator { 1938 if (empty()) { 1939 mutable_root() = rightmost_ = new_leaf_root_node(1); 1940 } 1941 1942 iterator iter = internal_upper_bound(key); 1943 if (iter.node == nullptr) { 1944 iter = end(); 1945 } 1946 return internal_emplace(iter, std::forward<ValueType>(v)); 1947 } 1948 1949 template <typename P> 1950 template <typename ValueType> 1951 auto btree<P>::insert_hint_multi(iterator position, ValueType &&v) -> iterator { 1952 if (!empty()) { 1953 const key_type &key = params_type::key(v); 1954 if (position == end() || !compare_keys(position.key(), key)) { 1955 if (position == begin() || 1956 !compare_keys(key, std::prev(position).key())) { 1957 // prev.key() <= key <= position.key() 1958 return internal_emplace(position, std::forward<ValueType>(v)); 1959 } 1960 } else { 1961 ++position; 1962 if (position == end() || !compare_keys(position.key(), key)) { 1963 // {original `position`}.key() < key < {current `position`}.key() 1964 return internal_emplace(position, std::forward<ValueType>(v)); 1965 } 1966 } 1967 } 1968 return insert_multi(std::forward<ValueType>(v)); 1969 } 1970 1971 template <typename P> 1972 template <typename InputIterator> 1973 void btree<P>::insert_iterator_multi(InputIterator b, InputIterator e) { 1974 for (; b != e; ++b) { 1975 insert_hint_multi(end(), *b); 1976 } 1977 } 1978 1979 template <typename P> 1980 auto btree<P>::operator=(const btree &x) -> btree & { 1981 if (this != &x) { 1982 clear(); 1983 1984 *mutable_key_comp() = x.key_comp(); 1985 if (absl::allocator_traits< 1986 allocator_type>::propagate_on_container_copy_assignment::value) { 1987 *mutable_allocator() = x.allocator(); 1988 } 1989 1990 copy_or_move_values_in_order(&x); 1991 } 1992 return *this; 1993 } 1994 1995 template <typename P> 1996 auto btree<P>::operator=(btree &&x) noexcept -> btree & { 1997 if (this != &x) { 1998 clear(); 1999 2000 using std::swap; 2001 if (absl::allocator_traits< 2002 allocator_type>::propagate_on_container_copy_assignment::value) { 2003 // Note: `root_` also contains the allocator and the key comparator. 2004 swap(root_, x.root_); 2005 swap(rightmost_, x.rightmost_); 2006 swap(size_, x.size_); 2007 } else { 2008 if (allocator() == x.allocator()) { 2009 swap(mutable_root(), x.mutable_root()); 2010 swap(*mutable_key_comp(), *x.mutable_key_comp()); 2011 swap(rightmost_, x.rightmost_); 2012 swap(size_, x.size_); 2013 } else { 2014 // We aren't allowed to propagate the allocator and the allocator is 2015 // different so we can't take over its memory. We must move each element 2016 // individually. We need both `x` and `this` to have `x`s key comparator 2017 // while moving the values so we can't swap the key comparators. 2018 *mutable_key_comp() = x.key_comp(); 2019 copy_or_move_values_in_order(&x); 2020 } 2021 } 2022 } 2023 return *this; 2024 } 2025 2026 template <typename P> 2027 auto btree<P>::erase(iterator iter) -> iterator { 2028 bool internal_delete = false; 2029 if (!iter.node->leaf()) { 2030 // Deletion of a value on an internal node. First, move the largest value 2031 // from our left child here, then delete that position (in remove_value() 2032 // below). We can get to the largest value from our left child by 2033 // decrementing iter. 2034 iterator internal_iter(iter); 2035 --iter; 2036 assert(iter.node->leaf()); 2037 params_type::move(mutable_allocator(), iter.node->slot(iter.position), 2038 internal_iter.node->slot(internal_iter.position)); 2039 internal_delete = true; 2040 } 2041 2042 // Delete the key from the leaf. 2043 iter.node->remove_value(iter.position, mutable_allocator()); 2044 --size_; 2045 2046 // We want to return the next value after the one we just erased. If we 2047 // erased from an internal node (internal_delete == true), then the next 2048 // value is ++(++iter). If we erased from a leaf node (internal_delete == 2049 // false) then the next value is ++iter. Note that ++iter may point to an 2050 // internal node and the value in the internal node may move to a leaf node 2051 // (iter.node) when rebalancing is performed at the leaf level. 2052 2053 iterator res = rebalance_after_delete(iter); 2054 2055 // If we erased from an internal node, advance the iterator. 2056 if (internal_delete) { 2057 ++res; 2058 } 2059 return res; 2060 } 2061 2062 template <typename P> 2063 auto btree<P>::rebalance_after_delete(iterator iter) -> iterator { 2064 // Merge/rebalance as we walk back up the tree. 2065 iterator res(iter); 2066 bool first_iteration = true; 2067 for (;;) { 2068 if (iter.node == root()) { 2069 try_shrink(); 2070 if (empty()) { 2071 return end(); 2072 } 2073 break; 2074 } 2075 if (iter.node->count() >= kMinNodeValues) { 2076 break; 2077 } 2078 bool merged = try_merge_or_rebalance(&iter); 2079 // On the first iteration, we should update `res` with `iter` because `res` 2080 // may have been invalidated. 2081 if (first_iteration) { 2082 res = iter; 2083 first_iteration = false; 2084 } 2085 if (!merged) { 2086 break; 2087 } 2088 iter.position = iter.node->position(); 2089 iter.node = iter.node->parent(); 2090 } 2091 2092 // Adjust our return value. If we're pointing at the end of a node, advance 2093 // the iterator. 2094 if (res.position == res.node->finish()) { 2095 res.position = res.node->finish() - 1; 2096 ++res; 2097 } 2098 2099 return res; 2100 } 2101 2102 template <typename P> 2103 auto btree<P>::erase_range(iterator begin, iterator end) 2104 -> std::pair<size_type, iterator> { 2105 difference_type count = std::distance(begin, end); 2106 assert(count >= 0); 2107 2108 if (count == 0) { 2109 return {0, begin}; 2110 } 2111 2112 if (count == size_) { 2113 clear(); 2114 return {count, this->end()}; 2115 } 2116 2117 if (begin.node == end.node) { 2118 erase_same_node(begin, end); 2119 size_ -= count; 2120 return {count, rebalance_after_delete(begin)}; 2121 } 2122 2123 const size_type target_size = size_ - count; 2124 while (size_ > target_size) { 2125 if (begin.node->leaf()) { 2126 const size_type remaining_to_erase = size_ - target_size; 2127 const size_type remaining_in_node = begin.node->finish() - begin.position; 2128 begin = erase_from_leaf_node( 2129 begin, (std::min)(remaining_to_erase, remaining_in_node)); 2130 } else { 2131 begin = erase(begin); 2132 } 2133 } 2134 return {count, begin}; 2135 } 2136 2137 template <typename P> 2138 void btree<P>::erase_same_node(iterator begin, iterator end) { 2139 assert(begin.node == end.node); 2140 assert(end.position > begin.position); 2141 2142 node_type *node = begin.node; 2143 size_type to_erase = end.position - begin.position; 2144 if (!node->leaf()) { 2145 // Delete all children between begin and end. 2146 for (size_type i = 0; i < to_erase; ++i) { 2147 internal_clear(node->child(begin.position + i + 1)); 2148 } 2149 // Rotate children after end into new positions. 2150 for (size_type i = begin.position + to_erase + 1; i <= node->finish(); 2151 ++i) { 2152 node->set_child(i - to_erase, node->child(i)); 2153 node->clear_child(i); 2154 } 2155 } 2156 node->remove_values_ignore_children(begin.position, to_erase, 2157 mutable_allocator()); 2158 2159 // Do not need to update rightmost_, because 2160 // * either end == this->end(), and therefore node == rightmost_, and still 2161 // exists 2162 // * or end != this->end(), and therefore rightmost_ hasn't been erased, since 2163 // it wasn't covered in [begin, end) 2164 } 2165 2166 template <typename P> 2167 auto btree<P>::erase_from_leaf_node(iterator begin, size_type to_erase) 2168 -> iterator { 2169 node_type *node = begin.node; 2170 assert(node->leaf()); 2171 assert(node->finish() > begin.position); 2172 assert(begin.position + to_erase <= node->finish()); 2173 2174 node->remove_values_ignore_children(begin.position, to_erase, 2175 mutable_allocator()); 2176 2177 size_ -= to_erase; 2178 2179 return rebalance_after_delete(begin); 2180 } 2181 2182 template <typename P> 2183 template <typename K> 2184 auto btree<P>::erase_unique(const K &key) -> size_type { 2185 const iterator iter = internal_find(key); 2186 if (iter.node == nullptr) { 2187 // The key doesn't exist in the tree, return nothing done. 2188 return 0; 2189 } 2190 erase(iter); 2191 return 1; 2192 } 2193 2194 template <typename P> 2195 template <typename K> 2196 auto btree<P>::erase_multi(const K &key) -> size_type { 2197 const iterator begin = internal_lower_bound(key); 2198 if (begin.node == nullptr) { 2199 // The key doesn't exist in the tree, return nothing done. 2200 return 0; 2201 } 2202 // Delete all of the keys between begin and upper_bound(key). 2203 const iterator end = internal_end(internal_upper_bound(key)); 2204 return erase_range(begin, end).first; 2205 } 2206 2207 template <typename P> 2208 void btree<P>::clear() { 2209 if (!empty()) { 2210 internal_clear(root()); 2211 } 2212 mutable_root() = EmptyNode(); 2213 rightmost_ = EmptyNode(); 2214 size_ = 0; 2215 } 2216 2217 template <typename P> 2218 void btree<P>::swap(btree &x) { 2219 using std::swap; 2220 if (absl::allocator_traits< 2221 allocator_type>::propagate_on_container_swap::value) { 2222 // Note: `root_` also contains the allocator and the key comparator. 2223 swap(root_, x.root_); 2224 } else { 2225 // It's undefined behavior if the allocators are unequal here. 2226 assert(allocator() == x.allocator()); 2227 swap(mutable_root(), x.mutable_root()); 2228 swap(*mutable_key_comp(), *x.mutable_key_comp()); 2229 } 2230 swap(rightmost_, x.rightmost_); 2231 swap(size_, x.size_); 2232 } 2233 2234 template <typename P> 2235 void btree<P>::verify() const { 2236 assert(root() != nullptr); 2237 assert(leftmost() != nullptr); 2238 assert(rightmost_ != nullptr); 2239 assert(empty() || size() == internal_verify(root(), nullptr, nullptr)); 2240 assert(leftmost() == (++const_iterator(root(), -1)).node); 2241 assert(rightmost_ == (--const_iterator(root(), root()->finish())).node); 2242 assert(leftmost()->leaf()); 2243 assert(rightmost_->leaf()); 2244 } 2245 2246 template <typename P> 2247 void btree<P>::rebalance_or_split(iterator *iter) { 2248 node_type *&node = iter->node; 2249 int &insert_position = iter->position; 2250 assert(node->count() == node->max_count()); 2251 assert(kNodeValues == node->max_count()); 2252 2253 // First try to make room on the node by rebalancing. 2254 node_type *parent = node->parent(); 2255 if (node != root()) { 2256 if (node->position() > parent->start()) { 2257 // Try rebalancing with our left sibling. 2258 node_type *left = parent->child(node->position() - 1); 2259 assert(left->max_count() == kNodeValues); 2260 if (left->count() < kNodeValues) { 2261 // We bias rebalancing based on the position being inserted. If we're 2262 // inserting at the end of the right node then we bias rebalancing to 2263 // fill up the left node. 2264 int to_move = (kNodeValues - left->count()) / 2265 (1 + (insert_position < kNodeValues)); 2266 to_move = (std::max)(1, to_move); 2267 2268 if (insert_position - to_move >= node->start() || 2269 left->count() + to_move < kNodeValues) { 2270 left->rebalance_right_to_left(to_move, node, mutable_allocator()); 2271 2272 assert(node->max_count() - node->count() == to_move); 2273 insert_position = insert_position - to_move; 2274 if (insert_position < node->start()) { 2275 insert_position = insert_position + left->count() + 1; 2276 node = left; 2277 } 2278 2279 assert(node->count() < node->max_count()); 2280 return; 2281 } 2282 } 2283 } 2284 2285 if (node->position() < parent->finish()) { 2286 // Try rebalancing with our right sibling. 2287 node_type *right = parent->child(node->position() + 1); 2288 assert(right->max_count() == kNodeValues); 2289 if (right->count() < kNodeValues) { 2290 // We bias rebalancing based on the position being inserted. If we're 2291 // inserting at the beginning of the left node then we bias rebalancing 2292 // to fill up the right node. 2293 int to_move = (kNodeValues - right->count()) / 2294 (1 + (insert_position > node->start())); 2295 to_move = (std::max)(1, to_move); 2296 2297 if (insert_position <= node->finish() - to_move || 2298 right->count() + to_move < kNodeValues) { 2299 node->rebalance_left_to_right(to_move, right, mutable_allocator()); 2300 2301 if (insert_position > node->finish()) { 2302 insert_position = insert_position - node->count() - 1; 2303 node = right; 2304 } 2305 2306 assert(node->count() < node->max_count()); 2307 return; 2308 } 2309 } 2310 } 2311 2312 // Rebalancing failed, make sure there is room on the parent node for a new 2313 // value. 2314 assert(parent->max_count() == kNodeValues); 2315 if (parent->count() == kNodeValues) { 2316 iterator parent_iter(node->parent(), node->position()); 2317 rebalance_or_split(&parent_iter); 2318 } 2319 } else { 2320 // Rebalancing not possible because this is the root node. 2321 // Create a new root node and set the current root node as the child of the 2322 // new root. 2323 parent = new_internal_node(parent); 2324 parent->init_child(parent->start(), root()); 2325 mutable_root() = parent; 2326 // If the former root was a leaf node, then it's now the rightmost node. 2327 assert(!parent->start_child()->leaf() || 2328 parent->start_child() == rightmost_); 2329 } 2330 2331 // Split the node. 2332 node_type *split_node; 2333 if (node->leaf()) { 2334 split_node = new_leaf_node(parent); 2335 node->split(insert_position, split_node, mutable_allocator()); 2336 if (rightmost_ == node) rightmost_ = split_node; 2337 } else { 2338 split_node = new_internal_node(parent); 2339 node->split(insert_position, split_node, mutable_allocator()); 2340 } 2341 2342 if (insert_position > node->finish()) { 2343 insert_position = insert_position - node->count() - 1; 2344 node = split_node; 2345 } 2346 } 2347 2348 template <typename P> 2349 void btree<P>::merge_nodes(node_type *left, node_type *right) { 2350 left->merge(right, mutable_allocator()); 2351 if (right->leaf()) { 2352 if (rightmost_ == right) rightmost_ = left; 2353 delete_leaf_node(right); 2354 } else { 2355 delete_internal_node(right); 2356 } 2357 } 2358 2359 template <typename P> 2360 bool btree<P>::try_merge_or_rebalance(iterator *iter) { 2361 node_type *parent = iter->node->parent(); 2362 if (iter->node->position() > parent->start()) { 2363 // Try merging with our left sibling. 2364 node_type *left = parent->child(iter->node->position() - 1); 2365 assert(left->max_count() == kNodeValues); 2366 if (1 + left->count() + iter->node->count() <= kNodeValues) { 2367 iter->position += 1 + left->count(); 2368 merge_nodes(left, iter->node); 2369 iter->node = left; 2370 return true; 2371 } 2372 } 2373 if (iter->node->position() < parent->finish()) { 2374 // Try merging with our right sibling. 2375 node_type *right = parent->child(iter->node->position() + 1); 2376 assert(right->max_count() == kNodeValues); 2377 if (1 + iter->node->count() + right->count() <= kNodeValues) { 2378 merge_nodes(iter->node, right); 2379 return true; 2380 } 2381 // Try rebalancing with our right sibling. We don't perform rebalancing if 2382 // we deleted the first element from iter->node and the node is not 2383 // empty. This is a small optimization for the common pattern of deleting 2384 // from the front of the tree. 2385 if (right->count() > kMinNodeValues && 2386 (iter->node->count() == 0 || iter->position > iter->node->start())) { 2387 int to_move = (right->count() - iter->node->count()) / 2; 2388 to_move = (std::min)(to_move, right->count() - 1); 2389 iter->node->rebalance_right_to_left(to_move, right, mutable_allocator()); 2390 return false; 2391 } 2392 } 2393 if (iter->node->position() > parent->start()) { 2394 // Try rebalancing with our left sibling. We don't perform rebalancing if 2395 // we deleted the last element from iter->node and the node is not 2396 // empty. This is a small optimization for the common pattern of deleting 2397 // from the back of the tree. 2398 node_type *left = parent->child(iter->node->position() - 1); 2399 if (left->count() > kMinNodeValues && 2400 (iter->node->count() == 0 || iter->position < iter->node->finish())) { 2401 int to_move = (left->count() - iter->node->count()) / 2; 2402 to_move = (std::min)(to_move, left->count() - 1); 2403 left->rebalance_left_to_right(to_move, iter->node, mutable_allocator()); 2404 iter->position += to_move; 2405 return false; 2406 } 2407 } 2408 return false; 2409 } 2410 2411 template <typename P> 2412 void btree<P>::try_shrink() { 2413 if (root()->count() > 0) { 2414 return; 2415 } 2416 // Deleted the last item on the root node, shrink the height of the tree. 2417 if (root()->leaf()) { 2418 assert(size() == 0); 2419 delete_leaf_node(root()); 2420 mutable_root() = EmptyNode(); 2421 rightmost_ = EmptyNode(); 2422 } else { 2423 node_type *child = root()->start_child(); 2424 child->make_root(); 2425 delete_internal_node(root()); 2426 mutable_root() = child; 2427 } 2428 } 2429 2430 template <typename P> 2431 template <typename IterType> 2432 inline IterType btree<P>::internal_last(IterType iter) { 2433 assert(iter.node != nullptr); 2434 while (iter.position == iter.node->finish()) { 2435 iter.position = iter.node->position(); 2436 iter.node = iter.node->parent(); 2437 if (iter.node->leaf()) { 2438 iter.node = nullptr; 2439 break; 2440 } 2441 } 2442 return iter; 2443 } 2444 2445 template <typename P> 2446 template <typename... Args> 2447 inline auto btree<P>::internal_emplace(iterator iter, Args &&... args) 2448 -> iterator { 2449 if (!iter.node->leaf()) { 2450 // We can't insert on an internal node. Instead, we'll insert after the 2451 // previous value which is guaranteed to be on a leaf node. 2452 --iter; 2453 ++iter.position; 2454 } 2455 const int max_count = iter.node->max_count(); 2456 if (iter.node->count() == max_count) { 2457 // Make room in the leaf for the new item. 2458 if (max_count < kNodeValues) { 2459 // Insertion into the root where the root is smaller than the full node 2460 // size. Simply grow the size of the root node. 2461 assert(iter.node == root()); 2462 iter.node = 2463 new_leaf_root_node((std::min<int>)(kNodeValues, 2 * max_count)); 2464 iter.node->swap(root(), mutable_allocator()); 2465 delete_leaf_node(root()); 2466 mutable_root() = iter.node; 2467 rightmost_ = iter.node; 2468 } else { 2469 rebalance_or_split(&iter); 2470 } 2471 } 2472 iter.node->emplace_value(iter.position, mutable_allocator(), 2473 std::forward<Args>(args)...); 2474 ++size_; 2475 return iter; 2476 } 2477 2478 template <typename P> 2479 template <typename K> 2480 inline auto btree<P>::internal_locate(const K &key) const 2481 -> SearchResult<iterator, is_key_compare_to::value> { 2482 return internal_locate_impl(key, is_key_compare_to()); 2483 } 2484 2485 template <typename P> 2486 template <typename K> 2487 inline auto btree<P>::internal_locate_impl( 2488 const K &key, std::false_type /* IsCompareTo */) const 2489 -> SearchResult<iterator, false> { 2490 iterator iter(const_cast<node_type *>(root())); 2491 for (;;) { 2492 iter.position = iter.node->lower_bound(key, key_comp()).value; 2493 // NOTE: we don't need to walk all the way down the tree if the keys are 2494 // equal, but determining equality would require doing an extra comparison 2495 // on each node on the way down, and we will need to go all the way to the 2496 // leaf node in the expected case. 2497 if (iter.node->leaf()) { 2498 break; 2499 } 2500 iter.node = iter.node->child(iter.position); 2501 } 2502 return {iter}; 2503 } 2504 2505 template <typename P> 2506 template <typename K> 2507 inline auto btree<P>::internal_locate_impl( 2508 const K &key, std::true_type /* IsCompareTo */) const 2509 -> SearchResult<iterator, true> { 2510 iterator iter(const_cast<node_type *>(root())); 2511 for (;;) { 2512 SearchResult<int, true> res = iter.node->lower_bound(key, key_comp()); 2513 iter.position = res.value; 2514 if (res.match == MatchKind::kEq) { 2515 return {iter, MatchKind::kEq}; 2516 } 2517 if (iter.node->leaf()) { 2518 break; 2519 } 2520 iter.node = iter.node->child(iter.position); 2521 } 2522 return {iter, MatchKind::kNe}; 2523 } 2524 2525 template <typename P> 2526 template <typename K> 2527 auto btree<P>::internal_lower_bound(const K &key) const -> iterator { 2528 iterator iter(const_cast<node_type *>(root())); 2529 for (;;) { 2530 iter.position = iter.node->lower_bound(key, key_comp()).value; 2531 if (iter.node->leaf()) { 2532 break; 2533 } 2534 iter.node = iter.node->child(iter.position); 2535 } 2536 return internal_last(iter); 2537 } 2538 2539 template <typename P> 2540 template <typename K> 2541 auto btree<P>::internal_upper_bound(const K &key) const -> iterator { 2542 iterator iter(const_cast<node_type *>(root())); 2543 for (;;) { 2544 iter.position = iter.node->upper_bound(key, key_comp()); 2545 if (iter.node->leaf()) { 2546 break; 2547 } 2548 iter.node = iter.node->child(iter.position); 2549 } 2550 return internal_last(iter); 2551 } 2552 2553 template <typename P> 2554 template <typename K> 2555 auto btree<P>::internal_find(const K &key) const -> iterator { 2556 auto res = internal_locate(key); 2557 if (res.HasMatch()) { 2558 if (res.IsEq()) { 2559 return res.value; 2560 } 2561 } else { 2562 const iterator iter = internal_last(res.value); 2563 if (iter.node != nullptr && !compare_keys(key, iter.key())) { 2564 return iter; 2565 } 2566 } 2567 return {nullptr, 0}; 2568 } 2569 2570 template <typename P> 2571 void btree<P>::internal_clear(node_type *node) { 2572 if (!node->leaf()) { 2573 for (int i = node->start(); i <= node->finish(); ++i) { 2574 internal_clear(node->child(i)); 2575 } 2576 delete_internal_node(node); 2577 } else { 2578 delete_leaf_node(node); 2579 } 2580 } 2581 2582 template <typename P> 2583 int btree<P>::internal_verify(const node_type *node, const key_type *lo, 2584 const key_type *hi) const { 2585 assert(node->count() > 0); 2586 assert(node->count() <= node->max_count()); 2587 if (lo) { 2588 assert(!compare_keys(node->key(node->start()), *lo)); 2589 } 2590 if (hi) { 2591 assert(!compare_keys(*hi, node->key(node->finish() - 1))); 2592 } 2593 for (int i = node->start() + 1; i < node->finish(); ++i) { 2594 assert(!compare_keys(node->key(i), node->key(i - 1))); 2595 } 2596 int count = node->count(); 2597 if (!node->leaf()) { 2598 for (int i = node->start(); i <= node->finish(); ++i) { 2599 assert(node->child(i) != nullptr); 2600 assert(node->child(i)->parent() == node); 2601 assert(node->child(i)->position() == i); 2602 count += internal_verify(node->child(i), 2603 i == node->start() ? lo : &node->key(i - 1), 2604 i == node->finish() ? hi : &node->key(i)); 2605 } 2606 } 2607 return count; 2608 } 2609 2610 } // namespace container_internal 2611 ABSL_NAMESPACE_END 2612 } // namespace absl 2613 2614 #endif // ABSL_CONTAINER_INTERNAL_BTREE_H_ 2615