目前我已经实现了映射值的引用计数缓存,如下所示:
//filename or name of bitmap, reference count, memory location...
std::map<std::string, std::pair<long, BITMAP*> > _cache;
使用 std::multimap 是更好的选择吗?
//filename or name of bitmap, memory location...
std::multimap<std::string, BITMAP*> _cache;
或者只是一种不同的方式?
- 编辑 -
这是为了清楚我的意图的特定类它旨在成为一个私有类,对用户从未见过的其余代码严格实用。对他们来说,他们只是在创建一个 Sprite。注意:该BITMAP
结构被认为是私有的,创建/销毁/修改结构的唯一方法是通过第 3 方 C 库中需要使用原始指针的众多函数之一。
位图缓存.h
#ifndef A2DE_CBITMAPCACHE_H
#define A2DE_CBITMAPCACHE_H
#include "../a2de_vals.h"
#include <allegro/file.h>
#include <allegro/gfx.h>
#include <allegro/draw.h>
#include <allegro/datafile.h>
#include <allegro/color.h>
#include <map>
#include <utility>
#include <string>
struct BITMAP;
_A2DE_BEGIN
class BitmapCache {
public:
static BITMAP* GetBitmap(std::string filename);
static BITMAP* StoreBitmap(std::string name, BITMAP* bmp);
static BITMAP* RetrieveBitmap(std::string name);
static std::string GetBitmapName(BITMAP* file);
static void RemoveBitmap(std::string name);
protected:
private:
static std::map<std::string, std::pair<long, BITMAP*> > _cache;
static void CleanCache();
};
_A2DE_END
#endif
位图缓存.cpp
#include "CBitmapCache.h"
#include <algorithm>
#include <map>
_A2DE_BEGIN
//filename or name of bitmap, reference count, memory location...
typedef std::map<std::string, std::pair<long, BITMAP*> > MapStrBmp;
typedef MapStrBmp::iterator MapStrBmpIter;
MapStrBmp BitmapCache::_cache;
BITMAP* BitmapCache::GetBitmap(std::string filename) {
//Return NULL if a bad filename was passed.
if(filename.empty()) return NULL;
if(exists(filename.c_str()) == false) return NULL;
//Reduce incorrect results by forcing slash equality.
filename = fix_filename_slashes(&filename[0]);
//Clean the cache if it's dirty.
CleanCache();
//Search for requested BITMAP.
MapStrBmpIter _iter = _cache.find(filename);
//If found, return it.
if(_iter != _cache.end()) {
_iter->second.first++;
return _iter->second.second;
}
//Otherwise, create it, store it, then return it.
BITMAP* result = load_bmp(filename.c_str(), NULL);
if(result == NULL) return NULL;
_cache.insert(std::make_pair(filename, std::make_pair(static_cast<long>(1), result)));
return result;
}
BITMAP* BitmapCache::StoreBitmap(std::string name, BITMAP* bmp) {
if(name.empty() || bmp == NULL) return NULL;
CleanCache();
name = fix_filename_slashes(&name[0]);
MapStrBmpIter _iter = _cache.find(name);
if(_iter != _cache.end()) {
_iter->second.first++;
return _iter->second.second;
}
_cache.insert(std::make_pair(name, std::make_pair(static_cast<long>(1), bmp)));
return bmp;
}
BITMAP* BitmapCache::RetrieveBitmap(std::string name) {
if(name.empty()) return NULL;
name = fix_filename_slashes(&name[0]);
MapStrBmpIter _iter = _cache.find(name);
if(_iter != _cache.end()) {
_iter->second.first++;
return _iter->second.second;
}
return NULL;
}
void BitmapCache::RemoveBitmap(std::string name) {
if(name.empty()) return;
name = fix_filename_slashes(&name[0]);
MapStrBmpIter _iter = _cache.find(name);
if(_iter != _cache.end()) {
_iter->second.first--;
CleanCache();
}
}
std::string BitmapCache::GetBitmapName(BITMAP* file) {
if(file == NULL) return std::string("");
CleanCache();
MapStrBmpIter b = _cache.begin();
MapStrBmpIter e = _cache.end();
for(MapStrBmpIter _iter = b; _iter != e; ++_iter) {
if(_iter->second.second != file) continue;
return _iter->first;
}
return std::string("");
}
void BitmapCache::CleanCache() {
//Clean the cache of any bitmaps that are no longer referenced.
MapStrBmpIter b = _cache.begin();
MapStrBmpIter e = _cache.end();
for(MapStrBmpIter _iter = b; _iter != e; /* DO NOTHING */ ) {
if(_iter->second.first > 0) {
++_iter;
continue;
}
destroy_bitmap(_iter->second.second);
_iter->second.second = NULL;
_cache.erase(_iter++);
}
}
_A2DE_END