547 lines
11 KiB
C
547 lines
11 KiB
C
|
/*++
|
||
|
|
||
|
CacheMt.h
|
||
|
|
||
|
This header file defines a template for
|
||
|
|
||
|
|
||
|
|
||
|
--*/
|
||
|
|
||
|
|
||
|
#ifndef _CACHEMT_H_
|
||
|
#define _CACHEMT_H_
|
||
|
|
||
|
|
||
|
// 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)();
|
||
|
|
||
|
#include "smartptr.h"
|
||
|
#include <fhashex.h>
|
||
|
#include <mtlib.h>
|
||
|
#include "cachemti.h"
|
||
|
|
||
|
|
||
|
//
|
||
|
// This is a little helper function for _ASSERT's - returns
|
||
|
// TRUE if lpv is an address on the calling thread's stack !
|
||
|
//
|
||
|
BOOL
|
||
|
FOnMyStack( LPVOID lpv ) ;
|
||
|
|
||
|
|
||
|
//
|
||
|
// 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 ;
|
||
|
}
|
||
|
} ;
|
||
|
|
||
|
template< class Data,
|
||
|
class Key,
|
||
|
class Constructor
|
||
|
>
|
||
|
class CacheImp : public CacheSelector
|
||
|
{
|
||
|
//
|
||
|
// This class exists to implement a generic Caching system.
|
||
|
// We assume that only a single thread ever enters any of our
|
||
|
// API's at a time. This class is not to be directly exposed
|
||
|
// to customers, instead CacheInterface<> exists to provide
|
||
|
// an API for customers.
|
||
|
//
|
||
|
|
||
|
public :
|
||
|
//
|
||
|
// Defines an element of the cache !
|
||
|
//
|
||
|
typedef TEntry< Data, Key > TENTRY ;
|
||
|
|
||
|
private :
|
||
|
//
|
||
|
// A signature DWORD for identifying these things in memory !
|
||
|
//
|
||
|
DWORD m_dwSignature ;
|
||
|
|
||
|
//
|
||
|
// Define the hashtable we use to hold Cache Elements !
|
||
|
//
|
||
|
typedef TFHashEx< TENTRY, Key > CACHELOOKUP ;
|
||
|
|
||
|
//
|
||
|
// The hash table we use to keep track of entries in the cache !
|
||
|
//
|
||
|
CACHELOOKUP m_Lookup ;
|
||
|
|
||
|
//
|
||
|
// This is the doubly linked list of elements in our cache !
|
||
|
//
|
||
|
CacheList m_ExpireList ;
|
||
|
|
||
|
//
|
||
|
// The number of subtract from the current time to
|
||
|
// determine our expire date !
|
||
|
//
|
||
|
ULARGE_INTEGER m_qwExpire ;
|
||
|
|
||
|
public :
|
||
|
|
||
|
//
|
||
|
// The following structures and functions define the
|
||
|
// portion of our interface designed to work with ASYNC
|
||
|
// mechanisms provide by TMtService<>
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// Defines the structure that holds all of the
|
||
|
// arguments for FindOrCreate
|
||
|
// We wrap this stuff all into one struct to make it
|
||
|
// easy to use the TMtServce<> family of templates !
|
||
|
//
|
||
|
struct FORC_ARG {
|
||
|
DWORD m_dwHash ;
|
||
|
Key& m_key ;
|
||
|
Constructor& m_constructor ;
|
||
|
FORC_ARG( DWORD dw,
|
||
|
Key& key,
|
||
|
Constructor& constructor
|
||
|
) :
|
||
|
m_dwHash( dw ),
|
||
|
m_key( key ),
|
||
|
m_constructor( constructor ) {
|
||
|
}
|
||
|
} ;
|
||
|
|
||
|
//
|
||
|
// Define the object that selects items for removal from the
|
||
|
// Cache -
|
||
|
//
|
||
|
typedef CacheCallback< Data > CCB_OBJ ;
|
||
|
|
||
|
//
|
||
|
// Arguments for Expunge !
|
||
|
//
|
||
|
struct EXP_ARG {
|
||
|
Key* m_pkey ;
|
||
|
TENTRY* m_pData ;
|
||
|
EXP_ARG( Key* pkey, TENTRY* pData ) :
|
||
|
m_pkey( pkey ),
|
||
|
m_pData( pData ) {
|
||
|
}
|
||
|
} ;
|
||
|
|
||
|
//
|
||
|
// Define the structure that holds all arguments for
|
||
|
// Expunge interface.
|
||
|
//
|
||
|
struct EXP_SPECIFIC_ARG {
|
||
|
//
|
||
|
// The object which selects what is to be removed from the cache
|
||
|
//
|
||
|
CCB_OBJ* m_pCacheCallback ;
|
||
|
//
|
||
|
// A pointer to an entry which should NOT be removed !
|
||
|
//
|
||
|
TENTRY* m_pProtected ;
|
||
|
//
|
||
|
// If TRUE kick things out even if they aren't ready to expire !
|
||
|
//
|
||
|
BOOL m_fForced ;
|
||
|
|
||
|
EXP_SPECIFIC_ARG( CCB_OBJ* pCallback,
|
||
|
TENTRY* pProtected,
|
||
|
BOOL fForced
|
||
|
) :
|
||
|
m_pCacheCallback( pCallback ),
|
||
|
m_pProtected( pProtected ),
|
||
|
m_fForced( fForced ) {
|
||
|
}
|
||
|
} ;
|
||
|
|
||
|
protected :
|
||
|
//
|
||
|
// When Executing ExpungeSpecific() - this holds onto the user
|
||
|
// provided Callback for selecting deleted items !
|
||
|
//
|
||
|
CCB_OBJ* m_pCurrent ;
|
||
|
|
||
|
//
|
||
|
// This member function removes entries from the cache -
|
||
|
// we remove them from the hash table which leads to destruction !
|
||
|
//
|
||
|
void
|
||
|
RemoveEntry(
|
||
|
CacheState* pCacheState
|
||
|
) ;
|
||
|
//
|
||
|
// This function checks to see whether we wish to remove an element !
|
||
|
//
|
||
|
BOOL
|
||
|
QueryRemoveEntry(
|
||
|
CacheState* pState
|
||
|
) ;
|
||
|
|
||
|
//
|
||
|
// FindOrCreate results
|
||
|
//
|
||
|
typedef CRefPtr< Data > FORC_RES ;
|
||
|
|
||
|
public :
|
||
|
|
||
|
CacheImp() ;
|
||
|
|
||
|
//
|
||
|
// If this function returns TRUE then callers can be
|
||
|
// notified at arbitrary times of the results.
|
||
|
// The BOOL return value is required by the TMtService templates.
|
||
|
//
|
||
|
//
|
||
|
BOOL
|
||
|
FindOrCreate(
|
||
|
FORC_ARG& args,
|
||
|
FORC_RES& result
|
||
|
) ;
|
||
|
//
|
||
|
// This function removes specified items from the cache !
|
||
|
//
|
||
|
BOOL
|
||
|
Expunge(
|
||
|
EXP_ARG& args,
|
||
|
DWORD& countExpunged
|
||
|
) ;
|
||
|
|
||
|
BOOL
|
||
|
ExpungeSpecific(
|
||
|
EXP_SPECIFIC_ARG& args,
|
||
|
DWORD& countExpunged
|
||
|
) ;
|
||
|
|
||
|
BOOL
|
||
|
Expire(
|
||
|
DWORD& countExpunged
|
||
|
) ;
|
||
|
|
||
|
//
|
||
|
// The following set of functions are for synchronous use
|
||
|
// such as Initialization and Termination of the 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)( const Key& ),
|
||
|
DWORD dwLifetimeSeconds,
|
||
|
DWORD cMaxInstances,
|
||
|
PSTOPHINT_FN pfnStopHint = NULL
|
||
|
) ;
|
||
|
|
||
|
//
|
||
|
// Compute the hash of a key - provided for debug purposes and _ASSERT's
|
||
|
// not for regular use !
|
||
|
//
|
||
|
DWORD
|
||
|
ComputeHash( Key& k ) ;
|
||
|
|
||
|
} ;
|
||
|
|
||
|
template< class Data,
|
||
|
class Key,
|
||
|
class Constructor >
|
||
|
class TAsyncCache {
|
||
|
public :
|
||
|
|
||
|
//
|
||
|
// The template class that implements the Cache.
|
||
|
//
|
||
|
typedef CacheImp< Data, Key, Constructor > IMP ;
|
||
|
|
||
|
private:
|
||
|
|
||
|
//
|
||
|
// Singature for identifying these Async Cache things
|
||
|
//
|
||
|
DWORD m_dwSignature ;
|
||
|
|
||
|
//
|
||
|
// This is the object which actually implements the Cache functionality
|
||
|
// NOTE: appears before CACHE_SERVICE so its constructor is called first !
|
||
|
//
|
||
|
IMP m_Implementation ;
|
||
|
|
||
|
public :
|
||
|
|
||
|
//
|
||
|
// A typedef for the objects we will take in our
|
||
|
// interface which get completion notifications.
|
||
|
//
|
||
|
typedef TCompletion< IMP::FORC_RES > COMP_OBJ ;
|
||
|
|
||
|
//
|
||
|
// A typedef for the objects which handle Expunge Completions !
|
||
|
// The completion function gets the number of objects expunged
|
||
|
// from the cache !
|
||
|
//
|
||
|
typedef TCompletion< DWORD > EXP_COMP_OBJ ;
|
||
|
|
||
|
//
|
||
|
// Some typedefs so that users can extract our template parameters
|
||
|
// back out !
|
||
|
//
|
||
|
typedef Data CACHEDATA ;
|
||
|
typedef Key CACHEKEY ;
|
||
|
|
||
|
private :
|
||
|
//
|
||
|
// The kind of object we use to encapsulate a call
|
||
|
// to the cache.
|
||
|
//
|
||
|
typedef TMFnDelay<
|
||
|
IMP,
|
||
|
IMP::FORC_RES,
|
||
|
IMP::FORC_ARG
|
||
|
> CACHE_CREATE_CALL ;
|
||
|
|
||
|
//
|
||
|
// The kind of object we use to encapsulate an Expunge Call
|
||
|
//
|
||
|
typedef TMFnDelay<
|
||
|
IMP,
|
||
|
DWORD,
|
||
|
IMP::EXP_ARG
|
||
|
> EXPUNGE_CALL ;
|
||
|
|
||
|
typedef TMFnDelay<
|
||
|
IMP,
|
||
|
DWORD,
|
||
|
IMP::EXP_SPECIFIC_ARG
|
||
|
> EXPUNGE_SPECIFIC ;
|
||
|
|
||
|
typedef TMFnNoArgDelay<
|
||
|
IMP,
|
||
|
DWORD
|
||
|
> EXPIRE_CALL ;
|
||
|
|
||
|
//
|
||
|
// Define the type of our CACHE_SERVICE
|
||
|
//
|
||
|
typedef TMtService< IMP > CACHE_SERVICE ;
|
||
|
|
||
|
//
|
||
|
// This is the object which manages the Queue of Async Cache requests !
|
||
|
//
|
||
|
CACHE_SERVICE m_Service ;
|
||
|
|
||
|
//
|
||
|
// Set to TRUE if we have been successfully initialized.
|
||
|
//
|
||
|
BOOL m_fGood ;
|
||
|
|
||
|
public :
|
||
|
|
||
|
//
|
||
|
// Default constructor
|
||
|
//
|
||
|
TAsyncCache() ;
|
||
|
|
||
|
//
|
||
|
// Find an Item in the Cache or Create an Item to be held in the Cache !
|
||
|
//
|
||
|
BOOL
|
||
|
FindOrCreate( CStateStackInterface& allocator,
|
||
|
DWORD dwHash,
|
||
|
Key& key,
|
||
|
Constructor& constructor,
|
||
|
COMP_OBJ* pComplete ) ;
|
||
|
|
||
|
//
|
||
|
// Remove an Item from the cache !
|
||
|
//
|
||
|
//
|
||
|
// Function which can be used to remove items from the Cache
|
||
|
//
|
||
|
BOOL
|
||
|
Expunge(
|
||
|
CStateStackInterface& allocator,
|
||
|
EXP_COMP_OBJ* pComplete,
|
||
|
Key* key = 0,
|
||
|
IMP::TENTRY* pData = 0
|
||
|
) ;
|
||
|
|
||
|
//
|
||
|
// 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(
|
||
|
CStateStackInterface& allocator,
|
||
|
EXP_COMP_OBJ* pComplete,
|
||
|
class CacheCallback< Data >* pSelector,
|
||
|
BOOL fForced,
|
||
|
TEntry<Data,Key>* pProtected = 0
|
||
|
) ;
|
||
|
|
||
|
//
|
||
|
// Expire old stuff in the cache - everything older than
|
||
|
// dwLifetimeSeconds (specified at Init() time
|
||
|
// which is NOT in use should be kicked out.
|
||
|
//
|
||
|
BOOL
|
||
|
Expire(
|
||
|
CStateStackInterface& allocator,
|
||
|
EXP_COMP_OBJ* pComplete
|
||
|
) ;
|
||
|
|
||
|
//
|
||
|
// 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)( const Key& ),
|
||
|
DWORD dwLifetimeSeconds,
|
||
|
DWORD cMaxInstances,
|
||
|
PSTOPHINT_FN pfnStopHint = NULL
|
||
|
) ;
|
||
|
} ;
|
||
|
|
||
|
|
||
|
template< class Data,
|
||
|
class Key,
|
||
|
class Constructor
|
||
|
>
|
||
|
class TMultiAsyncCache {
|
||
|
private :
|
||
|
|
||
|
typedef TAsyncCache< Data, Key, Constructor > ASYNCCACHEINSTANCE ;
|
||
|
|
||
|
//
|
||
|
// Signature for these objects in memory !
|
||
|
//
|
||
|
DWORD m_dwSignature ;
|
||
|
|
||
|
//
|
||
|
// Array of Caches to use for client requests
|
||
|
//
|
||
|
ASYNCCACHEINSTANCE* m_pCaches ;
|
||
|
|
||
|
//
|
||
|
// Number of ASYNCCACHEINSTANCE objects pointed to be m_pCaches !
|
||
|
//
|
||
|
DWORD m_cSubCaches ;
|
||
|
|
||
|
//
|
||
|
// The Hash Function to be used !
|
||
|
//
|
||
|
DWORD (*m_pfnHash)( const Key& ) ;
|
||
|
|
||
|
//
|
||
|
// Function which computes which of our child caches to use !
|
||
|
//
|
||
|
DWORD
|
||
|
ChooseInstance( DWORD dwHash ) ;
|
||
|
|
||
|
public :
|
||
|
|
||
|
typedef ASYNCCACHEINSTANCE::COMP_OBJ COMP_OBJ ;
|
||
|
typedef ASYNCCACHEINSTANCE::EXP_COMP_OBJ EXP_COMP_OBJ ;
|
||
|
|
||
|
TMultiAsyncCache() ;
|
||
|
~TMultiAsyncCache() ;
|
||
|
|
||
|
//
|
||
|
// 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 cCaches,
|
||
|
DWORD (*pfnHash)( const Key& ),
|
||
|
DWORD dwLifetimeSeconds,
|
||
|
DWORD cMaxInstances,
|
||
|
PSTOPHINT_FN pfnStopHint = NULL
|
||
|
) ;
|
||
|
|
||
|
//
|
||
|
// Find an Item in the Cache or Create an Item to be held in the Cache !
|
||
|
//
|
||
|
BOOL
|
||
|
FindOrCreate( CStateStackInterface& allocator,
|
||
|
DWORD dwHash,
|
||
|
Key& key,
|
||
|
Constructor& constructor,
|
||
|
COMP_OBJ* pComplete ) ;
|
||
|
|
||
|
//
|
||
|
//
|
||
|
//
|
||
|
BOOL
|
||
|
FindOrCreate( CStateStackInterface& allocator,
|
||
|
Key& key,
|
||
|
Constructor& constructor,
|
||
|
COMP_OBJ* pComplete
|
||
|
) ;
|
||
|
|
||
|
//
|
||
|
// Remove an Item from the cache !
|
||
|
//
|
||
|
//
|
||
|
// Function which can be used to remove items from the Cache
|
||
|
//
|
||
|
BOOL
|
||
|
Expunge(
|
||
|
CStateStackInterface& allocator,
|
||
|
EXP_COMP_OBJ* pComplete,
|
||
|
Key* key = 0
|
||
|
) ;
|
||
|
|
||
|
//
|
||
|
// 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(
|
||
|
CStateStackInterface& allocator,
|
||
|
EXP_COMP_OBJ* pComplete,
|
||
|
class CacheCallback< Data >* pSelector,
|
||
|
BOOL fForced
|
||
|
) ;
|
||
|
|
||
|
//
|
||
|
// Expire old stuff in the cache - everything older than
|
||
|
// dwLifetimeSeconds (specified at Init() time
|
||
|
// which is NOT in use should be kicked out.
|
||
|
//
|
||
|
BOOL
|
||
|
Expire(
|
||
|
CStateStackInterface& allocator,
|
||
|
EXP_COMP_OBJ* pComplete
|
||
|
) ;
|
||
|
} ;
|
||
|
|
||
|
#include "cachemtx.h"
|
||
|
|
||
|
#endif // _CACHEMT_H_
|
||
|
|
||
|
|