#include "SunClientPrecompiledHeader.h" #include "ItemUnitCacher.h" #include "ResourceManager.h" #include "GraphicResourceList.h" #include #include #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; m_pResourceUnitHashTable->Initialize( 10000 ); m_pResourceWaitForFree = new util::SolarHashTable; m_pResourceWaitForFree->Initialize( MAX_WZUNIT_CACHE+1 ); m_pWzUnitPool = new util::CMemoryPoolFactory; 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; }