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 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
78 | 78 |
79 friend class HashTable<Key, Value, Extractor, HashFunctions, Traits, Key Traits, Allocator>; | 79 friend class HashTable<Key, Value, Extractor, HashFunctions, Traits, Key Traits, Allocator>; |
80 friend class HashTableIterator<Key, Value, Extractor, HashFunctions, Tra its, KeyTraits, Allocator>; | 80 friend class HashTableIterator<Key, Value, Extractor, HashFunctions, Tra its, KeyTraits, Allocator>; |
81 | 81 |
82 void skipEmptyBuckets() | 82 void skipEmptyBuckets() |
83 { | 83 { |
84 while (m_position != m_endPosition && HashTableType::isEmptyOrDelete dBucket(*m_position)) | 84 while (m_position != m_endPosition && HashTableType::isEmptyOrDelete dBucket(*m_position)) |
85 ++m_position; | 85 ++m_position; |
86 } | 86 } |
87 | 87 |
88 HashTableConstIterator(PointerType position, PointerType endPosition) | 88 HashTableConstIterator(PointerType position, PointerType endPosition, co nst HashTableType* container) |
89 : m_position(position), m_endPosition(endPosition) | 89 : m_position(position) |
90 , m_endPosition(endPosition) | |
91 #ifdef ASSERT_ENABLED | |
92 , m_container(container) | |
93 , m_containerModifications(container->modifications()) | |
94 #endif | |
90 { | 95 { |
91 skipEmptyBuckets(); | 96 skipEmptyBuckets(); |
92 } | 97 } |
93 | 98 |
94 HashTableConstIterator(PointerType position, PointerType endPosition, Ha shItemKnownGoodTag) | 99 HashTableConstIterator(PointerType position, PointerType endPosition, co nst HashTableType* container, HashItemKnownGoodTag) |
95 : m_position(position), m_endPosition(endPosition) | 100 : m_position(position) |
101 , m_endPosition(endPosition) | |
102 #ifdef ASSERT_ENABLED | |
103 , m_container(container) | |
104 , m_containerModifications(container->modifications()) | |
105 #endif | |
96 { | 106 { |
97 } | 107 } |
98 | 108 |
109 void checkModifications() const | |
110 { | |
111 // HashTable and collections that build on it do not support | |
112 // modifications while there is an iterator in use. The exception | |
113 // is ListHashSet, which has its own iterators that tolerate | |
114 // modification of the underlying set. | |
115 ASSERT(m_containerModifications == m_container->modifications()); | |
116 } | |
117 | |
99 public: | 118 public: |
100 HashTableConstIterator() | 119 HashTableConstIterator() |
101 { | 120 { |
102 } | 121 } |
103 | 122 |
104 GetType get() const | 123 GetType get() const |
105 { | 124 { |
125 checkModifications(); | |
106 return m_position; | 126 return m_position; |
107 } | 127 } |
108 typename Traits::IteratorConstReferenceType operator*() const { return T raits::getToReferenceConstConversion(get()); } | 128 typename Traits::IteratorConstReferenceType operator*() const { return T raits::getToReferenceConstConversion(get()); } |
109 GetType operator->() const { return get(); } | 129 GetType operator->() const { return get(); } |
110 | 130 |
111 const_iterator& operator++() | 131 const_iterator& operator++() |
112 { | 132 { |
113 ASSERT(m_position != m_endPosition); | 133 ASSERT(m_position != m_endPosition); |
134 checkModifications(); | |
114 ++m_position; | 135 ++m_position; |
115 skipEmptyBuckets(); | 136 skipEmptyBuckets(); |
116 return *this; | 137 return *this; |
117 } | 138 } |
118 | 139 |
119 // postfix ++ intentionally omitted | 140 // postfix ++ intentionally omitted |
120 | 141 |
121 // Comparison. | 142 // Comparison. |
122 bool operator==(const const_iterator& other) const | 143 bool operator==(const const_iterator& other) const |
123 { | 144 { |
124 return m_position == other.m_position; | 145 return m_position == other.m_position; |
125 } | 146 } |
126 bool operator!=(const const_iterator& other) const | 147 bool operator!=(const const_iterator& other) const |
127 { | 148 { |
128 return m_position != other.m_position; | 149 return m_position != other.m_position; |
129 } | 150 } |
130 bool operator==(const iterator& other) const | 151 bool operator==(const iterator& other) const |
131 { | 152 { |
132 return *this == static_cast<const_iterator>(other); | 153 return *this == static_cast<const_iterator>(other); |
133 } | 154 } |
134 bool operator!=(const iterator& other) const | 155 bool operator!=(const iterator& other) const |
135 { | 156 { |
136 return *this != static_cast<const_iterator>(other); | 157 return *this != static_cast<const_iterator>(other); |
137 } | 158 } |
138 | 159 |
139 private: | 160 private: |
140 PointerType m_position; | 161 PointerType m_position; |
141 PointerType m_endPosition; | 162 PointerType m_endPosition; |
163 #ifdef ASSERT_ENABLED | |
164 const HashTableType* m_container; | |
165 int64_t m_containerModifications; | |
166 #endif | |
142 }; | 167 }; |
143 | 168 |
144 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> | 169 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> |
145 class HashTableIterator { | 170 class HashTableIterator { |
146 private: | 171 private: |
172 typedef HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTrait s, Allocator> HashTableType; | |
147 typedef HashTableIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> iterator; | 173 typedef HashTableIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> iterator; |
148 typedef HashTableConstIterator<Key, Value, Extractor, HashFunctions, Tra its, KeyTraits, Allocator> const_iterator; | 174 typedef HashTableConstIterator<Key, Value, Extractor, HashFunctions, Tra its, KeyTraits, Allocator> const_iterator; |
149 typedef Value ValueType; | 175 typedef Value ValueType; |
150 typedef typename Traits::IteratorGetType GetType; | 176 typedef typename Traits::IteratorGetType GetType; |
151 typedef ValueType* PointerType; | 177 typedef ValueType* PointerType; |
152 | 178 |
153 friend class HashTable<Key, Value, Extractor, HashFunctions, Traits, Key Traits, Allocator>; | 179 friend class HashTable<Key, Value, Extractor, HashFunctions, Traits, Key Traits, Allocator>; |
154 | 180 |
155 HashTableIterator(PointerType pos, PointerType end) : m_iterator(pos, en d) { } | 181 HashTableIterator(PointerType pos, PointerType end, const HashTableType* container) : m_iterator(pos, end, container) { } |
156 HashTableIterator(PointerType pos, PointerType end, HashItemKnownGoodTag tag) : m_iterator(pos, end, tag) { } | 182 HashTableIterator(PointerType pos, PointerType end, const HashTableType* container, HashItemKnownGoodTag tag) : m_iterator(pos, end, container, tag) { } |
157 | 183 |
158 public: | 184 public: |
159 HashTableIterator() { } | 185 HashTableIterator() { } |
160 | 186 |
161 // default copy, assignment and destructor are OK | 187 // default copy, assignment and destructor are OK |
162 | 188 |
163 GetType get() const { return const_cast<GetType>(m_iterator.get()); } | 189 GetType get() const { return const_cast<GetType>(m_iterator.get()); } |
164 typename Traits::IteratorReferenceType operator*() const { return Traits ::getToReferenceConversion(get()); } | 190 typename Traits::IteratorReferenceType operator*() const { return Traits ::getToReferenceConversion(get()); } |
165 GetType operator->() const { return get(); } | 191 GetType operator->() const { return get(); } |
166 | 192 |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
342 | 368 |
343 static bool isEmptyBucket(const ValueType& value) { return isHashTraitsE mptyValue<KeyTraits>(Extractor::extract(value)); } | 369 static bool isEmptyBucket(const ValueType& value) { return isHashTraitsE mptyValue<KeyTraits>(Extractor::extract(value)); } |
344 static bool isDeletedBucket(const ValueType& value) { return KeyTraits:: isDeletedValue(Extractor::extract(value)); } | 370 static bool isDeletedBucket(const ValueType& value) { return KeyTraits:: isDeletedValue(Extractor::extract(value)); } |
345 static bool isEmptyOrDeletedBucket(const ValueType& value) { return Hash TableHelper<ValueType, Extractor, KeyTraits>:: isEmptyOrDeletedBucket(value); } | 371 static bool isEmptyOrDeletedBucket(const ValueType& value) { return Hash TableHelper<ValueType, Extractor, KeyTraits>:: isEmptyOrDeletedBucket(value); } |
346 | 372 |
347 ValueType* lookup(KeyPeekInType key) { return lookup<IdentityTranslatorT ype>(key); } | 373 ValueType* lookup(KeyPeekInType key) { return lookup<IdentityTranslatorT ype>(key); } |
348 template<typename HashTranslator, typename T> ValueType* lookup(const T& ); | 374 template<typename HashTranslator, typename T> ValueType* lookup(const T& ); |
349 | 375 |
350 void trace(typename Allocator::Visitor*); | 376 void trace(typename Allocator::Visitor*); |
351 | 377 |
378 #ifdef ASSERT_ENABLED | |
379 int64_t modifications() const { return m_modifications; } | |
380 void registerModification() { m_modifications++; } | |
381 #else | |
382 int64_t modifications() const { return 0; } | |
383 void registerModification() { } | |
384 #endif | |
385 | |
352 private: | 386 private: |
353 static ValueType* allocateTable(unsigned size); | 387 static ValueType* allocateTable(unsigned size); |
354 static void deallocateTable(ValueType* table, unsigned size); | 388 static void deallocateTable(ValueType* table, unsigned size); |
355 | 389 |
356 typedef std::pair<ValueType*, bool> LookupType; | 390 typedef std::pair<ValueType*, bool> LookupType; |
357 typedef std::pair<LookupType, unsigned> FullLookupType; | 391 typedef std::pair<LookupType, unsigned> FullLookupType; |
358 | 392 |
359 LookupType lookupForWriting(const Key& key) { return lookupForWriting<Id entityTranslatorType>(key); }; | 393 LookupType lookupForWriting(const Key& key) { return lookupForWriting<Id entityTranslatorType>(key); }; |
360 template<typename HashTranslator, typename T> FullLookupType fullLookupF orWriting(const T&); | 394 template<typename HashTranslator, typename T> FullLookupType fullLookupF orWriting(const T&); |
361 template<typename HashTranslator, typename T> LookupType lookupForWritin g(const T&); | 395 template<typename HashTranslator, typename T> LookupType lookupForWritin g(const T&); |
362 | 396 |
363 void remove(ValueType*); | 397 void remove(ValueType*); |
364 | 398 |
365 bool shouldExpand() const { return (m_keyCount + m_deletedCount) * m_max Load >= m_tableSize; } | 399 bool shouldExpand() const { return (m_keyCount + m_deletedCount) * m_max Load >= m_tableSize; } |
366 bool mustRehashInPlace() const { return m_keyCount * m_minLoad < m_table Size * 2; } | 400 bool mustRehashInPlace() const { return m_keyCount * m_minLoad < m_table Size * 2; } |
367 bool shouldShrink() const { return m_keyCount * m_minLoad < m_tableSize && m_tableSize > KeyTraits::minimumTableSize; } | 401 bool shouldShrink() const { return m_keyCount * m_minLoad < m_tableSize && m_tableSize > KeyTraits::minimumTableSize; } |
368 void expand(); | 402 void expand(); |
369 void shrink() { rehash(m_tableSize / 2); } | 403 void shrink() { rehash(m_tableSize / 2); } |
370 | 404 |
371 void rehash(unsigned newTableSize); | 405 void rehash(unsigned newTableSize); |
372 void reinsert(ValueType&); | 406 void reinsert(ValueType&); |
373 | 407 |
374 static void initializeBucket(ValueType& bucket); | 408 static void initializeBucket(ValueType& bucket); |
375 static void deleteBucket(ValueType& bucket) { bucket.~ValueType(); Trait s::constructDeletedValue(bucket); } | 409 static void deleteBucket(ValueType& bucket) { bucket.~ValueType(); Trait s::constructDeletedValue(bucket); } |
376 | 410 |
377 FullLookupType makeLookupResult(ValueType* position, bool found, unsigne d hash) | 411 FullLookupType makeLookupResult(ValueType* position, bool found, unsigne d hash) |
378 { return FullLookupType(LookupType(position, found), hash); } | 412 { return FullLookupType(LookupType(position, found), hash); } |
379 | 413 |
380 iterator makeIterator(ValueType* pos) { return iterator(pos, m_table + m _tableSize); } | 414 iterator makeIterator(ValueType* pos) { return iterator(pos, m_table + m _tableSize, this); } |
381 const_iterator makeConstIterator(ValueType* pos) const { return const_it erator(pos, m_table + m_tableSize); } | 415 const_iterator makeConstIterator(ValueType* pos) const { return const_it erator(pos, m_table + m_tableSize, this); } |
382 iterator makeKnownGoodIterator(ValueType* pos) { return iterator(pos, m_ table + m_tableSize, HashItemKnownGood); } | 416 iterator makeKnownGoodIterator(ValueType* pos) { return iterator(pos, m_ table + m_tableSize, this, HashItemKnownGood); } |
383 const_iterator makeKnownGoodConstIterator(ValueType* pos) const { return const_iterator(pos, m_table + m_tableSize, HashItemKnownGood); } | 417 const_iterator makeKnownGoodConstIterator(ValueType* pos) const { return const_iterator(pos, m_table + m_tableSize, this, HashItemKnownGood); } |
384 | 418 |
385 static const unsigned m_maxLoad = 2; | 419 static const unsigned m_maxLoad = 2; |
386 static const unsigned m_minLoad = 6; | 420 static const unsigned m_minLoad = 6; |
387 | 421 |
388 ValueType* m_table; | 422 ValueType* m_table; |
389 unsigned m_tableSize; | 423 unsigned m_tableSize; |
390 unsigned m_tableSizeMask; | 424 unsigned m_tableSizeMask; |
391 unsigned m_keyCount; | 425 unsigned m_keyCount; |
392 unsigned m_deletedCount; | 426 unsigned m_deletedCount; |
427 #ifdef ASSERT_ENABLED | |
428 unsigned m_modifications; | |
429 #endif | |
393 | 430 |
394 #if DUMP_HASHTABLE_STATS_PER_TABLE | 431 #if DUMP_HASHTABLE_STATS_PER_TABLE |
395 public: | 432 public: |
396 mutable OwnPtr<Stats> m_stats; | 433 mutable OwnPtr<Stats> m_stats; |
397 #endif | 434 #endif |
398 | 435 |
399 template<bool x, typename T, typename U, typename V, typename W, typenam e X, typename Y, typename Z> friend struct WeakProcessingHashTableHelper; | 436 template<bool x, typename T, typename U, typename V, typename W, typenam e X, typename Y, typename Z> friend struct WeakProcessingHashTableHelper; |
400 }; | 437 }; |
401 | 438 |
402 // Set all the bits to one after the most significant bit: 00110101010 -> 00 111111111. | 439 // Set all the bits to one after the most significant bit: 00110101010 -> 00 111111111. |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
437 COMPILE_ASSERT(value > (2 * size), HashTableCapacityHoldsContentSize); | 474 COMPILE_ASSERT(value > (2 * size), HashTableCapacityHoldsContentSize); |
438 }; | 475 }; |
439 | 476 |
440 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> | 477 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> |
441 inline HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Al locator>::HashTable() | 478 inline HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Al locator>::HashTable() |
442 : m_table(0) | 479 : m_table(0) |
443 , m_tableSize(0) | 480 , m_tableSize(0) |
444 , m_tableSizeMask(0) | 481 , m_tableSizeMask(0) |
445 , m_keyCount(0) | 482 , m_keyCount(0) |
446 , m_deletedCount(0) | 483 , m_deletedCount(0) |
484 #ifdef ASSERT_ENABLED | |
485 , m_modifications(0) | |
486 #endif | |
447 #if DUMP_HASHTABLE_STATS_PER_TABLE | 487 #if DUMP_HASHTABLE_STATS_PER_TABLE |
448 , m_stats(adoptPtr(new Stats)) | 488 , m_stats(adoptPtr(new Stats)) |
449 #endif | 489 #endif |
450 { | 490 { |
451 } | 491 } |
452 | 492 |
453 inline unsigned doubleHash(unsigned key) | 493 inline unsigned doubleHash(unsigned key) |
454 { | 494 { |
455 key = ~key + (key >> 23); | 495 key = ~key + (key >> 23); |
456 key ^= (key << 12); | 496 key ^= (key << 12); |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
514 k = 1 | doubleHash(h); | 554 k = 1 | doubleHash(h); |
515 i = (i + k) & sizeMask; | 555 i = (i + k) & sizeMask; |
516 } | 556 } |
517 } | 557 } |
518 | 558 |
519 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> | 559 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> |
520 template<typename HashTranslator, typename T> | 560 template<typename HashTranslator, typename T> |
521 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) | 561 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) |
522 { | 562 { |
523 ASSERT(m_table); | 563 ASSERT(m_table); |
564 registerModification(); | |
Mikhail
2014/04/01 09:28:33
'lookupForWriting()' does not actually do modifica
Erik Corry
2014/04/01 10:21:29
Done.
| |
524 | 565 |
525 size_t k = 0; | 566 size_t k = 0; |
526 ValueType* table = m_table; | 567 ValueType* table = m_table; |
527 size_t sizeMask = m_tableSizeMask; | 568 size_t sizeMask = m_tableSizeMask; |
528 unsigned h = HashTranslator::hash(key); | 569 unsigned h = HashTranslator::hash(key); |
529 size_t i = h & sizeMask; | 570 size_t i = h & sizeMask; |
530 | 571 |
531 #if DUMP_HASHTABLE_STATS | 572 #if DUMP_HASHTABLE_STATS |
532 atomicIncrement(&HashTableStats::numAccesses); | 573 atomicIncrement(&HashTableStats::numAccesses); |
533 int probeCount = 0; | 574 int probeCount = 0; |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
576 k = 1 | doubleHash(h); | 617 k = 1 | doubleHash(h); |
577 i = (i + k) & sizeMask; | 618 i = (i + k) & sizeMask; |
578 } | 619 } |
579 } | 620 } |
580 | 621 |
581 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> | 622 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> |
582 template<typename HashTranslator, typename T> | 623 template<typename HashTranslator, typename T> |
583 inline typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyT raits, Allocator>::FullLookupType HashTable<Key, Value, Extractor, HashFunctions , Traits, KeyTraits, Allocator>::fullLookupForWriting(const T& key) | 624 inline typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyT raits, Allocator>::FullLookupType HashTable<Key, Value, Extractor, HashFunctions , Traits, KeyTraits, Allocator>::fullLookupForWriting(const T& key) |
584 { | 625 { |
585 ASSERT(m_table); | 626 ASSERT(m_table); |
627 registerModification(); | |
Mikhail
2014/04/01 09:28:33
I guess this can be also omitted as 'fullLookupFor
Erik Corry
2014/04/01 10:21:29
Done.
| |
586 | 628 |
587 size_t k = 0; | 629 size_t k = 0; |
588 ValueType* table = m_table; | 630 ValueType* table = m_table; |
589 size_t sizeMask = m_tableSizeMask; | 631 size_t sizeMask = m_tableSizeMask; |
590 unsigned h = HashTranslator::hash(key); | 632 unsigned h = HashTranslator::hash(key); |
591 size_t i = h & sizeMask; | 633 size_t i = h & sizeMask; |
592 | 634 |
593 #if DUMP_HASHTABLE_STATS | 635 #if DUMP_HASHTABLE_STATS |
594 atomicIncrement(&HashTableStats::numAccesses); | 636 atomicIncrement(&HashTableStats::numAccesses); |
595 int probeCount = 0; | 637 int probeCount = 0; |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
722 #if DUMP_HASHTABLE_STATS_PER_TABLE | 764 #if DUMP_HASHTABLE_STATS_PER_TABLE |
723 ++perTableProbeCount; | 765 ++perTableProbeCount; |
724 m_stats->recordCollisionAtCount(perTableProbeCount); | 766 m_stats->recordCollisionAtCount(perTableProbeCount); |
725 #endif | 767 #endif |
726 | 768 |
727 if (!k) | 769 if (!k) |
728 k = 1 | doubleHash(h); | 770 k = 1 | doubleHash(h); |
729 i = (i + k) & sizeMask; | 771 i = (i + k) & sizeMask; |
730 } | 772 } |
731 | 773 |
774 registerModification(); | |
775 | |
732 if (deletedEntry) { | 776 if (deletedEntry) { |
733 initializeBucket(*deletedEntry); | 777 initializeBucket(*deletedEntry); |
734 entry = deletedEntry; | 778 entry = deletedEntry; |
735 --m_deletedCount; | 779 --m_deletedCount; |
736 } | 780 } |
737 | 781 |
738 HashTranslator::translate(*entry, key, extra); | 782 HashTranslator::translate(*entry, key, extra); |
739 | 783 |
740 ++m_keyCount; | 784 ++m_keyCount; |
741 | 785 |
(...skipping 10 matching lines...) Expand all Loading... | |
752 return result; | 796 return result; |
753 } | 797 } |
754 | 798 |
755 return AddResult(entry, true); | 799 return AddResult(entry, true); |
756 } | 800 } |
757 | 801 |
758 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> | 802 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> |
759 template<typename HashTranslator, typename T, typename Extra> | 803 template<typename HashTranslator, typename T, typename Extra> |
760 typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::AddResult HashTable<Key, Value, Extractor, HashFunctions, Traits, Ke yTraits, Allocator>::addPassingHashCode(const T& key, const Extra& extra) | 804 typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::AddResult HashTable<Key, Value, Extractor, HashFunctions, Traits, Ke yTraits, Allocator>::addPassingHashCode(const T& key, const Extra& extra) |
761 { | 805 { |
806 registerModification(); | |
Mikhail
2014/04/01 09:28:33
looks like it should be consistent with the check
Erik Corry
2014/04/01 10:21:29
Done.
| |
762 if (!m_table) | 807 if (!m_table) |
763 expand(); | 808 expand(); |
764 | 809 |
765 FullLookupType lookupResult = fullLookupForWriting<HashTranslator>(key); | 810 FullLookupType lookupResult = fullLookupForWriting<HashTranslator>(key); |
766 | 811 |
767 ValueType* entry = lookupResult.first.first; | 812 ValueType* entry = lookupResult.first.first; |
768 bool found = lookupResult.first.second; | 813 bool found = lookupResult.first.second; |
769 unsigned h = lookupResult.second; | 814 unsigned h = lookupResult.second; |
770 | 815 |
771 if (found) | 816 if (found) |
(...skipping 19 matching lines...) Expand all Loading... | |
791 return result; | 836 return result; |
792 } | 837 } |
793 | 838 |
794 return AddResult(entry, true); | 839 return AddResult(entry, true); |
795 } | 840 } |
796 | 841 |
797 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> | 842 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> |
798 inline void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTrait s, Allocator>::reinsert(ValueType& entry) | 843 inline void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTrait s, Allocator>::reinsert(ValueType& entry) |
799 { | 844 { |
800 ASSERT(m_table); | 845 ASSERT(m_table); |
846 registerModification(); | |
801 ASSERT(!lookupForWriting(Extractor::extract(entry)).second); | 847 ASSERT(!lookupForWriting(Extractor::extract(entry)).second); |
802 ASSERT(!isDeletedBucket(*(lookupForWriting(Extractor::extract(entry)).fi rst))); | 848 ASSERT(!isDeletedBucket(*(lookupForWriting(Extractor::extract(entry)).fi rst))); |
803 #if DUMP_HASHTABLE_STATS | 849 #if DUMP_HASHTABLE_STATS |
804 atomicIncrement(&HashTableStats::numReinserts); | 850 atomicIncrement(&HashTableStats::numReinserts); |
805 #endif | 851 #endif |
806 #if DUMP_HASHTABLE_STATS_PER_TABLE | 852 #if DUMP_HASHTABLE_STATS_PER_TABLE |
807 ++m_stats->numReinserts; | 853 ++m_stats->numReinserts; |
808 #endif | 854 #endif |
809 | 855 |
810 Mover<ValueType, Traits::needsDestruction>::move(entry, *lookupForWritin g(Extractor::extract(entry)).first); | 856 Mover<ValueType, Traits::needsDestruction>::move(entry, *lookupForWritin g(Extractor::extract(entry)).first); |
(...skipping 24 matching lines...) Expand all Loading... | |
835 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> | 881 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> |
836 template <typename HashTranslator, typename T> | 882 template <typename HashTranslator, typename T> |
837 bool HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allo cator>::contains(const T& key) const | 883 bool HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allo cator>::contains(const T& key) const |
838 { | 884 { |
839 return const_cast<HashTable*>(this)->lookup<HashTranslator>(key); | 885 return const_cast<HashTable*>(this)->lookup<HashTranslator>(key); |
840 } | 886 } |
841 | 887 |
842 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> | 888 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> |
843 void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allo cator>::remove(ValueType* pos) | 889 void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allo cator>::remove(ValueType* pos) |
844 { | 890 { |
891 registerModification(); | |
845 #if DUMP_HASHTABLE_STATS | 892 #if DUMP_HASHTABLE_STATS |
846 atomicIncrement(&HashTableStats::numRemoves); | 893 atomicIncrement(&HashTableStats::numRemoves); |
847 #endif | 894 #endif |
848 #if DUMP_HASHTABLE_STATS_PER_TABLE | 895 #if DUMP_HASHTABLE_STATS_PER_TABLE |
849 ++m_stats->numRemoves; | 896 ++m_stats->numRemoves; |
850 #endif | 897 #endif |
851 | 898 |
852 deleteBucket(*pos); | 899 deleteBucket(*pos); |
853 ++m_deletedCount; | 900 ++m_deletedCount; |
854 --m_keyCount; | 901 --m_keyCount; |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
953 reinsert(oldTable[i]); | 1000 reinsert(oldTable[i]); |
954 | 1001 |
955 m_deletedCount = 0; | 1002 m_deletedCount = 0; |
956 | 1003 |
957 deallocateTable(oldTable, oldTableSize); | 1004 deallocateTable(oldTable, oldTableSize); |
958 } | 1005 } |
959 | 1006 |
960 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> | 1007 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> |
961 void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allo cator>::clear() | 1008 void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allo cator>::clear() |
962 { | 1009 { |
1010 registerModification(); | |
963 if (!m_table) | 1011 if (!m_table) |
964 return; | 1012 return; |
965 | 1013 |
966 deallocateTable(m_table, m_tableSize); | 1014 deallocateTable(m_table, m_tableSize); |
967 m_table = 0; | 1015 m_table = 0; |
968 m_tableSize = 0; | 1016 m_tableSize = 0; |
969 m_tableSizeMask = 0; | 1017 m_tableSizeMask = 0; |
970 m_keyCount = 0; | 1018 m_keyCount = 0; |
971 } | 1019 } |
972 | 1020 |
973 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> | 1021 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> |
974 HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator >::HashTable(const HashTable& other) | 1022 HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator >::HashTable(const HashTable& other) |
975 : m_table(0) | 1023 : m_table(0) |
976 , m_tableSize(0) | 1024 , m_tableSize(0) |
977 , m_tableSizeMask(0) | 1025 , m_tableSizeMask(0) |
978 , m_keyCount(0) | 1026 , m_keyCount(0) |
979 , m_deletedCount(0) | 1027 , m_deletedCount(0) |
1028 #ifdef ASSERT_ENABLED | |
1029 , m_modifications(0) | |
1030 #endif | |
980 #if DUMP_HASHTABLE_STATS_PER_TABLE | 1031 #if DUMP_HASHTABLE_STATS_PER_TABLE |
981 , m_stats(adoptPtr(new Stats(*other.m_stats))) | 1032 , m_stats(adoptPtr(new Stats(*other.m_stats))) |
982 #endif | 1033 #endif |
983 { | 1034 { |
984 // Copy the hash table the dumb way, by adding each element to the new t able. | 1035 // Copy the hash table the dumb way, by adding each element to the new t able. |
985 // It might be more efficient to copy the table slots, but it's not clea r that efficiency is needed. | 1036 // It might be more efficient to copy the table slots, but it's not clea r that efficiency is needed. |
986 const_iterator end = other.end(); | 1037 const_iterator end = other.end(); |
987 for (const_iterator it = other.begin(); it != end; ++it) | 1038 for (const_iterator it = other.begin(); it != end; ++it) |
988 add(*it); | 1039 add(*it); |
989 } | 1040 } |
990 | 1041 |
991 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> | 1042 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> |
992 void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allo cator>::swap(HashTable& other) | 1043 void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allo cator>::swap(HashTable& other) |
993 { | 1044 { |
994 std::swap(m_table, other.m_table); | 1045 std::swap(m_table, other.m_table); |
995 std::swap(m_tableSize, other.m_tableSize); | 1046 std::swap(m_tableSize, other.m_tableSize); |
996 std::swap(m_tableSizeMask, other.m_tableSizeMask); | 1047 std::swap(m_tableSizeMask, other.m_tableSizeMask); |
997 std::swap(m_keyCount, other.m_keyCount); | 1048 std::swap(m_keyCount, other.m_keyCount); |
998 std::swap(m_deletedCount, other.m_deletedCount); | 1049 std::swap(m_deletedCount, other.m_deletedCount); |
999 | 1050 |
1051 #ifdef ASSERT_ENABLED | |
1052 std::swap(m_modifications, other.m_modifications); | |
1053 #endif | |
1054 | |
1000 #if DUMP_HASHTABLE_STATS_PER_TABLE | 1055 #if DUMP_HASHTABLE_STATS_PER_TABLE |
1001 m_stats.swap(other.m_stats); | 1056 m_stats.swap(other.m_stats); |
1002 #endif | 1057 #endif |
1003 } | 1058 } |
1004 | 1059 |
1005 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> | 1060 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits, typename Allocator> |
1006 HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator >& HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> ::operator=(const HashTable& other) | 1061 HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator >& HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> ::operator=(const HashTable& other) |
1007 { | 1062 { |
1008 HashTable tmp(other); | 1063 HashTable tmp(other); |
1009 swap(tmp); | 1064 swap(tmp); |
(...skipping 17 matching lines...) Expand all Loading... | |
1027 if (table->m_table) { | 1082 if (table->m_table) { |
1028 // This just marks it live and does not push anything onto the | 1083 // This just marks it live and does not push anything onto the |
1029 // marking stack. | 1084 // marking stack. |
1030 Allocator::markNoTracing(visitor, table->m_table); | 1085 Allocator::markNoTracing(visitor, table->m_table); |
1031 // Now perform weak processing (this is a no-op if the backing | 1086 // Now perform weak processing (this is a no-op if the backing |
1032 // was accessible through an iterator and was already marked | 1087 // was accessible through an iterator and was already marked |
1033 // strongly). | 1088 // strongly). |
1034 for (typename HashTableType::ValueType* element = table->m_table + table->m_tableSize - 1; element >= table->m_table; element--) { | 1089 for (typename HashTableType::ValueType* element = table->m_table + table->m_tableSize - 1; element >= table->m_table; element--) { |
1035 if (!HashTableType::isEmptyOrDeletedBucket(*element)) { | 1090 if (!HashTableType::isEmptyOrDeletedBucket(*element)) { |
1036 if (Allocator::hasDeadMember(visitor, *element)) { | 1091 if (Allocator::hasDeadMember(visitor, *element)) { |
1092 table->registerModification(); | |
1037 HashTableType::deleteBucket(*element); // Also calls the destructor. | 1093 HashTableType::deleteBucket(*element); // Also calls the destructor. |
1038 table->m_deletedCount++; | 1094 table->m_deletedCount++; |
1039 table->m_keyCount--; | 1095 table->m_keyCount--; |
1040 // We don't rehash the backing until the next add | 1096 // We don't rehash the backing until the next add |
1041 // or delete, because that would cause allocation | 1097 // or delete, because that would cause allocation |
1042 // during GC. | 1098 // during GC. |
1043 } | 1099 } |
1044 } | 1100 } |
1045 } | 1101 } |
1046 } | 1102 } |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1166 inline bool operator!=(const HashTableIteratorAdapter<T, U>& a, const HashTa bleConstIteratorAdapter<T, U>& b) | 1222 inline bool operator!=(const HashTableIteratorAdapter<T, U>& a, const HashTa bleConstIteratorAdapter<T, U>& b) |
1167 { | 1223 { |
1168 return a.m_impl != b.m_impl; | 1224 return a.m_impl != b.m_impl; |
1169 } | 1225 } |
1170 | 1226 |
1171 } // namespace WTF | 1227 } // namespace WTF |
1172 | 1228 |
1173 #include "wtf/HashIterators.h" | 1229 #include "wtf/HashIterators.h" |
1174 | 1230 |
1175 #endif // WTF_HashTable_h | 1231 #endif // WTF_HashTable_h |
OLD | NEW |