Expand / shrink the table to the new specified size.
| 612 | |
| 613 | // Expand / shrink the table to the new specified size. |
| 614 | void Resize(size_t new_size) { |
| 615 | if (new_size < kMinBuckets) { |
| 616 | new_size = kMinBuckets; |
| 617 | } |
| 618 | DCHECK_GE(new_size, Size()); |
| 619 | T* const old_data = data_; |
| 620 | size_t old_num_buckets = num_buckets_; |
| 621 | // Reinsert all of the old elements. |
| 622 | const bool owned_data = owns_data_; |
| 623 | AllocateStorage(new_size); |
| 624 | for (size_t i = 0; i < old_num_buckets; ++i) { |
| 625 | T& element = old_data[i]; |
| 626 | if (!emptyfn_.IsEmpty(element)) { |
| 627 | data_[FirstAvailableSlot(IndexForHash(hashfn_(element)))] = std::move(element); |
| 628 | } |
| 629 | if (owned_data) { |
| 630 | allocfn_.destroy(allocfn_.address(element)); |
| 631 | } |
| 632 | } |
| 633 | if (owned_data) { |
| 634 | allocfn_.deallocate(old_data, old_num_buckets); |
| 635 | } |
| 636 | |
| 637 | // When we hit elements_until_expand_, we are at the max load factor and must expand again. |
| 638 | elements_until_expand_ = NumBuckets() * max_load_factor_; |
| 639 | } |
| 640 | |
| 641 | ALWAYS_INLINE size_t FirstAvailableSlot(size_t index) const { |
| 642 | DCHECK_LT(index, NumBuckets()); // Don't try to get a slot out of range. |