hashtable.hpp
Go to the documentation of this file.00001
00002
00005 #ifndef HASHTABLE_HPP
00006 #define HASHTABLE_HPP
00007
00008 template <class Titem_>
00009 struct CHashTableSlotT
00010 {
00011 typedef typename Titem_::Key Key;
00012
00013 Titem_ *m_pFirst;
00014
00015 CHashTableSlotT() : m_pFirst(NULL) {}
00016
00018 FORCEINLINE void Clear() {m_pFirst = NULL;}
00019
00021 FORCEINLINE const Titem_ *Find(const Key& key) const
00022 {
00023 for (const Titem_ *pItem = m_pFirst; pItem != NULL; pItem = pItem->GetHashNext()) {
00024 if (pItem->GetKey() == key) {
00025
00026 return pItem;
00027 }
00028 }
00029 return NULL;
00030 }
00031
00033 FORCEINLINE Titem_ *Find(const Key& key)
00034 {
00035 for (Titem_ *pItem = m_pFirst; pItem != NULL; pItem = pItem->GetHashNext()) {
00036 if (pItem->GetKey() == key) {
00037
00038 return pItem;
00039 }
00040 }
00041 return NULL;
00042 }
00043
00045 FORCEINLINE void Attach(Titem_& new_item)
00046 {
00047 assert(new_item.GetHashNext() == NULL);
00048 new_item.SetHashNext(m_pFirst);
00049 m_pFirst = &new_item;
00050 }
00051
00053 FORCEINLINE bool Detach(Titem_& item_to_remove)
00054 {
00055 if (m_pFirst == &item_to_remove) {
00056 m_pFirst = item_to_remove.GetHashNext();
00057 item_to_remove.SetHashNext(NULL);
00058 return true;
00059 }
00060 Titem_ *pItem = m_pFirst;
00061 while (true) {
00062 if (pItem == NULL) {
00063 return false;
00064 }
00065 Titem_ *pNextItem = pItem->GetHashNext();
00066 if (pNextItem == &item_to_remove) break;
00067 pItem = pNextItem;
00068 }
00069 pItem->SetHashNext(item_to_remove.GetHashNext());
00070 item_to_remove.SetHashNext(NULL);
00071 return true;
00072 }
00073
00075 FORCEINLINE Titem_ *Detach(const Key& key)
00076 {
00077
00078 if (m_pFirst == NULL) {
00079 return NULL;
00080 }
00081
00082 if (m_pFirst->GetKey() == key) {
00083 Titem_& ret_item = *m_pFirst;
00084 m_pFirst = m_pFirst->GetHashNext();
00085 ret_item.SetHashNext(NULL);
00086 return &ret_item;
00087 }
00088
00089 Titem_ *pPrev = m_pFirst;
00090 for (Titem_ *pItem = m_pFirst->GetHashNext(); pItem != NULL; pPrev = pItem, pItem = pItem->GetHashNext()) {
00091 if (pItem->GetKey() == key) {
00092
00093 pPrev->SetHashNext(pItem->GetHashNext());
00094 pItem->SetHashNext(NULL);
00095 return pItem;
00096 }
00097 }
00098 return NULL;
00099 }
00100 };
00101
00123 template <class Titem_, int Thash_bits_>
00124 class CHashTableT {
00125 public:
00126 typedef Titem_ Titem;
00127 typedef typename Titem_::Key Tkey;
00128 static const int Thash_bits = Thash_bits_;
00129 static const int Tcapacity = 1 << Thash_bits;
00130
00131 protected:
00134 typedef CHashTableSlotT<Titem_> Slot;
00135
00136 Slot *m_slots;
00137 int m_num_items;
00138
00139 public:
00140
00141 FORCEINLINE CHashTableT()
00142 {
00143
00144 m_slots = new Slot[Tcapacity];
00145 m_num_items = 0;
00146 }
00147
00148 ~CHashTableT() {delete [] m_slots; m_num_items = 0; m_slots = NULL;}
00149
00150 protected:
00152 FORCEINLINE static int CalcHash(const Tkey& key)
00153 {
00154 int32 hash = key.CalcHash();
00155 if ((8 * Thash_bits) < 32) hash ^= hash >> (min(8 * Thash_bits, 31));
00156 if ((4 * Thash_bits) < 32) hash ^= hash >> (min(4 * Thash_bits, 31));
00157 if ((2 * Thash_bits) < 32) hash ^= hash >> (min(2 * Thash_bits, 31));
00158 if ((1 * Thash_bits) < 32) hash ^= hash >> (min(1 * Thash_bits, 31));
00159 hash &= (1 << Thash_bits) - 1;
00160 return hash;
00161 }
00162
00164 FORCEINLINE static int CalcHash(const Titem_& item) {return CalcHash(item.GetKey());}
00165
00166 public:
00168 FORCEINLINE int Count() const {return m_num_items;}
00169
00171 FORCEINLINE void Clear() const {for (int i = 0; i < Tcapacity; i++) m_slots[i].Clear();}
00172
00174 const Titem_ *Find(const Tkey& key) const
00175 {
00176 int hash = CalcHash(key);
00177 const Slot& slot = m_slots[hash];
00178 const Titem_ *item = slot.Find(key);
00179 return item;
00180 }
00181
00183 Titem_ *Find(const Tkey& key)
00184 {
00185 int hash = CalcHash(key);
00186 Slot& slot = m_slots[hash];
00187 Titem_ *item = slot.Find(key);
00188 return item;
00189 }
00190
00192 Titem_ *TryPop(const Tkey& key)
00193 {
00194 int hash = CalcHash(key);
00195 Slot& slot = m_slots[hash];
00196 Titem_ *item = slot.Detach(key);
00197 if (item != NULL) {
00198 m_num_items--;
00199 }
00200 return item;
00201 }
00202
00204 Titem_& Pop(const Tkey& key)
00205 {
00206 Titem_ *item = TryPop(key);
00207 assert(item != NULL);
00208 return *item;
00209 }
00210
00212 bool TryPop(Titem_& item)
00213 {
00214 const Tkey& key = item.GetKey();
00215 int hash = CalcHash(key);
00216 Slot& slot = m_slots[hash];
00217 bool ret = slot.Detach(item);
00218 if (ret) {
00219 m_num_items--;
00220 }
00221 return ret;
00222 }
00223
00225 void Pop(Titem_& item)
00226 {
00227 bool ret = TryPop(item);
00228 assert(ret);
00229 }
00230
00232 void Push(Titem_& new_item)
00233 {
00234 int hash = CalcHash(new_item);
00235 Slot& slot = m_slots[hash];
00236 assert(slot.Find(new_item.GetKey()) == NULL);
00237 slot.Attach(new_item);
00238 m_num_items++;
00239 }
00240 };
00241
00242 #endif