gwnavruntime/kernel/SF_Hash.h Source File

SF_Hash.h
Go to the documentation of this file.
1 /*
2 * Copyright 2016 Autodesk, Inc. All rights reserved.
3 * Use of this software is subject to the terms of the Autodesk license agreement and any attachments or Appendices thereto provided at the time of installation or download,
4 * or which otherwise accompanies this software in either electronic or hard copy form, or which is signed by you and accepted by Autodesk.
5 */
6 
7 /**************************************************************************
8 
9 PublicHeader: None
10 Filename : KY_Hash.h
11 Content : Template hash-table/set implementation
12 Created : August 20, 2001
13 Authors : Michael Antonov, Sergey Sikorskiy
14 
15 **************************************************************************/
16 
17 #ifndef INC_KY_Kernel_Hash_H
18 #define INC_KY_Kernel_Hash_H
19 
22 
23 #undef new
24 
25 namespace Kaim {
26 
27 // ***** Hash Table Implementation
28 
29 // HastSet and Hash.
30 //
31 // Hash table, linear probing, internal chaining. One interesting/nice thing
32 // about this implementation is that the table itself is a flat chunk of memory
33 // containing no pointers, only relative indices. If the key and value types
34 // of the Hash contain no pointers, then the Hash can be serialized using raw IO.
35 //
36 // Never shrinks, unless you explicitly Clear() it. Expands on
37 // demand, though. For best results, if you know roughly how big your
38 // table will be, default it to that size when you create it.
39 //
40 // Key usability feature:
41 //
42 // 1. Allows node hash values to either be cached or not.
43 //
44 // 2. Allows for alternative keys with methods such as GetAlt(). Handy
45 // if you need to search nodes by their components; no need to create
46 // temporary nodes.
47 //
48 
49 
50 // *** Hash functors:
51 //
52 // IdentityHash - use when the key is already a good hash
53 // HFixedSizeHash - general hash based on object's in-memory representation.
54 
55 
56 // Hash is just the input value; can use this for integer-indexed hash tables.
57 template<class C>
58 class IdentityHash
59 {
60 public:
61  UPInt operator()(const C& data) const
62  { return (UPInt) data; }
63 };
64 
65 // Computes a hash of an object's representation.
66 template<class C>
67 class FixedSizeHash
68 {
69 public:
70  // Alternative: "sdbm" hash function, suggested at same web page
71  // above, http::/www.cs.yorku.ca/~oz/hash.html
72  // This is somewhat slower then Bernstein, but it works way better than the above
73  // hash function for hashing large numbers of 32-bit ints.
74  static KY_INLINE UPInt SDBM_Hash(const void* data_in, UPInt size, UPInt seed = 5381)
75  {
76  const UByte* data = (const UByte*) data_in;
77  UPInt h = seed;
78  while (size > 0)
79  {
80  size--;
81  h = (h << 16) + (h << 6) - h + (UPInt)data[size];
82  }
83  return h;
84  }
85 
86  UPInt operator()(const C& data) const
87  {
88  unsigned char* p = (unsigned char*) &data;
89  int size = sizeof(C);
90 
91  return SDBM_Hash(p, size);
92  }
93 };
94 
95 
96 
97 // *** HashsetEntry Entry types.
98 
99 // Compact hash table Entry type that re-computes hash keys during hash traversal.
100 // Good to use if the hash function is cheap or the hash value is already cached in C.
101 template<class C, class HashF>
102 class HashsetEntry
103 {
104 public:
105  // Internal chaining for collisions.
106  SPInt NextInChain;
107  C Value;
108 
109  HashsetEntry()
110  : NextInChain(-2) { }
111  HashsetEntry(const HashsetEntry& e)
112  : NextInChain(e.NextInChain), Value(e.Value) { }
113  HashsetEntry(const C& key, SPInt next)
114  : NextInChain(next), Value(key) { }
115 
116  bool IsEmpty() const { return NextInChain == -2; }
117  bool IsEndOfChain() const { return NextInChain == -1; }
118 
119  // Cached hash value access - can be optimized bu storing hash locally.
120  // Mask value only needs to be used if SetCachedHash is not implemented.
121  UPInt GetCachedHash(UPInt maskValue) const { return HashF()(Value) & maskValue; }
122  void SetCachedHash(UPInt) {}
123 
124  void Clear()
125  {
126  Value.~C(); // placement delete
127  NextInChain = -2;
128  }
129  // Free is only used from dtor of hash; Clear is used during regular operations:
130  // assignment, hash reallocations, value reassignments, so on.
131  void Free() { Clear(); }
132 };
133 
134 // Hash table Entry type that caches the Entry hash value for nodes, so that it
135 // does not need to be re-computed during access.
136 template<class C, class HashF>
137 class HashsetCachedEntry
138 {
139 public:
140  // Internal chaining for collisions.
141  SPInt NextInChain;
142  UPInt HashValue;
143  C Value;
144 
145  HashsetCachedEntry()
146  : NextInChain(-2) { }
147  HashsetCachedEntry(const HashsetCachedEntry& e)
148  : NextInChain(e.NextInChain), HashValue(e.HashValue), Value(e.Value) { }
149  HashsetCachedEntry(const C& key, SPInt next)
150  : NextInChain(next), Value(key) { }
151 
152  bool IsEmpty() const { return NextInChain == -2; }
153  bool IsEndOfChain() const { return NextInChain == -1; }
154 
155  // Cached hash value access - can be optimized bu storing hash locally.
156  // Mask value only needs to be used if SetCachedHash is not implemented.
157  UPInt GetCachedHash(UPInt maskValue) const { KY_UNUSED(maskValue); return HashValue; }
158  void SetCachedHash(UPInt hashValue) { HashValue = hashValue; }
159 
160  void Clear()
161  {
162  Value.~C();
163  NextInChain = -2;
164  }
165  // Free is only used from dtor of hash; Clear is used during regular operations:
166  // assignment, hash reallocations, value reassignments, so on.
167  void Free() { Clear(); }
168 };
169 
170 
171 
172 // *** HashSet implementation - relies on either cached or regular entries.
173 //
174 // Use: Entry = HashsetCachedEntry<C, HashF> if hashes are expensive to
175 // compute and thus need caching in entries.
176 // Entry = HashsetEntry<C, HashF> if hashes are already externally cached.
177 //
178 template<class C, class HashF = FixedSizeHash<C>,
179  class AltHashF = HashF,
180  class Allocator = AllocatorGH<C>,
181  class Entry = HashsetCachedEntry<C, HashF> >
182 class HashSetBase
183 {
184  enum { HashMinSize = 8 };
185 
186 public:
187  KY_MEMORY_REDEFINE_NEW(HashSetBase, Allocator::StatId)
188 
189  typedef HashSetBase<C, HashF, AltHashF, Allocator, Entry> SelfType;
190 
191  HashSetBase() : pTable(NULL) { }
192  HashSetBase(int sizeHint) : pTable(NULL) { SetCapacity(this, sizeHint); }
193  explicit HashSetBase(void* pmemAddr) : pTable(NULL){ KY_UNUSED(pmemAddr); }
194  HashSetBase(void* pmemAddr, int sizeHint) : pTable(NULL) { SetCapacity(pmemAddr, sizeHint); }
195  HashSetBase(const SelfType& src) : pTable(NULL) { Assign(this, src); }
196  ~HashSetBase()
197  {
198  if (pTable)
199  {
200  // Delete the entries.
201  for (UPInt i = 0, n = pTable->SizeMask; i <= n; i++)
202  {
203  Entry* e = &E(i);
204  if (!e->IsEmpty())
205  e->Free();
206  }
207 
208  Allocator::Free(pTable);
209  pTable = NULL;
210  }
211  }
212 
213 
214  void Assign(void* pmemAddr, const SelfType& src)
215  {
216  Clear();
217  if (src.IsEmpty() == false)
218  {
219  SetCapacity(pmemAddr, src.GetSize());
220 
221  for (ConstIterator it = src.Begin(); it != src.End(); ++it)
222  {
223  Add(pmemAddr, *it);
224  }
225  }
226  }
227 
228 
229  // Remove all entries from the HashSet table.
230  void Clear()
231  {
232  if (pTable)
233  {
234  // Delete the entries.
235  for (UPInt i = 0, n = pTable->SizeMask; i <= n; i++)
236  {
237  Entry* e = &E(i);
238  if (!e->IsEmpty())
239  e->Clear();
240  }
241 
242  Allocator::Free(pTable);
243  pTable = NULL;
244  }
245  }
246 
247  // Returns true if the HashSet is empty.
248  bool IsEmpty() const
249  {
250  return pTable == NULL || pTable->EntryCount == 0;
251  }
252 
253 
254  // Set a new or existing value under the key, to the value.
255  // Pass a different class of 'key' so that assignment reference object
256  // can be passed instead of the actual object.
257  template<class CRef>
258  void Set(void* pmemAddr, const CRef& key)
259  {
260  UPInt hashValue = HashF()(key);
261  SPInt index = (SPInt)-1;
262 
263  if (pTable != NULL)
264  index = findIndexCore(key, hashValue & pTable->SizeMask);
265 
266  if (index >= 0)
267  {
268  E(index).Value = key;
269  }
270  else
271  {
272  // Entry under key doesn't exist.
273  add(pmemAddr, key, hashValue);
274  }
275  }
276 
277  template<class CRef>
278  inline void Add(void* pmemAddr, const CRef& key)
279  {
280  UPInt hashValue = HashF()(key);
281  add(pmemAddr, key, hashValue);
282  }
283 
284  // Remove by alternative key.
285  template<class K>
286  void RemoveAlt(const K& key)
287  {
288  if (pTable == NULL)
289  return;
290 
291  UPInt hashValue = AltHashF()(key);
292  SPInt index = hashValue & pTable->SizeMask;
293 
294  Entry* e = &E(index);
295 
296  // If empty node or occupied by collider, we have nothing to remove.
297  if (e->IsEmpty() || (e->GetCachedHash(pTable->SizeMask) != (UPInt)index))
298  return;
299 
300  // Save index
301  SPInt naturalIndex = index;
302  SPInt prevIndex = -1;
303 
304  while ((e->GetCachedHash(pTable->SizeMask) != (UPInt)naturalIndex) || !(e->Value == key))
305  {
306  // Keep looking through the chain.
307  prevIndex = index;
308  index = e->NextInChain;
309  if (index == -1)
310  return; // End of chain, item not found
311  e = &E(index);
312  }
313 
314  // Found it - our item is at index
315  if (naturalIndex == index)
316  {
317  // If we have a follower, move it to us
318  if (!e->IsEndOfChain())
319  {
320  Entry* enext = &E(e->NextInChain);
321  e->Clear();
322  new (e) Entry(*enext);
323  // Point us to the follower's cell that will be cleared
324  e = enext;
325  }
326  }
327  else
328  {
329  // We are not at natural index, so deal with the prev items next index
330  E(prevIndex).NextInChain = e->NextInChain;
331  }
332 
333  // Clear us, of the follower cell that was moved.
334  e->Clear();
335  pTable->EntryCount --;
336  // Should we check the size to condense hash? ...
337  }
338 
339  // Remove by main key.
340  template<class CRef>
341  void Remove(const CRef& key)
342  {
343  RemoveAlt(key);
344  }
345 
346  // Retrieve the pointer to a value under the given key.
347  // - If there's no value under the key, then return NULL.
348  // - If there is a value, return the pointer.
349  template<class K>
350  C* Get(const K& key)
351  {
352  SPInt index = findIndex(key);
353  if (index >= 0)
354  return &E(index).Value;
355  return 0;
356  }
357 
358  template<class K>
359  const C* Get(const K& key) const
360  {
361  SPInt index = findIndex(key);
362  if (index >= 0)
363  return &E(index).Value;
364  return 0;
365  }
366 
367  // Alternative key versions of Get. Used by Hash.
368  template<class K>
369  const C* GetAlt(const K& key) const
370  {
371  SPInt index = findIndexAlt(key);
372  if (index >= 0)
373  return &E(index).Value;
374  return 0;
375  }
376 
377  template<class K>
378  C* GetAlt(const K& key)
379  {
380  SPInt index = findIndexAlt(key);
381  if (index >= 0)
382  return &E(index).Value;
383  return 0;
384  }
385 
386  template<class K>
387  bool GetAlt(const K& key, C* pval) const
388  {
389  SPInt index = findIndexAlt(key);
390  if (index >= 0)
391  {
392  if (pval)
393  *pval = E(index).Value;
394  return true;
395  }
396  return false;
397  }
398 
399 
400  UPInt GetSize() const
401  {
402  return pTable == NULL ? 0 : (UPInt)pTable->EntryCount;
403  }
404 
405 
406  // Resize the HashSet table to fit one more Entry. Often this
407  // doesn't involve any action.
408  void CheckExpand(void* pmemAddr)
409  {
410  if (pTable == NULL)
411  {
412  // Initial creation of table. Make a minimum-sized table.
413  setRawCapacity(pmemAddr, HashMinSize);
414  }
415  else if (pTable->EntryCount * 5 > (pTable->SizeMask + 1) * 4)
416  {
417  // pTable is more than 4/5 ths full. Expand.
418  setRawCapacity(pmemAddr, (pTable->SizeMask + 1) * 2);
419  }
420  }
421 
422  // Hint the bucket count to >= n.
423  void Resize(void* pmemAddr, UPInt n)
424  {
425  // Not really sure what this means in relation to
426  // STLport's hash_map... they say they "increase the
427  // bucket count to at least n" -- but does that mean
428  // their real capacity after Resize(n) is more like
429  // n*2 (since they do linked-list chaining within
430  // buckets?).
431  SetCapacity(pmemAddr, n);
432  }
433 
434  // Size the HashSet so that it can comfortably contain the given
435  // number of elements. If the HashSet already contains more
436  // elements than newSize, then this may be a no-op.
437  void SetCapacity(void* pmemAddr, UPInt newSize)
438  {
439  UPInt newRawSize = (newSize * 5) / 4;
440  if (newRawSize <= GetSize())
441  return;
442  setRawCapacity(pmemAddr, newRawSize);
443  }
444 
445  // Disable inappropriate 'operator ->' warning on MSVC6.
446 #ifdef KY_CC_MSVC
447 
448 #endif
449 
450  // Iterator API, like STL.
451  struct ConstIterator
452  {
453  const C& operator * () const
454  {
455  KY_ASSERT(Index >= 0 && Index <= (SPInt)pHash->pTable->SizeMask);
456  return pHash->E(Index).Value;
457  }
458 
459  const C* operator -> () const
460  {
461  KY_ASSERT(Index >= 0 && Index <= (SPInt)pHash->pTable->SizeMask);
462  return &pHash->E(Index).Value;
463  }
464 
465  void operator ++ ()
466  {
467  // Find next non-empty Entry.
468  if (Index <= (SPInt)pHash->pTable->SizeMask)
469  {
470  Index++;
471  while ((UPInt)Index <= pHash->pTable->SizeMask &&
472  pHash->E(Index).IsEmpty())
473  {
474  Index++;
475  }
476  }
477  }
478 
479  bool operator == (const ConstIterator& it) const
480  {
481  if (IsEnd() && it.IsEnd())
482  {
483  return true;
484  }
485  else
486  {
487  return (pHash == it.pHash) && (Index == it.Index);
488  }
489  }
490 
491  bool operator != (const ConstIterator& it) const
492  {
493  return ! (*this == it);
494  }
495 
496 
497  bool IsEnd() const
498  {
499  return (pHash == NULL) ||
500  (pHash->pTable == NULL) ||
501  (Index > (SPInt)pHash->pTable->SizeMask);
502  }
503 
504  ConstIterator()
505  : pHash(NULL), Index(0)
506  { }
507 
508  public:
509  // Constructor was intentionally made public to allow create
510  // iterator with arbitrary index.
511  ConstIterator(const SelfType* h, SPInt index)
512  : pHash(h), Index(index)
513  { }
514 
515  const SelfType* GetContainer() const
516  {
517  return pHash;
518  }
519  SPInt GetIndex() const
520  {
521  return Index;
522  }
523 
524  protected:
525  friend class HashSetBase<C, HashF, AltHashF, Allocator, Entry>;
526 
527  const SelfType* pHash;
528  SPInt Index;
529  };
530 
531  friend struct ConstIterator;
532 
533 
534  // Non-const Iterator; Get most of it from ConstIterator.
535  struct Iterator : public ConstIterator
536  {
537  // Allow non-const access to entries.
538  C& operator*() const
539  {
540  KY_ASSERT(ConstIterator::Index >= 0 && ConstIterator::Index <= (SPInt)ConstIterator::pHash->pTable->SizeMask);
541  return const_cast<SelfType*>(ConstIterator::pHash)->E(ConstIterator::Index).Value;
542  }
543 
544  C* operator->() const
545  {
546  return &(operator*());
547  }
548 
549  Iterator()
550  : ConstIterator(NULL, 0)
551  { }
552 
553  // Removes current element from Hash
554  void Remove()
555  {
556  RemoveAlt(operator*());
557  }
558 
559  template <class K>
560  void RemoveAlt(const K& key)
561  {
562  SelfType* phash = const_cast<SelfType*>(ConstIterator::pHash);
563  //Entry* ee = &phash->E(ConstIterator::Index);
564  //const C& key = ee->Value;
565 
566  UPInt hashValue = AltHashF()(key);
567  SPInt index = hashValue & phash->pTable->SizeMask;
568 
569  Entry* e = &phash->E(index);
570 
571  // If empty node or occupied by collider, we have nothing to remove.
572  if (e->IsEmpty() || (e->GetCachedHash(phash->pTable->SizeMask) != (UPInt)index))
573  return;
574 
575  // Save index
576  SPInt naturalIndex = index;
577  SPInt prevIndex = -1;
578 
579  while ((e->GetCachedHash(phash->pTable->SizeMask) != (UPInt)naturalIndex) || !(e->Value == key))
580  {
581  // Keep looking through the chain.
582  prevIndex = index;
583  index = e->NextInChain;
584  if (index == -1)
585  return; // End of chain, item not found
586  e = &phash->E(index);
587  }
588 
589  if (index == (SPInt)ConstIterator::Index)
590  {
591  // Found it - our item is at index
592  if (naturalIndex == index)
593  {
594  // If we have a follower, move it to us
595  if (!e->IsEndOfChain())
596  {
597  Entry* enext = &phash->E(e->NextInChain);
598  e->Clear();
599  new (e) Entry(*enext);
600  // Point us to the follower's cell that will be cleared
601  e = enext;
602  --ConstIterator::Index;
603  }
604  }
605  else
606  {
607  // We are not at natural index, so deal with the prev items next index
608  phash->E(prevIndex).NextInChain = e->NextInChain;
609  }
610 
611  // Clear us, of the follower cell that was moved.
612  e->Clear();
613  phash->pTable->EntryCount --;
614  }
615  else
616  KY_ASSERT(0); //?
617  }
618 
619  private:
620  friend class HashSetBase<C, HashF, AltHashF, Allocator, Entry>;
621 
622  Iterator(SelfType* h, SPInt i0)
623  : ConstIterator(h, i0)
624  { }
625  };
626 
627  friend struct Iterator;
628 
629  Iterator Begin()
630  {
631  if (pTable == 0)
632  return Iterator(NULL, 0);
633 
634  // Scan till we hit the First valid Entry.
635  UPInt i0 = 0;
636  while (i0 <= pTable->SizeMask && E(i0).IsEmpty())
637  {
638  i0++;
639  }
640  return Iterator(this, i0);
641  }
642  Iterator End() { return Iterator(NULL, 0); }
643 
644  ConstIterator Begin() const { return const_cast<SelfType*>(this)->Begin(); }
645  ConstIterator End() const { return const_cast<SelfType*>(this)->End(); }
646 
647  template<class K>
648  Iterator Find(const K& key)
649  {
650  SPInt index = findIndex(key);
651  if (index >= 0)
652  return Iterator(this, index);
653  return Iterator(NULL, 0);
654  }
655 
656  template<class K>
657  Iterator FindAlt(const K& key)
658  {
659  SPInt index = findIndexAlt(key);
660  if (index >= 0)
661  return Iterator(this, index);
662  return Iterator(NULL, 0);
663  }
664 
665  template<class K>
666  ConstIterator Find(const K& key) const { return const_cast<SelfType*>(this)->Find(key); }
667 
668  template<class K>
669  ConstIterator FindAlt(const K& key) const { return const_cast<SelfType*>(this)->FindAlt(key); }
670 
671 private:
672  // Find the index of the matching Entry. If no match, then return -1.
673  template<class K>
674  SPInt findIndex(const K& key) const
675  {
676  if (pTable == NULL)
677  return -1;
678  UPInt hashValue = HashF()(key) & pTable->SizeMask;
679  return findIndexCore(key, hashValue);
680  }
681 
682  template<class K>
683  SPInt findIndexAlt(const K& key) const
684  {
685  if (pTable == NULL)
686  return -1;
687  UPInt hashValue = AltHashF()(key) & pTable->SizeMask;
688  return findIndexCore(key, hashValue);
689  }
690 
691  // Find the index of the matching Entry. If no match, then return -1.
692  template<class K>
693  SPInt findIndexCore(const K& key, UPInt hashValue) const
694  {
695  // Table must exist.
696  KY_ASSERT(pTable != 0);
697  // Hash key must be 'and-ed' by the caller.
698  KY_ASSERT((hashValue & ~pTable->SizeMask) == 0);
699 
700  UPInt index = hashValue;
701  const Entry* e = &E(index);
702 
703  // If empty or occupied by a collider, not found.
704  if (e->IsEmpty() || (e->GetCachedHash(pTable->SizeMask) != index))
705  return -1;
706 
707  while(1)
708  {
709  KY_ASSERT(e->GetCachedHash(pTable->SizeMask) == hashValue);
710 
711  if (e->GetCachedHash(pTable->SizeMask) == hashValue && e->Value == key)
712  {
713  // Found it.
714  return index;
715  }
716  // Values can not be equal at this point.
717  // That would mean that the hash key for the same value differs.
718  KY_ASSERT(!(e->Value == key));
719 
720  // Keep looking through the chain.
721  index = e->NextInChain;
722  if (index == (UPInt)-1)
723  break; // end of chain
724 
725  e = &E(index);
726  KY_ASSERT(!e->IsEmpty());
727  }
728  return -1;
729  }
730 
731 
732  // Add a new value to the HashSet table, under the specified key.
733  template<class CRef>
734  void add(void* pmemAddr, const CRef& key, UPInt hashValue)
735  {
736  CheckExpand(pmemAddr);
737  hashValue &= pTable->SizeMask;
738 
739  pTable->EntryCount++;
740 
741  SPInt index = hashValue;
742  Entry* naturalEntry = &(E(index));
743 
744  if (naturalEntry->IsEmpty())
745  {
746  // Put the new Entry in.
747  new (naturalEntry) Entry(key, -1);
748  }
749  else
750  {
751  // Find a blank spot.
752  SPInt blankIndex = index;
753  do {
754  blankIndex = (blankIndex + 1) & pTable->SizeMask;
755  } while(!E(blankIndex).IsEmpty());
756 
757  Entry* blankEntry = &E(blankIndex);
758 
759  if (naturalEntry->GetCachedHash(pTable->SizeMask) == (UPInt)index)
760  {
761  // Collision. Link into this chain.
762 
763  // Move existing list head.
764  new (blankEntry) Entry(*naturalEntry); // placement new, copy ctor
765 
766  // Put the new info in the natural Entry.
767  naturalEntry->Value = key;
768  naturalEntry->NextInChain = blankIndex;
769  }
770  else
771  {
772  // Existing Entry does not naturally
773  // belong in this slot. Existing
774  // Entry must be moved.
775 
776  // Find natural location of collided element (i.e. root of chain)
777  SPInt collidedIndex = naturalEntry->GetCachedHash(pTable->SizeMask);
778  KY_ASSERT(collidedIndex >= 0 && collidedIndex <= (SPInt)pTable->SizeMask);
779  for (;;)
780  {
781  Entry* e = &E(collidedIndex);
782  if (e->NextInChain == index)
783  {
784  // Here's where we need to splice.
785  new (blankEntry) Entry(*naturalEntry);
786  e->NextInChain = blankIndex;
787  break;
788  }
789  collidedIndex = e->NextInChain;
790  KY_ASSERT(collidedIndex >= 0 && collidedIndex <= (SPInt)pTable->SizeMask);
791  }
792 
793  // Put the new data in the natural Entry.
794  naturalEntry->Value = key;
795  naturalEntry->NextInChain = -1;
796  }
797  }
798 
799  // Record hash value: has effect only if cached node is used.
800  naturalEntry->SetCachedHash(hashValue);
801  }
802 
803  // Index access helpers.
804  Entry& E(UPInt index)
805  {
806  // Must have pTable and access needs to be within bounds.
807  KY_ASSERT(index <= pTable->SizeMask);
808  return *(((Entry*) (pTable + 1)) + index);
809  }
810  const Entry& E(UPInt index) const
811  {
812  KY_ASSERT(index <= pTable->SizeMask);
813  return *(((Entry*) (pTable + 1)) + index);
814  }
815 
816 
817  // Resize the HashSet table to the given size (Rehash the
818  // contents of the current table). The arg is the number of
819  // HashSet table entries, not the number of elements we should
820  // actually contain (which will be less than this).
821  void setRawCapacity(void* pheapAddr, UPInt newSize)
822  {
823  if (newSize == 0)
824  {
825  // Special case.
826  Clear();
827  return;
828  }
829 
830  // Minimum size; don't incur rehashing cost when expanding
831  // very small tables. Not that we perform this check before
832  // 'log2f' call to avoid fp exception with newSize == 1.
833  if (newSize < HashMinSize)
834  newSize = HashMinSize;
835  else
836  {
837  // Force newSize to be a power of two.
838  int bits = Alg::UpperBit(newSize-1) + 1; // Chop( Log2f((float)(newSize-1)) + 1);
839  KY_ASSERT((UPInt(1) << bits) >= newSize);
840  newSize = UPInt(1) << bits;
841  }
842 
843  SelfType newHash;
844  newHash.pTable = (TableType*)
845  Allocator::Alloc(
846  pheapAddr,
847  sizeof(TableType) + sizeof(Entry) * newSize,
848  __FILE__, __LINE__);
849  // Need to do something on alloc failure!
850  KY_ASSERT(newHash.pTable);
851 
852  newHash.pTable->EntryCount = 0;
853  newHash.pTable->SizeMask = newSize - 1;
854  UPInt i, n;
855 
856  // Mark all entries as empty.
857  for (i = 0; i < newSize; i++)
858  newHash.E(i).NextInChain = -2;
859 
860  // Copy stuff to newHash
861  if (pTable)
862  {
863  for (i = 0, n = pTable->SizeMask; i <= n; i++)
864  {
865  Entry* e = &E(i);
866  if (e->IsEmpty() == false)
867  {
868  // Insert old Entry into new HashSet.
869  newHash.Add(pheapAddr, e->Value);
870  // placement delete of old element
871  e->Clear();
872  }
873  }
874 
875  // Delete our old data buffer.
876  Allocator::Free(pTable);
877  }
878 
879  // Steal newHash's data.
880  pTable = newHash.pTable;
881  newHash.pTable = NULL;
882  }
883 
884  struct TableType
885  {
886  UPInt EntryCount;
887  UPInt SizeMask;
888  // Entry array follows this structure
889  // in memory.
890  };
891  TableType* pTable;
892 };
893 
894 
895 
896 
897 template<class C, class HashF = FixedSizeHash<C>,
898  class AltHashF = HashF,
899  class Allocator = AllocatorGH<C>,
900  class Entry = HashsetCachedEntry<C, HashF> >
901 class HashSet : public HashSetBase<C, HashF, AltHashF, Allocator, Entry>
902 {
903 public:
904  typedef HashSetBase<C, HashF, AltHashF, Allocator, Entry> BaseType;
905  typedef HashSet<C, HashF, AltHashF, Allocator, Entry> SelfType;
906 
907  HashSet() { }
908  HashSet(int sizeHint) : BaseType(sizeHint) { }
909  explicit HashSet(void* pheap) : BaseType(pheap) { }
910  HashSet(void* pheap, int sizeHint) : BaseType(pheap, sizeHint) { }
911  HashSet(const SelfType& src) : BaseType(src) { }
912  ~HashSet() { }
913 
914  void operator = (const SelfType& src) { BaseType::Assign(this, src); }
915 
916  // Set a new or existing value under the key, to the value.
917  // Pass a different class of 'key' so that assignment reference object
918  // can be passed instead of the actual object.
919  template<class CRef>
920  void Set(const CRef& key)
921  {
922  BaseType::Set(this, key);
923  }
924 
925  template<class CRef>
926  inline void Add(const CRef& key)
927  {
928  BaseType::Add(this, key);
929  }
930 
931  // Resize the HashSet table to fit one more Entry. Often this
932  // doesn't involve any action.
933  void CheckExpand()
934  {
935  BaseType::CheckExpand(this);
936  }
937 
938  // Hint the bucket count to >= n.
939  void Resize(UPInt n)
940  {
941  BaseType::SetCapacity(this, n);
942  }
943 
944  // Size the HashSet so that it can comfortably contain the given
945  // number of elements. If the HashSet already contains more
946  // elements than newSize, then this may be a no-op.
947  void SetCapacity(UPInt newSize)
948  {
949  BaseType::SetCapacity(this, newSize);
950  }
951 
952 };
953 
954 // HashSet for local member only allocation (auto-heap).
955 template<class C, class HashF = FixedSizeHash<C>,
956  class AltHashF = HashF,
957  int SID = Stat_Default_Mem,
958  class Entry = HashsetCachedEntry<C, HashF> >
959 class HashSetLH : public HashSet<C, HashF, AltHashF, AllocatorLH<C, SID>, Entry>
960 {
961 public:
962  typedef HashSetLH<C, HashF, AltHashF, SID, Entry> SelfType;
963  typedef HashSet<C, HashF, AltHashF, AllocatorLH<C, SID>, Entry > BaseType;
964 
965  // Delegated constructors.
966  HashSetLH() { }
967  HashSetLH(int sizeHint) : BaseType(sizeHint) { }
968  HashSetLH(const SelfType& src) : BaseType(src) { }
969  ~HashSetLH() { }
970 
971  void operator = (const SelfType& src)
972  {
973  BaseType::operator = (src);
974  }
975 };
976 
977 template<class C, class HashF = FixedSizeHash<C>,
978  class AltHashF = HashF,
979  int SID = Stat_Default_Mem,
980  class Entry = HashsetCachedEntry<C, HashF> >
981 class HashSetDH : public HashSetBase<C, HashF, AltHashF, AllocatorDH<C, SID>, Entry>
982 {
983  void* pHeap;
984 public:
985  typedef HashSetDH<C, HashF, AltHashF, SID, Entry> SelfType;
986  typedef HashSetBase<C, HashF, AltHashF, AllocatorDH<C, SID>, Entry> BaseType;
987 
988  explicit HashSetDH(void* pheap) : pHeap(pheap) { }
989  HashSetDH(void* pheap, int sizeHint) : BaseType(pheap, sizeHint), pHeap(pheap) { }
990  HashSetDH(const SelfType& src) : BaseType(src), pHeap(src.pHeap) { }
991  ~HashSetDH() { }
992 
993  void operator = (const SelfType& src)
994  {
995  BaseType::Assign(src.pHeap, src);
996  pHeap = src.pHeap;
997  }
998 
999  // Set a new or existing value under the key, to the value.
1000  // Pass a different class of 'key' so that assignment reference object
1001  // can be passed instead of the actual object.
1002  template<class CRef>
1003  void Set(const CRef& key)
1004  {
1005  BaseType::Set(pHeap, key);
1006  }
1007 
1008  template<class CRef>
1009  inline void Add(const CRef& key)
1010  {
1011  BaseType::Add(pHeap, key);
1012  }
1013 
1014  // Resize the HashSet table to fit one more Entry. Often this
1015  // doesn't involve any action.
1016  void CheckExpand()
1017  {
1018  BaseType::CheckExpand(this);
1019  }
1020 
1021  // Hint the bucket count to >= n.
1022  void Resize(UPInt n)
1023  {
1024  BaseType::SetCapacity(pHeap, n);
1025  }
1026 
1027  // Size the HashSet so that it can comfortably contain the given
1028  // number of elements. If the HashSet already contains more
1029  // elements than newSize, then this may be a no-op.
1030  void SetCapacity(UPInt newSize)
1031  {
1032  BaseType::SetCapacity(pHeap, newSize);
1033  }
1034 
1035 };
1036 
1037 // HashSet with uncached hash code; declared for convenience.
1038 template<class C, class HashF = FixedSizeHash<C>,
1039  class AltHashF = HashF,
1040  class Allocator = AllocatorGH<C> >
1041 class HashSetUncached : public HashSet<C, HashF, AltHashF, Allocator, HashsetEntry<C, HashF> >
1042 {
1043 public:
1044 
1045  typedef HashSetUncached<C, HashF, AltHashF, Allocator> SelfType;
1046  typedef HashSet<C, HashF, AltHashF, Allocator, HashsetEntry<C, HashF> > BaseType;
1047 
1048  // Delegated constructors.
1049  HashSetUncached() { }
1050  HashSetUncached(int sizeHint) : BaseType(sizeHint) { }
1051  HashSetUncached(const SelfType& src) : BaseType(src) { }
1052  ~HashSetUncached() { }
1053 
1054  void operator = (const SelfType& src)
1055  {
1056  BaseType::operator = (src);
1057  }
1058 };
1059 
1060 // HashSet with uncached hash code, for local-only use.
1061 template<class C, class HashF = FixedSizeHash<C>,
1062  class AltHashF = HashF,
1063  int SID = Stat_Default_Mem >
1064 class HashSetUncachedLH : public HashSet<C, HashF, AltHashF, AllocatorLH<C, SID>, HashsetEntry<C, HashF> >
1065 {
1066 public:
1067 
1068  typedef HashSetUncachedLH<C, HashF, AltHashF, SID> SelfType;
1069  typedef HashSet<C, HashF, AltHashF, AllocatorLH<C, SID>, HashsetEntry<C, HashF> > BaseType;
1070 
1071  // Delegated constructors.
1072  HashSetUncachedLH() { }
1073  HashSetUncachedLH(int sizeHint) : BaseType(sizeHint) { }
1074  HashSetUncachedLH(const SelfType& src) : BaseType(src) { }
1075  ~HashSetUncachedLH() { }
1076 
1077  void operator = (const SelfType& src)
1078  {
1079  BaseType::operator = (src);
1080  }
1081 };
1082 
1083 // HashSet with uncached hash code, for using with custom heap.
1084 template<class C,
1085  class HashF = FixedSizeHash<C>,
1086  class AltHashF = HashF,
1087  int SID = Stat_Default_Mem >
1088 class HashSetUncachedDH : public HashSetDH<C, HashF, AltHashF, SID, HashsetEntry<C, HashF> >
1089 {
1090 public:
1091 
1092  typedef HashSetUncachedDH<C, HashF, AltHashF, SID> SelfType;
1093  typedef HashSetDH<C, HashF, AltHashF, SID, HashsetEntry<C, HashF> > BaseType;
1094 
1095  // Delegated constructors.
1096  explicit HashSetUncachedDH(void* pheap) : BaseType(pheap) { }
1097  HashSetUncachedDH(void* pheap, int sizeHint) : BaseType(pheap, sizeHint) { }
1098  HashSetUncachedDH(const SelfType& src) : BaseType(src) { }
1099  ~HashSetUncachedDH() { }
1100 
1101  void operator = (const SelfType& src)
1102  {
1103  BaseType::operator = (src);
1104  }
1105 };
1106 
1107 
1108 
1109 // ***** Hash hash table implementation
1110 
1111 // Node for Hash - necessary so that Hash can delegate its implementation
1112 // to HashSet.
1113 template<class C, class U, class HashF>
1114 struct HashNode
1115 {
1116  typedef HashNode<C, U, HashF> SelfType;
1117  typedef C FirstType;
1118  typedef U SecondType;
1119 
1120  C First;
1121  U Second;
1122 
1123  // NodeRef is used to allow passing of elements into HashSet
1124  // without using a temporary object.
1125  struct NodeRef
1126  {
1127  const C* pFirst;
1128  const U* pSecond;
1129 
1130  NodeRef(const C& f, const U& s) : pFirst(&f), pSecond(&s) { }
1131  NodeRef(const NodeRef& src) : pFirst(src.pFirst), pSecond(src.pSecond) { }
1132 
1133  // Enable computation of ghash_node_hashf.
1134  inline UPInt GetHash() const { return HashF()(*pFirst); }
1135  // Necessary conversion to allow HashNode::operator == to work.
1136  operator const C& () const { return *pFirst; }
1137  };
1138 
1139  // Note: No default constructor is necessary.
1140  HashNode(const HashNode& src) : First(src.First), Second(src.Second) { }
1141  HashNode(const NodeRef& src) : First(*src.pFirst), Second(*src.pSecond) { }
1142  void operator = (const NodeRef& src) { First = *src.pFirst; Second = *src.pSecond; }
1143 
1144 
1145  template<class K>
1146  bool operator == (const K& src) const { return (First == src); }
1147 
1148  template<class K>
1149  static UPInt CalcHash(const K& data) { return HashF()(data); }
1150  inline UPInt GetHash() const { return HashF()(First); }
1151 
1152  // Hash functors used with this node. A separate functor is used for alternative
1153  // key lookup so that it does not need to access the '.First' element.
1154  struct NodeHashF
1155  {
1156  template<class K>
1157  UPInt operator()(const K& data) const { return data.GetHash(); }
1158  };
1159  struct NodeAltHashF
1160  {
1161  template<class K>
1162  UPInt operator()(const K& data) const { return HashNode<C,U,HashF>::CalcHash(data); }
1163  };
1164 };
1165 
1166 
1167 
1168 // **** Extra hashset_entry types to allow NodeRef construction.
1169 
1170 // The big difference between the below types and the ones used in hash_set is that
1171 // these allow initializing the node with 'typename C::NodeRef& keyRef', which
1172 // is critical to avoid temporary node allocation on stack when using placement new.
1173 
1174 // Compact hash table Entry type that re-computes hash keys during hash traversal.
1175 // Good to use if the hash function is cheap or the hash value is already cached in C.
1176 template<class C, class HashF>
1177 class HashsetNodeEntry
1178 {
1179 public:
1180  // Internal chaining for collisions.
1181  SPInt NextInChain;
1182  C Value;
1183 
1184  HashsetNodeEntry()
1185  : NextInChain(-2) { }
1186  HashsetNodeEntry(const HashsetNodeEntry& e)
1187  : NextInChain(e.NextInChain), Value(e.Value) { }
1188  HashsetNodeEntry(const C& key, SPInt next)
1189  : NextInChain(next), Value(key) { }
1190  HashsetNodeEntry(const typename C::NodeRef& keyRef, SPInt next)
1191  : NextInChain(next), Value(keyRef) { }
1192 
1193  bool IsEmpty() const { return NextInChain == -2; }
1194  bool IsEndOfChain() const { return NextInChain == -1; }
1195  UPInt GetCachedHash(UPInt maskValue) const { return HashF()(Value) & maskValue; }
1196  void SetCachedHash(UPInt hashValue) { KY_UNUSED(hashValue); }
1197 
1198  void Clear()
1199  {
1200  Value.~C(); // placement delete
1201  NextInChain = -2;
1202  }
1203  // Free is only used from dtor of hash; Clear is used during regular operations:
1204  // assignment, hash reallocations, value reassignments, so on.
1205  void Free() { Clear(); }
1206 };
1207 
1208 // Hash table Entry type that caches the Entry hash value for nodes, so that it
1209 // does not need to be re-computed during access.
1210 template<class C, class HashF>
1211 class HashsetCachedNodeEntry
1212 {
1213 public:
1214  // Internal chaining for collisions.
1215  SPInt NextInChain;
1216  UPInt HashValue;
1217  C Value;
1218 
1219  HashsetCachedNodeEntry()
1220  : NextInChain(-2) { }
1221  HashsetCachedNodeEntry(const HashsetCachedNodeEntry& e)
1222  : NextInChain(e.NextInChain), HashValue(e.HashValue), Value(e.Value) { }
1223  HashsetCachedNodeEntry(const C& key, SPInt next)
1224  : NextInChain(next), Value(key) { }
1225  HashsetCachedNodeEntry(const typename C::NodeRef& keyRef, SPInt next)
1226  : NextInChain(next), Value(keyRef) { }
1227 
1228  bool IsEmpty() const { return NextInChain == -2; }
1229  bool IsEndOfChain() const { return NextInChain == -1; }
1230  UPInt GetCachedHash(UPInt maskValue) const { KY_UNUSED(maskValue); return HashValue; }
1231  void SetCachedHash(UPInt hashValue) { HashValue = hashValue; }
1232 
1233  void Clear()
1234  {
1235  Value.~C();
1236  NextInChain = -2;
1237  }
1238  // Free is only used from dtor of hash; Clear is used during regular operations:
1239  // assignment, hash reallocations, value reassignments, so on.
1240  void Free() { Clear(); }
1241 };
1242 
1243 
1244 template<class C, class U,
1245  class HashF = FixedSizeHash<C>,
1246  class Allocator = AllocatorGH<C>,
1247  class HashNode = Kaim::HashNode<C,U,HashF>,
1248  class Entry = HashsetCachedNodeEntry<HashNode, typename HashNode::NodeHashF>,
1249  class Container = HashSet<HashNode, typename HashNode::NodeHashF,
1250  typename HashNode::NodeAltHashF, Allocator,
1251  Entry> >
1252 class Hash
1253 {
1254 public:
1255  KY_MEMORY_REDEFINE_NEW(Hash, Allocator::StatId)
1256 
1257  // Types used for hash_set.
1258  typedef U ValueType;
1259  typedef Hash<C, U, HashF, Allocator, HashNode, Entry, Container> SelfType;
1260 
1261  // Actual hash table itself, implemented as hash_set.
1262  Container mHash;
1263 
1264 public:
1265  Hash() { }
1266  Hash(int sizeHint) : mHash(sizeHint) { }
1267  explicit Hash(void* pheap) : mHash(pheap) { }
1268  Hash(void* pheap, int sizeHint) : mHash(pheap, sizeHint) { }
1269  Hash(const SelfType& src) : mHash(src.mHash) { }
1270  ~Hash() { }
1271 
1272  void operator = (const SelfType& src) { mHash = src.mHash; }
1273 
1274  // Remove all entries from the Hash table.
1275  inline void Clear() { mHash.Clear(); }
1276  // Returns true if the Hash is empty.
1277  inline bool IsEmpty() const { return mHash.IsEmpty(); }
1278 
1279  // Access (set).
1280  inline void Set(const C& key, const U& value)
1281  {
1282  typename HashNode::NodeRef e(key, value);
1283  mHash.Set(e);
1284  }
1285  inline void Add(const C& key, const U& value)
1286  {
1287  typename HashNode::NodeRef e(key, value);
1288  mHash.Add(e);
1289  }
1290 
1291  // Removes an element by clearing its Entry.
1292  inline void Remove(const C& key)
1293  {
1294  mHash.RemoveAlt(key);
1295  }
1296  template<class K>
1297  inline void RemoveAlt(const K& key)
1298  {
1299  mHash.RemoveAlt(key);
1300  }
1301 
1302  // Retrieve the value under the given key.
1303  // - If there's no value under the key, then return false and leave *pvalue alone.
1304  // - If there is a value, return true, and Set *Pvalue to the Entry's value.
1305  // - If value == NULL, return true or false according to the presence of the key.
1306  bool Get(const C& key, U* pvalue) const
1307  {
1308  const HashNode* p = mHash.GetAlt(key);
1309  if (p)
1310  {
1311  if (pvalue)
1312  *pvalue = p->Second;
1313  return true;
1314  }
1315  return false;
1316  }
1317 
1318  template<class K>
1319  bool GetAlt(const K& key, U* pvalue) const
1320  {
1321  const HashNode* p = mHash.GetAlt(key);
1322  if (p)
1323  {
1324  if (pvalue)
1325  *pvalue = p->Second;
1326  return true;
1327  }
1328  return false;
1329  }
1330 
1331  // Retrieve the pointer to a value under the given key.
1332  // - If there's no value under the key, then return NULL.
1333  // - If there is a value, return the pointer.
1334  inline U* Get(const C& key)
1335  {
1336  HashNode* p = mHash.GetAlt(key);
1337  return p ? &p->Second : 0;
1338  }
1339  inline const U* Get(const C& key) const
1340  {
1341  const HashNode* p = mHash.GetAlt(key);
1342  return p ? &p->Second : 0;
1343  }
1344 
1345  template<class K>
1346  inline U* GetAlt(const K& key)
1347  {
1348  HashNode* p = mHash.GetAlt(key);
1349  return p ? &p->Second : 0;
1350  }
1351  template<class K>
1352  inline const U* GetAlt(const K& key) const
1353  {
1354  const HashNode* p = mHash.GetAlt(key);
1355  return p ? &p->Second : 0;
1356  }
1357 
1358  // Sizing methods - delegate to Hash.
1359  inline UPInt GetSize() const { return mHash.GetSize(); }
1360  inline void Resize(UPInt n) { mHash.Resize(n); }
1361  inline void SetCapacity(UPInt newSize) { mHash.SetCapacity(newSize); }
1362 
1363  // Iterator API, like STL.
1364  typedef typename Container::ConstIterator ConstIterator;
1365  typedef typename Container::Iterator Iterator;
1366 
1367  inline Iterator Begin() { return mHash.Begin(); }
1368  inline Iterator End() { return mHash.End(); }
1369  inline ConstIterator Begin() const { return mHash.Begin(); }
1370  inline ConstIterator End() const { return mHash.End(); }
1371 
1372  Iterator Find(const C& key) { return mHash.FindAlt(key); }
1373  ConstIterator Find(const C& key) const { return mHash.FindAlt(key); }
1374 
1375  template<class K>
1376  Iterator FindAlt(const K& key) { return mHash.FindAlt(key); }
1377  template<class K>
1378  ConstIterator FindAlt(const K& key) const { return mHash.FindAlt(key); }
1379 };
1380 
1381 
1382 
1383 // Local-only version of Hash
1384 template<class C, class U,
1385  class HashF = FixedSizeHash<C>,
1386  int SID = Stat_Default_Mem,
1387  class HashNode = Kaim::HashNode<C,U,HashF>,
1388  class Entry = HashsetCachedNodeEntry<HashNode, typename HashNode::NodeHashF> >
1389 class HashLH
1390  : public Hash<C, U, HashF, AllocatorLH<C, SID>, HashNode, Entry>
1391 {
1392 public:
1393  typedef HashLH<C, U, HashF, SID, HashNode, Entry> SelfType;
1394  typedef Hash<C, U, HashF, AllocatorLH<C, SID>, HashNode, Entry> BaseType;
1395 
1396  // Delegated constructors.
1397  HashLH() { }
1398  HashLH(int sizeHint) : BaseType(sizeHint) { }
1399  HashLH(const SelfType& src) : BaseType(src) { }
1400  ~HashLH() { }
1401  void operator = (const SelfType& src) { BaseType::operator = (src); }
1402 };
1403 
1404 
1405 // Custom-heap version of Hash
1406 template<class C, class U,
1407  class HashF = FixedSizeHash<C>,
1408  int SID = Stat_Default_Mem,
1409  class HashNode = Kaim::HashNode<C,U,HashF>,
1410  class Entry = HashsetCachedNodeEntry<HashNode, typename HashNode::NodeHashF> >
1411 class HashDH
1412  : public Hash<C, U, HashF, AllocatorDH<C, SID>, HashNode, Entry,
1413  HashSetDH<HashNode, typename HashNode::NodeHashF,
1414  typename HashNode::NodeAltHashF, SID, Entry> >
1415 {
1416 public:
1417  typedef HashDH<C, U, HashF, SID, HashNode, Entry> SelfType;
1418  typedef Hash<C, U, HashF, AllocatorDH<C, SID>, HashNode, Entry,
1419  HashSetDH<HashNode, typename HashNode::NodeHashF,
1420  typename HashNode::NodeAltHashF, SID, Entry> > BaseType;
1421 
1422  // Delegated constructors.
1423  explicit HashDH(void* pheap) : BaseType(pheap) { }
1424  HashDH(void* pheap, int sizeHint) : BaseType(pheap, sizeHint) { }
1425  HashDH(const SelfType& src) : BaseType(src) { }
1426  ~HashDH() { }
1427  void operator = (const SelfType& src) { BaseType::operator = (src); }
1428 };
1429 
1430 
1431 // Hash with uncached hash code; declared for convenience.
1432 template<class C, class U, class HashF = FixedSizeHash<C>, class Allocator = AllocatorGH<C> >
1433 class HashUncached
1434  : public Hash<C, U, HashF, Allocator, HashNode<C,U,HashF>,
1435  HashsetNodeEntry<HashNode<C,U,HashF>, typename HashNode<C,U,HashF>::NodeHashF> >
1436 {
1437 public:
1438  typedef HashUncached<C, U, HashF, Allocator> SelfType;
1439  typedef Hash<C, U, HashF, Allocator, HashNode<C,U,HashF>,
1440  HashsetNodeEntry<HashNode<C,U,HashF>, typename HashNode<C,U,HashF>::NodeHashF> > BaseType;
1441 
1442  // Delegated constructors.
1443  HashUncached() { }
1444  HashUncached(int sizeHint) : BaseType(sizeHint) { }
1445  HashUncached(const SelfType& src) : BaseType(src) { }
1446  ~HashUncached() { }
1447  void operator = (const SelfType& src) { BaseType::operator = (src); }
1448 };
1449 
1450 
1451 // Local heap member-only hash
1452 template<class C, class U, class HashF = FixedSizeHash<C>, int StatId = Stat_Default_Mem>
1453 class HashUncachedLH
1454  : public HashLH<C, U, HashF, StatId, HashNode<C,U,HashF>,
1455  HashsetNodeEntry<HashNode<C,U,HashF>, typename HashNode<C,U,HashF>::NodeHashF> >
1456 {
1457 public:
1458  typedef HashUncachedLH<C, U, HashF, StatId> SelfType;
1459  typedef HashLH<C, U, HashF, StatId, HashNode<C,U,HashF>,
1460  HashsetNodeEntry<HashNode<C,U,HashF>, typename HashNode<C,U,HashF>::NodeHashF> > BaseType;
1461 
1462  // Delegated constructors.
1463  HashUncachedLH() { }
1464  HashUncachedLH(int sizeHint) : BaseType(sizeHint) { }
1465  HashUncachedLH(const SelfType& src) : BaseType(src) { }
1466  ~HashUncachedLH() { }
1467  void operator = (const SelfType& src) { BaseType::operator = (src); }
1468 };
1469 
1470 // Custom-heap hash
1471 template<class C, class U, class HashF = FixedSizeHash<C>, int StatId = Stat_Default_Mem>
1472 class HashUncachedDH
1473  : public HashDH<C, U, HashF, StatId, HashNode<C,U,HashF>,
1474  HashsetNodeEntry<HashNode<C,U,HashF>, typename HashNode<C,U,HashF>::NodeHashF> >
1475 {
1476 public:
1477  typedef HashUncachedDH<C, U, HashF, StatId> SelfType;
1478  typedef HashDH<C, U, HashF, StatId, HashNode<C,U,HashF>,
1479  HashsetNodeEntry<HashNode<C,U,HashF>, typename HashNode<C,U,HashF>::NodeHashF> > BaseType;
1480 
1481  // Delegated constructors.
1482  explicit HashUncachedDH(void* pheap) : BaseType(pheap) { }
1483  HashUncachedDH(void* pheap, int sizeHint) : BaseType(pheap, sizeHint) { }
1484  HashUncachedDH(const SelfType& src) : BaseType(src) { }
1485  ~HashUncachedDH() { }
1486  void operator = (const SelfType& src) { BaseType::operator = (src); }
1487 };
1488 
1489 // And identity hash in which keys serve as hash value. Can be uncached,
1490 // since hash computation is assumed cheap.
1491 template<class C, class U, class Allocator = AllocatorGH<C>, class HashF = IdentityHash<C> >
1492 class HashIdentity
1493  : public HashUncached<C, U, HashF, Allocator>
1494 {
1495 public:
1496  typedef HashIdentity<C, U, Allocator, HashF> SelfType;
1497  typedef HashUncached<C, U, HashF, Allocator> BaseType;
1498 
1499  // Delegated constructors.
1500  HashIdentity() { }
1501  HashIdentity(int sizeHint) : BaseType(sizeHint) { }
1502  HashIdentity(const SelfType& src) : BaseType(src) { }
1503  ~HashIdentity() { }
1504  void operator = (const SelfType& src) { BaseType::operator = (src); }
1505 };
1506 
1507 
1508 
1509 // Local member-only heap hash identity
1510 template<class C, class U, int SID = Stat_Default_Mem, class HashF = IdentityHash<C> >
1511 class HashIdentityLH
1512  : public HashUncachedLH<C, U, HashF, SID>
1513 {
1514 public:
1515  typedef HashIdentityLH<C, U, SID, HashF> SelfType;
1516  typedef HashUncachedLH<C, U, HashF, SID> BaseType;
1517 
1518  // Delegated constructors.
1519  HashIdentityLH() { }
1520  HashIdentityLH(int sizeHint) : BaseType(sizeHint) { }
1521  HashIdentityLH(const SelfType& src) : BaseType(src) { }
1522  ~HashIdentityLH() { }
1523  void operator = (const SelfType& src) { BaseType::operator = (src); }
1524 };
1525 
1526 // Hash identity with specified heap
1527 template<class C, class U, int SID = Stat_Default_Mem, class HashF = IdentityHash<C> >
1528 class HashIdentityDH
1529  : public HashUncachedDH<C, U, HashF, SID>
1530 {
1531 public:
1532  typedef HashIdentityDH<C, U, SID, HashF> SelfType;
1533  typedef HashUncachedDH<C, U, HashF, SID> BaseType;
1534 
1535  // Delegated constructors.
1536  explicit HashIdentityDH(void* pheap) : BaseType(pheap) { }
1537  HashIdentityDH(void* pheap, int sizeHint) : BaseType(pheap, sizeHint) { }
1538  HashIdentityDH(const SelfType& src) : BaseType(src) { }
1539  ~HashIdentityDH() { }
1540  void operator = (const SelfType& src) { BaseType::operator = (src); }
1541 };
1542 
1543 } // Scaleform
1544 
1545 // Redefine operator 'new' if necessary.
1546 #if defined(KY_DEFINE_NEW)
1547 #define new KY_DEFINE_NEW
1548 #endif
1549 
1550 #endif
std::uint8_t UByte
uint8_t
Definition: SF_Types.h:134
The Autodesk Navigation namespace.
Definition: gamekitcrowddispersion.cpp:17
Vec2f operator*(KyFloat32 s, const Vec2f &v)
scalar * vec operator
Definition: vec2f.h:120