//+--------------------------------------------------------------------------- // // Microsoft Windows NT Security // Copyright (C) Microsoft Corporation, 1997 - 1999 // // File: lru.h // // Contents: LRU cache class definitions // // History: 22-Dec-97 kirtd Created // //---------------------------------------------------------------------------- #if !defined(__LRU_H__) #define __LRU_H__ #include // // Forward declaration of LRU cache classes // class CLruCache; class CLruEntry; typedef CLruCache* PCLRUCACHE; typedef CLruEntry* PCLRUENTRY; // // LRU cache bucket structure // typedef struct _LRU_CACHE_BUCKET { DWORD Usage; PCLRUENTRY pList; } LRU_CACHE_BUCKET, *PLRU_CACHE_BUCKET; // // CLruEntry class definition // class CLruEntry { public: // // Construction // CLruEntry ( IN PCLRUCACHE pCache, IN PCRYPT_DATA_BLOB pIdentifier, IN LPVOID pvData, OUT BOOL& rfResult ); ~CLruEntry (); // // Reference counting // inline VOID AddRef (); inline VOID Release (); // // Cache and Bucket access // inline PCLRUCACHE Cache (); inline PLRU_CACHE_BUCKET Bucket (); // // Data access // inline PCRYPT_DATA_BLOB Identifier (); inline LPVOID Data (); // // Link access // inline VOID SetPrevPointer (IN PCLRUENTRY pPrevEntry); inline VOID SetNextPointer (IN PCLRUENTRY pNextEntry); inline PCLRUENTRY PrevPointer (); inline PCLRUENTRY NextPointer (); // // LRU usage access // inline VOID SetUsage (DWORD Usage); inline DWORD Usage (); // // Cache Destruction notification // inline VOID OnCacheDestruction (); private: // // Reference count // ULONG m_cRefs; // // Cache pointer // PCLRUCACHE m_pCache; // // Entry information // CRYPT_DATA_BLOB m_Identifier; LPVOID m_pvData; // // Links // PCLRUENTRY m_pPrevEntry; PCLRUENTRY m_pNextEntry; PLRU_CACHE_BUCKET m_pBucket; // // Usage // DWORD m_Usage; }; // // CLruCache class definition // class CLruCache { public: // // Construction // CLruCache ( IN PLRU_CACHE_CONFIG pConfig, OUT BOOL& rfResult ); ~CLruCache (); // // Clearing the cache // VOID PurgeAllEntries ( IN DWORD dwFlags, IN OPTIONAL LPVOID pvRemovalContext ); // // Cache locking // inline VOID LockCache (); inline VOID UnlockCache (); // // LRU enable and disable // VOID EnableLruOfEntries (IN OPTIONAL LPVOID pvLruRemovalContext); VOID DisableLruOfEntries (); // // Cache entry manipulation // VOID InsertEntry ( IN PCLRUENTRY pEntry, IN OPTIONAL LPVOID pvLruRemovalContext ); VOID RemoveEntry ( IN PCLRUENTRY pEntry, IN DWORD dwFlags, IN OPTIONAL LPVOID pvRemovalContext ); VOID TouchEntry (IN PCLRUENTRY pEntry, IN DWORD dwFlags); // // Cache entry retrieval // PCLRUENTRY FindEntry (IN PCRYPT_DATA_BLOB pIdentifier, IN BOOL fTouchEntry); PCLRUENTRY NextMatchingEntry ( IN PCLRUENTRY pPrevEntry, IN BOOL fTouchEntry ); // // Cache bucket retrieval // inline PLRU_CACHE_BUCKET BucketFromIdentifier ( IN PCRYPT_DATA_BLOB pIdentifier ); // // Configuration access // // // Use the configured free function to release the // pvData in an entry // // MOTE: This is called from the CLruEntry destructor // inline VOID FreeEntryData (IN LPVOID pvData); // // Access the configuration flags // inline DWORD Flags (); // // Usage clock access // inline VOID IncrementUsageClock (); inline DWORD UsageClock (); // // Walk all cache entries // VOID WalkEntries (IN PFN_WALK_ENTRIES pfnWalk, IN LPVOID pvParameter); private: // // Cache configuration // LRU_CACHE_CONFIG m_Config; // // Cache lock // CRITICAL_SECTION m_Lock; // // Entry count // DWORD m_cEntries; // // Cache Buckets // PLRU_CACHE_BUCKET m_aBucket; // // Usage clock // DWORD m_UsageClock; // // LRU disabled count // DWORD m_cLruDisabled; // // Private methods // VOID RemoveEntryFromBucket ( IN PLRU_CACHE_BUCKET pBucket, IN PCLRUENTRY pEntry, IN DWORD dwFlags, IN OPTIONAL LPVOID pvRemovalContext ); PCLRUENTRY FindNextMatchingEntryInBucket ( IN PLRU_CACHE_BUCKET pBucket, IN PCLRUENTRY pCurrent, IN PCRYPT_DATA_BLOB pIdentifier, IN BOOL fTouchEntry ); VOID PurgeLeastRecentlyUsed (IN OPTIONAL LPVOID pvLruRemovalContext); inline VOID TouchEntryNoLock (IN PCLRUENTRY pEntry, IN DWORD dwFlags); }; // // Inline functions // //+--------------------------------------------------------------------------- // // Member: CLruEntry::AddRef, public // // Synopsis: increment entry reference count // //---------------------------------------------------------------------------- inline VOID CLruEntry::AddRef () { InterlockedIncrement( (LONG *)&m_cRefs ); } //+--------------------------------------------------------------------------- // // Member: CLruEntry::Release, public // // Synopsis: decrement entry reference count and if count goes to zero // free the entry // //---------------------------------------------------------------------------- inline VOID CLruEntry::Release () { if ( InterlockedDecrement( (LONG *)&m_cRefs ) == 0 ) { delete this; } } //+--------------------------------------------------------------------------- // // Member: CLruEntry::Cache, public // // Synopsis: return the internal cache pointer // //---------------------------------------------------------------------------- inline PCLRUCACHE CLruEntry::Cache () { return( m_pCache ); } //+--------------------------------------------------------------------------- // // Member: CLruEntry::Bucket, public // // Synopsis: return the internal cache bucket pointer // //---------------------------------------------------------------------------- inline PLRU_CACHE_BUCKET CLruEntry::Bucket () { return( m_pBucket ); } //+--------------------------------------------------------------------------- // // Member: CLruEntry::Identifier, public // // Synopsis: return the internal entry identifier // //---------------------------------------------------------------------------- inline PCRYPT_DATA_BLOB CLruEntry::Identifier () { return( &m_Identifier ); } //+--------------------------------------------------------------------------- // // Member: CLruEntry::Data, public // // Synopsis: return the internal entry data // //---------------------------------------------------------------------------- inline LPVOID CLruEntry::Data () { return( m_pvData ); } //+--------------------------------------------------------------------------- // // Member: CLruEntry::SetPrevPointer, public // // Synopsis: set the previous entry pointer // //---------------------------------------------------------------------------- inline VOID CLruEntry::SetPrevPointer (IN PCLRUENTRY pPrevEntry) { m_pPrevEntry = pPrevEntry; } //+--------------------------------------------------------------------------- // // Member: CLruEntry::SetNextPointer, public // // Synopsis: set the next entry pointer // //---------------------------------------------------------------------------- inline VOID CLruEntry::SetNextPointer (IN PCLRUENTRY pNextEntry) { m_pNextEntry = pNextEntry; } //+--------------------------------------------------------------------------- // // Member: CLruEntry::PrevPointer, public // // Synopsis: return the previous entry pointer // //---------------------------------------------------------------------------- inline PCLRUENTRY CLruEntry::PrevPointer () { return( m_pPrevEntry ); } //+--------------------------------------------------------------------------- // // Member: CLruEntry::NextPointer, public // // Synopsis: return the next entry pointer // //---------------------------------------------------------------------------- inline PCLRUENTRY CLruEntry::NextPointer () { return( m_pNextEntry ); } //+--------------------------------------------------------------------------- // // Member: CLruEntry::SetUsage, public // // Synopsis: set the usage on the entry object and on // the corresponding cache bucket // //---------------------------------------------------------------------------- inline VOID CLruEntry::SetUsage (IN DWORD Usage) { m_Usage = Usage; m_pBucket->Usage = Usage; } //+--------------------------------------------------------------------------- // // Member: CLruEntry::Usage, public // // Synopsis: return the internal entry usage // //---------------------------------------------------------------------------- inline DWORD CLruEntry::Usage () { return( m_Usage ); } //+--------------------------------------------------------------------------- // // Member: CLruEntry::OnCacheDestruction, public // // Synopsis: cleanup reference to cache that is being destroyed // //---------------------------------------------------------------------------- inline VOID CLruEntry::OnCacheDestruction () { m_pCache = NULL; m_pBucket = NULL; } //+--------------------------------------------------------------------------- // // Member: CLruCache::LockCache, public // // Synopsis: acquire the cache lock // //---------------------------------------------------------------------------- inline VOID CLruCache::LockCache () { if ( m_Config.dwFlags & LRU_CACHE_NO_SERIALIZE ) { return; } EnterCriticalSection( &m_Lock ); } //+--------------------------------------------------------------------------- // // Member: CLruCache::UnlockCache, public // // Synopsis: release the cache lock // //---------------------------------------------------------------------------- inline VOID CLruCache::UnlockCache () { if ( m_Config.dwFlags & LRU_CACHE_NO_SERIALIZE ) { return; } LeaveCriticalSection( &m_Lock ); } //+--------------------------------------------------------------------------- // // Member: CLruCache::BucketFromIdentifier, public // // Synopsis: retrieve the associated cache bucket given the entry identifier // //---------------------------------------------------------------------------- inline PLRU_CACHE_BUCKET CLruCache::BucketFromIdentifier ( IN PCRYPT_DATA_BLOB pIdentifier ) { DWORD Hash = ( *m_Config.pfnHash )( pIdentifier ); return( &m_aBucket[ Hash % m_Config.cBuckets ] ); } //+--------------------------------------------------------------------------- // // Member: CLruCache::FreeEntryData, public // // Synopsis: free the data using the configured free function // //---------------------------------------------------------------------------- inline VOID CLruCache::FreeEntryData (IN LPVOID pvData) { if ( m_Config.pfnFree != NULL ) { ( *m_Config.pfnFree )( pvData ); } } //+--------------------------------------------------------------------------- // // Member: CLruCache::Flags, public // // Synopsis: access the configured flags // //---------------------------------------------------------------------------- inline DWORD CLruCache::Flags () { return( m_Config.dwFlags ); } //+--------------------------------------------------------------------------- // // Member: CLruCache::IncrementUsageClock, public // // Synopsis: increment the usage clock // //---------------------------------------------------------------------------- inline VOID CLruCache::IncrementUsageClock () { m_UsageClock += 1; } //+--------------------------------------------------------------------------- // // Member: CLruCache::UsageClock, public // // Synopsis: return the usage clock value // //---------------------------------------------------------------------------- inline DWORD CLruCache::UsageClock () { return( m_UsageClock ); } //+--------------------------------------------------------------------------- // // Member: CLruCache::TouchEntryNoLock, public // // Synopsis: touch entry without taking the cache lock // //---------------------------------------------------------------------------- inline VOID CLruCache::TouchEntryNoLock (IN PCLRUENTRY pEntry, IN DWORD dwFlags) { if ( !( dwFlags & LRU_SUPPRESS_CLOCK_UPDATE ) ) { IncrementUsageClock(); } pEntry->SetUsage( UsageClock() ); } #endif