📄 objcache.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft shared
// source or premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license agreement,
// you are not authorized to use this source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the SOURCE.RTF on your install media or the root of your tools installation.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
//+---------------------------------------------------------------------------------
//
//
// File:
// objcache.cpp
//
// Contents:
//
// CObjCache class implementation
//
//----------------------------------------------------------------------------------
#include "Headers.h"
#ifdef UNDER_CE
#include "WinCEUtils.h"
#endif
////////////////////////////////////////////////////////////////////////////////////////////////////
// function: CObjCache::CObjCache()
//
// parameters:
//
// description:
// CObjCache constructor
// Use this constructor only with objects that do not need deleting.
// returns:
//
////////////////////////////////////////////////////////////////////////////////////////////////////
CObjCache::CObjCache()
: m_cCur(0),
m_cFound(0),
m_cBumped(0),
m_cObjStale(0),
m_cAccessDenied(0)
{
// No maximum, no delete/validate/getkey functions
m_cMax = 0;
m_CacheID = 0;
m_pfnObjectOK = NULL;
m_pfnDeleteObj = NULL; // Object is not deleted if this function is NULL
m_pfnGetKey = NULL;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// function: CObjCache::CObjCache()
//
// parameters:
//
// description:
// CObjCache constructor
// returns:
//
////////////////////////////////////////////////////////////////////////////////////////////////////
CObjCache:: CObjCache(
ULONG ulMax, // Max no of elements kept in cache, 0 if no limit
ULONG cid, // Cache id, used for tracing
PFNOBJECTOK pfnObjectOK, //Callback method that returns info on the state of object
PDESTROYFUNC pfnDestroyFunc, // Delete method for the object
PFNGETKEY pfnGetKey) : // Returns the hash key for the object
m_cCur(0), m_cFound(0), m_cBumped(0), m_cObjStale(0), m_cAccessDenied(0)
{
m_cMax = ulMax;
m_CacheID = cid;
m_pfnObjectOK = pfnObjectOK;
m_pfnDeleteObj = pfnDestroyFunc;
m_pfnGetKey = pfnGetKey;
// If there is a cMax, then we must have a m_pfnGetKey
if (m_cMax != 0)
ASSERT(m_pfnGetKey);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
// function: CObjCache::~CObjCache()
//
// parameters:
//
// description:
//
// returns:
//
////////////////////////////////////////////////////////////////////////////////////////////////////
CObjCache::~CObjCache()
{
;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// function: CObjCache::Insert
//
// parameters:
//
// description:
// Inserts an entry to the object cache, removing the LRU object
// if the cache is full.
// returns:
//
////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CObjCache::Insert(char * pszKey, void * pvData)
{
HRESULT hr = S_OK;
CObjCacheDoubleListEntry *DblEntry = NULL;
char *pszKey2;
if (m_cMax && (m_cCur >= m_cMax))
{
// Remove an item from the LRU end
DblEntry = (CObjCacheDoubleListEntry *) m_LRUObj.getTail();
ASSERT(DblEntry);
ASSERT(m_pfnGetKey);
pszKey2 = m_pfnGetKey(DblEntry->getData());
Delete(pszKey2);
m_cBumped++;
if ((m_cBumped % 32) == 0)
{
TRACEL((1, "CacheID: %d, Cache hits: %d, bumped from cache: %d, found stale: %d, access denied: %d\n",
m_CacheID, m_cFound, m_cBumped, m_cObjStale, m_cAccessDenied));
}
}
DblEntry = new CObjCacheDoubleListEntry(pvData);
CHK_BOOL(DblEntry, E_OUTOFMEMORY);
CHK(CStrHashTable::Insert(pszKey, (void *)DblEntry));
m_LRUObj.InsertHead((CDoubleListEntry *)DblEntry);
m_cCur++;
Cleanup:
return hr;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// function: CObjCache::Find()
//
// parameters:
//
// description:
//
// returns:
//
////////////////////////////////////////////////////////////////////////////////////////////////////
OBJ_STATE CObjCache::Find(char * pszKey, void **ppvData)
{
CObjCacheDoubleListEntry *DblEntry = NULL;
void *pvData;
OBJ_STATE objstate = OBJ_OK;
*ppvData = NULL;
DblEntry = (CObjCacheDoubleListEntry *) CStrHashTable::Find(pszKey);
if (!DblEntry)
return OBJ_NOTFOUND; // Not found
pvData = DblEntry->getData();
if (m_pfnObjectOK)
objstate = m_pfnObjectOK(pvData);
switch (objstate)
{
case OBJ_OK:
// Move the object to MRU end and return it
m_LRUObj.RemoveEntry((CDoubleListEntry *)DblEntry);
m_LRUObj.InsertHead((CDoubleListEntry *)DblEntry);
m_cFound++;
if ((m_cFound % 1024) == 0)
{
TRACEL((1, "CacheID: %d, Cache hits: %d, bumped from cache: %d, found stale: %d, access denied: %d\n",
m_CacheID, m_cFound, m_cBumped, m_cObjStale, m_cAccessDenied));
}
*ppvData = pvData;
break;
case OBJ_ACCESS_DENIED:
// Return Error
m_cAccessDenied++;
if ((m_cAccessDenied % 32) == 0)
{
TRACEL((1, "CacheID: %d, Cache hits: %d, bumped from cache: %d, found stale: %d, access denied: %d\n",
m_CacheID, m_cFound, m_cBumped, m_cObjStale, m_cAccessDenied));
}
break;
case OBJ_STALE:
// Object no longer valid. Free it and return
Delete(pszKey);
m_cObjStale++;
if ((m_cObjStale % 32) == 0)
{
TRACEL((1, "CacheID: %d, Cache hits: %d, bumped from cache: %d, found stale: %d, access denied: %d\n",
m_CacheID, m_cFound, m_cBumped, m_cObjStale, m_cAccessDenied));
}
break;
default:
return OBJ_NOTFOUND; // Unidentified remark
}
return objstate;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// function: CObjCache::Delete()
//
// parameters:
//
// description:
//
// returns:
//
////////////////////////////////////////////////////////////////////////////////////////////////////
void CObjCache::Delete(char * pszKey)
{
CObjCacheDoubleListEntry *DblEntry = NULL;
DblEntry = (CObjCacheDoubleListEntry *) CStrHashTable::Find(pszKey);
if (DblEntry)
{
m_LRUObj.RemoveEntry((CDoubleListEntry *)DblEntry);
ASSERT(DblEntry);
CStrHashTable::Delete(pszKey); // Calls back to DestroyData
m_cCur--;
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// function: CObjCache::DeleteAll()
//
// parameters:
//
// description:
// Deletes all the elements in the cache
// returns:
//
////////////////////////////////////////////////////////////////////////////////////////////////////
void CObjCache::DeleteAll()
{
CObjCacheDoubleListEntry *DblEntry = NULL;
TRACEL((1, "Object cache terminated: CacheID: %d, Cache hits: %d, bumped from cache: %d, found stale: %d, access denied: %d\n",
m_CacheID, m_cFound, m_cBumped, m_cObjStale, m_cAccessDenied));
while(!m_LRUObj.IsEmpty())
{
DblEntry = (CObjCacheDoubleListEntry *)m_LRUObj.getHead();
ASSERT(DblEntry);
m_LRUObj.RemoveEntry((CDoubleListEntry *)DblEntry);
}
CStrHashTable::DeleteAll(); // Calls back to DestroyData for each entry
m_cCur = 0;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// function: CObjCache::ClearCache()
//
// parameters:
//
// description:
// Clears the object cache class without freeing any memory
// Used in the case of an AV. Cannot delete memory since it may be corrupted.
// We have to live with memory leak in case of an AV.
// returns:
//
////////////////////////////////////////////////////////////////////////////////////////////////////
void CObjCache::ClearCache()
{
CStrHashTable::ClearHashTable();
m_LRUObj.ClearList();
m_cCur = 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -