OpenTTD Source  20240919-master-gdf0233f4c2
hashtable.hpp
Go to the documentation of this file.
1 /*
2  * This file is part of OpenTTD.
3  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6  */
7 
10 #ifndef HASHTABLE_HPP
11 #define HASHTABLE_HPP
12 
13 #include "../core/math_func.hpp"
14 
15 template <class Titem_>
17 {
18  typedef typename Titem_::Key Key; // make Titem_::Key a property of HashTable
19 
20  Titem_ *m_pFirst;
21 
22  inline CHashTableSlotT() : m_pFirst(nullptr) {}
23 
25  inline void Clear()
26  {
27  m_pFirst = nullptr;
28  }
29 
31  inline const Titem_ *Find(const Key &key) const
32  {
33  for (const Titem_ *pItem = m_pFirst; pItem != nullptr; pItem = pItem->GetHashNext()) {
34  if (pItem->GetKey() == key) {
35  /* we have found the item, return it */
36  return pItem;
37  }
38  }
39  return nullptr;
40  }
41 
43  inline Titem_ *Find(const Key &key)
44  {
45  for (Titem_ *pItem = m_pFirst; pItem != nullptr; pItem = pItem->GetHashNext()) {
46  if (pItem->GetKey() == key) {
47  /* we have found the item, return it */
48  return pItem;
49  }
50  }
51  return nullptr;
52  }
53 
55  inline void Attach(Titem_ &new_item)
56  {
57  assert(new_item.GetHashNext() == nullptr);
58  new_item.SetHashNext(m_pFirst);
59  m_pFirst = &new_item;
60  }
61 
63  inline bool Detach(Titem_ &item_to_remove)
64  {
65  if (m_pFirst == &item_to_remove) {
66  m_pFirst = item_to_remove.GetHashNext();
67  item_to_remove.SetHashNext(nullptr);
68  return true;
69  }
70  Titem_ *pItem = m_pFirst;
71  for (;;) {
72  if (pItem == nullptr) {
73  return false;
74  }
75  Titem_ *pNextItem = pItem->GetHashNext();
76  if (pNextItem == &item_to_remove) break;
77  pItem = pNextItem;
78  }
79  pItem->SetHashNext(item_to_remove.GetHashNext());
80  item_to_remove.SetHashNext(nullptr);
81  return true;
82  }
83 
85  inline Titem_ *Detach(const Key &key)
86  {
87  /* do we have any items? */
88  if (m_pFirst == nullptr) {
89  return nullptr;
90  }
91  /* is it our first item? */
92  if (m_pFirst->GetKey() == key) {
93  Titem_ &ret_item = *m_pFirst;
94  m_pFirst = m_pFirst->GetHashNext();
95  ret_item.SetHashNext(nullptr);
96  return &ret_item;
97  }
98  /* find it in the following items */
99  Titem_ *pPrev = m_pFirst;
100  for (Titem_ *pItem = m_pFirst->GetHashNext(); pItem != nullptr; pPrev = pItem, pItem = pItem->GetHashNext()) {
101  if (pItem->GetKey() == key) {
102  /* we have found the item, unlink and return it */
103  pPrev->SetHashNext(pItem->GetHashNext());
104  pItem->SetHashNext(nullptr);
105  return pItem;
106  }
107  }
108  return nullptr;
109  }
110 };
111 
134 template <class Titem_, int Thash_bits_>
135 class CHashTableT {
136 public:
137  typedef Titem_ Titem; // make Titem_ visible from outside of class
138  typedef typename Titem_::Key Tkey; // make Titem_::Key a property of HashTable
139  static const int Thash_bits = Thash_bits_; // publish num of hash bits
140  static const int Tcapacity = 1 << Thash_bits; // and num of slots 2^bits
141 
142 protected:
148 
149  Slot m_slots[Tcapacity]; // here we store our data (array of blobs)
150  int m_num_items; // item counter
151 
152 public:
153  /* default constructor */
154  inline CHashTableT() : m_num_items(0)
155  {
156  }
157 
158 protected:
160  inline static int CalcHash(const Tkey &key)
161  {
162  uint32_t hash = key.CalcHash();
163  hash -= (hash >> 17); // hash * 131071 / 131072
164  hash -= (hash >> 5); // * 31 / 32
165  hash &= (1 << Thash_bits) - 1; // modulo slots
166  return hash;
167  }
168 
170  inline static int CalcHash(const Titem_ &item)
171  {
172  return CalcHash(item.GetKey());
173  }
174 
175 public:
177  inline int Count() const
178  {
179  return m_num_items;
180  }
181 
183  inline void Clear()
184  {
185  for (int i = 0; i < Tcapacity; i++) m_slots[i].Clear();
186  }
187 
189  const Titem_ *Find(const Tkey &key) const
190  {
191  int hash = CalcHash(key);
192  const Slot &slot = m_slots[hash];
193  const Titem_ *item = slot.Find(key);
194  return item;
195  }
196 
198  Titem_ *Find(const Tkey &key)
199  {
200  int hash = CalcHash(key);
201  Slot &slot = m_slots[hash];
202  Titem_ *item = slot.Find(key);
203  return item;
204  }
205 
207  Titem_ *TryPop(const Tkey &key)
208  {
209  int hash = CalcHash(key);
210  Slot &slot = m_slots[hash];
211  Titem_ *item = slot.Detach(key);
212  if (item != nullptr) {
213  m_num_items--;
214  }
215  return item;
216  }
217 
219  Titem_ &Pop(const Tkey &key)
220  {
221  Titem_ *item = TryPop(key);
222  assert(item != nullptr);
223  return *item;
224  }
225 
227  bool TryPop(Titem_ &item)
228  {
229  const Tkey &key = item.GetKey();
230  int hash = CalcHash(key);
231  Slot &slot = m_slots[hash];
232  bool ret = slot.Detach(item);
233  if (ret) {
234  m_num_items--;
235  }
236  return ret;
237  }
238 
240  void Pop(Titem_ &item)
241  {
242  [[maybe_unused]] bool ret = TryPop(item);
243  assert(ret);
244  }
245 
247  void Push(Titem_ &new_item)
248  {
249  int hash = CalcHash(new_item);
250  Slot &slot = m_slots[hash];
251  assert(slot.Find(new_item.GetKey()) == nullptr);
252  slot.Attach(new_item);
253  m_num_items++;
254  }
255 };
256 
257 #endif /* HASHTABLE_HPP */
CHashTableSlotT::Detach
bool Detach(Titem_ &item_to_remove)
hash table slot helper - remove item from a slot
Definition: hashtable.hpp:63
CHashTableSlotT::Clear
void Clear()
hash table slot helper - clears the slot by simple forgetting its items
Definition: hashtable.hpp:25
CHashTableT::Slot
CHashTableSlotT< Titem_ > Slot
each slot contains pointer to the first item in the list, Titem contains pointer to the next item - G...
Definition: hashtable.hpp:147
CHashTableT::Pop
Titem_ & Pop(const Tkey &key)
non-const item search & removal
Definition: hashtable.hpp:219
CHashTableSlotT
Definition: hashtable.hpp:16
CHashTableT::CalcHash
static int CalcHash(const Tkey &key)
static helper - return hash for the given key modulo number of slots
Definition: hashtable.hpp:160
CHashTableSlotT::Attach
void Attach(Titem_ &new_item)
hash table slot helper - add new item to the slot
Definition: hashtable.hpp:55
CHashTableT::Find
const Titem_ * Find(const Tkey &key) const
const item search
Definition: hashtable.hpp:189
CHashTableT::TryPop
bool TryPop(Titem_ &item)
non-const item search & optional removal (if found)
Definition: hashtable.hpp:227
CHashTableT::Pop
void Pop(Titem_ &item)
non-const item search & removal
Definition: hashtable.hpp:240
CHashTableT::Count
int Count() const
item count
Definition: hashtable.hpp:177
CHashTableT::Clear
void Clear()
simple clear - forget all items - used by CSegmentCostCacheT.Flush()
Definition: hashtable.hpp:183
CHashTableT::TryPop
Titem_ * TryPop(const Tkey &key)
non-const item search & optional removal (if found)
Definition: hashtable.hpp:207
CHashTableT::CalcHash
static int CalcHash(const Titem_ &item)
static helper - return hash for the given item modulo number of slots
Definition: hashtable.hpp:170
CHashTableSlotT::Find
const Titem_ * Find(const Key &key) const
hash table slot helper - linear search for item with given key through the given blob - const version
Definition: hashtable.hpp:31
CHashTableSlotT::Find
Titem_ * Find(const Key &key)
hash table slot helper - linear search for item with given key through the given blob - non-const ver...
Definition: hashtable.hpp:43
CHashTableT::Find
Titem_ * Find(const Tkey &key)
non-const item search
Definition: hashtable.hpp:198
CHashTableT::Push
void Push(Titem_ &new_item)
add one item - copy it from the given item
Definition: hashtable.hpp:247
CHashTableT
class CHashTableT<Titem, Thash_bits> - simple hash table of pointers allocated elsewhere.
Definition: hashtable.hpp:135
CHashTableSlotT::Detach
Titem_ * Detach(const Key &key)
hash table slot helper - remove and return item from a slot
Definition: hashtable.hpp:85