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.

462 lines
9.1 KiB

  1. /*++
  2. Cacheint.h
  3. This file defines all of the classes required to support
  4. the generic cache manager, who's interface is defined in
  5. cache.h
  6. --*/
  7. #ifndef _CACHEINT_H_
  8. #define _CACHEINT_H_
  9. #include <windows.h>
  10. #include "dbgtrace.h"
  11. #include "smartptr.h"
  12. #include "fhash.h"
  13. #ifdef _USE_RWNH_
  14. #include "rwnew.h"
  15. typedef CShareLockNH _CACHELOCK ;
  16. #else
  17. #include "rw.h"
  18. typedef CShareLock _CACHELOCK ;
  19. #endif
  20. //
  21. // This class defines all the information we keep about
  22. // objects that we are holding in our cache.
  23. //
  24. //
  25. class CacheState {
  26. protected :
  27. //
  28. // Doubly linked list of CacheEntry BLOCKS !
  29. //
  30. class CacheState* m_pPrev ;
  31. class CacheState* m_pNext ;
  32. //
  33. // Cacge State Information - Time To Live and Orphanage status !
  34. //
  35. long m_TTL ;
  36. BOOL m_fOrphan ;
  37. //
  38. // Insert us into the list after the specified element !
  39. //
  40. void
  41. InsertAfter(
  42. class CacheState* pPrevious
  43. ) ;
  44. //
  45. // Insert us into the circular list before the specified element !
  46. //
  47. void
  48. InsertBefore(
  49. class CacheState* pNext
  50. ) ;
  51. //
  52. // Remove this element from the circular list !
  53. //
  54. void
  55. Remove() ;
  56. //
  57. // The CacheList object maintains a list of these objects and ages them
  58. // out !
  59. //
  60. friend class CacheList ;
  61. public :
  62. //
  63. // Default Constructor NULLS everything out !
  64. //
  65. CacheState( DWORD ttl = 0 ) :
  66. m_pPrev( 0 ), m_pNext( 0 ), m_TTL( ttl ), m_fOrphan( FALSE ) {
  67. #ifdef DEBUG
  68. InterlockedIncrement( &s_cCreated ) ;
  69. #endif
  70. }
  71. //
  72. // Copy Constructor relinks linked list ! we place ourselves in the linked list
  73. // after the rhs element.
  74. //
  75. CacheState( CacheState& rhs ) : m_pPrev( 0 ),
  76. m_pNext( 0 ),
  77. m_TTL( rhs.m_TTL ),
  78. m_fOrphan( rhs.m_fOrphan ) {
  79. if( rhs.m_pPrev != 0 )
  80. InsertAfter( &rhs ) ;
  81. #ifdef DEBUG
  82. InterlockedIncrement( &s_cCreated ) ;
  83. #endif
  84. }
  85. //
  86. // If we are in a linked list - the default destructor needs to remove us
  87. // from that list.
  88. //
  89. ~CacheState() ;
  90. //
  91. // Need a virtual function which we use to figure out when we can
  92. // safely remove an entry from the Cache !!
  93. //
  94. virtual BOOL fDeletable() { return TRUE ; }
  95. #ifdef DEBUG
  96. static long s_cCreated ;
  97. #endif
  98. } ;
  99. //
  100. // This class defines a couple of virtual functions
  101. // which are to be called from CacheList objects.
  102. //
  103. class CacheTable {
  104. protected :
  105. friend class CacheList ;
  106. //
  107. // Remove an entry from the Cache - return TRUE if
  108. // successful and pEntry destroyed.
  109. //
  110. virtual BOOL RemoveEntry(
  111. CacheState* pEntry
  112. ) ;
  113. //
  114. // Called to determine whether we want to remove a
  115. // specified entry from the cache.
  116. //
  117. virtual BOOL QueryRemoveEntry(
  118. CacheState* pEntry
  119. ) ;
  120. } ;
  121. class CacheList {
  122. private :
  123. //
  124. // Keep this element around so we can keep a doubly linked list
  125. // of the elements in the Cache List.
  126. //
  127. CacheState m_Head ;
  128. //
  129. // Make this private - nobody gets to copy us !
  130. //
  131. CacheList( CacheList& ) ;
  132. protected :
  133. //
  134. // Number of Elements in the Cache !
  135. //
  136. long m_cEntries ;
  137. //
  138. // Number of elements (approximately) ready to be removed from
  139. // the cache !
  140. //
  141. long m_cReadyToDie ;
  142. public :
  143. //
  144. // Maximum number of Elements in the List !
  145. //
  146. long m_cMax ;
  147. //
  148. // Stop hint function to be called during long shutdown loops.
  149. //
  150. PSTOPHINT_FN m_pfnStopHint;
  151. //
  152. // Initialize the Cache list !
  153. //
  154. CacheList( long Max = 128 ) ;
  155. #ifdef DEBUG
  156. //
  157. // In debug builds the destructor helps track how many of these
  158. // are created !!
  159. //
  160. ~CacheList() ;
  161. #endif
  162. //
  163. // Append an Entry into the CacheList. We Append as this element
  164. // should have the largest Age and most likely to be the last element expired !
  165. //
  166. // Returns TRUE if the number of entries is larger than our pre-ordained Maximum !
  167. //
  168. BOOL
  169. Append( const CacheState* pEntry ) ;
  170. //
  171. // Remove an arbitrary Entry from the CacheList !
  172. //
  173. // Returns TRUE if the number of remaining entries is larger than our pre-ordained Maximum !
  174. //
  175. BOOL
  176. Remove( const CacheState* pEntry ) ;
  177. //
  178. // Walk the list and Expire any entries in there !
  179. // This means we decrement TTL's and count up the number of
  180. // entries in the list we could drop right now !
  181. //
  182. BOOL
  183. Expire( DWORD& cReady ) ;
  184. //
  185. // Go find those elements who's TTL has dropped below 0 and
  186. // get rid of them from the cache !!
  187. //
  188. // NOTE - if fDoCheap is set to TRUE then we use m_cReadyToDie
  189. // to figure out if there's any work we can do !
  190. //
  191. BOOL
  192. Expunge( CacheTable* ptable,
  193. BOOL fDoCheap = FALSE,
  194. const CacheState* pProtected = 0
  195. ) ;
  196. //
  197. // Go remove a single element who's TTL haven't dropped below 0
  198. // and get rid of it from the Cache !
  199. //
  200. BOOL
  201. ForceExpunge( CacheTable* ptable,
  202. const CacheState* pProtected = 0
  203. ) ;
  204. //
  205. // Go find those elements who's TTL has dropped below 0 and
  206. // get rid of them from the cache !!
  207. //
  208. BOOL
  209. ExpungeSpecific( CacheTable* ptable,
  210. BOOL fForced
  211. ) ;
  212. //
  213. // Bump the life time of the specified object up,
  214. // as somebody is re-using it from the cache !
  215. //
  216. void
  217. LiveLonger( CacheState* pEntry,
  218. long ttl
  219. ) ;
  220. #ifdef DEBUG
  221. static long s_cCreated ;
  222. #endif
  223. } ;
  224. //
  225. // This template class adds one member to the 'CacheState' class,
  226. // which is the Reference counting pointer to the block of data we
  227. // are keeping in the Cache !
  228. // In addition - we let the user specify whether Cache Blocks must be
  229. // atomic. An atomic Cache block means we must never remove an element
  230. // from the Cache for which somebody external has a reference !
  231. // (ie if fAtomic == TRUE then we only remove elements from the cache
  232. // when the reference count on the Data is zero meaning that we have the
  233. // last reference !!!
  234. //
  235. //
  236. template< class Data, class Key, BOOL fAtomic = TRUE >
  237. class CacheEntry : public CacheState {
  238. public :
  239. CRefPtr< Data > m_pData ;
  240. //
  241. // Default constructor just passes on TTL data to CacheState object
  242. //
  243. CacheEntry( DWORD ttl=0 ) : CacheState( ttl ) {}
  244. //
  245. // We do not declare a copy constructor as the default
  246. // compiler provided copy constructor which invokes
  247. // base class and member variable copy constructors works fine !
  248. //
  249. // CacheEntry( CacheEntry& ) ;
  250. //
  251. // We do not declare a destructor as the default compiler
  252. // provided destructor works fine !
  253. //
  254. // ~CacheEntry() ;
  255. //
  256. // Return a reference to the Key data from the data portion !
  257. //
  258. Key& GetKey() {
  259. return m_pData->GetKey() ;
  260. }
  261. //
  262. // Return 0 if the provided Key matches that contained in the
  263. // data block !
  264. //
  265. int MatchKey( Key& key ) {
  266. return m_pData->MatchKey( key ) ;
  267. }
  268. //
  269. // Determine whether we can remove the Data represented by this
  270. // entry from the Cache. 'fAtomic' == TRUE means that we should
  271. // only release entries from the cache when the cache is the
  272. // only component holding a reference to the entry.
  273. // This ensures that two pieces of 'Data' which are located
  274. // with the same 'Key' never exist at the same time.
  275. //
  276. BOOL fDeleteable() {
  277. if( !fAtomic ) {
  278. return TRUE ;
  279. }
  280. return m_pData->m_refs == 0 ;
  281. }
  282. } ;
  283. //
  284. // This is a base class for those objects which wish to be
  285. // called on a regularily scheduled basis.
  286. //
  287. // The constructors for this class will automatically
  288. // put the object in a doubly linked list walked by a
  289. // background thread which periodically executes a virtual function.
  290. //
  291. //
  292. class CScheduleThread {
  293. private :
  294. //
  295. // Special constructor for the 'Head' element of the
  296. // doubly linked list this class maintains.
  297. //
  298. CScheduleThread( BOOL fSpecial ) ;
  299. protected :
  300. //
  301. // Has the scheduler been initialized ?
  302. //
  303. static BOOL s_fInitialized ;
  304. //
  305. // Crit sect protecting doubly linked list.
  306. //
  307. static CRITICAL_SECTION s_critScheduleList ;
  308. //
  309. // Handle to event used to terminate background thread.
  310. //
  311. static HANDLE s_hShutdown ;
  312. //
  313. // Handle to background thread.
  314. //
  315. static HANDLE s_hThread ;
  316. //
  317. // The head element of the doubly linked list.
  318. //
  319. static CScheduleThread s_Head ;
  320. //
  321. // The thread which calls our virtual functions
  322. //
  323. static DWORD WINAPI ScheduleThread( LPVOID lpv ) ;
  324. //
  325. // Previous and Next pointers which maintain doubly linked
  326. // list of scheduled itesm.
  327. //
  328. class CScheduleThread* m_pPrev ;
  329. class CScheduleThread* m_pNext ;
  330. protected :
  331. //
  332. // Derived classes should override this function -
  333. // it will be called on a regular basis by the scheduler thread.
  334. //
  335. virtual void Schedule( void ) {}
  336. //
  337. // Constructor and Destructor automagically manage
  338. // insertion into doubly linked list of other scheduled items.
  339. // These are protected as we want people to buid only
  340. // derived objects which use this.
  341. //
  342. CScheduleThread() ;
  343. //
  344. // Member functions which put us into the regular schedule !
  345. //
  346. void AddToSchedule() ;
  347. void RemoveFromSchedule() ;
  348. public :
  349. //
  350. // Initialize the class - don't construct
  351. // any derived objects before this is called.
  352. //
  353. static BOOL Init() ;
  354. //
  355. // Terminate class and background thread !
  356. //
  357. static void Term() ;
  358. //
  359. // Global which tells clients how frequently they
  360. // will be called !
  361. //
  362. static DWORD dwNotificationSeconds ;
  363. //
  364. // Destructor is protected - we should only be invoked
  365. // by derived class constructors
  366. //
  367. ~CScheduleThread() ;
  368. } ;
  369. #endif