Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

300 lines
6.9 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997-1999.
  5. //
  6. // File: thash.hxx
  7. //
  8. // Classes: THashTable
  9. //
  10. // History: 5-19-97 dlee Created
  11. //
  12. //----------------------------------------------------------------------------
  13. #pragma once
  14. const ULONG THASH_INIT_HASH_SIZE = 31;
  15. template <class T> class THashTable
  16. {
  17. public:
  18. THashTable( ULONG cHashInit ) :
  19. _size( __max( ComputeSize(cHashInit), THASH_INIT_HASH_SIZE ) ),
  20. _count( 0 ),
  21. _pTable( 0 ),
  22. _cDeleted( 0 ),
  23. _idInvalid( (T) -1 ),
  24. _idDeleted( (T) -2 )
  25. {
  26. ULONG cb = sizeof T * _size;
  27. _pTable = (T *) new BYTE [cb];
  28. RtlFillMemory( _pTable, cb, 0xFF );
  29. }
  30. void Reset(ULONG cHashInit)
  31. {
  32. _size = __max( ComputeSize(cHashInit), THASH_INIT_HASH_SIZE );
  33. _count = 0;
  34. _cDeleted = 0;
  35. delete[] ( (BYTE *) _pTable );
  36. _pTable = 0;
  37. ULONG cb = sizeof T * _size;
  38. _pTable = (T *) new BYTE [cb];
  39. RtlFillMemory( _pTable, cb, 0xFF );
  40. }
  41. ULONG HashT( T t ) { return (ULONG)((ULONG_PTR) t >> 2) % _size; }
  42. ~THashTable()
  43. {
  44. delete [] ( (BYTE *) _pTable );
  45. }
  46. ULONG AddEntry( T entry );
  47. BOOL DeleteEntry( T entry );
  48. const T GetEntry( ULONG i )
  49. {
  50. Win4Assert( i < _size );
  51. return _pTable[i];
  52. }
  53. ULONG Size() const { return _size; }
  54. BOOL Any() const { return 0 != _count; }
  55. ULONG Count() const { return _count; }
  56. BOOL IsFree( T t ) { return _idInvalid == t || _idDeleted == t; }
  57. BOOL LookUp(T t);
  58. private:
  59. BOOL DoLookUp( T t, ULONG & riTable );
  60. ULONG ComputeSize ( ULONG ulSize ) const;
  61. ULONG _size;
  62. ULONG _count;
  63. T * _pTable;
  64. ULONG _cDeleted;
  65. const T _idInvalid;
  66. const T _idDeleted;
  67. };
  68. //+---------------------------------------------------------------------------
  69. //
  70. // Function: LookUp
  71. //
  72. // Synopsis: Looks up for the specified wid in the hash table.
  73. //
  74. // Arguments: [t] - Entry to look up.
  75. //
  76. // Returns: TRUE if found; FALSE o/w
  77. //
  78. // History: 6-10-97 KrishnaN Created
  79. //
  80. //----------------------------------------------------------------------------
  81. template<class T> BOOL THashTable<T>::LookUp(T t)
  82. {
  83. ULONG i;
  84. return DoLookUp(t, i);
  85. } //LookUp
  86. //+---------------------------------------------------------------------------
  87. //
  88. // Function: DoLookUp
  89. //
  90. // Synopsis: Looks up for the specified wid in the hash table.
  91. //
  92. // Arguments: [t] - Entry to look up.
  93. // [riTable] - On output contains the index
  94. //
  95. // Returns: TRUE if found; FALSE o/w
  96. //
  97. // History: 5-19-97 dlee Created
  98. //
  99. //----------------------------------------------------------------------------
  100. template<class T> BOOL THashTable<T>::DoLookUp(
  101. T t,
  102. ULONG & riTable )
  103. {
  104. Win4Assert( 0 != _size );
  105. Win4Assert( _idInvalid != t );
  106. ULONG cur = HashT( t );
  107. ULONG start = cur;
  108. ULONG delta = cur;
  109. BOOL fFound = FALSE;
  110. while ( _idInvalid != _pTable[cur] )
  111. {
  112. if ( t == _pTable[cur] )
  113. {
  114. riTable = cur;
  115. fFound = TRUE;
  116. break;
  117. }
  118. else
  119. {
  120. cur = (cur + delta) % _size;
  121. if ( cur == start ) // wrapped around
  122. {
  123. if ( 1 != delta )
  124. {
  125. delta = 1;
  126. cur = (cur + 1) % _size;
  127. }
  128. else
  129. {
  130. break;
  131. }
  132. }
  133. }
  134. }
  135. return fFound;
  136. } //DoLookUp
  137. //+---------------------------------------------------------------------------
  138. //
  139. // Function: DeleteEntry
  140. //
  141. // Synopsis: Deletes the item.
  142. //
  143. // Arguments: [t] - entry to delete.
  144. //
  145. // Returns: TRUE if the given entry was present in the hash table.
  146. // FALSE o/w
  147. //
  148. // History: 5-19-97 dlee Created
  149. //
  150. // Notes: The entry deleted will be identified as "deleted" and will
  151. // be later available for "reuse".
  152. //
  153. //----------------------------------------------------------------------------
  154. template<class T> BOOL THashTable<T>::DeleteEntry( T t )
  155. {
  156. Win4Assert( _idInvalid != t );
  157. ULONG iTable;
  158. BOOL fFound = DoLookUp( t, iTable );
  159. if ( fFound )
  160. {
  161. Win4Assert( iTable < _size );
  162. Win4Assert( t == _pTable[iTable] );
  163. Win4Assert( _count > 0 );
  164. _pTable[iTable] = _idDeleted;
  165. _count--;
  166. _cDeleted++;
  167. }
  168. #if CIDBG == 1
  169. if ( !fFound )
  170. ciDebugOut(( DEB_FORCE, "delete %d 0x%x at 0x%x\n",
  171. fFound, t, iTable ));
  172. #endif // CIDBG == 1
  173. return fFound;
  174. } //DeleteEntry
  175. //+---------------------------------------------------------------------------
  176. //
  177. // Function: AddEntry
  178. //
  179. // Synopsis: Adds the specified entry to the hash table.
  180. //
  181. // Arguments: [t] - Entry to be added.
  182. //
  183. // History: 5-19-97 dlee Created
  184. //
  185. //----------------------------------------------------------------------------
  186. template<class T> ULONG THashTable<T>::AddEntry( T t )
  187. {
  188. Win4Assert( 0 != _size );
  189. Win4Assert( _idInvalid != t );
  190. Win4Assert( _idDeleted != t );
  191. ULONG cur = HashT( t );
  192. ULONG start = cur;
  193. //
  194. // Initialize use a delta which is not 1 to prevent data from getting
  195. // clumped in one place.
  196. //
  197. ULONG delta = cur;
  198. while ( !IsFree( _pTable[cur] ) )
  199. {
  200. if ( t == _pTable[cur] )
  201. {
  202. // just replacing the value
  203. _pTable[cur] = t;
  204. return cur;
  205. }
  206. cur = (cur + delta) % _size;
  207. if ( cur == start ) // wrapped around
  208. {
  209. // The hash table is full, but should never be full.
  210. Win4Assert( 1 != delta );
  211. delta = 1;
  212. cur = (cur + 1) % _size;
  213. }
  214. }
  215. if ( _idDeleted == _pTable[cur] )
  216. {
  217. Win4Assert( _cDeleted > 0 );
  218. _cDeleted--;
  219. }
  220. _pTable[cur] = t;
  221. _count++;
  222. return cur;
  223. } //AddEntry
  224. //+---------------------------------------------------------------------------
  225. //
  226. // Method: ComputeSize
  227. //
  228. // Synopsis: This routine figures out a size for the hash table. Preferably
  229. // a prime.
  230. //
  231. // Arguments: [ulSize] -- Indicates the minimum size to be returned.
  232. //
  233. // Returns: A size to be used for the hash table.
  234. //
  235. // History: 6-10-97 KrishnaN Created
  236. //
  237. // Notes:
  238. //
  239. //----------------------------------------------------------------------------
  240. template<class T> ULONG THashTable<T>::ComputeSize ( ULONG ulSize ) const
  241. {
  242. for (unsigned i = 0; i < g_cPrimes && g_aPrimes[i] < ulSize; i++);
  243. if (i < g_cPrimes)
  244. return g_aPrimes[i];
  245. //
  246. // return twice the size - 1. This large space will minimize collisions at the
  247. // cost of space.
  248. //
  249. return (2*ulSize - 1);
  250. }