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.

441 lines
8.0 KiB

  1. /*++
  2. CACHEMTI.H
  3. This file contains the definitions of all the internal classes
  4. used to implement the multithreaded cache.
  5. --*/
  6. #ifndef _CACHEMTI_H_
  7. #define _CACHEMTI_H_
  8. //
  9. // This class defines all the information we keep about
  10. // objects that we are holding in our cache.
  11. //
  12. //
  13. class CacheState {
  14. private :
  15. //
  16. // Signature for a piece of Cache state !
  17. //
  18. DWORD m_dwSignature ;
  19. //
  20. // No Copy construction !!!
  21. //
  22. CacheState( CacheState& ) ;
  23. protected :
  24. //
  25. // Doubly linked list of CacheEntry BLOCKS !
  26. //
  27. // This list is kept ordered by TTL, the newest blocks are at the end !
  28. //
  29. class CacheState* m_pPrev ;
  30. class CacheState* m_pNext ;
  31. //
  32. // Cache State information -
  33. // the time the item was last touched, as well as orphanage info.
  34. //
  35. FILETIME m_LastAccess ;
  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( ) :
  66. m_dwSignature( DWORD('atSC' ) ),
  67. m_pPrev( 0 ),
  68. m_pNext( 0 ),
  69. m_fOrphan( FALSE ) {
  70. #ifdef DEBUG
  71. InterlockedIncrement( &s_cCreated ) ;
  72. #endif
  73. ZeroMemory( &m_LastAccess, sizeof( m_LastAccess ) ) ;
  74. }
  75. #if 0
  76. //
  77. // Copy Constructor relinks linked list ! we place ourselves in the linked list
  78. // after the rhs element.
  79. //
  80. CacheState( CacheState& rhs ) :
  81. m_pBucket( 0 ),
  82. m_pPrev( 0 ),
  83. m_pNext( 0 ),
  84. m_LastAccess( rhs.m_LastAccess ),
  85. m_fOrphan( rhs.m_fOrphan ) {
  86. if( rhs.m_pPrev != 0 )
  87. InsertAfter( &rhs ) ;
  88. #ifdef DEBUG
  89. InterlockedIncrement( &s_cCreated ) ;
  90. #endif
  91. }
  92. #endif
  93. //
  94. // If we are in a linked list - the default destructor needs to remove us
  95. // from that list.
  96. //
  97. virtual ~CacheState() ;
  98. //
  99. // Need a virtual function which we use to figure out when we can
  100. // safely remove an entry from the Cache !!
  101. //
  102. virtual BOOL fDeletable() { return TRUE ; }
  103. //
  104. // Update the LastAccess time !
  105. //
  106. void
  107. Stamp( ) {
  108. GetSystemTimeAsFileTime( &m_LastAccess ) ;
  109. }
  110. //
  111. // Compare to entries by comparing their LastAccess time's !
  112. //
  113. BOOL
  114. operator <= ( CacheState& rhs ) {
  115. return CompareFileTime( &m_LastAccess, &rhs.m_LastAccess ) <= 0 ;
  116. }
  117. //
  118. // Compare to entries by comparing their LastAccess time's !
  119. //
  120. BOOL
  121. operator >= ( CacheState& rhs ) {
  122. return CompareFileTime( &m_LastAccess, &rhs.m_LastAccess ) >= 0 ;
  123. }
  124. //
  125. // Compare to entries by comparing their LastAccess time's !
  126. //
  127. BOOL
  128. operator > ( CacheState& rhs ) {
  129. return CompareFileTime( &m_LastAccess, &rhs.m_LastAccess ) > 0 ;
  130. }
  131. //
  132. // Tell us if this entry is older than the specified time !
  133. //
  134. BOOL
  135. OlderThan( FILETIME filetime ) {
  136. return CompareFileTime( &m_LastAccess, &filetime ) < 0 ;
  137. }
  138. //
  139. // Checks that the object is in a legal state !
  140. //
  141. virtual BOOL
  142. IsValid( ) ;
  143. #ifdef DEBUG
  144. static long s_cCreated ;
  145. #endif
  146. } ;
  147. //
  148. // This class defines a couple of virtual functions
  149. // which are to be called from CacheList objects.
  150. //
  151. class CacheTable {
  152. protected :
  153. friend class CacheList ;
  154. //
  155. // Remove an entry from the Cache - return TRUE if
  156. // successful and pEntry destroyed.
  157. //
  158. virtual void RemoveEntry(
  159. CacheState* pEntry
  160. ) ;
  161. } ;
  162. class CacheSelector : public CacheTable {
  163. protected :
  164. friend class CacheList ;
  165. //
  166. // Called to determine whether we want to remove a
  167. // specified entry from the cache.
  168. //
  169. virtual BOOL QueryRemoveEntry(
  170. CacheState* pEntry
  171. ) ;
  172. } ;
  173. template< class Data, class Key, BOOL fAtomic = TRUE >
  174. class TEntry : public CacheState {
  175. private :
  176. //
  177. // No copy constructor allowed !
  178. //
  179. TEntry( TEntry& ) ;
  180. public :
  181. //
  182. // For chaining in the hash table - this is our bucket pointer !
  183. //
  184. TEntry* m_pBucket ;
  185. CRefPtr< Data > m_pData ;
  186. //
  187. // Default constructor just passes on TTL data to CacheState object
  188. //
  189. TEntry( Data* pData ) :
  190. m_pBucket( 0 ),
  191. m_pData( pData ) {
  192. Stamp() ;
  193. }
  194. //
  195. // We do not declare a destructor as the default compiler
  196. // provided destructor works fine !
  197. //
  198. // ~CacheEntry() ;
  199. //
  200. // Return a reference to the Key data from the data portion !
  201. //
  202. void GetKey(Key &k) {
  203. m_pData->GetKey(k) ;
  204. }
  205. //
  206. // Return 0 if the provided Key matches that contained in the
  207. // data block !
  208. //
  209. int MatchKey( Key& key ) {
  210. return m_pData->MatchKey( key ) ;
  211. }
  212. //
  213. // Determine whether we can remove the Data represented by this
  214. // entry from the Cache. 'fAtomic' == TRUE means that we should
  215. // only release entries from the cache when the cache is the
  216. // only component holding a reference to the entry.
  217. // This ensures that two pieces of 'Data' which are located
  218. // with the same 'Key' never exist at the same time.
  219. //
  220. BOOL fDeleteable() {
  221. if( !fAtomic ) {
  222. return TRUE ;
  223. }
  224. return m_pData->m_refs == 0 ;
  225. }
  226. BOOL
  227. IsValid() {
  228. if( m_pData == 0 )
  229. return FALSE ;
  230. return CacheState::IsValid() ;
  231. }
  232. } ;
  233. class CacheList {
  234. private :
  235. //
  236. // Keep this element around so we can keep a doubly linked list
  237. // of the elements in the Cache List.
  238. //
  239. CacheState m_Head ;
  240. //
  241. // Make this private - nobody gets to copy us !
  242. //
  243. CacheList( CacheList& ) ;
  244. protected :
  245. //
  246. // Number of Elements in the Cache !
  247. //
  248. long m_cEntries ;
  249. public :
  250. //
  251. // Maximum number of Elements in the List !
  252. //
  253. long m_cMax ;
  254. //
  255. // Stop hint function to be called during long shutdown loops.
  256. //
  257. PSTOPHINT_FN m_pfnStopHint;
  258. //
  259. // Initialize the Cache list !
  260. //
  261. CacheList( long Max = 128 ) ;
  262. #ifdef DEBUG
  263. //
  264. // In debug builds the destructor helps track how many of these
  265. // are created !!
  266. //
  267. ~CacheList() ;
  268. #endif
  269. //
  270. // Append an Entry into the CacheList. We Append as this element
  271. // should have the largest Age and most likely to be the last element expired !
  272. //
  273. // Returns TRUE if the number of entries is larger than our pre-ordained Maximum !
  274. //
  275. BOOL
  276. Append( const CacheState* pEntry ) ;
  277. //
  278. // Remove an arbitrary Entry from the CacheList !
  279. //
  280. // Returns TRUE if the number of remaining entries is larger than our pre-ordained Maximum !
  281. //
  282. BOOL
  283. Remove( const CacheState* pEntry ) ;
  284. //
  285. // For users who destroy elements of the list, causing the
  286. // destructors to unlink elements and therefore skip Remove() -
  287. // call this so that our count of elements stays in sync.
  288. //
  289. void
  290. DecrementCount() {
  291. m_cEntries-- ;
  292. }
  293. //
  294. // Move an element to the end of the list.
  295. //
  296. void
  297. MoveToBack(
  298. CacheState* pEntry
  299. ) ;
  300. //
  301. // Walk the list and Expire any entries in there !
  302. // This means we decrement TTL's and count up the number of
  303. // entries in the list we could drop right now !
  304. //
  305. BOOL
  306. Expire( DWORD& cReady ) ;
  307. //
  308. // Go find those elements who's TTL has dropped below 0 and
  309. // get rid of them from the cache !!
  310. //
  311. // NOTE - if fDoCheap is set to TRUE then we use m_cReadyToDie
  312. // to figure out if there's any work we can do !
  313. //
  314. BOOL
  315. Expunge( CacheTable* ptable,
  316. FILETIME* filetimeExpire,
  317. DWORD& cExpunged,
  318. BOOL fDoCheap = FALSE,
  319. const CacheState* pProtected = 0
  320. ) ;
  321. //
  322. // Go remove a single element who's TTL haven't dropped below 0
  323. // and get rid of it from the Cache !
  324. //
  325. BOOL
  326. ForceExpunge( CacheTable* ptable,
  327. const CacheState* pProtected = 0
  328. ) ;
  329. //
  330. // Go find those elements who's TTL has dropped below 0 and
  331. // get rid of them from the cache !!
  332. //
  333. BOOL
  334. ExpungeSpecific( CacheSelector* ptable,
  335. BOOL fForced,
  336. DWORD &cExpunged
  337. ) ;
  338. //
  339. // Check to see whether the expiration list is in a valid state !
  340. //
  341. BOOL
  342. IsValid() ;
  343. #if 0
  344. //
  345. // Bump the life time of the specified object up,
  346. // as somebody is re-using it from the cache !
  347. //
  348. void
  349. LiveLonger( CacheState* pEntry,
  350. long ttl
  351. ) ;
  352. #endif
  353. #ifdef DEBUG
  354. static long s_cCreated ;
  355. #endif
  356. } ;
  357. #endif // _CACHEMTI_H_