Leaked source code of windows server 2003
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.
 
 
 
 
 
 

936 lines
17 KiB

/*++
Copyright (C) 1996-2001 Microsoft Corporation
Module Name:
Cache.H
Abstract:
History:
--*/
#ifndef _Cache_H
#define _Cache_H
#include <Allocator.h>
#include <Algorithms.h>
#include <TPQueue.h>
#include <AvlTree.h>
#include <lockst.h>
template<typename T>
class AutoLockGuard
{
T& m_lock;
int m_lockCount;
public:
AutoLockGuard(T& target);
~AutoLockGuard();
void Lock();
void UnLock();
};
template<typename T>
AutoLockGuard<T>::AutoLockGuard(T& target): m_lock(target), m_lockCount(0)
{
Lock();
}
template<typename T>
AutoLockGuard<T>::~AutoLockGuard()
{
if (m_lockCount) UnLock();
}
template<typename T>
void AutoLockGuard<T>::Lock()
{
_DBG_ASSERT(m_lockCount == 0);
m_lock.Lock();
m_lockCount++;
}
template<typename T>
void AutoLockGuard<T>::UnLock()
{
_DBG_ASSERT(m_lockCount > 0);
m_lock.UnLock();
m_lockCount--;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
template <class WmiKey>
class WmiCacheController : public IUnknown
{
public:
class WmiUniqueTimeout
{
private:
ULONG m_Ticks ;
LONG m_Counter ;
public:
WmiUniqueTimeout () : m_Ticks ( 0 ) , m_Counter ( 0 ) { ; }
WmiUniqueTimeout (
const ULONG &a_Ticks ,
const LONG &a_Counter
) : m_Ticks ( a_Ticks ) ,
m_Counter ( a_Counter )
{ ; }
ULONG GetTicks () const { return m_Ticks ; }
LONG GetCounter () const { return m_Counter ; }
friend bool operator == ( const WmiUniqueTimeout &a_Arg1 , const WmiUniqueTimeout &a_Arg2 )
{
LONG t_Compare ;
if ( ( t_Compare = a_Arg1.GetTicks () - a_Arg2.GetTicks () ) == 0 )
{
t_Compare = a_Arg1.GetCounter () - a_Arg2.GetCounter () ;
}
return t_Compare == 0 ? true : false ;
}
friend bool operator < ( const WmiUniqueTimeout &a_Arg1 , const WmiUniqueTimeout &a_Arg2 )
{
LONG t_Compare ;
if ( ( t_Compare = a_Arg1.GetTicks () - a_Arg2.GetTicks () ) == 0 )
{
t_Compare = a_Arg1.GetCounter () - a_Arg2.GetCounter () ;
}
return t_Compare < 0 ? true : false ;
}
} ;
class WmiCacheElement : public IUnknown
{
private:
LONG m_ReferenceCount ;
LONG m_InternalReferenceCount ;
LONG m_NonCylicReferenceCount ;
BOOL m_Decaying ;
BOOL m_Cached ;
BOOL m_Decayed ;
ULONG m_CallBackInternalRelease ;
WmiCacheController <WmiKey> *m_Controller ;
WmiKey m_Key ;
ULONG m_Period ;
public:
WmiCacheElement () :
m_ReferenceCount ( 0 ) ,
m_InternalReferenceCount ( 0 ) ,
m_NonCylicReferenceCount ( 0 ) ,
m_Controller ( NULL ) ,
m_Period ( 0 ) ,
m_Decaying ( FALSE ) ,
m_Decayed ( FALSE ) ,
m_Cached ( FALSE ) ,
m_CallBackInternalRelease ( 1 )
{
}
WmiCacheElement (
WmiCacheController <WmiKey> *a_Controller ,
const WmiKey &a_Key ,
const ULONG &a_Period
) : m_ReferenceCount ( 0 ) ,
m_InternalReferenceCount ( 0 ) ,
m_NonCylicReferenceCount ( 0 ) ,
m_Controller ( a_Controller ) ,
m_Period ( a_Period ) ,
m_Decaying ( FALSE ) ,
m_Decayed ( FALSE ) ,
m_Cached ( FALSE ) ,
m_CallBackInternalRelease ( 1 )
{
m_Key = a_Key ;
if ( m_Controller )
{
m_Controller->AddRef () ;
}
}
virtual ~WmiCacheElement ()
{
#if 0
wchar_t t_Buffer [ 128 ] ;
wsprintf ( t_Buffer , L"\n%lx - ~WmiCacheElement ( %lx ) " , GetTickCount () , this ) ;
OutputDebugString ( t_Buffer ) ;
#endif
#ifdef DBG
if ( m_ReferenceCount != 0 )
{
DebugBreak () ;
}
if ( m_InternalReferenceCount != 0 )
{
DebugBreak () ;
}
if ( m_NonCylicReferenceCount != 0 )
{
DebugBreak () ;
}
#endif
if ( m_Controller )
{
m_Controller->Release () ;
}
}
virtual void CallBackRelease () {} ;
virtual void CallBackInternalRelease () {} ;
virtual STDMETHODIMP QueryInterface ( REFIID , LPVOID FAR * )
{
return E_NOINTERFACE ;
}
virtual STDMETHODIMP_( ULONG ) AddRef ()
{
if ( m_Controller )
{
m_Controller->Lock () ;
}
ULONG t_ReferenceCount = InterlockedIncrement ( & m_ReferenceCount ) ;
if ( t_ReferenceCount == 1 )
{
InternalAddRef () ;
SetDecaying ( FALSE ) ;
}
if ( m_Controller )
{
m_Controller->UnLock () ;
}
return t_ReferenceCount ;
}
virtual STDMETHODIMP_( ULONG ) Release ()
{
if ( m_Controller )
{
m_Controller->Lock () ;
}
LONG t_ReferenceCount = InterlockedDecrement ( & m_ReferenceCount ) ;
if ( t_ReferenceCount == 0 )
{
CallBackRelease () ;
if ( m_Controller )
{
if ( GetCached () )
{
if ( GetDecayed () == FALSE )
{
if ( GetDecaying () == FALSE )
{
WmiStatusCode t_StatusCode = m_Controller->Decay ( *this ) ;
if ( t_StatusCode == e_StatusCode_Success )
{
SetDecaying ( TRUE ) ;
}
}
}
t_ReferenceCount = UnLockedInternalRelease () ;
}
else
{
t_ReferenceCount = UnLockedInternalRelease () ;
}
}
else
{
t_ReferenceCount = UnLockedInternalRelease () ;
}
}
else
{
#ifdef DBG
if ( t_ReferenceCount < 0 )
{
DebugBreak () ;
}
#endif
if ( m_Controller )
{
m_Controller->UnLock () ;
}
}
return t_ReferenceCount ;
}
STDMETHODIMP_( ULONG ) InternalAddRef ()
{
ULONG t_ReferenceCount = InterlockedIncrement ( & m_InternalReferenceCount ) ;
if ( t_ReferenceCount == 1 )
{
NonCyclicAddRef () ;
}
return t_ReferenceCount ;
}
STDMETHODIMP_( ULONG ) UnLockedInternalRelease ()
{
LONG t_ReferenceCount = InterlockedDecrement ( & m_InternalReferenceCount ) ;
if ( t_ReferenceCount == 0 )
{
BOOL t_DoCallBack = m_CallBackInternalRelease ;
m_CallBackInternalRelease = 0xbabab1ac ;
if ( GetCached () )
{
m_Controller->Delete ( m_Key ) ;
SetCached ( FALSE ) ;
}
if ( m_Controller )
{
m_Controller->UnLock () ;
}
if ( t_DoCallBack == 1 )
{
CallBackInternalRelease () ;
}
else
{
#ifdef DBG
DebugBreak () ;
#endif
}
NonCyclicRelease () ;
}
else
{
#ifdef DBG
if ( t_ReferenceCount < 0 )
{
DebugBreak () ;
}
#endif
if ( m_Controller )
{
m_Controller->UnLock () ;
}
}
return t_ReferenceCount ;
}
STDMETHODIMP_( ULONG ) InternalRelease ()
{
if ( m_Controller )
{
m_Controller->Lock () ;
}
LONG t_ReferenceCount = InterlockedDecrement ( & m_InternalReferenceCount ) ;
if ( t_ReferenceCount == 0 )
{
BOOL t_DoCallBack = m_CallBackInternalRelease ;
m_CallBackInternalRelease = 0xbabab1ac ;
BOOL t_Cached = GetCached () ;
if ( t_Cached )
{
m_Controller->Delete ( m_Key ) ;
SetCached ( FALSE ) ;
}
if ( m_Controller )
{
m_Controller->UnLock () ;
}
if ( t_DoCallBack == 1 )
{
CallBackInternalRelease () ;
}
else
{
#ifdef DBG
DebugBreak () ;
#endif
}
NonCyclicRelease () ;
}
else
{
#ifdef DBG
if ( t_ReferenceCount < 0 )
{
DebugBreak () ;
}
#endif
if ( m_Controller )
{
m_Controller->UnLock () ;
}
}
return t_ReferenceCount ;
}
STDMETHODIMP_( ULONG ) NonCyclicAddRef ()
{
return InterlockedIncrement ( & m_NonCylicReferenceCount ) ;
}
STDMETHODIMP_( ULONG ) NonCyclicRelease ()
{
ULONG t_ReferenceCount = InterlockedDecrement ( & m_NonCylicReferenceCount ) ;
if ( t_ReferenceCount == 0 )
{
delete this ;
}
return t_ReferenceCount ;
}
ULONG GetPeriod ()
{
return m_Period ;
}
void SetPeriod ( const ULONG &a_Period )
{
m_Period = a_Period ;
}
WmiKey &GetKey ()
{
return m_Key ;
}
void SetKey ( const WmiKey &a_Key )
{
m_Key = a_Key ;
}
BOOL GetDecaying ()
{
return m_Decaying ;
}
BOOL GetDecayed ()
{
return m_Decayed ;
}
BOOL GetCached ()
{
return m_Cached ;
}
void SetDecayed ( BOOL a_Decayed )
{
m_Decayed = a_Decayed ;
}
void SetDecaying ( BOOL a_Decay )
{
m_Decaying = a_Decay ;
}
void SetCached ( BOOL a_Cached )
{
m_Cached = a_Cached ;
}
void SetController ( WmiCacheController <WmiKey> *a_Controller )
{
if ( m_Controller )
{
m_Controller->Release () ;
}
m_Controller = a_Controller ;
if ( m_Controller )
{
m_Controller->AddRef () ;
}
}
WmiCacheController <WmiKey> *GetController ()
{
return m_Controller ;
}
} ;
typedef WmiAvlTree <WmiKey,WmiCacheElement *> Cache ;
typedef typename Cache :: Iterator Cache_Iterator ;
private:
typedef WmiTreePriorityQueue <WmiUniqueTimeout,WmiCacheElement *> CacheDecay ;
typedef typename CacheDecay :: Iterator CacheDecay_Iterator ;
WmiAllocator &m_Allocator ;
CriticalSection m_CriticalSection ;
LONG m_ReferenceCount ;
Cache m_Cache ;
CacheDecay m_CacheDecay ;
LONG m_Counter ;
protected:
public:
WmiCacheController ( WmiAllocator &a_Allocator ) ;
virtual ~WmiCacheController () ;
virtual STDMETHODIMP QueryInterface ( REFIID , LPVOID FAR * ) ;
virtual STDMETHODIMP_( ULONG ) AddRef () ;
virtual STDMETHODIMP_( ULONG ) Release () ;
virtual WmiStatusCode Initialize () ;
virtual WmiStatusCode UnInitialize () ;
virtual WmiStatusCode Lock () ;
virtual WmiStatusCode UnLock () ;
virtual WmiStatusCode Insert (
WmiCacheElement &a_Element ,
Cache_Iterator &a_Iterator
) ;
virtual WmiStatusCode Find ( const WmiKey &a_Key , Cache_Iterator &a_Iterator ) ;
virtual WmiStatusCode Shutdown () ;
virtual WmiStatusCode Shutdown ( const WmiKey &a_Key ) ;
virtual WmiStatusCode StrobeBegin ( const ULONG &a_Timeout ) ;
virtual WmiStatusCode Strobe ( ULONG &a_NextStrobeDelta ) ;
virtual WmiStatusCode Delete ( const WmiKey &a_Key ) ;
virtual WmiStatusCode Decay (
WmiCacheElement &a_Element
) ;
WmiStatusCode GetCache ( Cache *&a_Cache )
{
a_Cache = & m_Cache ;
return e_StatusCode_Success ;
}
CriticalSection* GetCriticalSection ()
{
return &m_CriticalSection ;
}
} ;
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
template <class WmiKey>
class WmiContainerController : public IUnknown
{
public:
class WmiContainerElement : public IUnknown
{
private:
LONG m_ReferenceCount ;
LONG m_InternalReferenceCount ;
LONG m_NonCylicReferenceCount ;
BOOL m_Cached ;
WmiContainerController <WmiKey> *m_Controller ;
WmiKey m_Key ;
ULONG m_CallBackInternalRelease ;
public:
WmiContainerElement () :
m_ReferenceCount ( 0 ) ,
m_InternalReferenceCount ( 0 ) ,
m_NonCylicReferenceCount ( 0 ) ,
m_Cached ( FALSE ) ,
m_Controller ( NULL ) ,
m_CallBackInternalRelease ( 1 )
{
}
WmiContainerElement (
WmiContainerController <WmiKey> *a_Controller ,
const WmiKey &a_Key
) : m_ReferenceCount ( 0 ) ,
m_InternalReferenceCount ( 0 ) ,
m_NonCylicReferenceCount ( 0 ) ,
m_Cached ( FALSE ) ,
m_Controller ( a_Controller ) ,
m_Key ( a_Key ) ,
m_CallBackInternalRelease ( 1 )
{
if ( m_Controller )
{
m_Controller->AddRef () ;
}
}
virtual ~WmiContainerElement ()
{
#ifdef DBG
if ( m_ReferenceCount != 0 )
{
DebugBreak () ;
}
if ( m_InternalReferenceCount != 0 )
{
DebugBreak () ;
}
if ( m_NonCylicReferenceCount != 0 )
{
DebugBreak () ;
}
#endif
if ( m_Controller )
{
m_Controller->Release () ;
}
}
virtual void CallBackRelease () {} ;
virtual void CallBackInternalRelease () {} ;
virtual STDMETHODIMP QueryInterface ( REFIID , LPVOID FAR * )
{
return E_NOINTERFACE ;
}
virtual STDMETHODIMP_( ULONG ) AddRef ()
{
ULONG t_ReferenceCount = InterlockedIncrement ( & m_ReferenceCount ) ;
if ( t_ReferenceCount == 1 )
{
InternalAddRef () ;
}
return t_ReferenceCount ;
}
virtual STDMETHODIMP_( ULONG ) Release ()
{
if ( m_Controller )
{
m_Controller->Lock () ;
}
LONG t_ReferenceCount = InterlockedDecrement ( & m_ReferenceCount ) ;
if ( t_ReferenceCount == 0 )
{
CallBackRelease () ;
if ( GetCached () )
{
LONG t_ReferenceCount = InterlockedDecrement ( & m_InternalReferenceCount ) ;
}
UnLockedInternalRelease () ;
}
else
{
#ifdef DBG
if ( t_ReferenceCount < 0 )
{
DebugBreak () ;
}
#endif
if ( m_Controller )
{
m_Controller->UnLock () ;
}
}
return t_ReferenceCount ;
}
virtual STDMETHODIMP_( ULONG ) InternalAddRef ()
{
ULONG t_ReferenceCount = InterlockedIncrement ( & m_InternalReferenceCount ) ;
if ( t_ReferenceCount == 1 )
{
NonCyclicAddRef () ;
}
return t_ReferenceCount ;
}
virtual STDMETHODIMP_( ULONG ) UnLockedInternalRelease ()
{
LONG t_ReferenceCount = InterlockedDecrement ( & m_InternalReferenceCount ) ;
if ( t_ReferenceCount == 0 )
{
BOOL t_DoCallBack = m_CallBackInternalRelease ;
m_CallBackInternalRelease = 0xbabab1ac ;
if ( m_Controller )
{
m_Controller->Delete ( m_Key ) ;
m_Controller->UnLock () ;
}
if ( t_DoCallBack == 1 )
{
CallBackInternalRelease () ;
}
NonCyclicRelease () ;
}
else
{
#ifdef DBG
if ( t_ReferenceCount < 0 )
{
DebugBreak () ;
}
#endif
if ( m_Controller )
{
m_Controller->UnLock () ;
}
}
return t_ReferenceCount ;
}
virtual STDMETHODIMP_( ULONG ) InternalRelease ()
{
if ( m_Controller )
{
m_Controller->Lock () ;
}
LONG t_ReferenceCount = InterlockedDecrement ( & m_InternalReferenceCount ) ;
if ( t_ReferenceCount == 0 )
{
BOOL t_DoCallBack = m_CallBackInternalRelease ;
m_CallBackInternalRelease = 0xbabab1ac ;
if ( m_Controller )
{
m_Controller->Delete ( m_Key ) ;
m_Controller->UnLock () ;
}
if ( t_DoCallBack == 1 )
{
CallBackInternalRelease () ;
}
else
{
#ifdef DBG
DebugBreak () ;
#endif
}
NonCyclicRelease () ;
}
else
{
#ifdef DBG
if ( t_ReferenceCount < 0 )
{
DebugBreak () ;
}
#endif
if ( m_Controller )
{
m_Controller->UnLock () ;
}
}
return t_ReferenceCount ;
}
virtual STDMETHODIMP_( ULONG ) NonCyclicAddRef ()
{
return InterlockedIncrement ( & m_NonCylicReferenceCount ) ;
}
virtual STDMETHODIMP_( ULONG ) NonCyclicRelease ()
{
ULONG t_ReferenceCount = InterlockedDecrement ( & m_NonCylicReferenceCount ) ;
if ( t_ReferenceCount == 0 )
{
delete this ;
}
return t_ReferenceCount ;
}
BOOL GetCached ()
{
return m_Cached ;
}
void SetCached ( BOOL a_Cached )
{
m_Cached = a_Cached ;
}
WmiKey &GetKey ()
{
return m_Key ;
}
void SetKey ( const WmiKey &a_Key )
{
m_Key = a_Key ;
}
void SetController ( WmiContainerController <WmiKey> *a_Controller )
{
if ( m_Controller )
{
m_Controller->Release () ;
}
m_Controller = a_Controller ;
if ( m_Controller )
{
m_Controller->AddRef () ;
}
}
WmiContainerController <WmiKey> *GetController ()
{
return m_Controller ;
}
} ;
typedef WmiAvlTree <WmiKey,WmiContainerElement *> Container ;
typedef typename Container :: Iterator Container_Iterator ;
private:
LONG m_ReferenceCount ;
CriticalSection m_CriticalSection ;
Container m_Container ;
protected:
public:
WmiContainerController ( WmiAllocator &a_Allocator ) ;
virtual ~WmiContainerController () ;
virtual STDMETHODIMP QueryInterface ( REFIID , LPVOID FAR * ) ;
virtual STDMETHODIMP_( ULONG ) AddRef () ;
virtual STDMETHODIMP_( ULONG ) Release () ;
virtual WmiStatusCode Initialize () ;
virtual WmiStatusCode UnInitialize () ;
virtual WmiStatusCode Lock () ;
virtual WmiStatusCode UnLock () ;
virtual WmiStatusCode Insert (
WmiContainerElement &a_Element ,
Container_Iterator &a_Iterator
) ;
virtual WmiStatusCode Find ( const WmiKey &a_Key , Container_Iterator &a_Iterator ) ;
virtual WmiStatusCode Shutdown () ;
virtual WmiStatusCode Delete ( const WmiKey &a_Key ) ;
virtual WmiStatusCode Strobe ( ULONG &a_NextStrobeDelta ) ;
WmiStatusCode GetContainer ( Container *&a_Container )
{
a_Container = & m_Container ;
return e_StatusCode_Success ;
}
CriticalSection* GetCriticalSection ()
{
return &m_CriticalSection ;
}
} ;
#include <Cache.cpp>
#endif _Cache_H