(http://www.stratos-ad.com/forums/style_images/1/pip.gif) GenericManager (http://www.stratos-ad.com/forums/style_images/1/pip.gif)
En estos dias de examenes que, curiosamente, te apetece programar mas de lo normal he programado en ratos libres este GenericManager. Lo cierto es que no añade nada nuevo y hace no mucho mas que la clase que publico Gunder en edevi ( http://209.50.244.56/edevi/nums/3/article....e.php?f=coc.php ) pero tiene cosas que pueden ser interesantes.
En mi caso uso este manager en dos casos que pueden servir como ejemplos:
typedef patterns::GenericManager<Texture,TextureLoader<GLTexture> > TextureManager;
typedef patterns::GenericManager<Texture,TextureLoader<GLTexture> >::Item TextureItem;
De esta forma se puede usar asi:
TextureItem textureid = TextureManager::Instance()->GetItem("Textura.tga");
(quizas ponga mi genericfactory algun dia y pegue el ejemplo de TextureLoader :)
Otra forma de uso es la siguiente:
class ShaderManager
:public patterns::GenericManager<Shader,Shader,std::string,false,ShaderManager>
{
...
};
de forma que al coger la instacia con el Metodo Instace retornara una instacia a ShaderManager (parece que no pero tiene su intringulis)
Sin mas el codigo es el siguiente:
namespace patterns
{
struct manager_null_type {};
//con precache siepre hay una instacia de cada item, solo se borran al final
template <class Type,class Super = Type,class Key = std::string, bool Create_if_not_exists = true,class Manager = manager_null_type >
class GenericManager
{
typedef GenericManager<Type,Super,Key,Create_if_not_exists,Manager> ManagerType;
//hack para evitar recursividad en el template
template <class T>
struct manager_traits
{
typedef T manager ;
};
template <>
struct manager_traits<manager_null_type>
{
typedef GenericManager<Type,Super,Key,Create_if_not_exists,manager_null_type> manager;
};
//fin hack
public:
typedef Type ItemBase;
class Item
{
friend ManagerType;
Type *p;
GenericManager *parent;
const Key *__key;
int *__count;
Item(const Key &s,GenericManager *p,Type *_p,int *c):
__key(&s),
parent(p),
__count(c),
p(_p)
{}
public:
/*explicit*/ Item(const Item &i = NullItem()):
__key(i.__key),
parent(i.parent),
__count(i.__count),
p(i.p)
{
add_ptr();
}
Item& operator=(const Item& other)
{
if(&other == this) return *this;
release_ptr();
__count = other.__count;
p = other.p;
parent = other.parent;
__key = other.__key;
add_ptr();
return *this;
}
void release_ptr()
{
if(__count &&!--(*__count)) parent->ReleaseItem(this);
}
void add_ptr()
{
if(__count) ++(*__count);
}
void __debug_info()
{
debuglog << "key: " << *__key << endl;
debuglog << "count: " << *__count << endl;
}
public:
~Item()
{
release_ptr();
}
operator bool()
{
return p!=0;
}
Type *operator->()
{
return p;
}
static Item NullItem()
{
static Item nullitem("",0,0,0);
return nullitem;
}
friend bool operator==(const Item &i,const Item &o)
{
if(i.p == o.p) return true;
else return false;
}
friend bool operator!=(const Item &i,const Item &o)
{
if(i.p != o.p) return true;
else return false;
}
};
private:
struct TypeCount
{
TypeCount(Type *_p):
p(_p),count(1){}
Type *p;
int count;
};
typedef std::map<Key,TypeCount*> TypeMap;
TypeMap Map;
protected:
GenericManager()
{}
public:
~GenericManager()
{
TypeMap::iterator i = Map.begin();
for(;i!= Map.end();++i)
{
debuglog << "deleting..." << (*i).first << endl;
delete (*i).second->p;
delete (*i).second;
}
}
//friend class manager_traits;
static manager_traits<Manager>::manager* Instance()
{
static manager_traits<Manager>::manager gm;
return &gm;
}
Item GetItem(const Key &key)
{
debuglog << "GetItem:: searching " << key.c_str() << endl;
TypeMap::iterator it = Map.find(key);
if(it == Map.end())
{
debuglog << "*NOT FOUND!*" << endl;
if(Create_if_not_exists)
{
if(!CreateItem(key)) return Item::NullItem() ;
}
else return Item::NullItem() ;
it = Map.find(key);
}
debuglog << "*FOUND!*" << endl;
TypeCount *i = (*it).second;//Map[key];
return Item((*it).first,this,i->p,&i->count);
}
bool CreateItem(const Key &key,Super *sp = 0)
{
debuglog << "CreateItem::creating... " << key.c_str() << endl;
TypeMap::iterator it = Map.find(key);
if(it == Map.end())
{
Type *p;
if(sp) p = sp;
else
{
p = new Super(key);
if(!p) return false;
}
Map[key] = new TypeCount(p);
//p->__key = const_cast(&(*Map.find(key)).first);
return true;
}
return false;
}
void ReleaseItem(Item *item)
{
//pre-erase [virtual]
TypeMap::iterator i = Map.find(*item->__key);
delete item->p;
delete (*i).second;
Map.erase(i);
}
void __debug_info()
{
debuglog << "numitems: " << Map.size() << endl;
TypeMap::iterator i = Map.begin();
for(;i!=Map.end();++i)
{
debuglog << (*i).first << " :" << (*i).second->count << endl;
}
}
};
};
[/list]
parece interesante. Buen trabajo (ole)
template madness rlz