FastVector.h (22966B)
1 // 2 // Copyright 2018 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 // FastVector.h: 7 // A vector class with a initial fixed size and variable growth. 8 // Based on FixedVector. 9 // 10 11 #ifndef COMMON_FASTVECTOR_H_ 12 #define COMMON_FASTVECTOR_H_ 13 14 #include "bitset_utils.h" 15 #include "common/debug.h" 16 17 #include <algorithm> 18 #include <array> 19 #include <initializer_list> 20 #include <iterator> 21 22 namespace angle 23 { 24 25 template <class Iter> 26 class WrapIter 27 { 28 public: 29 typedef Iter iterator_type; 30 typedef typename std::iterator_traits<iterator_type>::value_type value_type; 31 typedef typename std::iterator_traits<iterator_type>::difference_type difference_type; 32 typedef typename std::iterator_traits<iterator_type>::pointer pointer; 33 typedef typename std::iterator_traits<iterator_type>::reference reference; 34 typedef typename std::iterator_traits<iterator_type>::iterator_category iterator_category; 35 36 WrapIter() : mIter() {} 37 WrapIter(const Iter &iter) : mIter(iter) {} 38 ~WrapIter() = default; 39 40 WrapIter &operator=(const WrapIter &x) 41 { 42 mIter = x.mIter; 43 return *this; 44 } 45 46 bool operator==(const WrapIter &x) const { return mIter == x.mIter; } 47 bool operator!=(const WrapIter &x) const { return mIter != x.mIter; } 48 bool operator<(const WrapIter &x) const { return mIter < x.mIter; } 49 bool operator<=(const WrapIter &x) const { return mIter <= x.mIter; } 50 bool operator>(const WrapIter &x) const { return mIter > x.mIter; } 51 bool operator>=(const WrapIter &x) const { return mIter >= x.mIter; } 52 53 WrapIter &operator++() 54 { 55 mIter++; 56 return *this; 57 } 58 59 WrapIter operator++(int) 60 { 61 WrapIter tmp(mIter); 62 mIter++; 63 return tmp; 64 } 65 66 WrapIter operator+(difference_type n) 67 { 68 WrapIter tmp(mIter); 69 tmp.mIter += n; 70 return tmp; 71 } 72 73 WrapIter operator-(difference_type n) 74 { 75 WrapIter tmp(mIter); 76 tmp.mIter -= n; 77 return tmp; 78 } 79 80 difference_type operator-(const WrapIter &x) const { return mIter - x.mIter; } 81 82 iterator_type operator->() const { return mIter; } 83 84 reference operator*() const { return *mIter; } 85 86 private: 87 iterator_type mIter; 88 }; 89 90 template <class T, size_t N, class Storage = std::array<T, N>> 91 class FastVector final 92 { 93 public: 94 using value_type = typename Storage::value_type; 95 using size_type = typename Storage::size_type; 96 using reference = typename Storage::reference; 97 using const_reference = typename Storage::const_reference; 98 using pointer = typename Storage::pointer; 99 using const_pointer = typename Storage::const_pointer; 100 using iterator = WrapIter<T *>; 101 using const_iterator = WrapIter<const T *>; 102 103 FastVector(); 104 FastVector(size_type count, const value_type &value); 105 FastVector(size_type count); 106 107 FastVector(const FastVector<T, N, Storage> &other); 108 FastVector(FastVector<T, N, Storage> &&other); 109 FastVector(std::initializer_list<value_type> init); 110 111 template <class InputIt, std::enable_if_t<!std::is_integral<InputIt>::value, bool> = true> 112 FastVector(InputIt first, InputIt last); 113 114 FastVector<T, N, Storage> &operator=(const FastVector<T, N, Storage> &other); 115 FastVector<T, N, Storage> &operator=(FastVector<T, N, Storage> &&other); 116 FastVector<T, N, Storage> &operator=(std::initializer_list<value_type> init); 117 118 ~FastVector(); 119 120 reference at(size_type pos); 121 const_reference at(size_type pos) const; 122 123 reference operator[](size_type pos); 124 const_reference operator[](size_type pos) const; 125 126 pointer data(); 127 const_pointer data() const; 128 129 iterator begin(); 130 const_iterator begin() const; 131 132 iterator end(); 133 const_iterator end() const; 134 135 bool empty() const; 136 size_type size() const; 137 138 void clear(); 139 140 void push_back(const value_type &value); 141 void push_back(value_type &&value); 142 143 template <typename... Args> 144 void emplace_back(Args &&...args); 145 146 void pop_back(); 147 148 reference front(); 149 const_reference front() const; 150 151 reference back(); 152 const_reference back() const; 153 154 void swap(FastVector<T, N, Storage> &other); 155 156 void resize(size_type count); 157 void resize(size_type count, const value_type &value); 158 159 void reserve(size_type count); 160 161 // Specialty function that removes a known element and might shuffle the list. 162 void remove_and_permute(const value_type &element); 163 void remove_and_permute(iterator pos); 164 165 private: 166 void assign_from_initializer_list(std::initializer_list<value_type> init); 167 void ensure_capacity(size_t capacity); 168 bool uses_fixed_storage() const; 169 170 Storage mFixedStorage; 171 pointer mData = mFixedStorage.data(); 172 size_type mSize = 0; 173 size_type mReservedSize = N; 174 }; 175 176 template <class T, size_t N, class StorageN, size_t M, class StorageM> 177 bool operator==(const FastVector<T, N, StorageN> &a, const FastVector<T, M, StorageM> &b) 178 { 179 return a.size() == b.size() && std::equal(a.begin(), a.end(), b.begin()); 180 } 181 182 template <class T, size_t N, class StorageN, size_t M, class StorageM> 183 bool operator!=(const FastVector<T, N, StorageN> &a, const FastVector<T, M, StorageM> &b) 184 { 185 return !(a == b); 186 } 187 188 template <class T, size_t N, class Storage> 189 ANGLE_INLINE bool FastVector<T, N, Storage>::uses_fixed_storage() const 190 { 191 return mData == mFixedStorage.data(); 192 } 193 194 template <class T, size_t N, class Storage> 195 FastVector<T, N, Storage>::FastVector() 196 {} 197 198 template <class T, size_t N, class Storage> 199 FastVector<T, N, Storage>::FastVector(size_type count, const value_type &value) 200 { 201 ensure_capacity(count); 202 mSize = count; 203 std::fill(begin(), end(), value); 204 } 205 206 template <class T, size_t N, class Storage> 207 FastVector<T, N, Storage>::FastVector(size_type count) 208 { 209 ensure_capacity(count); 210 mSize = count; 211 } 212 213 template <class T, size_t N, class Storage> 214 FastVector<T, N, Storage>::FastVector(const FastVector<T, N, Storage> &other) 215 : FastVector(other.begin(), other.end()) 216 {} 217 218 template <class T, size_t N, class Storage> 219 FastVector<T, N, Storage>::FastVector(FastVector<T, N, Storage> &&other) : FastVector() 220 { 221 swap(other); 222 } 223 224 template <class T, size_t N, class Storage> 225 FastVector<T, N, Storage>::FastVector(std::initializer_list<value_type> init) 226 { 227 assign_from_initializer_list(init); 228 } 229 230 template <class T, size_t N, class Storage> 231 template <class InputIt, std::enable_if_t<!std::is_integral<InputIt>::value, bool>> 232 FastVector<T, N, Storage>::FastVector(InputIt first, InputIt last) 233 { 234 size_t newSize = last - first; 235 ensure_capacity(newSize); 236 mSize = newSize; 237 std::copy(first, last, begin()); 238 } 239 240 template <class T, size_t N, class Storage> 241 FastVector<T, N, Storage> &FastVector<T, N, Storage>::operator=( 242 const FastVector<T, N, Storage> &other) 243 { 244 ensure_capacity(other.mSize); 245 mSize = other.mSize; 246 std::copy(other.begin(), other.end(), begin()); 247 return *this; 248 } 249 250 template <class T, size_t N, class Storage> 251 FastVector<T, N, Storage> &FastVector<T, N, Storage>::operator=(FastVector<T, N, Storage> &&other) 252 { 253 swap(other); 254 return *this; 255 } 256 257 template <class T, size_t N, class Storage> 258 FastVector<T, N, Storage> &FastVector<T, N, Storage>::operator=( 259 std::initializer_list<value_type> init) 260 { 261 assign_from_initializer_list(init); 262 return *this; 263 } 264 265 template <class T, size_t N, class Storage> 266 FastVector<T, N, Storage>::~FastVector() 267 { 268 clear(); 269 if (!uses_fixed_storage()) 270 { 271 delete[] mData; 272 } 273 } 274 275 template <class T, size_t N, class Storage> 276 typename FastVector<T, N, Storage>::reference FastVector<T, N, Storage>::at(size_type pos) 277 { 278 ASSERT(pos < mSize); 279 return mData[pos]; 280 } 281 282 template <class T, size_t N, class Storage> 283 typename FastVector<T, N, Storage>::const_reference FastVector<T, N, Storage>::at( 284 size_type pos) const 285 { 286 ASSERT(pos < mSize); 287 return mData[pos]; 288 } 289 290 template <class T, size_t N, class Storage> 291 ANGLE_INLINE typename FastVector<T, N, Storage>::reference FastVector<T, N, Storage>::operator[]( 292 size_type pos) 293 { 294 ASSERT(pos < mSize); 295 return mData[pos]; 296 } 297 298 template <class T, size_t N, class Storage> 299 ANGLE_INLINE typename FastVector<T, N, Storage>::const_reference 300 FastVector<T, N, Storage>::operator[](size_type pos) const 301 { 302 ASSERT(pos < mSize); 303 return mData[pos]; 304 } 305 306 template <class T, size_t N, class Storage> 307 ANGLE_INLINE typename FastVector<T, N, Storage>::const_pointer 308 angle::FastVector<T, N, Storage>::data() const 309 { 310 return mData; 311 } 312 313 template <class T, size_t N, class Storage> 314 ANGLE_INLINE typename FastVector<T, N, Storage>::pointer angle::FastVector<T, N, Storage>::data() 315 { 316 return mData; 317 } 318 319 template <class T, size_t N, class Storage> 320 ANGLE_INLINE typename FastVector<T, N, Storage>::iterator FastVector<T, N, Storage>::begin() 321 { 322 return mData; 323 } 324 325 template <class T, size_t N, class Storage> 326 ANGLE_INLINE typename FastVector<T, N, Storage>::const_iterator FastVector<T, N, Storage>::begin() 327 const 328 { 329 return mData; 330 } 331 332 template <class T, size_t N, class Storage> 333 ANGLE_INLINE typename FastVector<T, N, Storage>::iterator FastVector<T, N, Storage>::end() 334 { 335 return mData + mSize; 336 } 337 338 template <class T, size_t N, class Storage> 339 ANGLE_INLINE typename FastVector<T, N, Storage>::const_iterator FastVector<T, N, Storage>::end() 340 const 341 { 342 return mData + mSize; 343 } 344 345 template <class T, size_t N, class Storage> 346 ANGLE_INLINE bool FastVector<T, N, Storage>::empty() const 347 { 348 return mSize == 0; 349 } 350 351 template <class T, size_t N, class Storage> 352 ANGLE_INLINE typename FastVector<T, N, Storage>::size_type FastVector<T, N, Storage>::size() const 353 { 354 return mSize; 355 } 356 357 template <class T, size_t N, class Storage> 358 void FastVector<T, N, Storage>::clear() 359 { 360 resize(0); 361 } 362 363 template <class T, size_t N, class Storage> 364 ANGLE_INLINE void FastVector<T, N, Storage>::push_back(const value_type &value) 365 { 366 if (mSize == mReservedSize) 367 ensure_capacity(mSize + 1); 368 mData[mSize++] = value; 369 } 370 371 template <class T, size_t N, class Storage> 372 ANGLE_INLINE void FastVector<T, N, Storage>::push_back(value_type &&value) 373 { 374 emplace_back(std::move(value)); 375 } 376 377 template <class T, size_t N, class Storage> 378 template <typename... Args> 379 ANGLE_INLINE void FastVector<T, N, Storage>::emplace_back(Args &&...args) 380 { 381 if (mSize == mReservedSize) 382 ensure_capacity(mSize + 1); 383 mData[mSize++] = std::move(T(std::forward<Args>(args)...)); 384 } 385 386 template <class T, size_t N, class Storage> 387 ANGLE_INLINE void FastVector<T, N, Storage>::pop_back() 388 { 389 ASSERT(mSize > 0); 390 mSize--; 391 } 392 393 template <class T, size_t N, class Storage> 394 ANGLE_INLINE typename FastVector<T, N, Storage>::reference FastVector<T, N, Storage>::front() 395 { 396 ASSERT(mSize > 0); 397 return mData[0]; 398 } 399 400 template <class T, size_t N, class Storage> 401 ANGLE_INLINE typename FastVector<T, N, Storage>::const_reference FastVector<T, N, Storage>::front() 402 const 403 { 404 ASSERT(mSize > 0); 405 return mData[0]; 406 } 407 408 template <class T, size_t N, class Storage> 409 ANGLE_INLINE typename FastVector<T, N, Storage>::reference FastVector<T, N, Storage>::back() 410 { 411 ASSERT(mSize > 0); 412 return mData[mSize - 1]; 413 } 414 415 template <class T, size_t N, class Storage> 416 ANGLE_INLINE typename FastVector<T, N, Storage>::const_reference FastVector<T, N, Storage>::back() 417 const 418 { 419 ASSERT(mSize > 0); 420 return mData[mSize - 1]; 421 } 422 423 template <class T, size_t N, class Storage> 424 void FastVector<T, N, Storage>::swap(FastVector<T, N, Storage> &other) 425 { 426 std::swap(mSize, other.mSize); 427 428 pointer tempData = other.mData; 429 if (uses_fixed_storage()) 430 other.mData = other.mFixedStorage.data(); 431 else 432 other.mData = mData; 433 if (tempData == other.mFixedStorage.data()) 434 mData = mFixedStorage.data(); 435 else 436 mData = tempData; 437 std::swap(mReservedSize, other.mReservedSize); 438 439 if (uses_fixed_storage() || other.uses_fixed_storage()) 440 std::swap(mFixedStorage, other.mFixedStorage); 441 } 442 443 template <class T, size_t N, class Storage> 444 void FastVector<T, N, Storage>::resize(size_type count) 445 { 446 if (count > mSize) 447 { 448 ensure_capacity(count); 449 } 450 mSize = count; 451 } 452 453 template <class T, size_t N, class Storage> 454 void FastVector<T, N, Storage>::resize(size_type count, const value_type &value) 455 { 456 if (count > mSize) 457 { 458 ensure_capacity(count); 459 std::fill(mData + mSize, mData + count, value); 460 } 461 mSize = count; 462 } 463 464 template <class T, size_t N, class Storage> 465 void FastVector<T, N, Storage>::reserve(size_type count) 466 { 467 ensure_capacity(count); 468 } 469 470 template <class T, size_t N, class Storage> 471 void FastVector<T, N, Storage>::assign_from_initializer_list(std::initializer_list<value_type> init) 472 { 473 ensure_capacity(init.size()); 474 mSize = init.size(); 475 size_t index = 0; 476 for (auto &value : init) 477 { 478 mData[index++] = value; 479 } 480 } 481 482 template <class T, size_t N, class Storage> 483 ANGLE_INLINE void FastVector<T, N, Storage>::remove_and_permute(const value_type &element) 484 { 485 size_t len = mSize - 1; 486 for (size_t index = 0; index < len; ++index) 487 { 488 if (mData[index] == element) 489 { 490 mData[index] = std::move(mData[len]); 491 break; 492 } 493 } 494 pop_back(); 495 } 496 497 template <class T, size_t N, class Storage> 498 ANGLE_INLINE void FastVector<T, N, Storage>::remove_and_permute(iterator pos) 499 { 500 ASSERT(pos >= begin()); 501 ASSERT(pos < end()); 502 size_t len = mSize - 1; 503 *pos = std::move(mData[len]); 504 pop_back(); 505 } 506 507 template <class T, size_t N, class Storage> 508 void FastVector<T, N, Storage>::ensure_capacity(size_t capacity) 509 { 510 // We have a minimum capacity of N. 511 if (mReservedSize < capacity) 512 { 513 ASSERT(capacity > N); 514 size_type newSize = std::max(mReservedSize, N); 515 while (newSize < capacity) 516 { 517 newSize *= 2; 518 } 519 520 pointer newData = new value_type[newSize]; 521 522 if (mSize > 0) 523 { 524 std::move(begin(), end(), newData); 525 } 526 527 if (!uses_fixed_storage()) 528 { 529 delete[] mData; 530 } 531 532 mData = newData; 533 mReservedSize = newSize; 534 } 535 } 536 537 template <class Value, size_t N> 538 class FastMap final 539 { 540 public: 541 FastMap() {} 542 ~FastMap() {} 543 544 Value &operator[](uint32_t key) 545 { 546 if (mData.size() <= key) 547 { 548 mData.resize(key + 1, {}); 549 } 550 return mData[key]; 551 } 552 553 const Value &operator[](uint32_t key) const 554 { 555 ASSERT(key < mData.size()); 556 return mData[key]; 557 } 558 559 void clear() { mData.clear(); } 560 561 bool empty() const { return mData.empty(); } 562 size_t size() const { return mData.size(); } 563 564 const Value *data() const { return mData.data(); } 565 566 bool operator==(const FastMap<Value, N> &other) const 567 { 568 return (size() == other.size()) && 569 (memcmp(data(), other.data(), size() * sizeof(Value)) == 0); 570 } 571 572 private: 573 FastVector<Value, N> mData; 574 }; 575 576 template <class Key, class Value, size_t N> 577 class FlatUnorderedMap final 578 { 579 public: 580 using Pair = std::pair<Key, Value>; 581 using Storage = FastVector<Pair, N>; 582 using iterator = typename Storage::iterator; 583 using const_iterator = typename Storage::const_iterator; 584 585 FlatUnorderedMap() = default; 586 ~FlatUnorderedMap() = default; 587 588 iterator begin() { return mData.begin(); } 589 const_iterator begin() const { return mData.begin(); } 590 iterator end() { return mData.end(); } 591 const_iterator end() const { return mData.end(); } 592 593 iterator find(const Key &key) 594 { 595 for (auto it = mData.begin(); it != mData.end(); ++it) 596 { 597 if (it->first == key) 598 { 599 return it; 600 } 601 } 602 return mData.end(); 603 } 604 605 const_iterator find(const Key &key) const 606 { 607 for (auto it = mData.begin(); it != mData.end(); ++it) 608 { 609 if (it->first == key) 610 { 611 return it; 612 } 613 } 614 return mData.end(); 615 } 616 617 Value &operator[](const Key &key) 618 { 619 iterator it = find(key); 620 if (it != end()) 621 { 622 return it->second; 623 } 624 625 mData.push_back(Pair(key, {})); 626 return mData.back().second; 627 } 628 629 void insert(Pair pair) 630 { 631 ASSERT(!contains(pair.first)); 632 mData.push_back(std::move(pair)); 633 } 634 635 void insert(const Key &key, Value value) { insert(Pair(key, value)); } 636 637 void erase(iterator pos) { mData.remove_and_permute(pos); } 638 639 bool contains(const Key &key) const { return find(key) != end(); } 640 641 void clear() { mData.clear(); } 642 643 bool get(const Key &key, Value *value) const 644 { 645 auto it = find(key); 646 if (it != end()) 647 { 648 *value = it->second; 649 return true; 650 } 651 return false; 652 } 653 654 bool empty() const { return mData.empty(); } 655 size_t size() const { return mData.size(); } 656 657 private: 658 FastVector<Pair, N> mData; 659 }; 660 661 template <class T, size_t N> 662 class FlatUnorderedSet final 663 { 664 public: 665 using Storage = FastVector<T, N>; 666 using iterator = typename Storage::iterator; 667 using const_iterator = typename Storage::const_iterator; 668 669 FlatUnorderedSet() = default; 670 ~FlatUnorderedSet() = default; 671 672 iterator begin() { return mData.begin(); } 673 const_iterator begin() const { return mData.begin(); } 674 iterator end() { return mData.end(); } 675 const_iterator end() const { return mData.end(); } 676 677 iterator find(const T &value) 678 { 679 for (auto it = mData.begin(); it != mData.end(); ++it) 680 { 681 if (*it == value) 682 { 683 return it; 684 } 685 } 686 return mData.end(); 687 } 688 689 const_iterator find(const T &value) const 690 { 691 for (auto it = mData.begin(); it != mData.end(); ++it) 692 { 693 if (*it == value) 694 { 695 return it; 696 } 697 } 698 return mData.end(); 699 } 700 701 bool empty() const { return mData.empty(); } 702 703 void insert(const T &value) 704 { 705 ASSERT(!contains(value)); 706 mData.push_back(value); 707 } 708 709 void erase(const T &value) 710 { 711 ASSERT(contains(value)); 712 mData.remove_and_permute(value); 713 } 714 715 void remove(const T &value) { erase(value); } 716 717 bool contains(const T &value) const { return find(value) != end(); } 718 719 void clear() { mData.clear(); } 720 721 bool operator==(const FlatUnorderedSet<T, N> &other) const { return mData == other.mData; } 722 723 private: 724 Storage mData; 725 }; 726 727 class FastIntegerSet final 728 { 729 public: 730 static constexpr size_t kWindowSize = 64; 731 static constexpr size_t kOneLessThanKWindowSize = kWindowSize - 1; 732 static constexpr size_t kShiftForDivision = 733 static_cast<size_t>(rx::Log2(static_cast<unsigned int>(kWindowSize))); 734 using KeyBitSet = angle::BitSet64<kWindowSize>; 735 736 ANGLE_INLINE FastIntegerSet(); 737 ANGLE_INLINE ~FastIntegerSet(); 738 739 ANGLE_INLINE void ensureCapacity(size_t size) 740 { 741 if (capacity() <= size) 742 { 743 reserve(size * 2); 744 } 745 } 746 747 ANGLE_INLINE void insert(uint64_t key) 748 { 749 size_t sizedKey = static_cast<size_t>(key); 750 751 ASSERT(!contains(sizedKey)); 752 ensureCapacity(sizedKey); 753 ASSERT(capacity() > sizedKey); 754 755 size_t index = sizedKey >> kShiftForDivision; 756 size_t offset = sizedKey & kOneLessThanKWindowSize; 757 758 mKeyData[index].set(offset, true); 759 } 760 761 ANGLE_INLINE bool contains(uint64_t key) const 762 { 763 size_t sizedKey = static_cast<size_t>(key); 764 765 size_t index = sizedKey >> kShiftForDivision; 766 size_t offset = sizedKey & kOneLessThanKWindowSize; 767 768 return (sizedKey < capacity()) && (mKeyData[index].test(offset)); 769 } 770 771 ANGLE_INLINE void clear() 772 { 773 for (KeyBitSet &it : mKeyData) 774 { 775 it.reset(); 776 } 777 } 778 779 ANGLE_INLINE bool empty() const 780 { 781 for (const KeyBitSet &it : mKeyData) 782 { 783 if (it.any()) 784 { 785 return false; 786 } 787 } 788 return true; 789 } 790 791 ANGLE_INLINE size_t size() const 792 { 793 size_t valid_entries = 0; 794 for (const KeyBitSet &it : mKeyData) 795 { 796 valid_entries += it.count(); 797 } 798 return valid_entries; 799 } 800 801 private: 802 ANGLE_INLINE size_t capacity() const { return kWindowSize * mKeyData.size(); } 803 804 ANGLE_INLINE void reserve(size_t newSize) 805 { 806 size_t alignedSize = rx::roundUpPow2(newSize, kWindowSize); 807 size_t count = alignedSize >> kShiftForDivision; 808 809 mKeyData.resize(count, KeyBitSet::Zero()); 810 } 811 812 std::vector<KeyBitSet> mKeyData; 813 }; 814 815 // This is needed to accommodate the chromium style guide error - 816 // [chromium-style] Complex constructor has an inlined body. 817 ANGLE_INLINE FastIntegerSet::FastIntegerSet() {} 818 ANGLE_INLINE FastIntegerSet::~FastIntegerSet() {} 819 820 template <typename Value> 821 class FastIntegerMap final 822 { 823 public: 824 FastIntegerMap() {} 825 ~FastIntegerMap() {} 826 827 ANGLE_INLINE void ensureCapacity(size_t size) 828 { 829 // Ensure key set has capacity 830 mKeySet.ensureCapacity(size); 831 832 // Ensure value vector has capacity 833 ensureCapacityImpl(size); 834 } 835 836 ANGLE_INLINE void insert(uint64_t key, Value value) 837 { 838 // Insert key 839 ASSERT(!mKeySet.contains(key)); 840 mKeySet.insert(key); 841 842 // Insert value 843 size_t sizedKey = static_cast<size_t>(key); 844 ensureCapacityImpl(sizedKey); 845 ASSERT(capacity() > sizedKey); 846 mValueData[sizedKey] = value; 847 } 848 849 ANGLE_INLINE bool contains(uint64_t key) const { return mKeySet.contains(key); } 850 851 ANGLE_INLINE bool get(uint64_t key, Value *out) const 852 { 853 if (!mKeySet.contains(key)) 854 { 855 return false; 856 } 857 858 size_t sizedKey = static_cast<size_t>(key); 859 *out = mValueData[sizedKey]; 860 return true; 861 } 862 863 ANGLE_INLINE void clear() { mKeySet.clear(); } 864 865 ANGLE_INLINE bool empty() const { return mKeySet.empty(); } 866 867 ANGLE_INLINE size_t size() const { return mKeySet.size(); } 868 869 private: 870 ANGLE_INLINE size_t capacity() const { return mValueData.size(); } 871 872 ANGLE_INLINE void ensureCapacityImpl(size_t size) 873 { 874 if (capacity() <= size) 875 { 876 reserve(size * 2); 877 } 878 } 879 880 ANGLE_INLINE void reserve(size_t newSize) 881 { 882 size_t alignedSize = rx::roundUpPow2(newSize, FastIntegerSet::kWindowSize); 883 mValueData.resize(alignedSize); 884 } 885 886 FastIntegerSet mKeySet; 887 std::vector<Value> mValueData; 888 }; 889 } // namespace angle 890 891 #endif // COMMON_FASTVECTOR_H_