Leaked source code of windows server 2003
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.

380 lines
9.8 KiB

  1. /*++
  2. Copyright (c) 1998-2001 Microsoft Corporation
  3. Module Name :
  4. WordHash.h
  5. Abstract:
  6. LKRhash test harness: hash table of words
  7. Author:
  8. George V. Reilly (GeorgeRe) 06-Jan-1998
  9. Environment:
  10. Win32 - User Mode
  11. Project:
  12. LKRhash
  13. Revision History:
  14. --*/
  15. #ifndef __WORDHASH_H__
  16. #define __WORDHASH_H__
  17. #define MAXKEYS 1000000
  18. #define MAX_THREADS MAXIMUM_WAIT_OBJECTS
  19. #define MAX_STRSIZE 300
  20. #ifdef LKR_PUBLIC_API
  21. typedef PLkrHashTable WordBaseTable;
  22. #include <lkrhash.h>
  23. #endif // LKR_PUBLIC_API
  24. #ifndef __LKRHASH_NO_NAMESPACE__
  25. #define LKRHASH_NS LKRhash
  26. using namespace LKRhash;
  27. #else
  28. #define LKRHASH_NS
  29. #endif // !__LKRHASH_NO_NAMESPACE__
  30. #ifndef __HASHFN_NO_NAMESPACE__
  31. using namespace HashFn;
  32. #endif // !__HASHFN_NO_NAMESPACE__
  33. #ifndef LKR_PUBLIC_API
  34. typedef LKRHASH_NS::CLKRHashTable WordBaseTable;
  35. // typedef LKRHASH_NS::CLKRLinearHashTable WordBaseTable;
  36. #endif
  37. // A string wrapper class that keeps track of the length of the string data.
  38. // A more useful string class would refcount the data and have copy-on-write
  39. // semantics (or use MFC's CString or STL's string classes).
  40. class CStr
  41. {
  42. public:
  43. const char* m_psz;
  44. short m_cch;
  45. bool m_fDynamic;
  46. static int sm_cchMax;
  47. CStr()
  48. : m_psz(NULL),
  49. m_cch(0),
  50. m_fDynamic(false)
  51. {
  52. }
  53. CStr(
  54. const char* psz,
  55. int cch,
  56. bool fDynamic)
  57. : m_psz(NULL),
  58. m_cch(static_cast<short>(cch)),
  59. m_fDynamic(fDynamic)
  60. {
  61. if (fDynamic)
  62. Set(psz, cch);
  63. else
  64. m_psz = psz;
  65. }
  66. void Set(
  67. const char* psz,
  68. int cch)
  69. {
  70. delete [] const_cast<char*>(m_psz);
  71. m_psz = new char[cch+1];
  72. if (m_psz != NULL)
  73. {
  74. strcpy(const_cast<char*>(m_psz), psz);
  75. m_cch = static_cast<short>(cch);
  76. m_fDynamic = true;
  77. sm_cchMax = max(m_cch, sm_cchMax);
  78. }
  79. else
  80. {
  81. m_cch = 0;
  82. m_fDynamic = false;
  83. }
  84. }
  85. ~CStr()
  86. {
  87. if (m_fDynamic)
  88. delete [] const_cast<char*>(m_psz);
  89. }
  90. };
  91. #ifdef HASHTEST_STATIC_DATA
  92. // length of longest string seen
  93. int CStr::sm_cchMax = 0;
  94. #endif
  95. // a word from the data file, which contains one 'word' per line (may
  96. // include spaces).
  97. class CWord
  98. {
  99. public:
  100. int m_cNotFound;
  101. CStr m_str;
  102. bool m_fInserted;
  103. bool m_fIterated;
  104. LONG m_cRefs;
  105. LONG m_cInsertIfNotFounds;
  106. int m_iIndex;
  107. CWord()
  108. : m_cNotFound(0),
  109. m_fInserted(false),
  110. m_fIterated(false),
  111. m_cRefs(0),
  112. m_cInsertIfNotFounds(0),
  113. m_iIndex(-1)
  114. {
  115. }
  116. ~CWord()
  117. {
  118. IRTLASSERT(m_cRefs == 0);
  119. #ifdef IRTLDEBUG
  120. if (m_cRefs != 0)
  121. IRTLTRACE(_TEXT("\"%hs\": %d, %d\n"), m_str.m_psz, m_cRefs,
  122. m_cInsertIfNotFounds);
  123. #endif
  124. }
  125. };
  126. // globals
  127. extern int g_nokeys ;
  128. extern CWord g_wordtable[MAXKEYS];
  129. const char*
  130. LK_AddRefReasonCode2String(
  131. LK_ADDREF_REASON lkar);
  132. #define DO_REF_COUNT false
  133. // A hash table of CWords, indexed by CStr*s.
  134. class CWordHash
  135. #ifndef LKR_PUBLIC_API
  136. : public CTypedHashTable<CWordHash, CWord, const CStr*, DO_REF_COUNT, WordBaseTable>
  137. #else
  138. : public TypedLkrHashTable<CWordHash, CWord, const CStr*, DO_REF_COUNT>
  139. #endif
  140. {
  141. public:
  142. static bool sm_fCaseInsensitive;
  143. static bool sm_fMemCmp;
  144. static int sm_nLastChars;
  145. static bool sm_fNonPagedAllocs;
  146. static bool sm_fRefTrace;
  147. static bool sm_fMultiKeys;
  148. static bool sm_fUseLocks;
  149. #ifndef LKR_PUBLIC_API
  150. friend class CTypedHashTable<CWordHash, CWord, const CStr*,
  151. DO_REF_COUNT, WordBaseTable>;
  152. #else
  153. friend class TypedLkrHashTable<CWordHash, CWord, const CStr*>;
  154. #endif
  155. static const CStr*
  156. ExtractKey(const CWord* pKey)
  157. {
  158. return &pKey->m_str;
  159. }
  160. static DWORD
  161. CalcKeyHash(const CStr* pstrKey)
  162. {
  163. const char* psz = pstrKey->m_psz;
  164. // use only the last few chars instead of whole string?
  165. if (sm_nLastChars > 0 && pstrKey->m_cch >= sm_nLastChars)
  166. psz = pstrKey->m_psz + pstrKey->m_cch - sm_nLastChars;
  167. IRTLASSERT(pstrKey->m_psz <= psz
  168. && psz < pstrKey->m_psz + pstrKey->m_cch);
  169. if (sm_fCaseInsensitive)
  170. return HashStringNoCase(psz, pstrKey->m_cch);
  171. else
  172. return HashString(psz, pstrKey->m_cch);
  173. }
  174. static int
  175. CompareKeys(const CStr* pstrKey1, const CStr* pstrKey2)
  176. {
  177. int nCmp;
  178. if (sm_fCaseInsensitive)
  179. {
  180. #if 1
  181. // if (sm_fMultiKeys)
  182. {
  183. // Hack that works for ASCII data
  184. nCmp = (pstrKey1->m_psz[0] & 0xDF)
  185. - (pstrKey2->m_psz[0] & 0xDF);
  186. if (nCmp != 0)
  187. return nCmp;
  188. }
  189. #endif
  190. // nCmp = pstrKey1->m_cch - pstrKey2->m_cch;
  191. // if (nCmp != 0)
  192. // return nCmp;
  193. if (sm_fMemCmp)
  194. return _memicmp(pstrKey1->m_psz, pstrKey2->m_psz,
  195. pstrKey1->m_cch);
  196. else
  197. return _stricmp(pstrKey1->m_psz, pstrKey2->m_psz);
  198. }
  199. else
  200. {
  201. #if 1
  202. // if (sm_fMultiKeys)
  203. {
  204. nCmp = pstrKey1->m_psz[0] - pstrKey2->m_psz[0];
  205. if (nCmp != 0)
  206. return nCmp;
  207. }
  208. #endif
  209. // nCmp = pstrKey1->m_cch - pstrKey2->m_cch;
  210. // if (nCmp != 0)
  211. // return nCmp;
  212. if (sm_fMemCmp)
  213. return memcmp(pstrKey1->m_psz, pstrKey2->m_psz,
  214. pstrKey1->m_cch);
  215. else
  216. return strcmp(pstrKey1->m_psz, pstrKey2->m_psz);
  217. }
  218. }
  219. static LONG
  220. AddRefRecord(CWord* pRec, LK_ADDREF_REASON lkar)
  221. {
  222. int nIncr = (lkar < 0) ? -1 : +1;
  223. LONG cRefs = nIncr + InterlockedExchangeAdd(&pRec->m_cRefs, nIncr);
  224. if (sm_fRefTrace)
  225. IRTLTRACE(_TEXT("\tAddRef key(%d, %p: \"%hs\"), %hs (%s), = %d\n"),
  226. pRec - g_wordtable, pRec, pRec->m_str.m_psz,
  227. (lkar > 0) ? "+1" : "-1",
  228. LKR_AddRefReasonAsString(lkar), cRefs);
  229. IRTLASSERT(cRefs >= 0);
  230. return cRefs;
  231. }
  232. CWordHash(
  233. unsigned maxload, // Bound on avg chain length
  234. size_t initsize, // Initial size of hash table.
  235. size_t num_subtbls // #subordinate hash tables.
  236. )
  237. #ifndef LKR_PUBLIC_API
  238. : CTypedHashTable<CWordHash, CWord, const CStr*,
  239. DO_REF_COUNT, WordBaseTable>
  240. ("wordhash", maxload, initsize, num_subtbls,
  241. sm_fMultiKeys, sm_fUseLocks
  242. # ifdef LKRHASH_KERNEL_MODE
  243. , sm_fNonPagedAllocs // use paged or NP pool
  244. # endif
  245. )
  246. #else // LKR_PUBLIC_API
  247. : TypedLkrHashTable<CWordHash, CWord, const CStr*>
  248. ("wordhash", (LK_TABLESIZE) initsize,
  249. sm_fMultiKeys, sm_fUseLocks)
  250. #endif // LKR_PUBLIC_API
  251. {}
  252. template <class _InputIterator>
  253. CWordHash(
  254. _InputIterator f,
  255. _InputIterator l,
  256. unsigned maxload, // Bound on avg chain length
  257. size_t initsize, // Initial size of hash table.
  258. size_t num_subtbls // #subordinate hash tables.
  259. )
  260. #ifndef LKR_PUBLIC_API
  261. : CTypedHashTable<CWordHash, CWord, const CStr*,
  262. DO_REF_COUNT, WordBaseTable>
  263. (f, l, "wordhash", maxload, initsize, num_subtbls)
  264. #else
  265. : TypedLkrHashTable<CWordHash, CWord, const CStr*>
  266. (f, l, "wordhash", (LK_TABLESIZE) initsize)
  267. #endif
  268. {}
  269. static const TCHAR*
  270. HashMethod()
  271. {
  272. TCHAR tszLast[20];
  273. static TCHAR s_tsz[80];
  274. if (sm_nLastChars > 0)
  275. _stprintf(tszLast, _TEXT("last %d"), sm_nLastChars);
  276. else
  277. _tcscpy(tszLast, _TEXT("all"));
  278. _stprintf(s_tsz, _TEXT("case-%ssensitive, %scmp, %s chars"),
  279. sm_fCaseInsensitive ? _TEXT("in") : _TEXT(""),
  280. sm_fMemCmp ? _TEXT("mem") : _TEXT("str"),
  281. tszLast);
  282. return s_tsz;
  283. }
  284. #ifdef LKR_PUBLIC_API
  285. typedef CLKRHashTable BaseHashTable;
  286. typedef BaseHashTable::TableLock TableLock;
  287. typedef BaseHashTable::BucketLock BucketLock;
  288. enum {
  289. NODES_PER_CLUMP = BaseHashTable::NODES_PER_CLUMP,
  290. };
  291. static const TCHAR* ClassName()
  292. {return _TEXT("PLkrHashTable");}
  293. static LK_TABLESIZE NumSubTables(DWORD& rinitsize, DWORD& rnum_subtbls)
  294. { return BaseHashTable::NumSubTables(rinitsize, rnum_subtbls); }
  295. int NumSubTables() const
  296. { return reinterpret_cast<BaseHashTable*>(m_plkr)->NumSubTables(); }
  297. void SetTableLockSpinCount(WORD wSpins)
  298. { reinterpret_cast<BaseHashTable*>(m_plkr)->SetTableLockSpinCount(wSpins);}
  299. void SetBucketLockSpinCount(WORD wSpins)
  300. { reinterpret_cast<BaseHashTable*>(m_plkr)->SetBucketLockSpinCount(wSpins);}
  301. CLKRHashTableStats GetStatistics() const
  302. { return reinterpret_cast<BaseHashTable*>(m_plkr)->GetStatistics();}
  303. #endif // LKR_PUBLIC_API
  304. protected:
  305. ~CWordHash() {}
  306. private:
  307. CWordHash(const CWordHash&);
  308. CWordHash& operator=(const CWordHash&);
  309. };
  310. #endif // __WORDHASH_H__