Foros - Stratos

Programadores => Código de la Semana => Mensaje iniciado por: ethernet en 26 de Febrero de 2004, 09:16:37 PM

Título: Genericmanager - Ethernet
Publicado por: ethernet en 26 de Febrero de 2004, 09:16:37 PM
 
(http://www.stratos-ad.com/forums/style_images/1/pip.gif)     GenericManager  (http://www.stratos-ad.com/forums/style_images/1/pip.gif)


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]


Título: Genericmanager - Ethernet
Publicado por: CoLSoN2 en 26 de Febrero de 2004, 09:40:41 PM
 parece interesante. Buen trabajo (ole)

template madness rlz