CachedFactory.h

00001 
00002 // The Loki Library
00003 // Copyright (c) 2006 by Guillaume Chatelet
00004 //
00005 // Code covered by the MIT License
00006 //
00007 // Permission to use, copy, modify, distribute and sell this software for any 
00008 // purpose is hereby granted without fee, provided that the above copyright 
00009 // notice appear in all copies and that both that copyright notice and this 
00010 // permission notice appear in supporting documentation.
00011 //
00012 // The authors make no representations about the suitability of this software
00013 // for any purpose. It is provided "as is" without express or implied warranty.
00014 //
00015 // This code DOES NOT accompany the book:
00016 // Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design 
00017 //     Patterns Applied". Copyright (c) 2001. Addison-Wesley.
00018 //
00020 #ifndef LOKI_CACHEDFACTORY_INC_
00021 #define LOKI_CACHEDFACTORY_INC_
00022 
00023 // $Id: CachedFactory.h 810 2007-02-25 14:36:28Z syntheticpp $
00024 
00025 #include <functional>
00026 #include <algorithm>
00027 #include <iostream>
00028 #include <vector>
00029 #include <iterator>
00030 #include <map>
00031 #include <cassert>
00032 #include <loki/Key.h>
00033 
00034 #ifdef DO_EXTRA_LOKI_TESTS
00035      #define D( x ) x
00036 #else
00037      #define D( x ) ;
00038 #endif
00039 
00040 #ifdef _MSC_VER
00041 #include <time.h>
00042 #endif
00043 
00056 namespace Loki
00057 {
00071      template<class AbstractProduct>     
00072      class SimplePointer
00073      {
00074      protected:
00075            typedef AbstractProduct* ProductReturn;
00076            ProductReturn encapsulate(AbstractProduct* pProduct)
00077            {
00078                 return pProduct;
00079            }
00080            
00081            AbstractProduct* release(ProductReturn &pProduct)
00082            {
00083                 AbstractProduct* pPointer(pProduct);
00084                 pProduct=NULL;
00085                 return pPointer;
00086            }
00087            const char* name(){return "pointer";}
00088      };
00089 
00108      class NeverCreate
00109      {
00110      protected:
00111             struct Exception : public std::exception
00112             {
00113                 const char* what() const throw() { return "NeverFetch Policy : No Fetching allowed"; }
00114             };
00115             
00116             bool canCreate()
00117             {
00118                 throw Exception();
00119             }
00120             
00121             void onCreate(){}
00122             void onDestroy(){}
00123             const char* name(){return "never";}
00124      };
00125      
00133      class AlwaysCreate
00134      {
00135      protected:
00136             bool canCreate()
00137             {
00138                 return true;
00139             }
00140 
00141             void onCreate(){}
00142             void onDestroy(){}
00143             const char* name(){return "always";}
00144      };
00145 
00146 
00158      // !! CAUTION !!
00159      // The std::clock() function is not quite precise
00160      // under linux this policy might not work.
00161      // TODO : get a better implementation (platform dependant)
00162      class RateLimitedCreation
00163      {
00164      private:
00165             typedef std::vector< clock_t > Vector;
00166             Vector m_vTimes;
00167             unsigned maxCreation;
00168             clock_t timeValidity;
00169             clock_t lastUpdate;
00170           
00171             void cleanVector()
00172             {
00173                using namespace std;
00174                     clock_t currentTime = clock();
00175                 D( cout << "currentTime = " << currentTime<< endl; )
00176                 D( cout << "currentTime - lastUpdate = " << currentTime - lastUpdate<< endl; )
00177                 if(currentTime - lastUpdate > timeValidity)
00178                 {
00179                     m_vTimes.clear();
00180                     D( cout << " is less than time validity " << timeValidity; )
00181                     D( cout << " so clearing vector" << endl; )
00182                 }
00183                 else
00184                 {
00185                     D( cout << "Cleaning time less than " << currentTime - timeValidity << endl; )
00186                     D( displayVector(); )
00187                     Vector::iterator newEnd = remove_if(m_vTimes.begin(), m_vTimes.end(), bind2nd(less<clock_t>(), currentTime - timeValidity));
00188                     // this rearrangement might be costly, consider optimization
00189                     // by calling cleanVector in less used onCreate function
00190                     // ... although it may not be correct
00191                     m_vTimes.erase(newEnd, m_vTimes.end());
00192                     D( displayVector(); )
00193                 }
00194                 lastUpdate = currentTime;
00195             }
00196 #ifdef DO_EXTRA_LOKI_TESTS        
00197             void displayVector()
00198             {
00199                 std::cout << "Vector : ";
00200                 copy(m_vTimes.begin(), m_vTimes.end(), std::ostream_iterator<clock_t>(std::cout, " "));
00201                 std::cout << std::endl;
00202             }
00203 #endif
00204      protected:
00205             RateLimitedCreation() : maxCreation(10), timeValidity(CLOCKS_PER_SEC), lastUpdate(clock())
00206             {}
00207             
00208             struct Exception : public std::exception
00209             {
00210                 const char* what() const throw() { return "RateLimitedCreation Policy : Exceeded the authorized creation rate"; }
00211             };
00212             
00213             bool canCreate()
00214             {
00215                 cleanVector();
00216                 if(m_vTimes.size()>maxCreation)
00217                     throw Exception();
00218                 else
00219                     return true;
00220             }
00221 
00222             void onCreate()
00223             {
00224                     m_vTimes.push_back(clock());
00225             }
00226             
00227             void onDestroy()
00228             {
00229             }
00230             const char* name(){return "rate limited";}
00231      public:
00232             // set the creation rate
00233             // No more than maxCreation within byTime milliseconds
00234             void setRate(unsigned maxCreation, unsigned byTime)
00235             {
00236                 assert(byTime>0);
00237                 this->maxCreation = maxCreation;
00238                 this->timeValidity = static_cast<clock_t>(byTime * CLOCKS_PER_SEC / 1000);
00239                 D( std::cout << "Setting no more than "<< maxCreation <<" creation within " << this->timeValidity <<" ms"<< std::endl; )
00240             }
00241      };
00242      
00253      class AmountLimitedCreation
00254      {
00255      private:
00256             unsigned maxCreation;
00257             unsigned created;
00258             
00259      protected:
00260             AmountLimitedCreation() : maxCreation(10), created(0)
00261             {}
00262             
00263             bool canCreate()
00264             {
00265                return !(created>=maxCreation);
00266             }
00267 
00268             void onCreate()
00269             {
00270                 ++created;
00271             }
00272             
00273             void onDestroy()
00274             {
00275                 --created;
00276             }
00277             const char* name(){return "amount limited";}
00278      public:
00279             // set the creation max amount
00280             void setMaxCreation(unsigned maxCreation)
00281             {
00282                 assert(maxCreation>0);
00283                 this->maxCreation = maxCreation;
00284                 D( std::cout << "Setting no more than " << maxCreation <<" creation" << std::endl; )
00285             }
00286      };
00287      
00295     class EvictionException : public std::exception
00296     {
00297     public:
00298         const char* what() const throw() { return "Eviction Policy : trying to make room but no objects are available"; }
00299     };
00300 
00301     // The following class is intented to provide helpers to sort
00302     // the container that will hold an eviction score
00303     template
00304     <
00305      typename ST, // Score type
00306      typename DT // Data type
00307     >
00308     class EvictionHelper
00309     {
00310     protected:
00311         typedef typename std::map< DT, ST >            HitMap;
00312         typedef typename HitMap::iterator              HitMapItr;
00313     private:
00314         typedef std::pair< ST, DT >                         SwappedPair;
00315         typedef std::multimap< ST, DT >                SwappedHitMap;
00316      typedef   typename SwappedHitMap::iterator   SwappedHitMapItr;
00317     protected:
00318         HitMap                                              m_mHitCount;
00319      
00320      // This function sorts the map according to the score
00321      // and returns the lower bound of the sorted container
00322      DT&  getLowerBound(){
00323           assert(!m_mHitCount.empty());
00324           // inserting the swapped pair into a multimap
00325           SwappedHitMap copyMap;
00326           for(HitMapItr itr = m_mHitCount.begin(); itr != m_mHitCount.end(); ++itr)
00327                copyMap.insert(SwappedPair((*itr).second, (*itr).first));
00328           if((*copyMap.rbegin()).first == 0) // the higher score is 0 ...
00329             throw EvictionException(); // there is no key evict
00330           return (*copyMap.begin()).second;
00331      }
00332     };
00333     
00346     template
00347     <
00348      typename DT, // Data Type (AbstractProduct*)
00349      typename ST = unsigned // default data type to use as Score Type
00350     >
00351     class EvictLRU : public EvictionHelper< ST , DT >
00352     {
00353     private:
00354      typedef EvictionHelper< ST , DT >  EH;
00355     protected:
00356         
00357         virtual ~EvictLRU(){}
00358         
00359      // OnStore initialize the counter for the new key
00360      // If the key already exists, the counter is reseted
00361      void onCreate(const DT& key)
00362         {
00363           EH::m_mHitCount[key] = 0;
00364      }
00365      
00366      void onFetch(const DT&)
00367         {
00368      }
00369      
00370      // onRelease increments the hit counter associated with the object
00371         void onRelease(const DT& key)
00372         {
00373           ++(EH::m_mHitCount[key]);
00374         }
00375 
00376      void onDestroy(const DT& key)
00377      {
00378             EH::m_mHitCount.erase(key);
00379      }
00380      
00381      // this function is implemented in Cache and redirected
00382      // to the Storage Policy
00383      virtual void remove(DT const key)=0;
00384 
00385      // LRU Eviction policy
00386      void evict()
00387      {
00388           remove(EH::getLowerBound());
00389      }
00390         const char* name(){return "LRU";}
00391     };
00392     
00404     template
00405     <
00406      typename DT, // Data Type (AbstractProduct*)
00407      typename ST = unsigned // default data type to use as Score Type
00408     >
00409     class EvictAging : public EvictionHelper< ST, DT >
00410     {
00411     private:
00412         EvictAging(const EvictAging&);
00413         EvictAging& operator=(const EvictAging&);
00414      typedef EvictionHelper< ST, DT >                       EH;
00415      typedef typename EH::HitMap                            HitMap;
00416      typedef typename EH::HitMapItr                         HitMapItr;
00417      
00418      // update the counter
00419           template<class T> struct updateCounter : public std::unary_function<T, void>
00420           {
00421                updateCounter(const DT& key): key_(key){}
00422                void operator()(T x)
00423                {
00424                     x.second = (x.first == key_ ? (x.second >> 1) | ( 1 << ((sizeof(ST)-1)*8) ) : x.second >> 1);
00425                D( std::cout <<  x.second << std::endl; )
00426                }
00427                const DT &key_;
00428             updateCounter(const updateCounter& rhs) : key_(rhs.key_){}
00429         private:
00430             updateCounter& operator=(const updateCounter& rhs);
00431           };
00432     protected:
00433          EvictAging(){}
00434          virtual ~EvictAging(){}
00435          
00436      // OnStore initialize the counter for the new key
00437      // If the key already exists, the counter is reseted
00438      void onCreate(const DT& key){
00439           EH::m_mHitCount[key] = 0;
00440      }
00441      
00442      void onFetch(const DT&){}
00443      
00444      // onRelease increments the hit counter associated with the object
00445      // Updating every counters by iterating over the map
00446      // If the key is the key of the fetched object :
00447      //  the counter is shifted to the right and it's MSB is set to 1
00448      // else
00449      //  the counter is shifted to the left
00450         void onRelease(const DT& key)
00451         {
00452           std::for_each(EH::m_mHitCount.begin(), EH::m_mHitCount.end(), updateCounter< typename HitMap::value_type >(key));
00453         }
00454         
00455         void onDestroy(const DT& key)
00456         {
00457             EH::m_mHitCount.erase(key);
00458         }
00459 
00460      // this function is implemented in Cache and redirected
00461      // to the Storage Policy
00462      virtual void remove(DT const key)=0;
00463 
00464      // LRU with Aging Eviction policy
00465      void evict()
00466      {
00467           remove(EH::getLowerBound());
00468      }
00469         const char* name(){return "LRU with aging";}
00470     };
00471     
00480     template
00481     <
00482      typename DT, // Data Type (AbstractProduct*)
00483      typename ST = void // Score Type not used by this policy
00484     >
00485     class EvictRandom
00486     {
00487     private:
00488      std::vector< DT >   m_vKeys;
00489      typedef typename std::vector< DT >::size_type     size_type;
00490      typedef typename std::vector< DT >::iterator      iterator;
00491 
00492     protected:
00493     
00494           virtual ~EvictRandom(){};
00495           
00496      void onCreate(const DT&){
00497      }
00498      
00499      void onFetch(const DT& ){
00500      }
00501 
00502      void onRelease(const DT& key){
00503             m_vKeys.push_back(key);
00504      }
00505      
00506      void onDestroy(const DT& key){
00507           using namespace std;
00508             m_vKeys.erase(remove_if(m_vKeys.begin(), m_vKeys.end(), bind2nd(equal_to< DT >(), key)), m_vKeys.end());
00509      }
00510      
00511      // Implemented in Cache and redirected to the Storage Policy
00512      virtual void remove(DT const key)=0;
00513 
00514      // Random Eviction policy
00515      void evict()
00516      {
00517           if(m_vKeys.empty())
00518               throw EvictionException();
00519           size_type random = static_cast<size_type>((m_vKeys.size()*rand())/int(RAND_MAX + 1));
00520           remove(*(m_vKeys.begin()+random));
00521      }
00522         const char* name(){return "random";}
00523     };
00524 
00541     class NoStatisticPolicy
00542     {
00543     protected:
00544         void onDebug(){}
00545         void onFetch(){}
00546         void onRelease(){}
00547         void onCreate(){}
00548         void onDestroy(){}
00549         const char* name(){return "no";}
00550     };
00551     
00567     class SimpleStatisticPolicy
00568     {
00569     private:
00570         unsigned allocated, created, hit, out, fetched;
00571     protected:
00572         SimpleStatisticPolicy() : allocated(0), created(0), hit(0), out(0), fetched(0)
00573         {
00574         }
00575         
00576         void onDebug()
00577         {
00578           using namespace std;
00579             cout << "############################" << endl;
00580             cout << "## About this cache " << this << endl;
00581             cout << "## + Created objects     : " << created << endl;
00582             cout << "## + Fetched objects     : " << fetched << endl;
00583             cout << "## + Destroyed objects   : " << created - allocated << endl;
00584             cout << "## + Cache hit           : " << hit << endl;
00585             cout << "## + Cache miss          : " << fetched - hit << endl;
00586             cout << "## + Currently allocated : " << allocated << endl;
00587             cout << "## + Currently out       : " << out << endl;
00588             cout << "############################" << endl;
00589             if(fetched!=0){
00590                 cout << "## Overall efficiency " << 100*double(hit)/fetched <<"%"<< endl;
00591                 cout << "############################" << endl;
00592             }
00593             cout << endl;
00594         }
00595         
00596         void onFetch()
00597         {
00598             ++fetched;
00599             ++out;
00600             ++hit;
00601         }
00602         void onRelease()
00603         {
00604             --out;
00605         }
00606         void onCreate()
00607         {
00608             ++created;
00609             ++allocated;
00610             --hit;
00611         }
00612         void onDestroy()
00613         {
00614             --allocated;
00615         }
00616 
00617         const char* name(){return "simple";}
00618     public:
00619         unsigned getCreated(){return created;}
00620         unsigned getFetched(){return fetched;}
00621         unsigned getHit(){return hit;}
00622         unsigned getMissed(){return fetched - hit;}
00623         unsigned getAllocated(){return allocated;}
00624         unsigned getOut(){return out;}
00625         unsigned getDestroyed(){return created-allocated;}
00626     }; 
00627     
00629     // Cache Factory definition
00631     class CacheException : public std::exception
00632     {
00633     public:
00634         const char* what() const throw() { return "Internal Cache Error"; }
00635     };
00636      
00648       template
00649      <
00650         class AbstractProduct,
00651         typename IdentifierType,
00652         typename CreatorParmTList = NullType,
00653         template<class> class EncapsulationPolicy = SimplePointer,
00654         class CreationPolicy = AlwaysCreate,
00655         template <typename , typename> class EvictionPolicy = EvictRandom,
00656         class StatisticPolicy = NoStatisticPolicy,
00657         template<typename, class> class FactoryErrorPolicy = DefaultFactoryError,
00658         class ObjVector = std::vector<AbstractProduct*>
00659      >
00660       class CachedFactory : 
00661             protected EncapsulationPolicy<AbstractProduct>,
00662             public CreationPolicy, public StatisticPolicy, EvictionPolicy< AbstractProduct * , unsigned >
00663       {
00664      private:
00665         typedef Factory< AbstractProduct, IdentifierType, CreatorParmTList, FactoryErrorPolicy> Factory;
00666         typedef FactoryImpl< AbstractProduct, IdentifierType, CreatorParmTList > Impl;
00667         typedef Functor< AbstractProduct* , CreatorParmTList > ProductCreator;
00668         typedef EncapsulationPolicy<AbstractProduct> NP;
00669         typedef CreationPolicy  CP;
00670         typedef StatisticPolicy SP;
00671         typedef EvictionPolicy< AbstractProduct* , unsigned > EP;
00672                 
00673         typedef typename Impl::Parm1 Parm1;
00674         typedef typename Impl::Parm2 Parm2;
00675         typedef typename Impl::Parm3 Parm3;
00676         typedef typename Impl::Parm4 Parm4;
00677         typedef typename Impl::Parm5 Parm5;
00678         typedef typename Impl::Parm6 Parm6;
00679         typedef typename Impl::Parm7 Parm7;
00680         typedef typename Impl::Parm8 Parm8;
00681         typedef typename Impl::Parm9 Parm9;
00682         typedef typename Impl::Parm10 Parm10;
00683         typedef typename Impl::Parm11 Parm11;
00684         typedef typename Impl::Parm12 Parm12;
00685         typedef typename Impl::Parm13 Parm13;
00686         typedef typename Impl::Parm14 Parm14;
00687         typedef typename Impl::Parm15 Parm15;
00688         
00689      public:
00690         typedef typename NP::ProductReturn ProductReturn;
00691      private:
00692         typedef Key< Impl, IdentifierType > Key;
00693         typedef std::map< Key, ObjVector >  KeyToObjVectorMap;
00694         typedef std::map< AbstractProduct*, Key >  FetchedObjToKeyMap;
00695         
00696         Factory             factory;
00697         KeyToObjVectorMap   fromKeyToObjVector;
00698         FetchedObjToKeyMap  providedObjects;
00699         unsigned            outObjects;
00700 
00701         ObjVector& getContainerFromKey(Key key){
00702             return fromKeyToObjVector[key];
00703         }
00704 
00705         AbstractProduct* const getPointerToObjectInContainer(ObjVector &entry)
00706         {
00707             if(entry.empty()) // No object available
00708             {   // the object will be created in the calling function.
00709                 // It has to be created in the calling function because of
00710                 // the variable number of parameters for CreateObject(...) method
00711                 return NULL;
00712             }
00713             else
00714             {   // returning the found object
00715                     AbstractProduct* pObject(entry.back());
00716                     assert(pObject!=NULL);
00717                     entry.pop_back();
00718                 return pObject;
00719             }
00720         }
00721         
00722         bool shouldCreateObject(AbstractProduct * const pProduct){
00723             if(pProduct!=NULL) // object already exists
00724                 return false;
00725             if(CP::canCreate()==false) // Are we allowed to Create ?
00726                 EP::evict(); // calling Eviction Policy to clean up
00727             return true;
00728         }
00729         
00730         void ReleaseObjectFromContainer(ObjVector &entry, AbstractProduct * const object)
00731         {
00732             entry.push_back(object);
00733         }
00734         
00735         void onFetch(AbstractProduct * const pProduct)
00736         {
00737             SP::onFetch();
00738             EP::onFetch(pProduct);
00739             ++outObjects;
00740         }
00741         
00742         void onRelease(AbstractProduct * const pProduct)
00743         {
00744             SP::onRelease();
00745             EP::onRelease(pProduct);
00746             --outObjects;
00747         }
00748         
00749         void onCreate(AbstractProduct * const pProduct)
00750         {
00751             CP::onCreate();
00752             SP::onCreate();
00753             EP::onCreate(pProduct);
00754         }
00755         
00756         void onDestroy(AbstractProduct * const pProduct)
00757         {
00758             CP::onDestroy();
00759             SP::onDestroy();
00760             EP::onDestroy(pProduct);
00761         }
00762           
00763           // delete the object
00764           template<class T> struct deleteObject : public std::unary_function<T, void>
00765           {
00766                void operator()(T x){ delete x; }
00767           };
00768 
00769           // delete the objects in the vector
00770           template<class T> struct deleteVectorObjects : public std::unary_function<T, void>
00771           {
00772                void operator()(T x){
00773                     ObjVector &vec(x.second);
00774                     std::for_each(vec.begin(), vec.end(), deleteObject< typename ObjVector::value_type>());
00775                }
00776           };
00777 
00778           // delete the keys of the map
00779           template<class T> struct deleteMapKeys : public std::unary_function<T, void>
00780           {
00781                void operator()(T x){ delete x.first; }
00782           };            
00783 
00784      protected:
00785         virtual void remove(AbstractProduct * const pProduct)
00786         {
00787             typename FetchedObjToKeyMap::iterator fetchedItr = providedObjects.find(pProduct);
00788             if(fetchedItr!=providedObjects.end()) // object is unreleased.
00789                 throw CacheException();
00790             bool productRemoved = false;
00791             typename KeyToObjVectorMap::iterator objVectorItr;
00792             typename ObjVector::iterator objItr;
00793             for(objVectorItr=fromKeyToObjVector.begin();objVectorItr!=fromKeyToObjVector.end();++objVectorItr)
00794             {
00795                 ObjVector &v((*objVectorItr).second);
00796                 objItr = remove_if(v.begin(), v.end(), std::bind2nd(std::equal_to<AbstractProduct*>(), pProduct));
00797                 if(objItr != v.end()) // we found the vector containing pProduct and removed it
00798                 {
00799                     onDestroy(pProduct); // warning policies we are about to destroy an object
00800                     v.erase(objItr, v.end()); // real removing
00801                     productRemoved = true;
00802                     break;
00803                 }
00804             }
00805             if(productRemoved==false)
00806                 throw CacheException(); // the product is not in the cache ?!
00807             delete pProduct; // deleting it
00808         }
00809 
00810      public:
00811         CachedFactory() : factory(), fromKeyToObjVector(), providedObjects(), outObjects(0)
00812         {
00813         }
00814 
00815         ~CachedFactory()
00816         {
00817           using namespace std;
00818             // debug information
00819             SP::onDebug();
00820             // cleaning the Cache
00821             for_each(fromKeyToObjVector.begin(), fromKeyToObjVector.end(),
00822                deleteVectorObjects< typename KeyToObjVectorMap::value_type >()
00823             );
00824             if(!providedObjects.empty())
00825             {
00826                     // The factory is responsible for the creation and destruction of objects.
00827                     // If objects are out during the destruction of the Factory : deleting anyway.
00828                     // This might not be a good idea. But throwing an exception in a destructor is
00829                     // considered as a bad pratice and asserting might be too much.
00830                     // What to do ? Leaking memory or corrupting in use pointers ? hmm...
00831                 D( cout << "====>>  Cache destructor : deleting "<< providedObjects.size()<<" in use objects  <<====" << endl << endl; )
00832                 for_each(providedObjects.begin(), providedObjects.end(),
00833                      deleteMapKeys< typename FetchedObjToKeyMap::value_type >()
00834                 );
00835             }
00836         }
00837         
00839         // Acts as the proxy pattern and //
00840         // forwards factory methods      //
00842         
00843         bool Register(const IdentifierType& id, ProductCreator creator)
00844         {
00845             return factory.Register(id, creator);
00846         }
00847         
00848         template <class PtrObj, typename CreaFn>
00849         bool Register(const IdentifierType& id, const PtrObj& p, CreaFn fn)
00850         {
00851             return factory.Register(id, p, fn);
00852         }
00853         
00854         bool Unregister(const IdentifierType& id)
00855         {
00856             return factory.Unregister(id);
00857         }
00858 
00860         std::vector<IdentifierType>& RegisteredIds()
00861         {
00862             return factory.RegisteredIds();
00863         }
00864 
00865         ProductReturn CreateObject(const IdentifierType& id)
00866         {
00867             Key key(id);
00868             AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
00869             if(shouldCreateObject(pProduct))
00870             {
00871                 pProduct = factory.CreateObject(key.id);
00872                 onCreate(pProduct);
00873             }
00874             onFetch(pProduct);
00875             providedObjects[pProduct] = key;
00876             return NP::encapsulate(pProduct);
00877         }
00878         
00879         ProductReturn CreateObject(const IdentifierType& id,
00880                         Parm1 p1)
00881         {
00882             Key key(id,p1);
00883             AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
00884             if(shouldCreateObject(pProduct))
00885             {
00886                 pProduct = factory.CreateObject(key.id,key.p1);
00887                 onCreate(pProduct);
00888             }
00889             onFetch(pProduct);
00890             providedObjects[pProduct] = key;
00891             return NP::encapsulate(pProduct);
00892         }
00893 
00894         ProductReturn CreateObject(const IdentifierType& id,
00895                         Parm1 p1, Parm2 p2)
00896         {
00897             Key key(id,p1,p2);
00898             AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
00899             if(shouldCreateObject(pProduct))
00900             {
00901                 pProduct = factory.CreateObject(key.id,key.p1,key.p2);
00902                 onCreate(pProduct);
00903             }
00904             onFetch(pProduct);
00905             providedObjects[pProduct] = key;
00906             return NP::encapsulate(pProduct);
00907         }
00908 
00909         ProductReturn CreateObject(const IdentifierType& id,
00910                         Parm1 p1, Parm2 p2, Parm3 p3)
00911         {
00912             Key key(id,p1,p2,p3);
00913             AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
00914             if(shouldCreateObject(pProduct))
00915             {
00916                 pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3);
00917                 onCreate(pProduct);
00918             }
00919             onFetch(pProduct);
00920             providedObjects[pProduct] = key;
00921             return NP::encapsulate(pProduct);
00922         }
00923 
00924         ProductReturn CreateObject(const IdentifierType& id,
00925                         Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4)
00926         {
00927             Key key(id,p1,p2,p3,p4);
00928             AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
00929             if(shouldCreateObject(pProduct))
00930             {
00931                 pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
00932                 ,key.p4);
00933                 onCreate(pProduct);
00934             }
00935             onFetch(pProduct);
00936             providedObjects[pProduct] = key;
00937             return NP::encapsulate(pProduct);
00938         }
00939 
00940         ProductReturn CreateObject(const IdentifierType& id,
00941                         Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5)
00942         {
00943             Key key(id,p1,p2,p3,p4,p5);
00944             AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
00945             if(shouldCreateObject(pProduct))
00946             {
00947                 pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
00948                 ,key.p4,key.p5);
00949                 onCreate(pProduct);
00950             }
00951             onFetch(pProduct);
00952             providedObjects[pProduct] = key;
00953             return NP::encapsulate(pProduct);
00954         }
00955 
00956         ProductReturn CreateObject(const IdentifierType& id,
00957                         Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
00958                         Parm6 p6)
00959         {
00960             Key key(id,p1,p2,p3,p4,p5,p6);
00961             AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
00962             if(shouldCreateObject(pProduct))
00963             {
00964                 pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
00965                 ,key.p4,key.p5,key.p6);
00966                 onCreate(pProduct);
00967             }
00968             onFetch(pProduct);
00969             providedObjects[pProduct] = key;
00970             return NP::encapsulate(pProduct);
00971         }
00972 
00973         ProductReturn CreateObject(const IdentifierType& id,
00974                         Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
00975                         Parm6 p6, Parm7 p7 )
00976         {
00977             Key key(id,p1,p2,p3,p4,p5,p6,p7);
00978             AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
00979             if(shouldCreateObject(pProduct))
00980             {
00981                 pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
00982                 ,key.p4,key.p5,key.p6,key.p7);
00983                 onCreate(pProduct);
00984             }
00985             onFetch(pProduct);
00986             providedObjects[pProduct] = key;
00987             return NP::encapsulate(pProduct);
00988         }
00989 
00990         ProductReturn CreateObject(const IdentifierType& id,
00991                         Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
00992                         Parm6 p6, Parm7 p7, Parm8 p8)
00993         {
00994             Key key(id,p1,p2,p3,p4,p5,p6,p7,p8);
00995             AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
00996             if(shouldCreateObject(pProduct))
00997             {
00998                 pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
00999                 ,key.p4,key.p5,key.p6,key.p7,key.p8);
01000                 onCreate(pProduct);
01001             }
01002             onFetch(pProduct);
01003             providedObjects[pProduct] = key;
01004             return NP::encapsulate(pProduct);
01005         }
01006 
01007         ProductReturn CreateObject(const IdentifierType& id,
01008                         Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
01009                         Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9)
01010         {
01011             Key key(id,p1,p2,p3,p4,p5,p6,p7,p8,p9);
01012             AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
01013             if(shouldCreateObject(pProduct))
01014             {
01015                 pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
01016                 ,key.p4,key.p5,key.p6,key.p7,key.p8,key.p9);
01017                 onCreate(pProduct);
01018             }
01019             onFetch(pProduct);
01020             providedObjects[pProduct] = key;
01021             return NP::encapsulate(pProduct);
01022         }
01023         
01024         ProductReturn CreateObject(const IdentifierType& id,
01025                         Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
01026                         Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9,Parm10 p10)
01027         {
01028             Key key(id,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10);
01029             AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
01030             if(shouldCreateObject(pProduct))
01031             {
01032                 pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
01033                 ,key.p4,key.p5,key.p6,key.p7,key.p8,key.p9,key.p10);
01034                 onCreate(pProduct);
01035             }
01036             onFetch(pProduct);
01037             providedObjects[pProduct] = key;
01038             return NP::encapsulate(pProduct);
01039         }
01040 
01041         ProductReturn CreateObject(const IdentifierType& id,
01042                         Parm1  p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5  p5,
01043                         Parm6  p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10,
01044                         Parm11 p11)
01045         {
01046             Key key(id,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11);
01047             AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
01048             if(shouldCreateObject(pProduct))
01049             {
01050                 pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
01051                 ,key.p4,key.p5,key.p6,key.p7,key.p8,key.p9,key.p10,key.p11);
01052                 onCreate(pProduct);
01053             }
01054             onFetch(pProduct);
01055             providedObjects[pProduct] = key;
01056             return NP::encapsulate(pProduct);
01057         }
01058 
01059         ProductReturn CreateObject(const IdentifierType& id,
01060                         Parm1  p1,  Parm2  p2, Parm3 p3, Parm4 p4, Parm5  p5,
01061                         Parm6  p6,  Parm7  p7, Parm8 p8, Parm9 p9, Parm10 p10,
01062                         Parm11 p11, Parm12 p12)
01063         {
01064             Key key(id,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12);
01065             AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
01066             if(shouldCreateObject(pProduct))
01067             {
01068                 pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
01069                 ,key.p4,key.p5,key.p6,key.p7,key.p8,key.p9,key.p10,key.p11,key.p12);
01070                 onCreate(pProduct);
01071             }
01072             onFetch(pProduct);
01073             providedObjects[pProduct] = key;
01074             return NP::encapsulate(pProduct);
01075         }
01076 
01077         ProductReturn CreateObject(const IdentifierType& id,
01078                         Parm1  p1,  Parm2  p2,  Parm3  p3, Parm4 p4, Parm5  p5,
01079                         Parm6  p6,  Parm7  p7,  Parm8  p8, Parm9 p9, Parm10 p10,
01080                         Parm11 p11, Parm12 p12, Parm13 p13)
01081         {
01082             Key key(id,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13);
01083             AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
01084             if(shouldCreateObject(pProduct))
01085             {
01086                 pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
01087                 ,key.p4,key.p5,key.p6,key.p7,key.p8,key.p9,key.p10,key.p11,key.p12
01088                 ,key.p13);
01089                 onCreate(pProduct);
01090             }
01091             onFetch(pProduct);
01092             providedObjects[pProduct] = key;
01093             return NP::encapsulate(pProduct);
01094         }
01095 
01096         ProductReturn CreateObject(const IdentifierType& id,
01097                         Parm1  p1,  Parm2  p2,  Parm3  p3,  Parm4  p4, Parm5  p5,
01098                         Parm6  p6,  Parm7  p7,  Parm8  p8,  Parm9  p9, Parm10 p10,
01099                         Parm11 p11, Parm12 p12, Parm13 p13, Parm14 p14)
01100         {
01101             Key key(id,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14);
01102             AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
01103             if(shouldCreateObject(pProduct))
01104             {
01105                 pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
01106                 ,key.p4,key.p5,key.p6,key.p7,key.p8,key.p9,key.p10,key.p11,key.p12
01107                 ,key.p13,key.p14);
01108                 onCreate(pProduct);
01109             }
01110             onFetch(pProduct);
01111             providedObjects[pProduct] = key;
01112             return NP::encapsulate(pProduct);
01113         }
01114 
01115         ProductReturn CreateObject(const IdentifierType& id,
01116                         Parm1  p1,  Parm2  p2,  Parm3  p3,  Parm4  p4,  Parm5  p5,
01117                         Parm6  p6,  Parm7  p7,  Parm8  p8,  Parm9  p9,  Parm10 p10,
01118                         Parm11 p11, Parm12 p12, Parm13 p13, Parm14 p14, Parm15 p15)
01119         {
01120             Key key(id,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14,p15);
01121             AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
01122             if(shouldCreateObject(pProduct))
01123             {
01124                 pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
01125                 ,key.p4,key.p5,key.p6,key.p7,key.p8,key.p9,key.p10,key.p11,key.p12
01126                 ,key.p13,key.p14,key.p15);
01127                 onCreate(pProduct);
01128             }
01129             onFetch(pProduct);
01130             providedObjects[pProduct] = key;
01131             return NP::encapsulate(pProduct);
01132         }
01133 
01135 
01140         void ReleaseObject(ProductReturn &object)
01141         {
01142             AbstractProduct* pProduct(NP::release(object));
01143             typename FetchedObjToKeyMap::iterator itr = providedObjects.find(pProduct);
01144             if(itr == providedObjects.end())
01145                 throw CacheException();
01146             onRelease(pProduct);
01147             ReleaseObjectFromContainer(getContainerFromKey((*itr).second), pProduct);
01148             providedObjects.erase(itr);
01149         }
01150         
01152         void displayCacheType()
01153         {
01154           using namespace std;
01155             cout << "############################" << endl;
01156             cout << "## Cache configuration" << endl;
01157             cout << "## + Encapsulation " << NP::name() << endl;
01158             cout << "## + Creating      " << CP::name() << endl;
01159             cout << "## + Eviction      " << EP::name() << endl;
01160             cout << "## + Statistics    " << SP::name() << endl;
01161             cout << "############################" << endl;
01162         }
01163      };
01164 } // namespace Loki
01165 
01166 #endif // end file guardian
01167 

Generated on Sun Feb 25 16:52:21 2007 for Loki by  doxygen 1.5.1-p1