1 //===- HashBase.h ---------------------------------------------------------===// 2 // 3 // The MCLinker Project 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 #ifndef MCLD_HASH_BASE_H 10 #define MCLD_HASH_BASE_H 11 #ifdef ENABLE_UNITTEST 12 #include <gtest.h> 13 #endif 14 #include <llvm/ADT/StringRef.h> 15 #include <cstdlib> 16 17 namespace mcld { 18 19 /** forward declaration **/ 20 template<typename HashTableImplTy> 21 class ChainIteratorBase; 22 23 template<typename HashTableImplTy> 24 class EntryIteratorBase; 25 26 /** \class HashBucket 27 * \brief HashBucket is an entry in the hash table. 28 */ 29 template<typename HashEntryTy> 30 class HashBucket 31 { 32 public: 33 typedef HashEntryTy entry_type; 34 35 public: 36 unsigned int FullHashValue; 37 entry_type *Entry; 38 39 public: 40 static entry_type* getEmptyBucket(); 41 static entry_type* getTombstone(); 42 43 }; 44 45 /** \class HashTableImpl 46 * \brief HashTableImpl is the base class of HashTable. 47 * 48 * HashTableImpl uses open-addressing, linear probing hash table. 49 * linear probing hash table obviously has high performance when the 50 * load factor is less than 0.7. 51 * The drawback is that the number of the stored items can notbe more 52 * than the size of the hash table. 53 * 54 * MCLinker tries to merge every things in the same HashEntry. It can 55 * keep every thing in the same cache line and improve the locality 56 * efficiently. HashTableImpl provides a template argument to change the 57 * definition of HashEntries. 58 * 59 * HashEntryTy must provide getKey() and getKenLength() functions. 60 * 61 * Different environments have different demands of HashFunctions. For 62 * example, on-device linkers needs a more light-weight hash function 63 * than static linkers. HashTableImpl also provides a template argument to 64 * change the hash functions. 65 */ 66 template<typename HashEntryTy, 67 typename HashFunctionTy> 68 class HashTableImpl 69 { 70 private: 71 static const unsigned int NumOfInitBuckets = 16; 72 73 public: 74 typedef size_t size_type; 75 typedef HashFunctionTy hasher; 76 typedef HashEntryTy entry_type; 77 typedef typename HashEntryTy::key_type key_type; 78 typedef HashBucket<HashEntryTy> bucket_type; 79 typedef HashTableImpl<HashEntryTy, HashFunctionTy> Self; 80 81 82 public: 83 HashTableImpl(); 84 explicit HashTableImpl(unsigned int pInitSize); 85 virtual ~HashTableImpl(); 86 87 // ----- observers ----- // 88 bool empty() const; 89 90 size_t numOfBuckets() const 91 { return m_NumOfBuckets; } 92 93 size_t numOfEntries() const 94 { return m_NumOfEntries; } 95 96 hasher& hash() 97 { return m_Hasher; } 98 99 const hasher& hash() const 100 { return m_Hasher; } 101 102 protected: 103 /// initialize the hash table. 104 void init(unsigned int pInitSize); 105 106 void clear(); 107 108 /// lookUpBucketFor - search the index of bucket whose key is p>ey 109 // @return the index of the found bucket 110 unsigned int lookUpBucketFor(const key_type& pKey); 111 112 /// findKey - finds an element with key pKey 113 // return the index of the element, or -1 when the element does not exist. 114 int findKey(const key_type& pKey) const; 115 116 /// mayRehash - check the load_factor, compute the new size, and then doRehash 117 void mayRehash(); 118 119 /// doRehash - re-new the hash table, and rehash all elements into the new buckets 120 void doRehash(unsigned int pNewSize); 121 122 friend class ChainIteratorBase<Self>; 123 friend class ChainIteratorBase<const Self>; 124 friend class EntryIteratorBase<Self>; 125 friend class EntryIteratorBase<const Self>; 126 protected: 127 // Array of Buckets 128 bucket_type* m_Buckets; 129 unsigned int m_NumOfBuckets; 130 unsigned int m_NumOfEntries; 131 unsigned int m_NumOfTombstones; 132 hasher m_Hasher; 133 134 }; 135 136 #include "HashBase.tcc" 137 138 } // namespace of mcld 139 140 #endif 141 142