📄 hashtable.h
字号:
typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::const_iterator HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::find(const T& key) const { if (!m_table) return end(); ValueType* entry = const_cast<HashTable*>(this)->lookup<T, HashTranslator>(key); if (!entry) return end(); return makeKnownGoodConstIterator(entry); } template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> template <typename T, typename HashTranslator> bool HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::contains(const T& key) const { if (!m_table) return false; return const_cast<HashTable*>(this)->lookup<T, HashTranslator>(key); } template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::removeAndInvalidateWithoutEntryConsistencyCheck(ValueType* pos) { invalidateIterators(); remove(pos); } template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::removeAndInvalidate(ValueType* pos) { invalidateIterators(); checkTableConsistency(); remove(pos); } template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::remove(ValueType* pos) {#if DUMP_HASHTABLE_STATS atomicIncrement(&HashTableStats::numRemoves);#endif deleteBucket(*pos); ++m_deletedCount; --m_keyCount; if (shouldShrink()) shrink(); checkTableConsistency(); } template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> inline void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::remove(iterator it) { if (it == end()) return; removeAndInvalidate(const_cast<ValueType*>(it.m_iterator.m_position)); } template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> inline void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::removeWithoutEntryConsistencyCheck(iterator it) { if (it == end()) return; removeAndInvalidateWithoutEntryConsistencyCheck(const_cast<ValueType*>(it.m_iterator.m_position)); } template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> inline void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::remove(const KeyType& key) { remove(find(key)); } template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::allocateTable(int size) { // would use a template member function with explicit specializations here, but // gcc doesn't appear to support that if (Traits::emptyValueIsZero) return static_cast<ValueType*>(fastZeroedMalloc(size * sizeof(ValueType))); ValueType* result = static_cast<ValueType*>(fastMalloc(size * sizeof(ValueType))); for (int i = 0; i < size; i++) initializeBucket(result[i]); return result; } template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::deallocateTable(ValueType* table, int size) { if (Traits::needsDestruction) { for (int i = 0; i < size; ++i) { if (!isDeletedBucket(table[i])) table[i].~ValueType(); } } fastFree(table); } template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::expand() { int newSize; if (m_tableSize == 0) newSize = m_minTableSize; else if (mustRehashInPlace()) newSize = m_tableSize; else newSize = m_tableSize * 2; rehash(newSize); } template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::rehash(int newTableSize) { checkTableConsistencyExceptSize(); int oldTableSize = m_tableSize; ValueType* oldTable = m_table;#if DUMP_HASHTABLE_STATS if (oldTableSize != 0) atomicIncrement(&HashTableStats::numRehashes);#endif m_tableSize = newTableSize; m_tableSizeMask = newTableSize - 1; m_table = allocateTable(newTableSize); for (int i = 0; i != oldTableSize; ++i) if (!isEmptyOrDeletedBucket(oldTable[i])) reinsert(oldTable[i]); m_deletedCount = 0; deallocateTable(oldTable, oldTableSize); checkTableConsistency(); } template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::clear() { invalidateIterators(); deallocateTable(m_table, m_tableSize); m_table = 0; m_tableSize = 0; m_tableSizeMask = 0; m_keyCount = 0; } template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::HashTable(const HashTable& other) : m_table(0) , m_tableSize(0) , m_tableSizeMask(0) , m_keyCount(0) , m_deletedCount(0)#if CHECK_HASHTABLE_ITERATORS , m_iterators(0)#endif { // Copy the hash table the dumb way, by adding each element to the new table. // It might be more efficient to copy the table slots, but it's not clear that efficiency is needed. const_iterator end = other.end(); for (const_iterator it = other.begin(); it != end; ++it) add(*it); } template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::swap(HashTable& other) { invalidateIterators(); other.invalidateIterators(); ValueType* tmp_table = m_table; m_table = other.m_table; other.m_table = tmp_table; int tmp_tableSize = m_tableSize; m_tableSize = other.m_tableSize; other.m_tableSize = tmp_tableSize; int tmp_tableSizeMask = m_tableSizeMask; m_tableSizeMask = other.m_tableSizeMask; other.m_tableSizeMask = tmp_tableSizeMask; int tmp_keyCount = m_keyCount; m_keyCount = other.m_keyCount; other.m_keyCount = tmp_keyCount; int tmp_deletedCount = m_deletedCount; m_deletedCount = other.m_deletedCount; other.m_deletedCount = tmp_deletedCount; } template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>& HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::operator=(const HashTable& other) { HashTable tmp(other); swap(tmp); return *this; }#if CHECK_HASHTABLE_CONSISTENCY template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::checkTableConsistency() const { checkTableConsistencyExceptSize(); ASSERT(!shouldExpand()); ASSERT(!shouldShrink()); } template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::checkTableConsistencyExceptSize() const { if (!m_table) return; int count = 0; int deletedCount = 0; for (int j = 0; j < m_tableSize; ++j) { ValueType* entry = m_table + j; if (isEmptyBucket(*entry)) continue; if (isDeletedBucket(*entry)) { ++deletedCount; continue; } const_iterator it = find(Extractor::extract(*entry)); ASSERT(entry == it.m_position); ++count; } ASSERT(count == m_keyCount); ASSERT(deletedCount == m_deletedCount); ASSERT(m_tableSize >= m_minTableSize); ASSERT(m_tableSizeMask); ASSERT(m_tableSize == m_tableSizeMask + 1); }#endif // CHECK_HASHTABLE_CONSISTENCY#if CHECK_HASHTABLE_ITERATORS template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::invalidateIterators() { MutexLocker lock(m_mutex); const_iterator* next; for (const_iterator* p = m_iterators; p; p = next) { next = p->m_next; p->m_table = 0; p->m_next = 0; p->m_previous = 0; } m_iterators = 0; } template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> void addIterator(const HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>* table, HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>* it) { it->m_table = table; it->m_previous = 0; // Insert iterator at head of doubly-linked list of iterators. if (!table) { it->m_next = 0; } else { MutexLocker lock(table->m_mutex); ASSERT(table->m_iterators != it); it->m_next = table->m_iterators; table->m_iterators = it; if (it->m_next) { ASSERT(!it->m_next->m_previous); it->m_next->m_previous = it; } } } template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> void removeIterator(HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>* it) { typedef HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits> HashTableType; typedef HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits> const_iterator; // Delete iterator from doubly-linked list of iterators. if (!it->m_table) { ASSERT(!it->m_next); ASSERT(!it->m_previous); } else { MutexLocker lock(it->m_table->m_mutex); if (it->m_next) { ASSERT(it->m_next->m_previous == it); it->m_next->m_previous = it->m_previous; } if (it->m_previous) { ASSERT(it->m_table->m_iterators != it); ASSERT(it->m_previous->m_next == it); it->m_previous->m_next = it->m_next; } else { ASSERT(it->m_table->m_iterators == it); it->m_table->m_iterators = it->m_next; } } it->m_table = 0; it->m_next = 0; it->m_previous = 0; }#endif // CHECK_HASHTABLE_ITERATORS // iterator adapters template<typename HashTableType, typename ValueType> struct HashTableConstIteratorAdapter { HashTableConstIteratorAdapter(const typename HashTableType::const_iterator& impl) : m_impl(impl) {} const ValueType* get() const { return (const ValueType*)m_impl.get(); } const ValueType& operator*() const { return *get(); } const ValueType* operator->() const { return get(); } HashTableConstIteratorAdapter& operator++() { ++m_impl; return *this; } // postfix ++ intentionally omitted typename HashTableType::const_iterator m_impl; }; template<typename HashTableType, typename ValueType> struct HashTableIteratorAdapter { HashTableIteratorAdapter(const typename HashTableType::iterator& impl) : m_impl(impl) {} ValueType* get() const { return (ValueType*)m_impl.get(); } ValueType& operator*() const { return *get(); } ValueType* operator->() const { return get(); } HashTableIteratorAdapter& operator++() { ++m_impl; return *this; } // postfix ++ intentionally omitted operator HashTableConstIteratorAdapter<HashTableType, ValueType>() { typename HashTableType::const_iterator i = m_impl; return i; } typename HashTableType::iterator m_impl; }; template<typename T, typename U> inline bool operator==(const HashTableConstIteratorAdapter<T, U>& a, const HashTableConstIteratorAdapter<T, U>& b) { return a.m_impl == b.m_impl; } template<typename T, typename U> inline bool operator!=(const HashTableConstIteratorAdapter<T, U>& a, const HashTableConstIteratorAdapter<T, U>& b) { return a.m_impl != b.m_impl; } template<typename T, typename U> inline bool operator==(const HashTableIteratorAdapter<T, U>& a, const HashTableIteratorAdapter<T, U>& b) { return a.m_impl == b.m_impl; } template<typename T, typename U> inline bool operator!=(const HashTableIteratorAdapter<T, U>& a, const HashTableIteratorAdapter<T, U>& b) { return a.m_impl != b.m_impl; }} // namespace WTF#include "HashIterators.h"#endif // WTF_HashTable_h
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -