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.

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