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.

489 lines
9.9 KiB

  1. /*++
  2. Cache.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. Key& GetKey() ;
  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 _CACHE_H_
  70. #define _CACHE_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 "cacheint.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 Constructor,
  123. BOOL fAtomic = TRUE
  124. >
  125. class Cache : public CScheduleThread,
  126. CacheTable {
  127. private :
  128. //
  129. // Define a 'CACHEENTRY' object which holds all the
  130. // necessary data for each object which is placed in the cache !
  131. //
  132. typedef CacheEntry< Data, Key, fAtomic > CACHEENTRY ;
  133. //
  134. // Define callback objects for Expunge Operations.
  135. //
  136. typedef CacheCallback< Data > CALLBACKOBJ;
  137. //
  138. // Is the 'Cache' initialized and in a valid state !
  139. //
  140. BOOL m_fValid ;
  141. //
  142. // A list of everything in the Cache, used for TTL processing
  143. //
  144. CacheList m_ExpireList ;
  145. //
  146. // A hash table we use to find things within the Cache
  147. //
  148. TFHash< CACHEENTRY, Key > m_Lookup ;
  149. //
  150. // Pointer to a runtime-user provided function which is used
  151. // to determine what things should be removed from the Cache
  152. //
  153. BOOL (* m_pfnExpungeSpecific )( Data & ) ;
  154. //
  155. // Pointer to a runtime-user provided object derived from CacheCallback< Data >
  156. // which lets the user invoke some function for each item in the Cache !
  157. //
  158. CALLBACKOBJ* m_pCallbackObject ;
  159. //
  160. // Reader writer lock which protects all these data structures !
  161. //
  162. _CACHELOCK m_Lock ;
  163. //
  164. // The initial TTL we should assign to all newly cached objects !
  165. //
  166. DWORD m_TTL ;
  167. protected :
  168. //
  169. // Virtual function called by CScheduleThread's thread which
  170. // we use to bump TTL counters
  171. //
  172. void
  173. Schedule();
  174. //
  175. // Function which removes an Entry from the Cache !
  176. //
  177. BOOL
  178. RemoveEntry(
  179. CacheState* pEntry
  180. ) ;
  181. //
  182. // Virtual Function called by CacheList when we pass call
  183. // CacheList::ExpungeSpecific
  184. //
  185. BOOL
  186. QueryRemoveEntry(
  187. CacheState* pEntry
  188. ) ;
  189. //
  190. // Function which can remove a specific item from the Cache
  191. // or walk the Cache deleting all the expired items.
  192. //
  193. //
  194. BOOL
  195. ExpungeInternal(
  196. const CACHEENTRY* pProtected = 0,
  197. BOOL fDoCheap = FALSE,
  198. Key* key=0,
  199. CACHEENTRY* pData = 0
  200. ) ;
  201. public :
  202. //
  203. // INTERNAL API's - These are public for convenience - not intended
  204. // for Use outside of cachelib !!
  205. //
  206. //
  207. // Either find an item in the cache or Construct a new item
  208. // and place it in the Cache.
  209. // return the result through pDataOut no matter what !
  210. //
  211. BOOL
  212. FindOrCreateInternal(
  213. DWORD dwHash,
  214. Key& key,
  215. Constructor& constructor,
  216. CRefPtr< Data >& pDataOut
  217. ) ;
  218. //
  219. // Constructor - cMax specifies the maximum number of entries
  220. // we should hold in the cache.
  221. //
  222. Cache( ) ;
  223. //
  224. // Destructor - remove ourselves from schedule list before continuing !
  225. //
  226. ~Cache() ;
  227. //
  228. // Initialization function - take pointer to function
  229. // which should be used to compute hash values on Key's
  230. // Also takes the number of seconds objects should live in
  231. // the cache !
  232. //
  233. BOOL
  234. Init(
  235. DWORD (*pfnHash)( const Key& ),
  236. DWORD dwLifetimeSeconds,
  237. DWORD cMaxInstances,
  238. PSTOPHINT_FN pfnStopHint = NULL
  239. ) ;
  240. //
  241. // Function which can be used to remove items from the Cache
  242. // If default args are used we pick an expired item in the Cache
  243. // to remove
  244. //
  245. BOOL
  246. Expunge(
  247. Key* key = 0,
  248. CACHEENTRY* pData = 0
  249. ) ;
  250. //
  251. // Function which can be passed a function pointer to determine
  252. // exactly what items are to be removed from the Cache.
  253. // if fForced == TRUE then items are removed from the Cache
  254. // no matter what.
  255. //
  256. BOOL
  257. ExpungeSpecific(
  258. CALLBACKOBJ* pCallback,
  259. BOOL fForced
  260. ) ;
  261. //
  262. // Either find an item in the cache or Construct a new item
  263. // and place it in the Cache.
  264. // return the result through pDataOut no matter what !
  265. //
  266. BOOL
  267. FindOrCreate(
  268. Key& key,
  269. Constructor& constructor,
  270. CRefPtr< Data >& pDataOut
  271. ) ;
  272. #ifdef DEBUG
  273. static long s_cCreated ;
  274. #endif
  275. } ;
  276. template < class Data,
  277. class Key,
  278. class Constructor,
  279. BOOL fAtomic = TRUE
  280. >
  281. class MultiCache {
  282. private :
  283. //
  284. // Define a 'CACHEENTRY' object which holds all the
  285. // necessary data for each object which is placed in the cache !
  286. //
  287. typedef CacheEntry< Data, Key, fAtomic > CACHEENTRY ;
  288. //
  289. // Define callback objects for Expunge Operations.
  290. //
  291. typedef CacheCallback< Data > CALLBACKOBJ;
  292. //
  293. // Define the type for a single instance !
  294. //
  295. typedef Cache< Data, Key, 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)( const Key& ) ;
  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. // Constructor - cMax specifies the maximum number of entries
  320. // we should hold in the cache.
  321. //
  322. MultiCache( ) ;
  323. //
  324. // Destructor - destroys are various sub cache's
  325. //
  326. ~MultiCache() ;
  327. //
  328. // Initialization function - take pointer to function
  329. // which should be used to compute hash values on Key's
  330. // Also takes the number of seconds objects should live in
  331. // the cache !
  332. //
  333. BOOL
  334. Init(
  335. DWORD (*pfnHash)( const Key& ),
  336. DWORD dwLifetimeSeconds,
  337. DWORD cSubCaches,
  338. DWORD cMaxElements,
  339. PSTOPHINT_FN pfnStopHint = NULL
  340. ) ;
  341. //
  342. // Function which can be used to remove items from the Cache
  343. // If default args are used we pick an expired item in the Cache
  344. // to remove
  345. //
  346. BOOL
  347. Expunge(
  348. Key* key = 0,
  349. CACHEENTRY* pData = 0
  350. ) ;
  351. //
  352. // Function which can be passed a function pointer to determine
  353. // exactly what items are to be removed from the Cache.
  354. // if fForced == TRUE then items are removed from the Cache
  355. // no matter what.
  356. //
  357. BOOL
  358. ExpungeSpecific(
  359. CALLBACKOBJ* pCallback,
  360. BOOL fForced
  361. ) ;
  362. //
  363. // Either find an item in the cache or Construct a new item
  364. // and place it in the Cache.
  365. // return the result through pDataOut no matter what !
  366. //
  367. BOOL
  368. FindOrCreate(
  369. Key& key,
  370. Constructor& constructor,
  371. CRefPtr< Data >& pDataOut
  372. ) ;
  373. //
  374. // Either find an item in the cache or Construct a new item
  375. // and place it in the Cache.
  376. // return the result through pDataOut no matter what !
  377. // NOTE : This is for use when the caller has a cheaper
  378. // way to compute the hash value then us - in debug we
  379. // need to assure that the caller correctly computes this !
  380. //
  381. BOOL
  382. FindOrCreate(
  383. Key& key,
  384. DWORD dwHash,
  385. Constructor& constructor,
  386. CRefPtr< Data >& pDataOut
  387. ) ;
  388. } ;
  389. #include "cacheimp.h"
  390. #endif // _CACHE_H_