現在、次のようにマップの値の参照カウントキャッシュを実装しています。
//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;
それとも別のやり方ですか?
- 編集 -
これが私の意図を明確にするための特定のクラスです。これは、ユーザーには決して表示されない残りのコードに対して厳密にユーティリティであるプライベートクラスであることが意図されています。彼らにとって、彼らはただスプライトを作成しているだけです。注:構造体はプライベートと見なされ、BITMAP
構造体を作成/破棄/変更する唯一の方法は、生のポインターの使用を必要とするサードパーティのCライブラリにある多くの関数の1つを使用することです。
BitmapCache.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
BitmapCache.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