556 lines
13 KiB
C++
556 lines
13 KiB
C++
#include "SunClientPrecompiledHeader.h"
|
|
#include "ItemUnitCacher.h"
|
|
#include "ResourceManager.h"
|
|
#include "GraphicResourceList.h"
|
|
#include <SCSlotHeader.h>
|
|
#include <float.h>
|
|
#include "Application.h"
|
|
#include "GlobalFunc.h"
|
|
|
|
const int RESOURCE_RELEASE_TIME = 300000; //如果不参考5分钟以上,则完全删除
|
|
|
|
const int MAX_WZUNIT_CACHE = 120;
|
|
const int RESOURCE_RELEASE_CHECK = 10000; //10秒1次检查
|
|
//const int RESOURCE_RELEASE_TIME = 1800000; //30分钟以上不参考完全删除
|
|
//
|
|
//const int MAX_WZUNIT_CACHE = 120;
|
|
//const int RESOURCE_RELEASE_CHECK = 120000; //2分钟1次检查
|
|
|
|
ResourceCacher::ResourceCacher()
|
|
{
|
|
m_pResourceUnitHashTable = new util::SolarHashTable<ResourceWzUnit *>;
|
|
m_pResourceUnitHashTable->Initialize( 10000 );
|
|
|
|
m_pResourceWaitForFree = new util::SolarHashTable<ResourceWzUnit *>;
|
|
m_pResourceWaitForFree->Initialize( MAX_WZUNIT_CACHE+1 );
|
|
|
|
m_pWzUnitPool = new util::CMemoryPoolFactory<ResourceWzUnit>;
|
|
m_pWzUnitPool->Initialize( 10000, 500 );
|
|
|
|
m_dwSkippingTick = 0;
|
|
}
|
|
|
|
ResourceCacher::~ResourceCacher()
|
|
{
|
|
ResourceWzUnit * pWzUnit = NULL;
|
|
|
|
if (m_pResourceUnitHashTable)
|
|
{
|
|
m_pResourceUnitHashTable->SetFirst();
|
|
while( pWzUnit = m_pResourceUnitHashTable->GetNext() )
|
|
{
|
|
g_pSunRenderer->x_pManagerWzUnitLoader->DestroyWzUnit( pWzUnit->m_wiID );
|
|
m_pWzUnitPool->Free( pWzUnit );
|
|
}
|
|
m_pResourceUnitHashTable->RemoveAll();
|
|
delete m_pResourceUnitHashTable;
|
|
m_pResourceUnitHashTable = NULL;
|
|
}
|
|
|
|
if (m_pResourceWaitForFree)
|
|
{
|
|
m_pResourceWaitForFree->RemoveAll();
|
|
delete m_pResourceWaitForFree;
|
|
m_pResourceWaitForFree = NULL;
|
|
|
|
}
|
|
|
|
if (m_pWzUnitPool)
|
|
{
|
|
m_pWzUnitPool->Release();
|
|
delete m_pWzUnitPool;
|
|
}
|
|
}
|
|
|
|
|
|
VOID ResourceCacher::Init()
|
|
{
|
|
}
|
|
|
|
|
|
VOID ResourceCacher::LoadResource( RESOURCECODE resourceCode ,float fRequestRateResizeTexture, bool pre_load, bool is_npc)
|
|
{
|
|
assert(resourceCode);
|
|
assert(resourceCode >= ENGINE_RESOURCE_ID_OFFSET);
|
|
|
|
RESOURCE_INFO *pInfo = GraphicResourceList::Instance()->GetItemInfo(resourceCode - ENGINE_RESOURCE_ID_OFFSET);
|
|
|
|
assert(pInfo && "无效的资源代码.");
|
|
|
|
// check file
|
|
BOOL bExist = FALSE;
|
|
if (pInfo)
|
|
{
|
|
if (is_npc)
|
|
{
|
|
size_t file_length = strlen(pInfo->szFilename);
|
|
|
|
if ((file_length + strlen("_NPC")) < 128)//128是该缓冲尺寸的MAX
|
|
{
|
|
TCHAR* temp_string = pInfo->szFilename + (file_length - strlen(".wzu"));
|
|
strcat(temp_string, "_NPC.wzu");
|
|
}
|
|
}
|
|
|
|
if( GENERALPARAM->IsUsePackFile() )
|
|
{
|
|
DA_FILE hFile = g_pApplication->GetDiscAccess()->OpenFile(ePFN_RESOURCE, pInfo->szFilename, DA_READ, SM_READ, OD_OPEN_EXISTING);
|
|
if (INVALID_DA_FILE != hFile )
|
|
{
|
|
bExist = TRUE;
|
|
g_pApplication->GetDiscAccess()->CloseFile( hFile );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
FILE *fp = fopen(pInfo->szFilename,"rb");
|
|
if (fp)
|
|
{
|
|
bExist = TRUE;
|
|
fclose(fp);
|
|
}
|
|
}
|
|
}
|
|
|
|
// load file
|
|
#define DEFAULT_MESH_NAME "Data\\Item\\Item1001.wzu"
|
|
|
|
char * filename = NULL;
|
|
if (bExist)
|
|
{
|
|
filename = pInfo->szFilename;
|
|
}
|
|
else
|
|
{
|
|
filename = DEFAULT_MESH_NAME;
|
|
|
|
WRITELOG(eLOG_LEVEL_ERR, c_wOUTPUT_LOG_FILE, _T("[code: %d] 不存在资源代替%s加载"), (int)(resourceCode - ENGINE_RESOURCE_ID_OFFSET), filename);
|
|
}
|
|
|
|
DWORD load_style = ULS_DEFAULT;
|
|
|
|
if (pre_load)
|
|
{
|
|
load_style |= ULS_NO_MULTITHREAD;
|
|
}
|
|
|
|
if( resourceCode != g_pSunRenderer->x_pManagerWzUnitLoader->LoadWzUnit( resourceCode, filename,TRUE,load_style,fRequestRateResizeTexture ))
|
|
{
|
|
#ifdef _DEV_VER
|
|
MessageBoxA(NULL, "资源数据Error", filename, MB_OK);
|
|
WRITELOG(eLOG_LEVEL_ERR, c_wOUTPUT_LOG_FILE, _T("[%s][code: %d] 无法加载资源"), filename, resourceCode - ENGINE_RESOURCE_ID_OFFSET);
|
|
#endif
|
|
}
|
|
|
|
// 临时打造效果子类型.
|
|
CWzUnit * pWzUnit = g_pSunRenderer->x_pManagerWzUnitLoader->GetWzUnit( resourceCode );
|
|
|
|
ResourceWzUnit * pUnit = (ResourceWzUnit *) m_pWzUnitPool->Alloc();
|
|
if(pUnit)
|
|
{
|
|
pUnit->m_pwzUnit = pWzUnit;
|
|
pUnit->m_wiID = resourceCode;
|
|
pUnit->m_iRefCount = 0;
|
|
pUnit->m_iErrorFlag = 0;
|
|
pUnit->m_iReleaseTime = 0;
|
|
|
|
assert( NULL == m_pResourceUnitHashTable->GetData( resourceCode ) );
|
|
m_pResourceUnitHashTable->Add( pUnit, resourceCode );
|
|
|
|
}
|
|
}
|
|
|
|
CWzUnit * ResourceCacher::GetResourceWzUnit( RESOURCECODE resourceCode ,float fRequestRateResizeTexture, bool bPreLoad /*=false*/, bool bFreeMost /*=true*/, bool is_npc /*=false*/)
|
|
{
|
|
if (resourceCode == 0)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
ResourceWzUnit* pUnit = m_pResourceUnitHashTable->GetData( resourceCode );
|
|
|
|
if( pUnit == NULL )
|
|
{
|
|
LoadResource( resourceCode ,fRequestRateResizeTexture, is_npc);
|
|
pUnit = m_pResourceUnitHashTable->GetData( resourceCode );
|
|
pUnit->m_iRefCount = 1;
|
|
pUnit->m_iReleaseTime = 0;
|
|
pUnit->m_bFreeMost = bFreeMost;
|
|
}
|
|
else
|
|
{
|
|
if( bPreLoad == false )
|
|
pUnit->m_iRefCount++;
|
|
|
|
pUnit->m_iReleaseTime = 0;
|
|
|
|
|
|
// Free列表中的话会再次删除.
|
|
if( ResourceWzUnit* pFree = m_pResourceWaitForFree->GetData(resourceCode) )
|
|
{
|
|
m_pResourceWaitForFree->Remove(resourceCode);
|
|
}
|
|
}
|
|
|
|
return pUnit->m_pwzUnit;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
/**
|
|
*/
|
|
void
|
|
ResourceCacher::SetUnitForceRemove( RESOURCECODE resourceCode )
|
|
{
|
|
ResourceWzUnit * pUnit = m_pResourceUnitHashTable->GetData( resourceCode );
|
|
if( !pUnit )
|
|
{
|
|
assert(!"ResourceCacher::SetUnitForceRemove 未加载的资源.");
|
|
}
|
|
else
|
|
{
|
|
pUnit->SetForceRemove();
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
/**
|
|
*/
|
|
bool
|
|
ResourceCacher::IsUnitForceRemove( RESOURCECODE resourceCode )
|
|
{
|
|
ResourceWzUnit * pUnit = m_pResourceUnitHashTable->GetData( resourceCode );
|
|
if( !pUnit )
|
|
{
|
|
assert(!"ResourceCacher::IsUnitForceRemove 未加载的资源.");
|
|
}
|
|
else
|
|
{
|
|
return pUnit->IsForceRemove();
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void ResourceCacher::AddToFreeList( ResourceWzUnit *pCurUnit,RESOURCECODE resourceCode)
|
|
{
|
|
if (!m_pResourceWaitForFree)
|
|
{
|
|
return;
|
|
}
|
|
|
|
int count = m_pResourceWaitForFree->GetDataNum();
|
|
|
|
// 如果草还没满就放进去结束。
|
|
if (count < MAX_WZUNIT_CACHE)
|
|
{
|
|
pCurUnit->m_iReleaseTime = RESOURCE_RELEASE_TIME;
|
|
m_pResourceWaitForFree->Add(pCurUnit,resourceCode);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
DWORD bestcount = ULONG_MAX;
|
|
ResourceWzUnit *pBest = NULL;
|
|
|
|
// 在池中找出最有参考价值的人.
|
|
m_pResourceWaitForFree->SetFirst();
|
|
|
|
ResourceWzUnit *pWzUnit = m_pResourceWaitForFree->GetNext();
|
|
pBest = pWzUnit;
|
|
|
|
RESOURCE_INFO *pInfo = GraphicResourceList::Instance()->GetItemInfo(pWzUnit->m_wiID - ENGINE_RESOURCE_ID_OFFSET);
|
|
// 如果Resource InforList上没有的人被签名的话会优先卸载
|
|
if(pInfo)
|
|
{
|
|
if (bestcount > (DWORD)pInfo->dwTotalRefCount)
|
|
{
|
|
bestcount = (DWORD)pInfo->dwTotalRefCount;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bestcount = 0;
|
|
}
|
|
|
|
pWzUnit = m_pResourceWaitForFree->GetNext();
|
|
|
|
while( pWzUnit )
|
|
{
|
|
RESOURCE_INFO *pInfo = GraphicResourceList::Instance()->GetItemInfo(pWzUnit->m_wiID - ENGINE_RESOURCE_ID_OFFSET);
|
|
if(pInfo)
|
|
{
|
|
if (bestcount > (DWORD)pInfo->dwTotalRefCount)
|
|
{
|
|
bestcount = pInfo->dwTotalRefCount;
|
|
pBest = pWzUnit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// 如果Resource InforList上没有的人被签名的话会优先卸载
|
|
bestcount = 0;
|
|
pBest = pWzUnit;
|
|
}
|
|
|
|
pWzUnit = m_pResourceWaitForFree->GetNext();
|
|
}
|
|
|
|
// 把最终要删除的人和现在作为仁慈进来的人进行比较。
|
|
//RefCount删除最低的家伙.
|
|
if (pBest)
|
|
{
|
|
DWORD curcount = 0;
|
|
|
|
RESOURCE_INFO *pInfo = GraphicResourceList::Instance()->GetItemInfo(resourceCode - ENGINE_RESOURCE_ID_OFFSET);
|
|
if(pInfo)
|
|
{
|
|
curcount = pInfo->dwTotalRefCount;
|
|
}
|
|
|
|
// 即使是这样也会把作为仁慈进来的人抹去。往不更新列表的方向走.
|
|
if (curcount <= bestcount)
|
|
{
|
|
g_pSunRenderer->x_pManagerWzUnitLoader->DestroyWzUnit( pCurUnit->m_wiID );
|
|
m_pResourceUnitHashTable->Remove(pCurUnit->m_wiID);
|
|
m_pWzUnitPool->Free(pCurUnit);
|
|
}
|
|
else
|
|
{
|
|
// 旧的擦掉,放新的~
|
|
g_pSunRenderer->x_pManagerWzUnitLoader->DestroyWzUnit( pBest->m_wiID );
|
|
m_pResourceUnitHashTable->Remove(pBest->m_wiID);
|
|
m_pResourceWaitForFree->Remove(pBest->m_wiID);
|
|
m_pWzUnitPool->Free(pBest);
|
|
|
|
pCurUnit->m_iReleaseTime = RESOURCE_RELEASE_TIME;
|
|
m_pResourceWaitForFree->Add(pCurUnit,resourceCode);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//利索斯留着的筛子,只会减少计数.
|
|
void ResourceCacher::ReleaseResourceCount( RESOURCECODE resourceCode)
|
|
{
|
|
ResourceWzUnit * pUnit = m_pResourceUnitHashTable->GetData( resourceCode );
|
|
if(pUnit)
|
|
{
|
|
if (pUnit->m_iRefCount > 0)
|
|
{
|
|
pUnit->m_iRefCount--;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void ResourceCacher::ReleaseResourceWzUnit( RESOURCECODE resourceCode )
|
|
{
|
|
ResourceWzUnit * pUnit = m_pResourceUnitHashTable->GetData( resourceCode );
|
|
if( !pUnit )
|
|
{
|
|
assert(!"ResourceCacher::ReleaseItemUnit 未加载的资源.");
|
|
}
|
|
else
|
|
{
|
|
if (pUnit->m_iRefCount > 0)
|
|
{
|
|
pUnit->m_iRefCount--;
|
|
// ref count为0时取消.
|
|
|
|
if (pUnit->m_iRefCount == 0)
|
|
{
|
|
// 如果开着强制清除的话.
|
|
if (pUnit->IsForceRemove())
|
|
{
|
|
g_pSunRenderer->x_pManagerWzUnitLoader->DestroyWzUnit( pUnit->m_wiID );
|
|
m_pResourceUnitHashTable->Remove(resourceCode);
|
|
m_pWzUnitPool->Free(pUnit);
|
|
}
|
|
// 否则,删除优先列表.
|
|
else
|
|
{
|
|
AddToFreeList(pUnit,resourceCode);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
assert(!"ResourceCacher::ReleaseItemUnit 错误的引用计数");
|
|
}
|
|
}
|
|
}
|
|
|
|
int ResourceCacher::SetErrorFlag( RESOURCECODE resourceCode ,int iErrorFlag)
|
|
{
|
|
ResourceWzUnit * pUnit = m_pResourceUnitHashTable->GetData( resourceCode );
|
|
if( !pUnit )
|
|
{
|
|
assert(!"ResourceCacher::SetErrorFlag 未加载的资源.");
|
|
}
|
|
else
|
|
{
|
|
pUnit->m_iErrorFlag = iErrorFlag;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int ResourceCacher::GetErrorFlag( RESOURCECODE resourceCode )
|
|
{
|
|
ResourceWzUnit * pUnit = m_pResourceUnitHashTable->GetData( resourceCode );
|
|
if( !pUnit )
|
|
{
|
|
assert(!"ResourceCacher::GetErrorFlag 未加载的资源.");
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
return pUnit->m_iErrorFlag;
|
|
}
|
|
}
|
|
|
|
void ResourceCacher::Process(DWORD dwTick)
|
|
{
|
|
ResourceWzUnit * pWzUnit = NULL;
|
|
|
|
if (m_pResourceWaitForFree)
|
|
{
|
|
//2分钟只检查1次。
|
|
if(m_dwSkippingTick > RESOURCE_RELEASE_CHECK)
|
|
{
|
|
if(m_pResourceWaitForFree->GetDataNum())
|
|
{
|
|
m_pResourceWaitForFree->SetFirst();
|
|
|
|
pWzUnit = m_pResourceWaitForFree->GetNext();
|
|
while( pWzUnit )
|
|
{
|
|
//pWzUnit->m_iReleaseTime -= dwTick;
|
|
pWzUnit->m_iReleaseTime -= RESOURCE_RELEASE_CHECK;
|
|
|
|
if ((pWzUnit->m_iReleaseTime < 0))
|
|
{
|
|
g_pSunRenderer->x_pManagerWzUnitLoader->DestroyWzUnit( pWzUnit->m_wiID );
|
|
m_pResourceUnitHashTable->Remove(pWzUnit->m_wiID);
|
|
m_pResourceWaitForFree->Remove(pWzUnit->m_wiID);
|
|
m_pWzUnitPool->Free( pWzUnit );
|
|
|
|
pWzUnit = m_pResourceWaitForFree->GetNext();
|
|
}
|
|
else
|
|
{
|
|
pWzUnit = m_pResourceWaitForFree->GetNext();
|
|
}
|
|
}
|
|
}
|
|
|
|
m_dwSkippingTick = 0;
|
|
}
|
|
else
|
|
{
|
|
m_dwSkippingTick += dwTick;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void ResourceCacher::ReleaseAllCachedUnit()
|
|
{
|
|
ResourceWzUnit * pWzUnit = NULL;
|
|
ResourceWzUnit * pNextWzUnit = NULL;
|
|
|
|
if (m_pResourceWaitForFree)
|
|
{
|
|
m_pResourceWaitForFree->SetFirst();
|
|
|
|
pWzUnit = m_pResourceWaitForFree->GetNext();
|
|
while( pWzUnit )
|
|
{
|
|
g_pSunRenderer->x_pManagerWzUnitLoader->DestroyWzUnit( pWzUnit->m_wiID );
|
|
m_pResourceUnitHashTable->Remove(pWzUnit->m_wiID);
|
|
m_pWzUnitPool->Free( pWzUnit );
|
|
|
|
pWzUnit = m_pResourceWaitForFree->GetNext();
|
|
}
|
|
|
|
m_pResourceWaitForFree->RemoveAll();
|
|
}
|
|
}
|
|
|
|
void ResourceCacher::ReleaseMostUnit()
|
|
{
|
|
ResourceWzUnit * pWzUnit = NULL;
|
|
ResourceWzUnit * pNextWzUnit = NULL;
|
|
|
|
if (m_pResourceWaitForFree)
|
|
{
|
|
m_pResourceWaitForFree->SetFirst();
|
|
|
|
pWzUnit = m_pResourceWaitForFree->GetNext();
|
|
while( pWzUnit )
|
|
{
|
|
if(true == pWzUnit->m_bFreeMost)
|
|
{
|
|
pNextWzUnit = m_pResourceWaitForFree->GetNext();
|
|
|
|
g_pSunRenderer->x_pManagerWzUnitLoader->DestroyWzUnit( pWzUnit->m_wiID );
|
|
m_pResourceUnitHashTable->Remove(pWzUnit->m_wiID);
|
|
m_pResourceWaitForFree->Remove(pWzUnit->m_wiID);
|
|
m_pWzUnitPool->Free( pWzUnit );
|
|
|
|
pWzUnit = pNextWzUnit;
|
|
}
|
|
else
|
|
{
|
|
pWzUnit = m_pResourceWaitForFree->GetNext();
|
|
}
|
|
}
|
|
}
|
|
|
|
pWzUnit = NULL;
|
|
if (m_pResourceUnitHashTable)
|
|
{
|
|
m_pResourceUnitHashTable->SetFirst();
|
|
pWzUnit = m_pResourceUnitHashTable->GetNext();
|
|
while( pWzUnit )
|
|
{
|
|
if(pWzUnit->m_bFreeMost)
|
|
{
|
|
pNextWzUnit = m_pResourceUnitHashTable->GetNext();
|
|
|
|
g_pSunRenderer->x_pManagerWzUnitLoader->DestroyWzUnit( pWzUnit->m_wiID );
|
|
m_pResourceUnitHashTable->Remove(pWzUnit->m_wiID);
|
|
m_pWzUnitPool->Free( pWzUnit );
|
|
|
|
pWzUnit = pNextWzUnit;
|
|
}
|
|
else
|
|
{
|
|
pWzUnit = m_pResourceUnitHashTable->GetNext();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
int ResourceCacher::GetLoadedResourceCount()
|
|
{
|
|
if (m_pResourceUnitHashTable)
|
|
{
|
|
return m_pResourceUnitHashTable->GetDataNum();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int ResourceCacher::GetWaitForFreeResourceCount()
|
|
{
|
|
if (m_pResourceWaitForFree)
|
|
{
|
|
return m_pResourceWaitForFree->GetDataNum();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|