1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
|
namespace Naos
{
/** Cette classe représente un cache LRU (Last Recent Used) de ressource et permet
donc de gérer le nombre maximal de ressources voulu.
@Note
Dans ce cache on utilise 2 conteneurs : un std::list et std::map. Pourquoi ?
On utilise un std::list pour conserver l'ordre des ressources dans le cache en fonction
des utilisations qui en sont faites.
On utilise un std::map pour faciliter la recherche des ressources dans le cache. De
plus un std::map fourni une complexité logarithmique pour la recherche d'éléments comparé
à une compléxité linéaire pour un std::list.
*/
template<class T>
class _NaosExport_ ResourceLRUCache
{
private:
typedef typename std::list<Resource<T> > ResourceCache;
typedef typename std::list<Resource<T> >::iterator ItResourceCache;
typedef typename std::map<Ogre::String, ItResourceCache> ResourceIndex;
typedef typename std::map<Ogre::String, ItResourceCache>::iterator ItResourceIndex;
private:
/// Taille maximale du cache LRU.
size_t mMaxSize;
/// Cache de resource.
ResourceCache mResourceCache;
/// Index des ressource dans le cache
ResourceIndex mResourceIndex;
public:
/**
* Constructeur par défaut.
* @Param _maxSize : taille maximale du cache en nombre de ressource.
*/
ResourceLRUCache(size_t _maxSize):
mMaxSize(_maxSize)
{}
/**
* Destructeur
*/
~ResourceLRUCache(void)
{
mResourceCache.clear();
mResourceIndex.clear();
}
/**
* Ajoute une ressource dans le cache.
* @Param _resource : resource à ajouter.
*/
void addResource(const Resource<T>& _resource)
{
ItResourceIndex it = mResourceIndex.find(_resource.getName());
// Si la ressource est déjà présente dans le cache on la déplace au début de ce dernier.
if(it != mResourceIndex.end())
{
mResourceCache.erase((*it).second);
mResourceCache.push_front(_resource);
mResourceIndex.erase(it);
mResourceIndex[_resource.getName()] = mResourceCache.begin();
}
else
{
// Si le cache est plein.
if(mResourceCache.size() == mMaxSize)
{
// On retire la dernière ressource du cache c'est-à-dire celle utilisée le moins récemment.
Resource<T> resourceToRemove = mResourceCache.back();
Ogre::String resourceName = resourceToRemove.getName();
mResourceIndex.erase(resourceName);
mResourceCache.pop_back();
}
mResourceCache.push_front(_resource);
mResourceIndex[_resource.getName()] = mResourceCache.begin();
}
}
void removeResource(const Ogre::String& _resourceName)
{
ItResourceIndex it = mResourceIndex.find(_resourceName);
if(it != mResourceIndex.end())
{
mResourceCache.erase((*it).second);
mResourceIndex.erase(it);
}
}
Resource<T> getResource(const Ogre::String& _resourceName)
{
ItResourceIndex it = mResourceIndex.find(_resourceName);
if(it != mResourceIndex.end())
{
return (*(*it).second);
}
else
{
return Resource<T>();
}
}
bool isResourceInCache(const Ogre::String& _resourceName) const
{
return mResourceIndex.find(_resourceName) != mResourceIndex.end();
}
};
} // Naos. |
Partager