windows-nt/Source/XPSP1/NT/inetsrv/iis/staxinc/cachex.h
2020-09-26 16:20:57 +08:00

495 lines
10 KiB
C++

/*++
Cachex.h
This file defines some templates which implement
a generic cache manager.
In order to use the Cache manager, your class must
have the following :
//
// SampleClass derives from CRefCount as smart pointers
// 'CRefPtr<Data>' are used to manage the life time of cached
// objects.
//
class SampleClass : public CRefCount {
//
// Cached class has a constructor which takes two
// arguments, the Key used to find the Data in the Cache
// and the 'Constructor' (which is a type specified in
// the cache template) which contains whatever
// initialization data that needs to be passed.
//
// The Cached class should do minimal work within the
// constructor. The FindOrCreate() function will also
// call an innitialization class which finishes initialization
// of the object.
//
SampleClass( Key& k, Constructor &constructor ) ;
//
// If the Cached class does not do all of its initialization
// in its Constructor, then The ExclusiveLock() function must
// guarantee that no clients can use the object untill the
// lock is released.
//
// If the Cached class is completely initialized after the
// constructor is called then this can be a no-op function.
//
ExclusiveLock() ;
//
// After this is called clients may use the object.
//
ExclusiveUnlock() ;
//
// The Init() function is called by FindOrCreate()
// after the contructor has been invoked. This function
// must complete any initialization required.
//
// Member functions are called by FindOrCreate() in this order :
//
// SampleClass() // Constructor is called
// ExclusiveLock()
// Init()
// ExclusiveUnlock()
//
// All Cache Client code must be able to deal with objects
// returned from the cache which failed initialization for
// whatever reason.
//
BOOL Init( Constructor& constructor ) ;
//
// This function must return a reference to the
// Key value stored within the data.
//
void GetKey(Key& key) ;
//
// Must return non-zero if the provided Key matches
// the one stored in the data .
//
int MatchKey( Key& ) ;
} ;
--*/
#ifndef _CACHEX_H_
#define _CACHEX_H_
#ifndef _ASSERT
#define _ASSERT(x) if(!(x)) DebugBreak() ; else
#endif
// This callback function is used to issue a stop hint during a
// long spin while shutting down so that the shutdown won't time
// out.
typedef void (*PSTOPHINT_FN)();
//
// cacheint.h includes all the necessary helper classes
// etc... that make the general cache engine work !
//
//
#include "cacheinx.h"
//
// Utility class for those which wish to have pools of locks for
// their objects !
//
class CLockPool {
private :
//
// Array of locks to share amongst Xover data structures
//
_CACHELOCK m_locks[256] ;
//
//
//
long m_lockIndex ;
public :
_CACHELOCK* AllocateLock() {
return &m_locks[ DWORD(InterlockedIncrement( &m_lockIndex )) % 256 ] ;
}
} ;
//
// CacheCallback class - clients can pass an object derived from
// this into the Cache for functions which require some kind of user
// callback processing !
//
template < class Data >
class CacheCallback {
public :
virtual BOOL fRemoveCacheItem( Data* d ) {
return FALSE ;
}
} ;
//
// Call these functions to initialize the Cache Library
//
extern BOOL __stdcall CacheLibraryInit() ;
extern BOOL __stdcall CacheLibraryTerm() ;
template < class Data,
class Key,
class KEYREF, /* This is the type used to point or reference items in the cache*/
class Constructor,
BOOL fAtomic = TRUE
>
class Cache : public CScheduleThread,
CacheTable {
private :
//
// Define a 'CACHEENTRY' object which holds all the
// necessary data for each object which is placed in the cache !
//
typedef CacheEntry< Data, Key, KEYREF, fAtomic > CACHEENTRY ;
//
// Define callback objects for Expunge Operations.
//
typedef CacheCallback< Data > CALLBACKOBJ;
//
// Is the 'Cache' initialized and in a valid state !
//
BOOL m_fValid ;
//
// A list of everything in the Cache, used for TTL processing
//
CacheList m_ExpireList ;
//
// A hash table we use to find things within the Cache
//
TFHashEx< CACHEENTRY, Key, KEYREF > m_Lookup ;
//
// Pointer to a runtime-user provided function which is used
// to determine what things should be removed from the Cache
//
BOOL (* m_pfnExpungeSpecific )( Data & ) ;
//
// Pointer to a runtime-user provided object derived from CacheCallback< Data >
// which lets the user invoke some function for each item in the Cache !
//
CALLBACKOBJ* m_pCallbackObject ;
//
// Reader writer lock which protects all these data structures !
//
_CACHELOCK m_Lock ;
//
// The initial TTL we should assign to all newly cached objects !
//
DWORD m_TTL ;
protected :
//
// Virtual function called by CScheduleThread's thread which
// we use to bump TTL counters
//
void
Schedule();
//
// Function which removes an Entry from the Cache !
//
BOOL
RemoveEntry(
CacheState* pEntry
) ;
//
// Virtual Function called by CacheList when we pass call
// CacheList::ExpungeSpecific
//
BOOL
QueryRemoveEntry(
CacheState* pEntry
) ;
//
// Function which can remove a specific item from the Cache
// or walk the Cache deleting all the expired items.
//
//
BOOL
ExpungeInternal(
KEYREF key,
CACHEENTRY* pData = 0,
BOOL fIgnoreKey = TRUE,
const CACHEENTRY* pProtected = 0,
BOOL fDoCheap = FALSE
) ;
public :
//
// INTERNAL API's - These are public for convenience - not intended
// for Use outside of cachelib !!
//
//
// Either find an item in the cache or Construct a new item
// and place it in the Cache.
// return the result through pDataOut no matter what !
//
BOOL
FindOrCreateInternal(
DWORD dwHash,
KEYREF key,
Constructor& constructor,
CRefPtr< Data >& pDataOut
) ;
//
// Constructor - cMax specifies the maximum number of entries
// we should hold in the cache.
//
Cache( ) ;
//
// Destructor - remove ourselves from schedule list before continuing !
//
~Cache() ;
//
// Initialization function - take pointer to function
// which should be used to compute hash values on Key's
// Also takes the number of seconds objects should live in
// the cache !
//
BOOL
Init(
DWORD (*pfnHash)( KEYREF ),
DWORD dwLifetimeSeconds,
DWORD cMaxInstances,
PSTOPHINT_FN pfnStopHint = NULL
) ;
//
// Function which can be used to remove items from the Cache
// If default args are used we pick an expired item in the Cache
// to remove
//
BOOL
Expunge(
KEYREF key,
CACHEENTRY* pData = 0,
BOOL fIgnoreKey = TRUE
) ;
//
// Function which can be passed a function pointer to determine
// exactly what items are to be removed from the Cache.
// if fForced == TRUE then items are removed from the Cache
// no matter what.
//
BOOL
ExpungeSpecific(
CALLBACKOBJ* pCallback,
BOOL fForced
) ;
//
// Either find an item in the cache or Construct a new item
// and place it in the Cache.
// return the result through pDataOut no matter what !
//
BOOL
FindOrCreate(
KEYREF key,
Constructor& constructor,
CRefPtr< Data >& pDataOut
) ;
#ifdef DEBUG
static long s_cCreated ;
#endif
} ;
template < class Data,
class Key,
class KEYREF, /* This is the type used to point or reference items in the cache*/
class Constructor,
BOOL fAtomic = TRUE
>
class MultiCache {
private :
//
// Define a 'CACHEENTRY' object which holds all the
// necessary data for each object which is placed in the cache !
//
typedef CacheEntry< Data, Key, KEYREF, fAtomic > CACHEENTRY ;
//
// Define the type for a single instance !
//
typedef Cache< Data, Key, KEYREF, Constructor, fAtomic > CACHEINSTANCE ;
//
// Is the 'Cache' initialized and in a valid state !
//
BOOL m_fValid ;
//
// Pointer to the various Cache's we subdivide our work into
//
CACHEINSTANCE *m_pCaches ;
//
// Number of sub cache's we use to split up the work !
//
DWORD m_cSubCaches ;
//
// We use the hash function to choose which of our subcaches to work with !
//
DWORD (*m_pfnHash)( KEYREF ) ;
//
// Return the correct cache instance to hold the selected piece of data !
//
//DWORD ChooseInstance( Key& k ) ;
DWORD ChooseInstance( DWORD dwHash ) ;
public :
//
// Define callback objects for Expunge Operations.
//
typedef CacheCallback< Data > CALLBACKOBJ;
//
// Constructor - cMax specifies the maximum number of entries
// we should hold in the cache.
//
MultiCache( ) ;
//
// Destructor - destroys are various sub cache's
//
~MultiCache() ;
//
// Initialization function - take pointer to function
// which should be used to compute hash values on Key's
// Also takes the number of seconds objects should live in
// the cache !
//
BOOL
Init(
DWORD (*pfnHash)( KEYREF ),
DWORD dwLifetimeSeconds,
DWORD cSubCaches,
DWORD cMaxElements,
PSTOPHINT_FN pfnStopHint = NULL
) ;
//
// Function which can be used to remove items from the Cache
// If default args are used we pick an expired item in the Cache
// to remove
//
BOOL
Expunge(
KEYREF key,
CACHEENTRY* pData = 0,
BOOL fExpungeAll = FALSE
) ;
//
// Function which can be passed a function pointer to determine
// exactly what items are to be removed from the Cache.
// if fForced == TRUE then items are removed from the Cache
// no matter what.
//
BOOL
ExpungeSpecific(
CALLBACKOBJ* pCallback,
BOOL fForced
) ;
//
// Either find an item in the cache or Construct a new item
// and place it in the Cache.
// return the result through pDataOut no matter what !
//
BOOL
FindOrCreate(
KEYREF key,
Constructor& constructor,
CRefPtr< Data >& pDataOut
) ;
//
// Either find an item in the cache or Construct a new item
// and place it in the Cache.
// return the result through pDataOut no matter what !
// NOTE : This is for use when the caller has a cheaper
// way to compute the hash value then us - in debug we
// need to assure that the caller correctly computes this !
//
BOOL
FindOrCreate(
KEYREF key,
DWORD dwHash,
Constructor& constructor,
CRefPtr< Data >& pDataOut
) ;
} ;
#include "cacheimx.h"
#endif // _CACHEX_H_