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.

494 lines
10 KiB

  1. /*++
  2. Cachex.h
  3. This file defines some templates which implement
  4. a generic cache manager.
  5. In order to use the Cache manager, your class must
  6. have the following :
  7. //
  8. // SampleClass derives from CRefCount as smart pointers
  9. // 'CRefPtr<Data>' are used to manage the life time of cached
  10. // objects.
  11. //
  12. class SampleClass : public CRefCount {
  13. //
  14. // Cached class has a constructor which takes two
  15. // arguments, the Key used to find the Data in the Cache
  16. // and the 'Constructor' (which is a type specified in
  17. // the cache template) which contains whatever
  18. // initialization data that needs to be passed.
  19. //
  20. // The Cached class should do minimal work within the
  21. // constructor. The FindOrCreate() function will also
  22. // call an innitialization class which finishes initialization
  23. // of the object.
  24. //
  25. SampleClass( Key& k, Constructor &constructor ) ;
  26. //
  27. // If the Cached class does not do all of its initialization
  28. // in its Constructor, then The ExclusiveLock() function must
  29. // guarantee that no clients can use the object untill the
  30. // lock is released.
  31. //
  32. // If the Cached class is completely initialized after the
  33. // constructor is called then this can be a no-op function.
  34. //
  35. ExclusiveLock() ;
  36. //
  37. // After this is called clients may use the object.
  38. //
  39. ExclusiveUnlock() ;
  40. //
  41. // The Init() function is called by FindOrCreate()
  42. // after the contructor has been invoked. This function
  43. // must complete any initialization required.
  44. //
  45. // Member functions are called by FindOrCreate() in this order :
  46. //
  47. // SampleClass() // Constructor is called
  48. // ExclusiveLock()
  49. // Init()
  50. // ExclusiveUnlock()
  51. //
  52. // All Cache Client code must be able to deal with objects
  53. // returned from the cache which failed initialization for
  54. // whatever reason.
  55. //
  56. BOOL Init( Constructor& constructor ) ;
  57. //
  58. // This function must return a reference to the
  59. // Key value stored within the data.
  60. //
  61. void GetKey(Key& key) ;
  62. //
  63. // Must return non-zero if the provided Key matches
  64. // the one stored in the data .
  65. //
  66. int MatchKey( Key& ) ;
  67. } ;
  68. --*/
  69. #ifndef _CACHEX_H_
  70. #define _CACHEX_H_
  71. #ifndef _ASSERT
  72. #define _ASSERT(x) if(!(x)) DebugBreak() ; else
  73. #endif
  74. // This callback function is used to issue a stop hint during a
  75. // long spin while shutting down so that the shutdown won't time
  76. // out.
  77. typedef void (*PSTOPHINT_FN)();
  78. //
  79. // cacheint.h includes all the necessary helper classes
  80. // etc... that make the general cache engine work !
  81. //
  82. //
  83. #include "cacheinx.h"
  84. //
  85. // Utility class for those which wish to have pools of locks for
  86. // their objects !
  87. //
  88. class CLockPool {
  89. private :
  90. //
  91. // Array of locks to share amongst Xover data structures
  92. //
  93. _CACHELOCK m_locks[256] ;
  94. //
  95. //
  96. //
  97. long m_lockIndex ;
  98. public :
  99. _CACHELOCK* AllocateLock() {
  100. return &m_locks[ DWORD(InterlockedIncrement( &m_lockIndex )) % 256 ] ;
  101. }
  102. } ;
  103. //
  104. // CacheCallback class - clients can pass an object derived from
  105. // this into the Cache for functions which require some kind of user
  106. // callback processing !
  107. //
  108. template < class Data >
  109. class CacheCallback {
  110. public :
  111. virtual BOOL fRemoveCacheItem( Data* d ) {
  112. return FALSE ;
  113. }
  114. } ;
  115. //
  116. // Call these functions to initialize the Cache Library
  117. //
  118. extern BOOL __stdcall CacheLibraryInit() ;
  119. extern BOOL __stdcall CacheLibraryTerm() ;
  120. template < class Data,
  121. class Key,
  122. class KEYREF, /* This is the type used to point or reference items in the cache*/
  123. class Constructor,
  124. BOOL fAtomic = TRUE
  125. >
  126. class Cache : public CScheduleThread,
  127. CacheTable {
  128. private :
  129. //
  130. // Define a 'CACHEENTRY' object which holds all the
  131. // necessary data for each object which is placed in the cache !
  132. //
  133. typedef CacheEntry< Data, Key, KEYREF, fAtomic > CACHEENTRY ;
  134. //
  135. // Define callback objects for Expunge Operations.
  136. //
  137. typedef CacheCallback< Data > CALLBACKOBJ;
  138. //
  139. // Is the 'Cache' initialized and in a valid state !
  140. //
  141. BOOL m_fValid ;
  142. //
  143. // A list of everything in the Cache, used for TTL processing
  144. //
  145. CacheList m_ExpireList ;
  146. //
  147. // A hash table we use to find things within the Cache
  148. //
  149. TFHashEx< CACHEENTRY, Key, KEYREF > m_Lookup ;
  150. //
  151. // Pointer to a runtime-user provided function which is used
  152. // to determine what things should be removed from the Cache
  153. //
  154. BOOL (* m_pfnExpungeSpecific )( Data & ) ;
  155. //
  156. // Pointer to a runtime-user provided object derived from CacheCallback< Data >
  157. // which lets the user invoke some function for each item in the Cache !
  158. //
  159. CALLBACKOBJ* m_pCallbackObject ;
  160. //
  161. // Reader writer lock which protects all these data structures !
  162. //
  163. _CACHELOCK m_Lock ;
  164. //
  165. // The initial TTL we should assign to all newly cached objects !
  166. //
  167. DWORD m_TTL ;
  168. protected :
  169. //
  170. // Virtual function called by CScheduleThread's thread which
  171. // we use to bump TTL counters
  172. //
  173. void
  174. Schedule();
  175. //
  176. // Function which removes an Entry from the Cache !
  177. //
  178. BOOL
  179. RemoveEntry(
  180. CacheState* pEntry
  181. ) ;
  182. //
  183. // Virtual Function called by CacheList when we pass call
  184. // CacheList::ExpungeSpecific
  185. //
  186. BOOL
  187. QueryRemoveEntry(
  188. CacheState* pEntry
  189. ) ;
  190. //
  191. // Function which can remove a specific item from the Cache
  192. // or walk the Cache deleting all the expired items.
  193. //
  194. //
  195. BOOL
  196. ExpungeInternal(
  197. KEYREF key,
  198. CACHEENTRY* pData = 0,
  199. BOOL fIgnoreKey = TRUE,
  200. const CACHEENTRY* pProtected = 0,
  201. BOOL fDoCheap = FALSE
  202. ) ;
  203. public :
  204. //
  205. // INTERNAL API's - These are public for convenience - not intended
  206. // for Use outside of cachelib !!
  207. //
  208. //
  209. // Either find an item in the cache or Construct a new item
  210. // and place it in the Cache.
  211. // return the result through pDataOut no matter what !
  212. //
  213. BOOL
  214. FindOrCreateInternal(
  215. DWORD dwHash,
  216. KEYREF key,
  217. Constructor& constructor,
  218. CRefPtr< Data >& pDataOut
  219. ) ;
  220. //
  221. // Constructor - cMax specifies the maximum number of entries
  222. // we should hold in the cache.
  223. //
  224. Cache( ) ;
  225. //
  226. // Destructor - remove ourselves from schedule list before continuing !
  227. //
  228. ~Cache() ;
  229. //
  230. // Initialization function - take pointer to function
  231. // which should be used to compute hash values on Key's
  232. // Also takes the number of seconds objects should live in
  233. // the cache !
  234. //
  235. BOOL
  236. Init(
  237. DWORD (*pfnHash)( KEYREF ),
  238. DWORD dwLifetimeSeconds,
  239. DWORD cMaxInstances,
  240. PSTOPHINT_FN pfnStopHint = NULL
  241. ) ;
  242. //
  243. // Function which can be used to remove items from the Cache
  244. // If default args are used we pick an expired item in the Cache
  245. // to remove
  246. //
  247. BOOL
  248. Expunge(
  249. KEYREF key,
  250. CACHEENTRY* pData = 0,
  251. BOOL fIgnoreKey = TRUE
  252. ) ;
  253. //
  254. // Function which can be passed a function pointer to determine
  255. // exactly what items are to be removed from the Cache.
  256. // if fForced == TRUE then items are removed from the Cache
  257. // no matter what.
  258. //
  259. BOOL
  260. ExpungeSpecific(
  261. CALLBACKOBJ* pCallback,
  262. BOOL fForced
  263. ) ;
  264. //
  265. // Either find an item in the cache or Construct a new item
  266. // and place it in the Cache.
  267. // return the result through pDataOut no matter what !
  268. //
  269. BOOL
  270. FindOrCreate(
  271. KEYREF key,
  272. Constructor& constructor,
  273. CRefPtr< Data >& pDataOut
  274. ) ;
  275. #ifdef DEBUG
  276. static long s_cCreated ;
  277. #endif
  278. } ;
  279. template < class Data,
  280. class Key,
  281. class KEYREF, /* This is the type used to point or reference items in the cache*/
  282. class Constructor,
  283. BOOL fAtomic = TRUE
  284. >
  285. class MultiCache {
  286. private :
  287. //
  288. // Define a 'CACHEENTRY' object which holds all the
  289. // necessary data for each object which is placed in the cache !
  290. //
  291. typedef CacheEntry< Data, Key, KEYREF, fAtomic > CACHEENTRY ;
  292. //
  293. // Define the type for a single instance !
  294. //
  295. typedef Cache< Data, Key, KEYREF, Constructor, fAtomic > CACHEINSTANCE ;
  296. //
  297. // Is the 'Cache' initialized and in a valid state !
  298. //
  299. BOOL m_fValid ;
  300. //
  301. // Pointer to the various Cache's we subdivide our work into
  302. //
  303. CACHEINSTANCE *m_pCaches ;
  304. //
  305. // Number of sub cache's we use to split up the work !
  306. //
  307. DWORD m_cSubCaches ;
  308. //
  309. // We use the hash function to choose which of our subcaches to work with !
  310. //
  311. DWORD (*m_pfnHash)( KEYREF ) ;
  312. //
  313. // Return the correct cache instance to hold the selected piece of data !
  314. //
  315. //DWORD ChooseInstance( Key& k ) ;
  316. DWORD ChooseInstance( DWORD dwHash ) ;
  317. public :
  318. //
  319. // Define callback objects for Expunge Operations.
  320. //
  321. typedef CacheCallback< Data > CALLBACKOBJ;
  322. //
  323. // Constructor - cMax specifies the maximum number of entries
  324. // we should hold in the cache.
  325. //
  326. MultiCache( ) ;
  327. //
  328. // Destructor - destroys are various sub cache's
  329. //
  330. ~MultiCache() ;
  331. //
  332. // Initialization function - take pointer to function
  333. // which should be used to compute hash values on Key's
  334. // Also takes the number of seconds objects should live in
  335. // the cache !
  336. //
  337. BOOL
  338. Init(
  339. DWORD (*pfnHash)( KEYREF ),
  340. DWORD dwLifetimeSeconds,
  341. DWORD cSubCaches,
  342. DWORD cMaxElements,
  343. PSTOPHINT_FN pfnStopHint = NULL
  344. ) ;
  345. //
  346. // Function which can be used to remove items from the Cache
  347. // If default args are used we pick an expired item in the Cache
  348. // to remove
  349. //
  350. BOOL
  351. Expunge(
  352. KEYREF key,
  353. CACHEENTRY* pData = 0,
  354. BOOL fExpungeAll = FALSE
  355. ) ;
  356. //
  357. // Function which can be passed a function pointer to determine
  358. // exactly what items are to be removed from the Cache.
  359. // if fForced == TRUE then items are removed from the Cache
  360. // no matter what.
  361. //
  362. BOOL
  363. ExpungeSpecific(
  364. CALLBACKOBJ* pCallback,
  365. BOOL fForced
  366. ) ;
  367. //
  368. // Either find an item in the cache or Construct a new item
  369. // and place it in the Cache.
  370. // return the result through pDataOut no matter what !
  371. //
  372. BOOL
  373. FindOrCreate(
  374. KEYREF key,
  375. Constructor& constructor,
  376. CRefPtr< Data >& pDataOut
  377. ) ;
  378. //
  379. // Either find an item in the cache or Construct a new item
  380. // and place it in the Cache.
  381. // return the result through pDataOut no matter what !
  382. // NOTE : This is for use when the caller has a cheaper
  383. // way to compute the hash value then us - in debug we
  384. // need to assure that the caller correctly computes this !
  385. //
  386. BOOL
  387. FindOrCreate(
  388. KEYREF key,
  389. DWORD dwHash,
  390. Constructor& constructor,
  391. CRefPtr< Data >& pDataOut
  392. ) ;
  393. } ;
  394. #include "cacheimx.h"
  395. #endif // _CACHEX_H_