OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2005, 2006, 2007, 2008, 2011, 2012 Apple Inc. All rights reserv
ed. | 2 * Copyright (C) 2005, 2006, 2007, 2008, 2011, 2012 Apple Inc. All rights reserv
ed. |
3 * Copyright (C) 2008 David Levin <levin@chromium.org> | 3 * Copyright (C) 2008 David Levin <levin@chromium.org> |
4 * | 4 * |
5 * This library is free software; you can redistribute it and/or | 5 * This library is free software; you can redistribute it and/or |
6 * modify it under the terms of the GNU Library General Public | 6 * modify it under the terms of the GNU Library General Public |
7 * License as published by the Free Software Foundation; either | 7 * License as published by the Free Software Foundation; either |
8 * version 2 of the License, or (at your option) any later version. | 8 * version 2 of the License, or (at your option) any later version. |
9 * | 9 * |
10 * This library is distributed in the hope that it will be useful, | 10 * This library is distributed in the hope that it will be useful, |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
54 }; | 54 }; |
55 | 55 |
56 #endif | 56 #endif |
57 | 57 |
58 template<typename Key, typename Value, typename Extractor, typename HashFunc
tions, typename Traits, typename KeyTraits, typename Allocator> | 58 template<typename Key, typename Value, typename Extractor, typename HashFunc
tions, typename Traits, typename KeyTraits, typename Allocator> |
59 class HashTable; | 59 class HashTable; |
60 template<typename Key, typename Value, typename Extractor, typename HashFunc
tions, typename Traits, typename KeyTraits, typename Allocator> | 60 template<typename Key, typename Value, typename Extractor, typename HashFunc
tions, typename Traits, typename KeyTraits, typename Allocator> |
61 class HashTableIterator; | 61 class HashTableIterator; |
62 template<typename Key, typename Value, typename Extractor, typename HashFunc
tions, typename Traits, typename KeyTraits, typename Allocator> | 62 template<typename Key, typename Value, typename Extractor, typename HashFunc
tions, typename Traits, typename KeyTraits, typename Allocator> |
63 class HashTableConstIterator; | 63 class HashTableConstIterator; |
| 64 template<typename Value, typename HashFunctions, typename HashTraits, typena
me Allocator> |
| 65 class LinkedHashSet; |
64 template<bool x, typename T, typename U, typename V, typename W, typename X,
typename Y, typename Z> | 66 template<bool x, typename T, typename U, typename V, typename W, typename X,
typename Y, typename Z> |
65 struct WeakProcessingHashTableHelper; | 67 struct WeakProcessingHashTableHelper; |
66 | 68 |
67 typedef enum { HashItemKnownGood } HashItemKnownGoodTag; | 69 typedef enum { HashItemKnownGood } HashItemKnownGoodTag; |
68 | 70 |
69 template<typename Key, typename Value, typename Extractor, typename HashFunc
tions, typename Traits, typename KeyTraits, typename Allocator> | 71 template<typename Key, typename Value, typename Extractor, typename HashFunc
tions, typename Traits, typename KeyTraits, typename Allocator> |
70 class HashTableConstIterator { | 72 class HashTableConstIterator { |
71 private: | 73 private: |
72 typedef HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTrait
s, Allocator> HashTableType; | 74 typedef HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTrait
s, Allocator> HashTableType; |
73 typedef HashTableIterator<Key, Value, Extractor, HashFunctions, Traits,
KeyTraits, Allocator> iterator; | 75 typedef HashTableIterator<Key, Value, Extractor, HashFunctions, Traits,
KeyTraits, Allocator> iterator; |
(...skipping 23 matching lines...) Expand all Loading... |
97 } | 99 } |
98 | 100 |
99 HashTableConstIterator(PointerType position, PointerType endPosition, co
nst HashTableType* container, HashItemKnownGoodTag) | 101 HashTableConstIterator(PointerType position, PointerType endPosition, co
nst HashTableType* container, HashItemKnownGoodTag) |
100 : m_position(position) | 102 : m_position(position) |
101 , m_endPosition(endPosition) | 103 , m_endPosition(endPosition) |
102 #ifdef ASSERT_ENABLED | 104 #ifdef ASSERT_ENABLED |
103 , m_container(container) | 105 , m_container(container) |
104 , m_containerModifications(container->modifications()) | 106 , m_containerModifications(container->modifications()) |
105 #endif | 107 #endif |
106 { | 108 { |
| 109 ASSERT(m_containerModifications == m_container->modifications()); |
107 } | 110 } |
108 | 111 |
109 void checkModifications() const | 112 void checkModifications() const |
110 { | 113 { |
111 // HashTable and collections that build on it do not support | 114 // HashTable and collections that build on it do not support |
112 // modifications while there is an iterator in use. The exception | 115 // modifications while there is an iterator in use. The exception |
113 // is ListHashSet, which has its own iterators that tolerate | 116 // is ListHashSet, which has its own iterators that tolerate |
114 // modification of the underlying set. | 117 // modification of the underlying set. |
115 ASSERT(m_containerModifications == m_container->modifications()); | 118 ASSERT(m_containerModifications == m_container->modifications()); |
116 } | 119 } |
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
365 | 368 |
366 void remove(KeyPeekInType); | 369 void remove(KeyPeekInType); |
367 void remove(iterator); | 370 void remove(iterator); |
368 void remove(const_iterator); | 371 void remove(const_iterator); |
369 void clear(); | 372 void clear(); |
370 | 373 |
371 static bool isEmptyBucket(const ValueType& value) { return isHashTraitsE
mptyValue<KeyTraits>(Extractor::extract(value)); } | 374 static bool isEmptyBucket(const ValueType& value) { return isHashTraitsE
mptyValue<KeyTraits>(Extractor::extract(value)); } |
372 static bool isDeletedBucket(const ValueType& value) { return KeyTraits::
isDeletedValue(Extractor::extract(value)); } | 375 static bool isDeletedBucket(const ValueType& value) { return KeyTraits::
isDeletedValue(Extractor::extract(value)); } |
373 static bool isEmptyOrDeletedBucket(const ValueType& value) { return Hash
TableHelper<ValueType, Extractor, KeyTraits>:: isEmptyOrDeletedBucket(value); } | 376 static bool isEmptyOrDeletedBucket(const ValueType& value) { return Hash
TableHelper<ValueType, Extractor, KeyTraits>:: isEmptyOrDeletedBucket(value); } |
374 | 377 |
375 ValueType* lookup(KeyPeekInType key) { return lookup<IdentityTranslatorT
ype>(key); } | 378 ValueType* lookup(KeyPeekInType key) { return lookup<IdentityTranslatorT
ype, KeyPeekInType>(key); } |
376 template<typename HashTranslator, typename T> ValueType* lookup(const T&
); | 379 template<typename HashTranslator, typename T> ValueType* lookup(T); |
| 380 template<typename HashTranslator, typename T> const ValueType* lookup(T)
const; |
377 | 381 |
378 void trace(typename Allocator::Visitor*); | 382 void trace(typename Allocator::Visitor*); |
379 | 383 |
380 #ifdef ASSERT_ENABLED | 384 #ifdef ASSERT_ENABLED |
381 int64_t modifications() const { return m_modifications; } | 385 int64_t modifications() const { return m_modifications; } |
382 void registerModification() { m_modifications++; } | 386 void registerModification() { m_modifications++; } |
| 387 // HashTable and collections that build on it do not support |
| 388 // modifications while there is an iterator in use. The exception is |
| 389 // ListHashSet, which has its own iterators that tolerate modification |
| 390 // of the underlying set. |
| 391 void checkModifications(int64_t mods) const { ASSERT(mods == m_modificat
ions); } |
383 #else | 392 #else |
384 int64_t modifications() const { return 0; } | 393 int64_t modifications() const { return 0; } |
385 void registerModification() { } | 394 void registerModification() { } |
| 395 void checkModifications(int64_t mods) const { } |
386 #endif | 396 #endif |
387 | 397 |
388 private: | 398 private: |
389 static ValueType* allocateTable(unsigned size); | 399 static ValueType* allocateTable(unsigned size); |
390 static void deleteAllBucketsAndDeallocate(ValueType* table, unsigned siz
e); | 400 static void deleteAllBucketsAndDeallocate(ValueType* table, unsigned siz
e); |
391 | 401 |
392 typedef std::pair<ValueType*, bool> LookupType; | 402 typedef std::pair<ValueType*, bool> LookupType; |
393 typedef std::pair<LookupType, unsigned> FullLookupType; | 403 typedef std::pair<LookupType, unsigned> FullLookupType; |
394 | 404 |
395 LookupType lookupForWriting(const Key& key) { return lookupForWriting<Id
entityTranslatorType>(key); }; | 405 LookupType lookupForWriting(const Key& key) { return lookupForWriting<Id
entityTranslatorType>(key); }; |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
429 #ifdef ASSERT_ENABLED | 439 #ifdef ASSERT_ENABLED |
430 unsigned m_modifications; | 440 unsigned m_modifications; |
431 #endif | 441 #endif |
432 | 442 |
433 #if DUMP_HASHTABLE_STATS_PER_TABLE | 443 #if DUMP_HASHTABLE_STATS_PER_TABLE |
434 public: | 444 public: |
435 mutable OwnPtr<Stats> m_stats; | 445 mutable OwnPtr<Stats> m_stats; |
436 #endif | 446 #endif |
437 | 447 |
438 template<bool x, typename T, typename U, typename V, typename W, typenam
e X, typename Y, typename Z> friend struct WeakProcessingHashTableHelper; | 448 template<bool x, typename T, typename U, typename V, typename W, typenam
e X, typename Y, typename Z> friend struct WeakProcessingHashTableHelper; |
| 449 template<typename T, typename U, typename V, typename W> friend class Li
nkedHashSet; |
439 }; | 450 }; |
440 | 451 |
441 // Set all the bits to one after the most significant bit: 00110101010 -> 00
111111111. | 452 // Set all the bits to one after the most significant bit: 00110101010 -> 00
111111111. |
442 template<unsigned size> struct OneifyLowBits; | 453 template<unsigned size> struct OneifyLowBits; |
443 template<> | 454 template<> |
444 struct OneifyLowBits<0> { | 455 struct OneifyLowBits<0> { |
445 static const unsigned value = 0; | 456 static const unsigned value = 0; |
446 }; | 457 }; |
447 template<unsigned number> | 458 template<unsigned number> |
448 struct OneifyLowBits { | 459 struct OneifyLowBits { |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
497 key = ~key + (key >> 23); | 508 key = ~key + (key >> 23); |
498 key ^= (key << 12); | 509 key ^= (key << 12); |
499 key ^= (key >> 7); | 510 key ^= (key >> 7); |
500 key ^= (key << 2); | 511 key ^= (key << 2); |
501 key ^= (key >> 20); | 512 key ^= (key >> 20); |
502 return key; | 513 return key; |
503 } | 514 } |
504 | 515 |
505 template<typename Key, typename Value, typename Extractor, typename HashFunc
tions, typename Traits, typename KeyTraits, typename Allocator> | 516 template<typename Key, typename Value, typename Extractor, typename HashFunc
tions, typename Traits, typename KeyTraits, typename Allocator> |
506 template<typename HashTranslator, typename T> | 517 template<typename HashTranslator, typename T> |
507 inline Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTra
its, Allocator>::lookup(const T& key) | 518 inline Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTra
its, Allocator>::lookup(T key) |
508 { | 519 { |
509 ValueType* table = m_table; | 520 return const_cast<Value*>(const_cast<const HashTable*>(this)->lookup<Has
hTranslator, T>(key)); |
| 521 } |
| 522 |
| 523 template<typename Key, typename Value, typename Extractor, typename HashFunc
tions, typename Traits, typename KeyTraits, typename Allocator> |
| 524 template<typename HashTranslator, typename T> |
| 525 inline const Value* HashTable<Key, Value, Extractor, HashFunctions, Traits,
KeyTraits, Allocator>::lookup(T key) const |
| 526 { |
| 527 const ValueType* table = m_table; |
510 if (!table) | 528 if (!table) |
511 return 0; | 529 return 0; |
512 | 530 |
513 size_t k = 0; | 531 size_t k = 0; |
514 size_t sizeMask = m_tableSizeMask; | 532 size_t sizeMask = m_tableSizeMask; |
515 unsigned h = HashTranslator::hash(key); | 533 unsigned h = HashTranslator::hash(key); |
516 size_t i = h & sizeMask; | 534 size_t i = h & sizeMask; |
517 | 535 |
518 #if DUMP_HASHTABLE_STATS | 536 #if DUMP_HASHTABLE_STATS |
519 atomicIncrement(&HashTableStats::numAccesses); | 537 atomicIncrement(&HashTableStats::numAccesses); |
520 int probeCount = 0; | 538 int probeCount = 0; |
521 #endif | 539 #endif |
522 | 540 |
523 #if DUMP_HASHTABLE_STATS_PER_TABLE | 541 #if DUMP_HASHTABLE_STATS_PER_TABLE |
524 ++m_stats->numAccesses; | 542 ++m_stats->numAccesses; |
525 int perTableProbeCount = 0; | 543 int perTableProbeCount = 0; |
526 #endif | 544 #endif |
527 | 545 |
528 while (1) { | 546 while (1) { |
529 ValueType* entry = table + i; | 547 const ValueType* entry = table + i; |
530 | 548 |
531 // we count on the compiler to optimize out this branch | 549 // we count on the compiler to optimize out this branch |
532 if (HashFunctions::safeToCompareToEmptyOrDeleted) { | 550 if (HashFunctions::safeToCompareToEmptyOrDeleted) { |
533 if (HashTranslator::equal(Extractor::extract(*entry), key)) | 551 if (HashTranslator::equal(Extractor::extract(*entry), key)) |
534 return entry; | 552 return entry; |
535 | 553 |
536 if (isEmptyBucket(*entry)) | 554 if (isEmptyBucket(*entry)) |
537 return 0; | 555 return 0; |
538 } else { | 556 } else { |
539 if (isEmptyBucket(*entry)) | 557 if (isEmptyBucket(*entry)) |
(...skipping 16 matching lines...) Expand all Loading... |
556 k = 1 | doubleHash(h); | 574 k = 1 | doubleHash(h); |
557 i = (i + k) & sizeMask; | 575 i = (i + k) & sizeMask; |
558 } | 576 } |
559 } | 577 } |
560 | 578 |
561 template<typename Key, typename Value, typename Extractor, typename HashFunc
tions, typename Traits, typename KeyTraits, typename Allocator> | 579 template<typename Key, typename Value, typename Extractor, typename HashFunc
tions, typename Traits, typename KeyTraits, typename Allocator> |
562 template<typename HashTranslator, typename T> | 580 template<typename HashTranslator, typename T> |
563 inline typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyT
raits, Allocator>::LookupType HashTable<Key, Value, Extractor, HashFunctions, Tr
aits, KeyTraits, Allocator>::lookupForWriting(const T& key) | 581 inline typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyT
raits, Allocator>::LookupType HashTable<Key, Value, Extractor, HashFunctions, Tr
aits, KeyTraits, Allocator>::lookupForWriting(const T& key) |
564 { | 582 { |
565 ASSERT(m_table); | 583 ASSERT(m_table); |
| 584 registerModification(); |
566 | 585 |
567 size_t k = 0; | 586 size_t k = 0; |
568 ValueType* table = m_table; | 587 ValueType* table = m_table; |
569 size_t sizeMask = m_tableSizeMask; | 588 size_t sizeMask = m_tableSizeMask; |
570 unsigned h = HashTranslator::hash(key); | 589 unsigned h = HashTranslator::hash(key); |
571 size_t i = h & sizeMask; | 590 size_t i = h & sizeMask; |
572 | 591 |
573 #if DUMP_HASHTABLE_STATS | 592 #if DUMP_HASHTABLE_STATS |
574 atomicIncrement(&HashTableStats::numAccesses); | 593 atomicIncrement(&HashTableStats::numAccesses); |
575 int probeCount = 0; | 594 int probeCount = 0; |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
618 k = 1 | doubleHash(h); | 637 k = 1 | doubleHash(h); |
619 i = (i + k) & sizeMask; | 638 i = (i + k) & sizeMask; |
620 } | 639 } |
621 } | 640 } |
622 | 641 |
623 template<typename Key, typename Value, typename Extractor, typename HashFunc
tions, typename Traits, typename KeyTraits, typename Allocator> | 642 template<typename Key, typename Value, typename Extractor, typename HashFunc
tions, typename Traits, typename KeyTraits, typename Allocator> |
624 template<typename HashTranslator, typename T> | 643 template<typename HashTranslator, typename T> |
625 inline typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyT
raits, Allocator>::FullLookupType HashTable<Key, Value, Extractor, HashFunctions
, Traits, KeyTraits, Allocator>::fullLookupForWriting(const T& key) | 644 inline typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyT
raits, Allocator>::FullLookupType HashTable<Key, Value, Extractor, HashFunctions
, Traits, KeyTraits, Allocator>::fullLookupForWriting(const T& key) |
626 { | 645 { |
627 ASSERT(m_table); | 646 ASSERT(m_table); |
| 647 registerModification(); |
628 | 648 |
629 size_t k = 0; | 649 size_t k = 0; |
630 ValueType* table = m_table; | 650 ValueType* table = m_table; |
631 size_t sizeMask = m_tableSizeMask; | 651 size_t sizeMask = m_tableSizeMask; |
632 unsigned h = HashTranslator::hash(key); | 652 unsigned h = HashTranslator::hash(key); |
633 size_t i = h & sizeMask; | 653 size_t i = h & sizeMask; |
634 | 654 |
635 #if DUMP_HASHTABLE_STATS | 655 #if DUMP_HASHTABLE_STATS |
636 atomicIncrement(&HashTableStats::numAccesses); | 656 atomicIncrement(&HashTableStats::numAccesses); |
637 int probeCount = 0; | 657 int probeCount = 0; |
(...skipping 590 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1228 inline bool operator!=(const HashTableIteratorAdapter<T, U>& a, const HashTa
bleConstIteratorAdapter<T, U>& b) | 1248 inline bool operator!=(const HashTableIteratorAdapter<T, U>& a, const HashTa
bleConstIteratorAdapter<T, U>& b) |
1229 { | 1249 { |
1230 return a.m_impl != b.m_impl; | 1250 return a.m_impl != b.m_impl; |
1231 } | 1251 } |
1232 | 1252 |
1233 } // namespace WTF | 1253 } // namespace WTF |
1234 | 1254 |
1235 #include "wtf/HashIterators.h" | 1255 #include "wtf/HashIterators.h" |
1236 | 1256 |
1237 #endif // WTF_HashTable_h | 1257 #endif // WTF_HashTable_h |
OLD | NEW |