00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00020 #ifndef LOKI_CACHEDFACTORY_INC_
00021 #define LOKI_CACHEDFACTORY_INC_
00022
00023
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
00159
00160
00161
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
00189
00190
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
00233
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
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
00302
00303 template
00304 <
00305 typename ST,
00306 typename DT
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
00321
00322 DT& getLowerBound(){
00323 assert(!m_mHitCount.empty());
00324
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)
00329 throw EvictionException();
00330 return (*copyMap.begin()).second;
00331 }
00332 };
00333
00346 template
00347 <
00348 typename DT,
00349 typename ST = unsigned
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
00360
00361 void onCreate(const DT& key)
00362 {
00363 EH::m_mHitCount[key] = 0;
00364 }
00365
00366 void onFetch(const DT&)
00367 {
00368 }
00369
00370
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
00382
00383 virtual void remove(DT const key)=0;
00384
00385
00386 void evict()
00387 {
00388 remove(EH::getLowerBound());
00389 }
00390 const char* name(){return "LRU";}
00391 };
00392
00404 template
00405 <
00406 typename DT,
00407 typename ST = unsigned
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
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
00437
00438 void onCreate(const DT& key){
00439 EH::m_mHitCount[key] = 0;
00440 }
00441
00442 void onFetch(const DT&){}
00443
00444
00445
00446
00447
00448
00449
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
00461
00462 virtual void remove(DT const key)=0;
00463
00464
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,
00483 typename ST = void
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
00512 virtual void remove(DT const key)=0;
00513
00514
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
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())
00708 {
00709
00710
00711 return NULL;
00712 }
00713 else
00714 {
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)
00724 return false;
00725 if(CP::canCreate()==false)
00726 EP::evict();
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
00764 template<class T> struct deleteObject : public std::unary_function<T, void>
00765 {
00766 void operator()(T x){ delete x; }
00767 };
00768
00769
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
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())
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())
00798 {
00799 onDestroy(pProduct);
00800 v.erase(objItr, v.end());
00801 productRemoved = true;
00802 break;
00803 }
00804 }
00805 if(productRemoved==false)
00806 throw CacheException();
00807 delete pProduct;
00808 }
00809
00810 public:
00811 CachedFactory() : factory(), fromKeyToObjVector(), providedObjects(), outObjects(0)
00812 {
00813 }
00814
00815 ~CachedFactory()
00816 {
00817 using namespace std;
00818
00819 SP::onDebug();
00820
00821 for_each(fromKeyToObjVector.begin(), fromKeyToObjVector.end(),
00822 deleteVectorObjects< typename KeyToObjVectorMap::value_type >()
00823 );
00824 if(!providedObjects.empty())
00825 {
00826
00827
00828
00829
00830
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
00840
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 }
01165
01166 #endif // end file guardian
01167