1111#include " StdInc.h"
1212#include " CClientVectorGraphic.h"
1313
14+ namespace
15+ {
16+ const std::int64_t TEMPORARY_TEXTURES_CLEANUP_THRESHOLD = 1000ll ;
17+ const std::size_t TEMPORARY_TEXTURES_DELETE_THRESHOLD = 2u ;
18+ }
19+
1420// //////////////////////////////////////////////////////////////
1521//
1622// CClientRenderElementManager::CClientRenderElementManager
@@ -283,20 +289,22 @@ CClientVectorGraphic* CClientRenderElementManager::CreateVectorGraphic(uint widt
283289CClientTexture* CClientRenderElementManager::FindAutoTexture (const SString& strFullFilePath, const SString& strUniqueName)
284290{
285291 // Check if we've already done this file
286- CClientTexture* * ppTextureElement = MapFind (m_AutoTextureMap, strUniqueName);
292+ SAutoTexture * ppTextureElement = MapFind (m_AutoTextureMap, strUniqueName);
287293 if (!ppTextureElement)
288294 {
289295 // Try to create
290296 CClientTexture* pNewTextureElement = CreateTexture (strFullFilePath);
291297 if (!pNewTextureElement)
292- return NULL ;
298+ return nullptr ;
293299
294300 // Add to automap if created
295- MapSet (m_AutoTextureMap, strUniqueName, pNewTextureElement);
301+ MapSet (m_AutoTextureMap, strUniqueName, SAutoTexture{ pNewTextureElement} );
296302 ppTextureElement = MapFind (m_AutoTextureMap, strUniqueName);
297303 }
298304
299- return *ppTextureElement;
305+ ppTextureElement->lastUse = CTickCount::Now ();
306+
307+ return ppTextureElement->texture ;
300308}
301309
302310// //////////////////////////////////////////////////////////////
@@ -318,9 +326,9 @@ void CClientRenderElementManager::Remove(CClientRenderElement* pElement)
318326 // Remove from auto texture map
319327 if (pElement->IsA (CClientTexture::GetClassId ()))
320328 {
321- for (std::map<SString, CClientTexture*>::iterator iter = m_AutoTextureMap.begin (); iter != m_AutoTextureMap.end (); ++iter)
329+ for (auto iter = m_AutoTextureMap.begin (); iter != m_AutoTextureMap.end (); ++iter)
322330 {
323- if (iter->second == pElement)
331+ if (iter->second . texture == pElement)
324332 {
325333 m_AutoTextureMap.erase (iter);
326334 break ;
@@ -350,3 +358,35 @@ void CClientRenderElementManager::Remove(CClientRenderElement* pElement)
350358 CRenderItem* pRenderItem = pElement->GetRenderItem ();
351359 SAFE_RELEASE (pRenderItem);
352360}
361+
362+ void CClientRenderElementManager::DoPulse ()
363+ {
364+ const CTickCount now = CTickCount::Now ();
365+
366+ std::vector<CClientTexture*> deleteCandidates;
367+ deleteCandidates.reserve (TEMPORARY_TEXTURES_DELETE_THRESHOLD);
368+
369+ for (const auto & [texName, texInfo] : m_AutoTextureMap)
370+ {
371+ const std::int64_t timeElapsedMs = (now - texInfo.lastUse ).ToLongLong ();
372+ if (timeElapsedMs < TEMPORARY_TEXTURES_CLEANUP_THRESHOLD)
373+ continue ;
374+
375+ CTextureItem* textureItem = texInfo.texture ->GetTextureItem ();
376+ if (textureItem && textureItem->m_iRefCount > 1 )
377+ continue ;
378+
379+ // CElementDeleter::Delete causes changes in m_AutoTextureMap
380+ // and we cannot delete a texture while iterating over it
381+ deleteCandidates.push_back (texInfo.texture );
382+
383+ // The deletion procedure can be expensive
384+ // and we're interested in capping on the number of deleted texture at once
385+ if (deleteCandidates.size () == TEMPORARY_TEXTURES_DELETE_THRESHOLD)
386+ break ;
387+ }
388+
389+ for (CClientTexture* texture : deleteCandidates)
390+ g_pClientGame->GetElementDeleter ()->Delete (texture, true );
391+
392+ }
0 commit comments