1 ////////////////////////////////////////////////////////////////////////////////
3 // Copyright (c) 2006 by Guillaume Chatelet
5 // Code covered by the MIT License
7 // Permission to use, copy, modify, distribute and sell this software for any
8 // purpose is hereby granted without fee, provided that the above copyright
9 // notice appear in all copies and that both that copyright notice and this
10 // permission notice appear in supporting documentation.
12 // The authors make no representations about the suitability of this software
13 // for any purpose. It is provided "as is" without express or implied warranty.
15 // This code DOES NOT accompany the book:
16 // Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
17 // Patterns Applied". Copyright (c) 2001. Addison-Wesley.
19 ////////////////////////////////////////////////////////////////////////////////
20 #ifndef LOKI_CACHEDFACTORY_INC_
21 #define LOKI_CACHEDFACTORY_INC_
23 // $Id: CachedFactory.h 950 2009-01-26 19:45:54Z syntheticpp $
34 #ifdef DO_EXTRA_LOKI_TESTS
40 #if defined(_MSC_VER) || defined(__CYGWIN__)
45 * \defgroup FactoriesGroup Factories
46 * \defgroup CachedFactoryGroup Cached Factory
47 * \ingroup FactoriesGroup
48 * \brief CachedFactory provides an extension of a Factory with caching
51 * Once used objects are returned to the CachedFactory that manages its
53 * If your code uses lots of "long to construct/destruct objects" using the
54 * CachedFactory will surely speedup the execution.
59 * \defgroup EncapsulationPolicyCachedFactoryGroup Encapsulation policies
60 * \ingroup CachedFactoryGroup
61 * \brief Defines how the object is returned to the client
64 * \class SimplePointer
65 * \ingroup EncapsulationPolicyCachedFactoryGroup
66 * \brief No encaspulation : returns the pointer
68 * This implementation does not make any encapsulation.
69 * It simply returns the object's pointer.
71 template<class AbstractProduct>
75 typedef AbstractProduct *ProductReturn;
76 ProductReturn encapsulate(AbstractProduct *pProduct)
81 AbstractProduct *release(ProductReturn &pProduct)
83 AbstractProduct *pPointer(pProduct);
94 * \defgroup CreationPolicyCachedFactoryGroup Creation policies
95 * \ingroup CachedFactoryGroup
96 * \brief Defines a way to limit the creation operation.
98 * For instance one may want to be alerted (Exception) when
99 * - Cache has created a more than X object within the last x seconds
100 * - Cache creation rate has increased dramatically
102 * which may result from bad caching strategy, or critical overload
106 * \ingroup CreationPolicyCachedFactoryGroup
107 * \brief Never allows creation. Testing purposes only.
109 * Using this policy will throw an exception.
114 struct Exception : public std::exception
116 const char *what() const throw()
118 return "NeverFetch Policy : No Fetching allowed";
136 * \class AlwaysCreate
137 * \ingroup CreationPolicyCachedFactoryGroup
138 * \brief Always allows creation.
140 * Doesn't limit the creation in any way
160 * \class RateLimitedCreation
161 * \ingroup CreationPolicyCachedFactoryGroup
162 * \brief Limit in rate.
164 * This implementation will prevent from Creating more than maxCreation objects
165 * within byTime ms by throwing an exception.
166 * Could be usefull to detect prevent loads (http connection for instance).
167 * Use the setRate method to set the rate parameters.
168 * default is 10 objects in a second.
171 // The std::clock() function is not quite precise
172 // under linux this policy might not work.
173 // TODO : get a better implementation (platform dependant)
174 class RateLimitedCreation
177 typedef std::vector< clock_t > Vector;
179 unsigned maxCreation;
180 clock_t timeValidity;
186 clock_t currentTime = clock();
187 D( cout << "currentTime = " << currentTime<< endl; )
188 D( cout << "currentTime - lastUpdate = " << currentTime - lastUpdate<< endl; )
189 if(currentTime - lastUpdate > timeValidity)
192 D( cout << " is less than time validity " << timeValidity; )
193 D( cout << " so clearing vector" << endl; )
197 D( cout << "Cleaning time less than " << currentTime - timeValidity << endl; )
198 D( displayVector(); )
199 Vector::iterator newEnd = remove_if(m_vTimes.begin(), m_vTimes.end(), bind2nd(less<clock_t>(), currentTime - timeValidity));
200 // this rearrangement might be costly, consider optimization
201 // by calling cleanVector in less used onCreate function
202 // ... although it may not be correct
203 m_vTimes.erase(newEnd, m_vTimes.end());
204 D( displayVector(); )
206 lastUpdate = currentTime;
208 #ifdef DO_EXTRA_LOKI_TESTS
211 std::cout << "Vector : ";
212 copy(m_vTimes.begin(), m_vTimes.end(), std::ostream_iterator<clock_t>(std::cout, " "));
213 std::cout << std::endl;
217 RateLimitedCreation() : maxCreation(10), timeValidity(CLOCKS_PER_SEC), lastUpdate(clock())
220 struct Exception : public std::exception
222 const char *what() const throw()
224 return "RateLimitedCreation Policy : Exceeded the authorized creation rate";
231 if(m_vTimes.size()>maxCreation)
239 m_vTimes.push_back(clock());
247 return "rate limited";
250 // set the creation rate
251 // No more than maxCreation within byTime milliseconds
252 void setRate(unsigned maxCreation, unsigned byTime)
255 this->maxCreation = maxCreation;
256 this->timeValidity = static_cast<clock_t>(byTime * CLOCKS_PER_SEC / 1000);
257 D( std::cout << "Setting no more than "<< maxCreation <<" creation within " << this->timeValidity <<" ms"<< std::endl; )
262 * \class AmountLimitedCreation
263 * \ingroup CreationPolicyCachedFactoryGroup
264 * \brief Limit by number of objects
266 * This implementation will prevent from Creating more than maxCreation objects
267 * within byTime ms by calling eviction policy.
268 * Use the setRate method to set the rate parameters.
269 * default is 10 objects.
271 class AmountLimitedCreation
274 unsigned maxCreation;
278 AmountLimitedCreation() : maxCreation(10), created(0)
283 return !(created>=maxCreation);
297 return "amount limited";
300 // set the creation max amount
301 void setMaxCreation(unsigned maxCreation)
303 assert(maxCreation>0);
304 this->maxCreation = maxCreation;
305 D( std::cout << "Setting no more than " << maxCreation <<" creation" << std::endl; )
310 * \defgroup EvictionPolicyCachedFactoryGroup Eviction policies
311 * \ingroup CachedFactoryGroup
312 * \brief Gathers informations about the stored objects and choose a
313 * candidate for eviction.
316 class EvictionException : public std::exception
319 const char *what() const throw()
321 return "Eviction Policy : trying to make room but no objects are available";
325 // The following class is intented to provide helpers to sort
326 // the container that will hold an eviction score
329 typename ST, // Score type
330 typename DT // Data type
335 typedef typename std::map< DT, ST > HitMap;
336 typedef typename HitMap::iterator HitMapItr;
338 typedef std::pair< ST, DT > SwappedPair;
339 typedef std::multimap< ST, DT > SwappedHitMap;
340 typedef typename SwappedHitMap::iterator SwappedHitMapItr;
344 // This function sorts the map according to the score
345 // and returns the lower bound of the sorted container
348 assert(!m_mHitCount.empty());
349 // inserting the swapped pair into a multimap
350 SwappedHitMap copyMap;
351 for(HitMapItr itr = m_mHitCount.begin(); itr != m_mHitCount.end(); ++itr)
352 copyMap.insert(SwappedPair((*itr).second, (*itr).first));
353 if((*copyMap.rbegin()).first == 0) // the higher score is 0 ...
354 throw EvictionException(); // there is no key evict
355 return (*copyMap.begin()).second;
361 * \ingroup EvictionPolicyCachedFactoryGroup
362 * \brief Evicts least accessed objects first.
364 * Implementation of the Least recent used algorithm as
365 * described in http://en.wikipedia.org/wiki/Page_replacement_algorithms .
367 * WARNING : If an object is heavily fetched
368 * (more than ULONG_MAX = UINT_MAX = 4294967295U)
369 * it could unfortunately be removed from the cache.
373 typename DT, // Data Type (AbstractProduct*)
374 typename ST = unsigned // default data type to use as Score Type
376 class EvictLRU : public EvictionHelper< ST , DT >
379 typedef EvictionHelper< ST , DT > EH;
382 virtual ~EvictLRU() {}
384 // OnStore initialize the counter for the new key
385 // If the key already exists, the counter is reseted
386 void onCreate(const DT &key)
388 EH::m_mHitCount[key] = 0;
391 void onFetch(const DT &)
395 // onRelease increments the hit counter associated with the object
396 void onRelease(const DT &key)
398 ++(EH::m_mHitCount[key]);
401 void onDestroy(const DT &key)
403 EH::m_mHitCount.erase(key);
406 // this function is implemented in Cache and redirected
407 // to the Storage Policy
408 virtual void remove(DT const key)=0;
410 // LRU Eviction policy
413 remove(EH::getLowerBound());
423 * \ingroup EvictionPolicyCachedFactoryGroup
424 * \brief LRU aware of the time span of use
426 * Implementation of the Aging algorithm as
427 * described in http://en.wikipedia.org/wiki/Page_replacement_algorithms .
429 * This method is much more costly than evict LRU so
430 * if you need extreme performance consider switching to EvictLRU
434 typename DT, // Data Type (AbstractProduct*)
435 typename ST = unsigned // default data type to use as Score Type
437 class EvictAging : public EvictionHelper< ST, DT >
440 EvictAging(const EvictAging &);
441 EvictAging &operator=(const EvictAging &);
442 typedef EvictionHelper< ST, DT > EH;
443 typedef typename EH::HitMap HitMap;
444 typedef typename EH::HitMapItr HitMapItr;
446 // update the counter
447 template<class T> struct updateCounter : public std::unary_function<T, void>
449 updateCounter(const DT &key): key_(key) {}
452 x.second = (x.first == key_ ? (x.second >> 1) | ( 1 << ((sizeof(ST)-1)*8) ) : x.second >> 1);
453 D( std::cout << x.second << std::endl; )
456 updateCounter(const updateCounter &rhs) : key_(rhs.key_) {}
458 updateCounter &operator=(const updateCounter &rhs);
462 virtual ~EvictAging() {}
464 // OnStore initialize the counter for the new key
465 // If the key already exists, the counter is reseted
466 void onCreate(const DT &key)
468 EH::m_mHitCount[key] = 0;
471 void onFetch(const DT &) {}
473 // onRelease increments the hit counter associated with the object
474 // Updating every counters by iterating over the map
475 // If the key is the key of the fetched object :
476 // the counter is shifted to the right and it's MSB is set to 1
478 // the counter is shifted to the left
479 void onRelease(const DT &key)
481 std::for_each(EH::m_mHitCount.begin(), EH::m_mHitCount.end(), updateCounter< typename HitMap::value_type >(key));
484 void onDestroy(const DT &key)
486 EH::m_mHitCount.erase(key);
489 // this function is implemented in Cache and redirected
490 // to the Storage Policy
491 virtual void remove(DT const key)=0;
493 // LRU with Aging Eviction policy
496 remove(EH::getLowerBound());
500 return "LRU with aging";
506 * \ingroup EvictionPolicyCachedFactoryGroup
507 * \brief Evicts a random object
509 * Implementation of the Random algorithm as
510 * described in http://en.wikipedia.org/wiki/Page_replacement_algorithms .
514 typename DT, // Data Type (AbstractProduct*)
515 typename ST = void // Score Type not used by this policy
520 std::vector< DT > m_vKeys;
521 typedef typename std::vector< DT >::size_type size_type;
522 typedef typename std::vector< DT >::iterator iterator;
526 virtual ~EvictRandom() {}
528 void onCreate(const DT &)
532 void onFetch(const DT & )
536 void onRelease(const DT &key)
538 m_vKeys.push_back(key);
541 void onDestroy(const DT &key)
544 m_vKeys.erase(remove_if(m_vKeys.begin(), m_vKeys.end(), bind2nd(equal_to< DT >(), key)), m_vKeys.end());
547 // Implemented in Cache and redirected to the Storage Policy
548 virtual void remove(DT const key)=0;
550 // Random Eviction policy
554 throw EvictionException();
555 size_type random = static_cast<size_type>((m_vKeys.size()*rand())/(static_cast<size_type>(RAND_MAX) + 1));
556 remove(*(m_vKeys.begin()+random));
565 * \defgroup StatisticPolicyCachedFactoryGroup Statistic policies
566 * \ingroup CachedFactoryGroup
567 * \brief Gathers information about the cache.
569 * For debugging purpose this policy proposes to gather informations
570 * about the cache. This could be useful to determine whether the cache is
571 * mandatory or if the policies are well suited to the application.
574 * \class NoStatisticPolicy
575 * \ingroup StatisticPolicyCachedFactoryGroup
578 * Should be used in release code for better performances
580 class NoStatisticPolicy
595 * \class SimpleStatisticPolicy
596 * \ingroup StatisticPolicyCachedFactoryGroup
597 * \brief Simple statistics
599 * Provides the following informations about the cache :
602 * - Destroyed objects
605 * - Currently allocated
607 * - Cache overall efficiency
609 class SimpleStatisticPolicy
612 unsigned allocated, created, hit, out, fetched;
614 SimpleStatisticPolicy() : allocated(0), created(0), hit(0), out(0), fetched(0)
621 cout << "############################" << endl;
622 cout << "## About this cache " << this << endl;
623 cout << "## + Created objects : " << created << endl;
624 cout << "## + Fetched objects : " << fetched << endl;
625 cout << "## + Destroyed objects : " << created - allocated << endl;
626 cout << "## + Cache hit : " << hit << endl;
627 cout << "## + Cache miss : " << fetched - hit << endl;
628 cout << "## + Currently allocated : " << allocated << endl;
629 cout << "## + Currently out : " << out << endl;
630 cout << "############################" << endl;
633 cout << "## Overall efficiency " << 100*double(hit)/fetched <<"%"<< endl;
634 cout << "############################" << endl;
665 unsigned getCreated()
669 unsigned getFetched()
679 return fetched - hit;
681 unsigned getAllocated()
689 unsigned getDestroyed()
691 return created-allocated;
695 ///////////////////////////////////////////////////////////////////////////
696 // Cache Factory definition
697 ///////////////////////////////////////////////////////////////////////////
698 class CacheException : public std::exception
701 const char *what() const throw()
703 return "Internal Cache Error";
708 * \class CachedFactory
709 * \ingroup CachedFactoryGroup
710 * \brief Factory with caching support
712 * This class acts as a Factory (it creates objects)
713 * but also keeps the already created objects to prevent
714 * long constructions time.
716 * Note this implementation do not retain ownership.
720 class AbstractProduct,
721 typename IdentifierType,
722 typename CreatorParmTList = NullType,
723 template<class> class EncapsulationPolicy = SimplePointer,
724 class CreationPolicy = AlwaysCreate,
725 template <typename , typename> class EvictionPolicy = EvictRandom,
726 class StatisticPolicy = NoStatisticPolicy,
727 template<typename, class> class FactoryErrorPolicy = DefaultFactoryError,
728 class ObjVector = std::vector<AbstractProduct *>
730 class CachedFactory :
731 protected EncapsulationPolicy<AbstractProduct>,
732 public CreationPolicy, public StatisticPolicy, EvictionPolicy< AbstractProduct * , unsigned >
735 typedef Factory< AbstractProduct, IdentifierType, CreatorParmTList, FactoryErrorPolicy> MyFactory;
736 typedef FactoryImpl< AbstractProduct, IdentifierType, CreatorParmTList > Impl;
737 typedef Functor< AbstractProduct * , CreatorParmTList > ProductCreator;
738 typedef EncapsulationPolicy<AbstractProduct> NP;
739 typedef CreationPolicy CP;
740 typedef StatisticPolicy SP;
741 typedef EvictionPolicy< AbstractProduct * , unsigned > EP;
743 typedef typename Impl::Parm1 Parm1;
744 typedef typename Impl::Parm2 Parm2;
745 typedef typename Impl::Parm3 Parm3;
746 typedef typename Impl::Parm4 Parm4;
747 typedef typename Impl::Parm5 Parm5;
748 typedef typename Impl::Parm6 Parm6;
749 typedef typename Impl::Parm7 Parm7;
750 typedef typename Impl::Parm8 Parm8;
751 typedef typename Impl::Parm9 Parm9;
752 typedef typename Impl::Parm10 Parm10;
753 typedef typename Impl::Parm11 Parm11;
754 typedef typename Impl::Parm12 Parm12;
755 typedef typename Impl::Parm13 Parm13;
756 typedef typename Impl::Parm14 Parm14;
757 typedef typename Impl::Parm15 Parm15;
760 typedef typename NP::ProductReturn ProductReturn;
762 typedef Key< Impl, IdentifierType > MyKey;
763 typedef std::map< MyKey, ObjVector > KeyToObjVectorMap;
764 typedef std::map< AbstractProduct *, MyKey > FetchedObjToKeyMap;
767 KeyToObjVectorMap fromKeyToObjVector;
768 FetchedObjToKeyMap providedObjects;
771 ObjVector &getContainerFromKey(MyKey key)
773 return fromKeyToObjVector[key];
776 AbstractProduct *const getPointerToObjectInContainer(ObjVector &entry)
778 if(entry.empty()) // No object available
780 // the object will be created in the calling function.
781 // It has to be created in the calling function because of
782 // the variable number of parameters for CreateObject(...) method
787 // returning the found object
788 AbstractProduct *pObject(entry.back());
789 assert(pObject!=NULL);
795 bool shouldCreateObject(AbstractProduct *const pProduct)
797 if(pProduct!=NULL) // object already exists
799 if(CP::canCreate()==false) // Are we allowed to Create ?
800 EP::evict(); // calling Eviction Policy to clean up
804 void ReleaseObjectFromContainer(ObjVector &entry, AbstractProduct *const object)
806 entry.push_back(object);
809 void onFetch(AbstractProduct *const pProduct)
812 EP::onFetch(pProduct);
816 void onRelease(AbstractProduct *const pProduct)
819 EP::onRelease(pProduct);
823 void onCreate(AbstractProduct *const pProduct)
827 EP::onCreate(pProduct);
830 void onDestroy(AbstractProduct *const pProduct)
834 EP::onDestroy(pProduct);
838 template<class T> struct deleteObject : public std::unary_function<T, void>
846 // delete the objects in the vector
847 template<class T> struct deleteVectorObjects : public std::unary_function<T, void>
851 ObjVector &vec(x.second);
852 std::for_each(vec.begin(), vec.end(), deleteObject< typename ObjVector::value_type>());
856 // delete the keys of the map
857 template<class T> struct deleteMapKeys : public std::unary_function<T, void>
866 virtual void remove(AbstractProduct *const pProduct)
868 typename FetchedObjToKeyMap::iterator fetchedItr = providedObjects.find(pProduct);
869 if(fetchedItr!=providedObjects.end()) // object is unreleased.
870 throw CacheException();
871 bool productRemoved = false;
872 typename KeyToObjVectorMap::iterator objVectorItr;
873 typename ObjVector::iterator objItr;
874 for(objVectorItr=fromKeyToObjVector.begin(); objVectorItr!=fromKeyToObjVector.end(); ++objVectorItr)
876 ObjVector &v((*objVectorItr).second);
877 objItr = remove_if(v.begin(), v.end(), std::bind2nd(std::equal_to<AbstractProduct *>(), pProduct));
878 if(objItr != v.end()) // we found the vector containing pProduct and removed it
880 onDestroy(pProduct); // warning policies we are about to destroy an object
881 v.erase(objItr, v.end()); // real removing
882 productRemoved = true;
886 if(productRemoved==false)
887 throw CacheException(); // the product is not in the cache ?!
888 delete pProduct; // deleting it
892 CachedFactory() : factory(), fromKeyToObjVector(), providedObjects(), outObjects(0)
901 // cleaning the Cache
902 for_each(fromKeyToObjVector.begin(), fromKeyToObjVector.end(),
903 deleteVectorObjects< typename KeyToObjVectorMap::value_type >()
905 if(!providedObjects.empty())
907 // The factory is responsible for the creation and destruction of objects.
908 // If objects are out during the destruction of the Factory : deleting anyway.
909 // This might not be a good idea. But throwing an exception in a destructor is
910 // considered as a bad pratice and asserting might be too much.
911 // What to do ? Leaking memory or corrupting in use pointers ? hmm...
912 D( cout << "====>> Cache destructor : deleting "<< providedObjects.size()<<" in use objects <<====" << endl << endl; )
913 for_each(providedObjects.begin(), providedObjects.end(),
914 deleteMapKeys< typename FetchedObjToKeyMap::value_type >()
919 ///////////////////////////////////
920 // Acts as the proxy pattern and //
921 // forwards factory methods //
922 ///////////////////////////////////
924 bool Register(const IdentifierType &id, ProductCreator creator)
926 return factory.Register(id, creator);
929 template <class PtrObj, typename CreaFn>
930 bool Register(const IdentifierType &id, const PtrObj &p, CreaFn fn)
932 return factory.Register(id, p, fn);
935 bool Unregister(const IdentifierType &id)
937 return factory.Unregister(id);
940 /// Return the registered ID in this Factory
941 std::vector<IdentifierType>& RegisteredIds()
943 return factory.RegisteredIds();
946 ProductReturn CreateObject(const IdentifierType &id)
949 AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
950 if(shouldCreateObject(pProduct))
952 pProduct = factory.CreateObject(key.id);
956 providedObjects[pProduct] = key;
957 return NP::encapsulate(pProduct);
960 ProductReturn CreateObject(const IdentifierType &id,
964 AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
965 if(shouldCreateObject(pProduct))
967 pProduct = factory.CreateObject(key.id,key.p1);
971 providedObjects[pProduct] = key;
972 return NP::encapsulate(pProduct);
975 ProductReturn CreateObject(const IdentifierType &id,
979 AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
980 if(shouldCreateObject(pProduct))
982 pProduct = factory.CreateObject(key.id,key.p1,key.p2);
986 providedObjects[pProduct] = key;
987 return NP::encapsulate(pProduct);
990 ProductReturn CreateObject(const IdentifierType &id,
991 Parm1 p1, Parm2 p2, Parm3 p3)
993 MyKey key(id,p1,p2,p3);
994 AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
995 if(shouldCreateObject(pProduct))
997 pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3);
1001 providedObjects[pProduct] = key;
1002 return NP::encapsulate(pProduct);
1005 ProductReturn CreateObject(const IdentifierType &id,
1006 Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4)
1008 MyKey key(id,p1,p2,p3,p4);
1009 AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
1010 if(shouldCreateObject(pProduct))
1012 pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
1017 providedObjects[pProduct] = key;
1018 return NP::encapsulate(pProduct);
1021 ProductReturn CreateObject(const IdentifierType &id,
1022 Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5)
1024 MyKey key(id,p1,p2,p3,p4,p5);
1025 AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
1026 if(shouldCreateObject(pProduct))
1028 pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
1033 providedObjects[pProduct] = key;
1034 return NP::encapsulate(pProduct);
1037 ProductReturn CreateObject(const IdentifierType &id,
1038 Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1041 MyKey key(id,p1,p2,p3,p4,p5,p6);
1042 AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
1043 if(shouldCreateObject(pProduct))
1045 pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
1046 ,key.p4,key.p5,key.p6);
1050 providedObjects[pProduct] = key;
1051 return NP::encapsulate(pProduct);
1054 ProductReturn CreateObject(const IdentifierType &id,
1055 Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1056 Parm6 p6, Parm7 p7 )
1058 MyKey key(id,p1,p2,p3,p4,p5,p6,p7);
1059 AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
1060 if(shouldCreateObject(pProduct))
1062 pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
1063 ,key.p4,key.p5,key.p6,key.p7);
1067 providedObjects[pProduct] = key;
1068 return NP::encapsulate(pProduct);
1071 ProductReturn CreateObject(const IdentifierType &id,
1072 Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1073 Parm6 p6, Parm7 p7, Parm8 p8)
1075 MyKey key(id,p1,p2,p3,p4,p5,p6,p7,p8);
1076 AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
1077 if(shouldCreateObject(pProduct))
1079 pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
1080 ,key.p4,key.p5,key.p6,key.p7,key.p8);
1084 providedObjects[pProduct] = key;
1085 return NP::encapsulate(pProduct);
1088 ProductReturn CreateObject(const IdentifierType &id,
1089 Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1090 Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9)
1092 MyKey key(id,p1,p2,p3,p4,p5,p6,p7,p8,p9);
1093 AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
1094 if(shouldCreateObject(pProduct))
1096 pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
1097 ,key.p4,key.p5,key.p6,key.p7,key.p8,key.p9);
1101 providedObjects[pProduct] = key;
1102 return NP::encapsulate(pProduct);
1105 ProductReturn CreateObject(const IdentifierType &id,
1106 Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1107 Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9,Parm10 p10)
1109 MyKey key(id,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10);
1110 AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
1111 if(shouldCreateObject(pProduct))
1113 pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
1114 ,key.p4,key.p5,key.p6,key.p7,key.p8,key.p9,key.p10);
1118 providedObjects[pProduct] = key;
1119 return NP::encapsulate(pProduct);
1122 ProductReturn CreateObject(const IdentifierType &id,
1123 Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1124 Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10,
1127 MyKey key(id,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11);
1128 AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
1129 if(shouldCreateObject(pProduct))
1131 pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
1132 ,key.p4,key.p5,key.p6,key.p7,key.p8,key.p9,key.p10,key.p11);
1136 providedObjects[pProduct] = key;
1137 return NP::encapsulate(pProduct);
1140 ProductReturn CreateObject(const IdentifierType &id,
1141 Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1142 Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10,
1143 Parm11 p11, Parm12 p12)
1145 MyKey key(id,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12);
1146 AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
1147 if(shouldCreateObject(pProduct))
1149 pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
1150 ,key.p4,key.p5,key.p6,key.p7,key.p8,key.p9,key.p10,key.p11,key.p12);
1154 providedObjects[pProduct] = key;
1155 return NP::encapsulate(pProduct);
1158 ProductReturn CreateObject(const IdentifierType &id,
1159 Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1160 Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10,
1161 Parm11 p11, Parm12 p12, Parm13 p13)
1163 MyKey key(id,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13);
1164 AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
1165 if(shouldCreateObject(pProduct))
1167 pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
1168 ,key.p4,key.p5,key.p6,key.p7,key.p8,key.p9,key.p10,key.p11,key.p12
1173 providedObjects[pProduct] = key;
1174 return NP::encapsulate(pProduct);
1177 ProductReturn CreateObject(const IdentifierType &id,
1178 Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1179 Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10,
1180 Parm11 p11, Parm12 p12, Parm13 p13, Parm14 p14)
1182 MyKey key(id,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14);
1183 AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
1184 if(shouldCreateObject(pProduct))
1186 pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
1187 ,key.p4,key.p5,key.p6,key.p7,key.p8,key.p9,key.p10,key.p11,key.p12
1192 providedObjects[pProduct] = key;
1193 return NP::encapsulate(pProduct);
1196 ProductReturn CreateObject(const IdentifierType &id,
1197 Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
1198 Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10,
1199 Parm11 p11, Parm12 p12, Parm13 p13, Parm14 p14, Parm15 p15)
1201 MyKey key(id,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14,p15);
1202 AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
1203 if(shouldCreateObject(pProduct))
1205 pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
1206 ,key.p4,key.p5,key.p6,key.p7,key.p8,key.p9,key.p10,key.p11,key.p12
1207 ,key.p13,key.p14,key.p15);
1211 providedObjects[pProduct] = key;
1212 return NP::encapsulate(pProduct);
1215 /// Use this function to release the object
1217 * if execution brakes in this function then you tried
1218 * to release an object that wasn't provided by this Cache
1219 * ... which is bad :-)
1221 void ReleaseObject(ProductReturn &object)
1223 AbstractProduct *pProduct(NP::release(object));
1224 typename FetchedObjToKeyMap::iterator itr = providedObjects.find(pProduct);
1225 if(itr == providedObjects.end())
1226 throw CacheException();
1227 onRelease(pProduct);
1228 ReleaseObjectFromContainer(getContainerFromKey((*itr).second), pProduct);
1229 providedObjects.erase(itr);
1232 /// display the cache configuration
1233 void displayCacheType()
1235 using namespace std;
1236 cout << "############################" << endl;
1237 cout << "## Cache configuration" << endl;
1238 cout << "## + Encapsulation " << NP::name() << endl;
1239 cout << "## + Creating " << CP::name() << endl;
1240 cout << "## + Eviction " << EP::name() << endl;
1241 cout << "## + Statistics " << SP::name() << endl;
1242 cout << "############################" << endl;
1247 #endif // end file guardian