GEL  2
GEL is a library for Geometry and Linear Algebra
/Users/jab/Documents/Teaching/02585/GEL2_and_demos/GEL/src/Util/ResourceManager.h
00001 #ifndef __UTIL_RESOURCE_MANAGER_H
00002 #define __UTIL_RESOURCE_MANAGER_H
00003 
00004 #include <cassert>
00005 #include <string>
00006 #include <list>
00007 #include <typeinfo>
00008 
00009 #define CLEAN_SHUTDOWN 1
00010 
00011 namespace Util
00012 {
00013 
00014         typedef unsigned char FlagByte;
00015         const FlagByte REMOVE_WHEN_UNUSED = 0x01;
00016         const FlagByte STATIC_RESOURCE    = 0x02;
00017 
00023         template<class RES>
00024         class ResourceRecord
00025         {
00027     const std::string name;
00028 
00030                 RES * const res;
00031                 
00033                 int usage;
00034 
00036                 FlagByte flags;
00037 
00038         public:
00039         
00041                 ResourceRecord(): res(0), usage(0), flags(0) {}
00042 
00044                 ResourceRecord(const std::string& _name, RES* _res, bool static_res=false): 
00045                         name(_name), 
00046                         res(_res), 
00047                         usage(0), 
00048                         flags(static_res ? STATIC_RESOURCE : 0) 
00049                 {
00050                         assert(res != 0);
00051                 }
00052 
00053                 ~ResourceRecord() 
00054                 {
00055 #if CLEAN_SHUTDOWN
00056                         assert(usage==0);               
00057 #endif
00058                 }
00059         
00060                 void erase_resource()
00061                 {
00062                         assert(usage==0);
00063                         if(!(flags&STATIC_RESOURCE)) 
00064                                 {
00065                                         delete res;
00066                                 }
00067                 }
00068 
00070                 void increment_usage() 
00071                 {
00072                         assert(usage>=0);
00073                         ++usage;
00074                 }
00075 
00077                 void decrement_usage() 
00078                 {
00079                         assert(usage>0);
00080                         --usage;
00081                 }
00082 
00084                 int get_usage() const { return usage; }
00085 
00087                 const std::string& get_name() const {return name;}
00088 
00090                 RES * const get_ptr() 
00091                 {
00092                         return res;
00093                 }
00094 
00096                 const RES * const get_ptr() const 
00097                 {
00098                         return res;
00099                 }
00100 
00101                 void remove_when_unused() 
00102                 {
00103 /*                      assert(!(flags&STATIC_RESOURCE)); */
00104 /*                      if(!(flags&STATIC_RESOURCE)) */
00105                                 flags = flags|REMOVE_WHEN_UNUSED;
00106                 }
00107 
00108                 FlagByte get_flags() const { return flags;}
00109         
00110         };
00111 
00112 
00113         template<class RES> class ResourceManager;
00114 
00115 
00125         template<class RES>
00126         class ResourcePtr
00127         {
00128                 typedef ResourceRecord<RES> RR;
00129                 typedef std::list<RR> RRList;
00130                 typedef typename RRList::iterator RRListIter;
00131 
00132                 static RRListIter get_null_rrlist_iter()
00133                 {
00134                         static RRList l;
00135                         return l.end();
00136                 }
00137 
00138 #define NULL_RRLIST_ITER ResourcePtr<RES>::get_null_rrlist_iter()               
00139 
00140                 friend class ResourceManager<RES>;
00141 
00142         private:                
00143                 RRListIter rr;
00144                 RES* res;
00145         
00148                 explicit ResourcePtr(const RRListIter& _rr): rr(_rr), res(0)
00149                 {
00150                         if(rr != NULL_RRLIST_ITER)
00151                                 {
00152                                         rr->increment_usage();
00153                                         res = rr->get_ptr();
00154                                 }
00155                 }
00156 
00157                 void decrement_usage();
00158         
00159         public:
00160         
00161                 ResourcePtr(): rr(NULL_RRLIST_ITER), res(0) {}
00162         
00163                 ResourcePtr(const ResourcePtr& r2): rr(r2.rr), res(0)
00164                 {
00165                         if(rr != NULL_RRLIST_ITER)
00166                                 {
00167                                         rr->increment_usage();
00168                                         res = rr->get_ptr();
00169                                 }
00170                 }
00171 
00172                 const ResourcePtr& operator=(const ResourcePtr& r2) 
00173                 {
00174                         // Guard against self-assignment
00175                         if (r2.rr != this->rr)
00176                                 {
00177                                         if(rr != NULL_RRLIST_ITER)      decrement_usage();
00178 
00179                                         rr  = r2.rr;
00180                                         res = 0;
00181 
00182                                         if(rr != NULL_RRLIST_ITER)
00183                                                 {
00184                                                         res = rr->get_ptr();
00185                                                         rr->increment_usage();
00186                                                 }
00187                                 }
00188                         return *this;
00189                 }
00190 
00191                 ~ResourcePtr() {decrement_usage();}
00192 
00193                 RES& operator*() const 
00194                 {
00195                         assert(rr != NULL_RRLIST_ITER);
00196                         assert(res != 0);
00197                         return *res;
00198                 }
00199 
00200                 RES* const operator->() const 
00201                 {
00202                         assert(rr != NULL_RRLIST_ITER);
00203                         assert(res !=0);
00204                         return res;
00205                 }
00206 
00207                 RES* const get_raw_ptr() const 
00208                 {
00209                         assert(rr != NULL_RRLIST_ITER);
00210                         assert(res != 0);
00211                         return res;
00212                 }
00213 
00214                 int usage() const
00215                 {
00216                         if(rr != NULL_RRLIST_ITER)
00217                                 return rr->get_usage();
00218                         return -1;
00219                 }
00220 
00221                 bool is_valid() const {return rr != NULL_RRLIST_ITER;}
00222 
00223                 void relinquish_resource()
00224                 {
00225                         ResourcePtr p;
00226                         *this = p;
00227                 }
00228 
00231                 void remove_when_unused() {     rr->remove_when_unused(); }
00232         };
00233 
00234 
00249         template<class RES>
00250         class ResourceManager
00251         {
00252                 typedef ResourceRecord<RES> RR;
00253                 typedef std::list<RR> RRList;
00254                 typedef typename RRList::iterator RRListIter;
00255                 RRList resources;
00256         
00257                 ResourceManager(): resources(0) {}
00258                 ResourceManager(const ResourceManager&);
00259                 ResourceManager& operator=(const ResourceManager&);
00260 
00261         public:
00262 
00263 
00264                 ~ResourceManager()
00265                 {
00266 #if CLEAN_SHUTDOWN
00267                         RRListIter i = resources.begin(); 
00268                         while(i != resources.end())
00269                                 {
00270                                         if(i->get_usage()==0)
00271                                                 {
00272                                                         RRListIter tmp = i;
00273                                                         ++i;
00274                                                         erase_resource(tmp);
00275                                                 }
00276                                         else
00277                                                 {
00278                                                         std::cout << "Warning, ResourceManager:\n\n"
00279                                                                                                 << (typeid(this).name())
00280                                                                                                 << "\n\nis shutting down, and resource \n\n" 
00281                                                                                                 << i->get_name() << "\n\nhas usage: " << i->get_usage()
00282                                                                                                 << std::endl;
00283                                                         std::cout <<
00284                                                                 "In other words, this resource is not unused at this\n"
00285                                                                 "point. That is unfortunate because then it cannot\n"
00286                                                                 "be deleted (since it might be used by some other\n"
00287                                                                 "part of the program during shutdown). Please ensure\n"
00288                                                                 "that all resources are unused at program\n"
00289                                                                 "termination. If you use a global ResourcePtr, this is\n"
00290                                                                 "done by calling relinquish_resource just before\n"
00291                                                                 "exiting.\n"
00292                                                                                                 << std::endl;
00293                                                         ++i;
00294                                                 }
00295                                 }
00296 #endif
00297                 }
00298 
00299                 int get_no_resources() const
00300                 {
00301                         return resources.size();
00302                 }
00303 
00304                 static ResourceManager& get_instance() 
00305                 {
00306                         static ResourceManager instance;
00307                         return instance;
00308                 }
00309 
00310                 void erase_resource(RRListIter iter)
00311                 {
00312                         iter->erase_resource();
00313                         resources.erase(iter);
00314                 }
00315 
00318                 ResourcePtr<RES> get_resource_ptr(const std::string& str)
00319                 {
00320                         for(RRListIter i = resources.begin(); i != resources.end(); ++i)
00321                                 if((*i).get_name() == str) 
00322                                         return ResourcePtr<RES>(i);
00323                         return ResourcePtr<RES>(NULL_RRLIST_ITER);
00324                 }
00325 
00329                 ResourcePtr<RES> register_resource(const std::string& str, 
00330                                                                                                                                                          RES* res, bool static_resource)
00331                 {
00332                         for(RRListIter i = resources.begin(); i != resources.end(); ++i)
00333                                 if(i->get_name() == str)
00334                                         return (ResourcePtr<RES>(NULL_RRLIST_ITER));
00335 
00336                         resources.push_front(RR(str, res, static_resource));
00337                         ResourcePtr<RES> ptr = ResourcePtr<RES>(resources.begin());
00338                         return ptr;
00339                 }
00340 
00341 /*              friend class ResourcePtr<RES>;
00342                 friend int get_no_resources<RES>();
00343                 friend ResourcePtr<RES> get_resource_ptr<RES>(const std::string& str); 
00344                 friend ResourcePtr<RES> register_static_resource<RES>(const std::string&,
00345                                                                                                                                                                                                                                         RES*); 
00346                 friend ResourcePtr<RES> register_dynamic_resource<RES>(const std::string&,
00347                                                                                                                                                                                                                                          RES*);*/ 
00348         };
00349 
00350         template<class RES>
00351         inline void ResourcePtr<RES>::decrement_usage()
00352         {
00353                 assert( (rr == NULL_RRLIST_ITER) || (res != 0));
00354                 if(rr != NULL_RRLIST_ITER)
00355                         {
00356                                 rr->decrement_usage();
00357                                 if(rr->get_usage() == 0 && (rr->get_flags()&REMOVE_WHEN_UNUSED))
00358                                         {
00359                                                 ResourceManager<RES>& man = ResourceManager<RES>::get_instance();
00360                                                 man.erase_resource(rr);
00361                                         }
00362                         }
00363         }
00364 
00365         template<class RES>
00366         inline int get_no_resources()
00367         {
00368                 ResourceManager<RES>& man = ResourceManager<RES>::get_instance();
00369                 return man.get_no_resources();
00370         }
00371 
00372         template<class RES>
00373         inline ResourcePtr<RES> get_resource_ptr(const std::string& str)
00374         {
00375                 ResourceManager<RES>& man = ResourceManager<RES>::get_instance();
00376                 return man.get_resource_ptr(str);
00377         }
00378 
00379         template<class RES>
00380         inline ResourcePtr<RES> register_dynamic_resource(const std::string& str,RES* res)
00381         {
00382                 ResourceManager<RES>& man = ResourceManager<RES>::get_instance();
00383                 ResourcePtr<RES> ptr = man.register_resource(str, res, false);
00384                 return ptr;
00385         }
00386 
00387         template<class RES>
00388         inline ResourcePtr<RES> register_static_resource(const std::string& str,RES* res)
00389         {
00390                 ResourceManager<RES>& man = ResourceManager<RES>::get_instance();
00391                 ResourcePtr<RES> ptr = man.register_resource(str, res, true);
00392                 return ptr;
00393         }
00394 
00395 }
00396 
00397 
00398 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations