summaryrefslogtreecommitdiff
path: root/shared/loki/CachedFactory.h
diff options
context:
space:
mode:
Diffstat (limited to 'shared/loki/CachedFactory.h')
-rw-r--r--shared/loki/CachedFactory.h2002
1 files changed, 1007 insertions, 995 deletions
diff --git a/shared/loki/CachedFactory.h b/shared/loki/CachedFactory.h
index 15c9a801..567b035c 100644
--- a/shared/loki/CachedFactory.h
+++ b/shared/loki/CachedFactory.h
@@ -4,16 +4,16 @@
//
// Code covered by the MIT License
//
-// Permission to use, copy, modify, distribute and sell this software for any
-// purpose is hereby granted without fee, provided that the above copyright
-// notice appear in all copies and that both that copyright notice and this
+// Permission to use, copy, modify, distribute and sell this software for any
+// purpose is hereby granted without fee, provided that the above copyright
+// notice appear in all copies and that both that copyright notice and this
// permission notice appear in supporting documentation.
//
// The authors make no representations about the suitability of this software
// for any purpose. It is provided "as is" without express or implied warranty.
//
// This code DOES NOT accompany the book:
-// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
+// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
//
////////////////////////////////////////////////////////////////////////////////
@@ -32,9 +32,9 @@
#include <loki/Key.h>
#ifdef DO_EXTRA_LOKI_TESTS
- #define D( x ) x
+#define D( x ) x
#else
- #define D( x ) ;
+#define D( x ) ;
#endif
#if defined(_MSC_VER) || defined(__CYGWIN__)
@@ -47,7 +47,7 @@
* \ingroup FactoriesGroup
* \brief CachedFactory provides an extension of a Factory with caching
* support.
- *
+ *
* Once used objects are returned to the CachedFactory that manages its
* destruction.
* If your code uses lots of "long to construct/destruct objects" using the
@@ -60,231 +60,231 @@ namespace Loki
* \ingroup CachedFactoryGroup
* \brief Defines how the object is returned to the client
*/
- /**
- * \class SimplePointer
- * \ingroup EncapsulationPolicyCachedFactoryGroup
- * \brief No encaspulation : returns the pointer
- *
- * This implementation does not make any encapsulation.
- * It simply returns the object's pointer.
- */
- template<class AbstractProduct>
- class SimplePointer
- {
- protected:
- typedef AbstractProduct* ProductReturn;
- ProductReturn encapsulate(AbstractProduct* pProduct)
- {
- return pProduct;
- }
-
- AbstractProduct* release(ProductReturn &pProduct)
- {
- AbstractProduct* pPointer(pProduct);
- pProduct=NULL;
- return pPointer;
- }
- const char* name(){return "pointer";}
- };
+/**
+ * \class SimplePointer
+ * \ingroup EncapsulationPolicyCachedFactoryGroup
+ * \brief No encaspulation : returns the pointer
+ *
+ * This implementation does not make any encapsulation.
+ * It simply returns the object's pointer.
+ */
+template<class AbstractProduct>
+class SimplePointer
+{
+protected:
+ typedef AbstractProduct* ProductReturn;
+ ProductReturn encapsulate(AbstractProduct* pProduct)
+ {
+ return pProduct;
+ }
+
+ AbstractProduct* release(ProductReturn& pProduct)
+ {
+ AbstractProduct* pPointer(pProduct);
+ pProduct=NULL;
+ return pPointer;
+ }
+ const char* name() {return "pointer";}
+};
/**
* \defgroup CreationPolicyCachedFactoryGroup Creation policies
* \ingroup CachedFactoryGroup
* \brief Defines a way to limit the creation operation.
- *
+ *
* For instance one may want to be alerted (Exception) when
* - Cache has created a more than X object within the last x seconds
* - Cache creation rate has increased dramatically
* .
* which may result from bad caching strategy, or critical overload
*/
- /**
- * \class NeverCreate
- * \ingroup CreationPolicyCachedFactoryGroup
- * \brief Never allows creation. Testing purposes only.
- *
- * Using this policy will throw an exception.
- */
- class NeverCreate
- {
- protected:
- struct Exception : public std::exception
- {
- const char* what() const throw() { return "NeverFetch Policy : No Fetching allowed"; }
- };
-
- bool canCreate()
- {
- throw Exception();
- }
-
- void onCreate(){}
- void onDestroy(){}
- const char* name(){return "never";}
- };
-
- /**
- * \class AlwaysCreate
- * \ingroup CreationPolicyCachedFactoryGroup
- * \brief Always allows creation.
- *
- * Doesn't limit the creation in any way
- */
- class AlwaysCreate
- {
- protected:
- bool canCreate()
- {
- return true;
- }
+/**
+ * \class NeverCreate
+ * \ingroup CreationPolicyCachedFactoryGroup
+ * \brief Never allows creation. Testing purposes only.
+ *
+ * Using this policy will throw an exception.
+ */
+class NeverCreate
+{
+protected:
+ struct Exception : public std::exception
+ {
+ const char* what() const throw() { return "NeverFetch Policy : No Fetching allowed"; }
+ };
- void onCreate(){}
- void onDestroy(){}
- const char* name(){return "always";}
- };
+ bool canCreate()
+ {
+ throw Exception();
+ }
+ void onCreate() {}
+ void onDestroy() {}
+ const char* name() {return "never";}
+};
- /**
- * \class RateLimitedCreation
- * \ingroup CreationPolicyCachedFactoryGroup
- * \brief Limit in rate.
- *
- * This implementation will prevent from Creating more than maxCreation objects
- * within byTime ms by throwing an exception.
- * Could be usefull to detect prevent loads (http connection for instance).
- * Use the setRate method to set the rate parameters.
- * default is 10 objects in a second.
- */
- // !! CAUTION !!
- // The std::clock() function is not quite precise
- // under linux this policy might not work.
- // TODO : get a better implementation (platform dependant)
- class RateLimitedCreation
- {
- private:
- typedef std::vector< clock_t > Vector;
- Vector m_vTimes;
- unsigned maxCreation;
- clock_t timeValidity;
- clock_t lastUpdate;
-
- void cleanVector()
- {
- using namespace std;
- clock_t currentTime = clock();
- D( cout << "currentTime = " << currentTime<< endl; )
- D( cout << "currentTime - lastUpdate = " << currentTime - lastUpdate<< endl; )
- if(currentTime - lastUpdate > timeValidity)
- {
- m_vTimes.clear();
- D( cout << " is less than time validity " << timeValidity; )
- D( cout << " so clearing vector" << endl; )
- }
- else
- {
- D( cout << "Cleaning time less than " << currentTime - timeValidity << endl; )
- D( displayVector(); )
- Vector::iterator newEnd = remove_if(m_vTimes.begin(), m_vTimes.end(), bind2nd(less<clock_t>(), currentTime - timeValidity));
- // this rearrangement might be costly, consider optimization
- // by calling cleanVector in less used onCreate function
- // ... although it may not be correct
- m_vTimes.erase(newEnd, m_vTimes.end());
- D( displayVector(); )
- }
- lastUpdate = currentTime;
- }
-#ifdef DO_EXTRA_LOKI_TESTS
- void displayVector()
- {
- std::cout << "Vector : ";
- copy(m_vTimes.begin(), m_vTimes.end(), std::ostream_iterator<clock_t>(std::cout, " "));
- std::cout << std::endl;
- }
+/**
+ * \class AlwaysCreate
+ * \ingroup CreationPolicyCachedFactoryGroup
+ * \brief Always allows creation.
+ *
+ * Doesn't limit the creation in any way
+ */
+class AlwaysCreate
+{
+protected:
+ bool canCreate()
+ {
+ return true;
+ }
+
+ void onCreate() {}
+ void onDestroy() {}
+ const char* name() {return "always";}
+};
+
+
+/**
+ * \class RateLimitedCreation
+ * \ingroup CreationPolicyCachedFactoryGroup
+ * \brief Limit in rate.
+ *
+ * This implementation will prevent from Creating more than maxCreation objects
+ * within byTime ms by throwing an exception.
+ * Could be usefull to detect prevent loads (http connection for instance).
+ * Use the setRate method to set the rate parameters.
+ * default is 10 objects in a second.
+ */
+// !! CAUTION !!
+// The std::clock() function is not quite precise
+// under linux this policy might not work.
+// TODO : get a better implementation (platform dependant)
+class RateLimitedCreation
+{
+private:
+ typedef std::vector< clock_t > Vector;
+ Vector m_vTimes;
+ unsigned maxCreation;
+ clock_t timeValidity;
+ clock_t lastUpdate;
+
+ void cleanVector()
+ {
+ using namespace std;
+ clock_t currentTime = clock();
+ D( cout << "currentTime = " << currentTime<< endl; )
+ D( cout << "currentTime - lastUpdate = " << currentTime - lastUpdate<< endl; )
+ if(currentTime - lastUpdate > timeValidity)
+ {
+ m_vTimes.clear();
+ D( cout << " is less than time validity " << timeValidity; )
+ D( cout << " so clearing vector" << endl; )
+ }
+ else
+ {
+ D( cout << "Cleaning time less than " << currentTime - timeValidity << endl; )
+ D( displayVector(); )
+ Vector::iterator newEnd = remove_if(m_vTimes.begin(), m_vTimes.end(), bind2nd(less<clock_t>(), currentTime - timeValidity));
+ // this rearrangement might be costly, consider optimization
+ // by calling cleanVector in less used onCreate function
+ // ... although it may not be correct
+ m_vTimes.erase(newEnd, m_vTimes.end());
+ D( displayVector(); )
+ }
+ lastUpdate = currentTime;
+ }
+#ifdef DO_EXTRA_LOKI_TESTS
+ void displayVector()
+ {
+ std::cout << "Vector : ";
+ copy(m_vTimes.begin(), m_vTimes.end(), std::ostream_iterator<clock_t>(std::cout, " "));
+ std::cout << std::endl;
+ }
#endif
- protected:
- RateLimitedCreation() : maxCreation(10), timeValidity(CLOCKS_PER_SEC), lastUpdate(clock())
- {}
-
- struct Exception : public std::exception
- {
- const char* what() const throw() { return "RateLimitedCreation Policy : Exceeded the authorized creation rate"; }
- };
-
- bool canCreate()
- {
- cleanVector();
- if(m_vTimes.size()>maxCreation)
- throw Exception();
- else
- return true;
- }
+protected:
+ RateLimitedCreation() : maxCreation(10), timeValidity(CLOCKS_PER_SEC), lastUpdate(clock())
+ {}
- void onCreate()
- {
- m_vTimes.push_back(clock());
- }
-
- void onDestroy()
- {
- }
- const char* name(){return "rate limited";}
- public:
- // set the creation rate
- // No more than maxCreation within byTime milliseconds
- void setRate(unsigned maxCreation, unsigned byTime)
- {
- assert(byTime>0);
- this->maxCreation = maxCreation;
- this->timeValidity = static_cast<clock_t>(byTime * CLOCKS_PER_SEC / 1000);
- D( std::cout << "Setting no more than "<< maxCreation <<" creation within " << this->timeValidity <<" ms"<< std::endl; )
- }
- };
-
- /**
- * \class AmountLimitedCreation
- * \ingroup CreationPolicyCachedFactoryGroup
- * \brief Limit by number of objects
- *
- * This implementation will prevent from Creating more than maxCreation objects
- * within byTime ms by calling eviction policy.
- * Use the setRate method to set the rate parameters.
- * default is 10 objects.
- */
- class AmountLimitedCreation
- {
- private:
- unsigned maxCreation;
- unsigned created;
-
- protected:
- AmountLimitedCreation() : maxCreation(10), created(0)
- {}
-
- bool canCreate()
- {
- return !(created>=maxCreation);
- }
+ struct Exception : public std::exception
+ {
+ const char* what() const throw() { return "RateLimitedCreation Policy : Exceeded the authorized creation rate"; }
+ };
+
+ bool canCreate()
+ {
+ cleanVector();
+ if(m_vTimes.size()>maxCreation)
+ throw Exception();
+ else
+ return true;
+ }
+
+ void onCreate()
+ {
+ m_vTimes.push_back(clock());
+ }
+
+ void onDestroy()
+ {
+ }
+ const char* name() {return "rate limited";}
+public:
+ // set the creation rate
+ // No more than maxCreation within byTime milliseconds
+ void setRate(unsigned maxCreation, unsigned byTime)
+ {
+ assert(byTime>0);
+ this->maxCreation = maxCreation;
+ this->timeValidity = static_cast<clock_t>(byTime * CLOCKS_PER_SEC / 1000);
+ D( std::cout << "Setting no more than "<< maxCreation <<" creation within " << this->timeValidity <<" ms"<< std::endl; )
+ }
+};
+
+/**
+ * \class AmountLimitedCreation
+ * \ingroup CreationPolicyCachedFactoryGroup
+ * \brief Limit by number of objects
+ *
+ * This implementation will prevent from Creating more than maxCreation objects
+ * within byTime ms by calling eviction policy.
+ * Use the setRate method to set the rate parameters.
+ * default is 10 objects.
+ */
+class AmountLimitedCreation
+{
+private:
+ unsigned maxCreation;
+ unsigned created;
+
+protected:
+ AmountLimitedCreation() : maxCreation(10), created(0)
+ {}
+
+ bool canCreate()
+ {
+ return !(created>=maxCreation);
+ }
+
+ void onCreate()
+ {
+ ++created;
+ }
+
+ void onDestroy()
+ {
+ --created;
+ }
+ const char* name() {return "amount limited";}
+public:
+ // set the creation max amount
+ void setMaxCreation(unsigned maxCreation)
+ {
+ assert(maxCreation>0);
+ this->maxCreation = maxCreation;
+ D( std::cout << "Setting no more than " << maxCreation <<" creation" << std::endl; )
+ }
+};
- void onCreate()
- {
- ++created;
- }
-
- void onDestroy()
- {
- --created;
- }
- const char* name(){return "amount limited";}
- public:
- // set the creation max amount
- void setMaxCreation(unsigned maxCreation)
- {
- assert(maxCreation>0);
- this->maxCreation = maxCreation;
- D( std::cout << "Setting no more than " << maxCreation <<" creation" << std::endl; )
- }
- };
-
/**
* \defgroup EvictionPolicyCachedFactoryGroup Eviction policies
* \ingroup CachedFactoryGroup
@@ -292,875 +292,887 @@ namespace Loki
* candidate for eviction.
*/
- class EvictionException : public std::exception
+class EvictionException : public std::exception
+{
+public:
+ const char* what() const throw() { return "Eviction Policy : trying to make room but no objects are available"; }
+};
+
+// The following class is intented to provide helpers to sort
+// the container that will hold an eviction score
+template
+<
+typename ST, // Score type
+ typename DT // Data type
+ >
+class EvictionHelper
+{
+protected:
+ typedef typename std::map< DT, ST > HitMap;
+ typedef typename HitMap::iterator HitMapItr;
+private:
+ typedef std::pair< ST, DT > SwappedPair;
+ typedef std::multimap< ST, DT > SwappedHitMap;
+ typedef typename SwappedHitMap::iterator SwappedHitMapItr;
+protected:
+ HitMap m_mHitCount;
+
+ // This function sorts the map according to the score
+ // and returns the lower bound of the sorted container
+ DT& getLowerBound()
{
- public:
- const char* what() const throw() { return "Eviction Policy : trying to make room but no objects are available"; }
- };
+ assert(!m_mHitCount.empty());
+ // inserting the swapped pair into a multimap
+ SwappedHitMap copyMap;
+ for(HitMapItr itr = m_mHitCount.begin(); itr != m_mHitCount.end(); ++itr)
+ copyMap.insert(SwappedPair((*itr).second, (*itr).first));
+ if((*copyMap.rbegin()).first == 0) // the higher score is 0 ...
+ throw EvictionException(); // there is no key evict
+ return (*copyMap.begin()).second;
+ }
+};
- // The following class is intented to provide helpers to sort
- // the container that will hold an eviction score
- template
- <
- typename ST, // Score type
- typename DT // Data type
- >
- class EvictionHelper
- {
- protected:
- typedef typename std::map< DT, ST > HitMap;
- typedef typename HitMap::iterator HitMapItr;
- private:
- typedef std::pair< ST, DT > SwappedPair;
- typedef std::multimap< ST, DT > SwappedHitMap;
- typedef typename SwappedHitMap::iterator SwappedHitMapItr;
- protected:
- HitMap m_mHitCount;
-
- // This function sorts the map according to the score
- // and returns the lower bound of the sorted container
- DT& getLowerBound(){
- assert(!m_mHitCount.empty());
- // inserting the swapped pair into a multimap
- SwappedHitMap copyMap;
- for(HitMapItr itr = m_mHitCount.begin(); itr != m_mHitCount.end(); ++itr)
- copyMap.insert(SwappedPair((*itr).second, (*itr).first));
- if((*copyMap.rbegin()).first == 0) // the higher score is 0 ...
- throw EvictionException(); // there is no key evict
- return (*copyMap.begin()).second;
- }
- };
-
- /**
- * \class EvictLRU
- * \ingroup EvictionPolicyCachedFactoryGroup
- * \brief Evicts least accessed objects first.
- *
- * Implementation of the Least recent used algorithm as
- * described in http://en.wikipedia.org/wiki/Page_replacement_algorithms .
- *
- * WARNING : If an object is heavily fetched
- * (more than ULONG_MAX = UINT_MAX = 4294967295U)
- * it could unfortunately be removed from the cache.
- */
- template
- <
- typename DT, // Data Type (AbstractProduct*)
- typename ST = unsigned // default data type to use as Score Type
- >
- class EvictLRU : public EvictionHelper< ST , DT >
+/**
+ * \class EvictLRU
+ * \ingroup EvictionPolicyCachedFactoryGroup
+ * \brief Evicts least accessed objects first.
+ *
+ * Implementation of the Least recent used algorithm as
+ * described in http://en.wikipedia.org/wiki/Page_replacement_algorithms .
+ *
+ * WARNING : If an object is heavily fetched
+ * (more than ULONG_MAX = UINT_MAX = 4294967295U)
+ * it could unfortunately be removed from the cache.
+ */
+template
+<
+typename DT, // Data Type (AbstractProduct*)
+ typename ST = unsigned // default data type to use as Score Type
+ >
+class EvictLRU : public EvictionHelper< ST , DT >
+{
+private:
+ typedef EvictionHelper< ST , DT > EH;
+protected:
+
+ virtual ~EvictLRU() {}
+
+ // OnStore initialize the counter for the new key
+ // If the key already exists, the counter is reseted
+ void onCreate(const DT& key)
{
- private:
- typedef EvictionHelper< ST , DT > EH;
- protected:
-
- virtual ~EvictLRU(){}
-
- // OnStore initialize the counter for the new key
- // If the key already exists, the counter is reseted
- void onCreate(const DT& key)
- {
- EH::m_mHitCount[key] = 0;
- }
-
- void onFetch(const DT&)
- {
- }
-
- // onRelease increments the hit counter associated with the object
- void onRelease(const DT& key)
- {
- ++(EH::m_mHitCount[key]);
- }
+ EH::m_mHitCount[key] = 0;
+ }
- void onDestroy(const DT& key)
- {
- EH::m_mHitCount.erase(key);
- }
-
- // this function is implemented in Cache and redirected
- // to the Storage Policy
- virtual void remove(DT const key)=0;
-
- // LRU Eviction policy
- void evict()
- {
- remove(EH::getLowerBound());
- }
- const char* name(){return "LRU";}
- };
-
- /**
- * \class EvictAging
- * \ingroup EvictionPolicyCachedFactoryGroup
- * \brief LRU aware of the time span of use
- *
- * Implementation of the Aging algorithm as
- * described in http://en.wikipedia.org/wiki/Page_replacement_algorithms .
- *
- * This method is much more costly than evict LRU so
- * if you need extreme performance consider switching to EvictLRU
- */
- template
- <
- typename DT, // Data Type (AbstractProduct*)
- typename ST = unsigned // default data type to use as Score Type
- >
- class EvictAging : public EvictionHelper< ST, DT >
+ void onFetch(const DT&)
{
- private:
- EvictAging(const EvictAging&);
- EvictAging& operator=(const EvictAging&);
- typedef EvictionHelper< ST, DT > EH;
- typedef typename EH::HitMap HitMap;
- typedef typename EH::HitMapItr HitMapItr;
-
- // update the counter
- template<class T> struct updateCounter : public std::unary_function<T, void>
- {
- updateCounter(const DT& key): key_(key){}
- void operator()(T x)
- {
- x.second = (x.first == key_ ? (x.second >> 1) | ( 1 << ((sizeof(ST)-1)*8) ) : x.second >> 1);
- D( std::cout << x.second << std::endl; )
- }
- const DT &key_;
- updateCounter(const updateCounter& rhs) : key_(rhs.key_){}
- private:
- updateCounter& operator=(const updateCounter& rhs);
- };
- protected:
- EvictAging(){}
- virtual ~EvictAging(){}
-
- // OnStore initialize the counter for the new key
- // If the key already exists, the counter is reseted
- void onCreate(const DT& key){
- EH::m_mHitCount[key] = 0;
- }
-
- void onFetch(const DT&){}
-
- // onRelease increments the hit counter associated with the object
- // Updating every counters by iterating over the map
- // If the key is the key of the fetched object :
- // the counter is shifted to the right and it's MSB is set to 1
- // else
- // the counter is shifted to the left
- void onRelease(const DT& key)
- {
- std::for_each(EH::m_mHitCount.begin(), EH::m_mHitCount.end(), updateCounter< typename HitMap::value_type >(key));
- }
-
- void onDestroy(const DT& key)
- {
- EH::m_mHitCount.erase(key);
- }
+ }
- // this function is implemented in Cache and redirected
- // to the Storage Policy
- virtual void remove(DT const key)=0;
+ // onRelease increments the hit counter associated with the object
+ void onRelease(const DT& key)
+ {
+ ++(EH::m_mHitCount[key]);
+ }
- // LRU with Aging Eviction policy
- void evict()
- {
- remove(EH::getLowerBound());
- }
- const char* name(){return "LRU with aging";}
- };
-
- /**
- * \class EvictRandom
- * \ingroup EvictionPolicyCachedFactoryGroup
- * \brief Evicts a random object
- *
- * Implementation of the Random algorithm as
- * described in http://en.wikipedia.org/wiki/Page_replacement_algorithms .
- */
- template
- <
- typename DT, // Data Type (AbstractProduct*)
- typename ST = void // Score Type not used by this policy
- >
- class EvictRandom
+ void onDestroy(const DT& key)
+ {
+ EH::m_mHitCount.erase(key);
+ }
+
+ // this function is implemented in Cache and redirected
+ // to the Storage Policy
+ virtual void remove(DT const key)=0;
+
+ // LRU Eviction policy
+ void evict()
{
+ remove(EH::getLowerBound());
+ }
+ const char* name() {return "LRU";}
+};
+
+/**
+ * \class EvictAging
+ * \ingroup EvictionPolicyCachedFactoryGroup
+ * \brief LRU aware of the time span of use
+ *
+ * Implementation of the Aging algorithm as
+ * described in http://en.wikipedia.org/wiki/Page_replacement_algorithms .
+ *
+ * This method is much more costly than evict LRU so
+ * if you need extreme performance consider switching to EvictLRU
+ */
+template
+<
+typename DT, // Data Type (AbstractProduct*)
+ typename ST = unsigned // default data type to use as Score Type
+ >
+class EvictAging : public EvictionHelper< ST, DT >
+{
+private:
+ EvictAging(const EvictAging&);
+ EvictAging& operator=(const EvictAging&);
+ typedef EvictionHelper< ST, DT > EH;
+ typedef typename EH::HitMap HitMap;
+ typedef typename EH::HitMapItr HitMapItr;
+
+ // update the counter
+ template<class T> struct updateCounter : public std::unary_function<T, void>
+ {
+ updateCounter(const DT& key): key_(key) {}
+ void operator()(T x)
+ {
+ x.second = (x.first == key_ ? (x.second >> 1) | ( 1 << ((sizeof(ST)-1)*8) ) : x.second >> 1);
+ D( std::cout << x.second << std::endl; )
+ }
+ const DT& key_;
+ updateCounter(const updateCounter& rhs) : key_(rhs.key_) {}
private:
- std::vector< DT > m_vKeys;
- typedef typename std::vector< DT >::size_type size_type;
- typedef typename std::vector< DT >::iterator iterator;
-
- protected:
-
- virtual ~EvictRandom(){}
-
- void onCreate(const DT&){
- }
-
- void onFetch(const DT& ){
- }
-
- void onRelease(const DT& key){
- m_vKeys.push_back(key);
- }
-
- void onDestroy(const DT& key){
- using namespace std;
- m_vKeys.erase(remove_if(m_vKeys.begin(), m_vKeys.end(), bind2nd(equal_to< DT >(), key)), m_vKeys.end());
- }
-
- // Implemented in Cache and redirected to the Storage Policy
- virtual void remove(DT const key)=0;
-
- // Random Eviction policy
- void evict()
- {
- if(m_vKeys.empty())
- throw EvictionException();
- size_type random = static_cast<size_type>((m_vKeys.size()*rand())/(static_cast<size_type>(RAND_MAX) + 1));
- remove(*(m_vKeys.begin()+random));
- }
- const char* name(){return "random";}
+ updateCounter& operator=(const updateCounter& rhs);
};
+protected:
+ EvictAging() {}
+ virtual ~EvictAging() {}
+
+ // OnStore initialize the counter for the new key
+ // If the key already exists, the counter is reseted
+ void onCreate(const DT& key)
+ {
+ EH::m_mHitCount[key] = 0;
+ }
+
+ void onFetch(const DT&) {}
+
+ // onRelease increments the hit counter associated with the object
+ // Updating every counters by iterating over the map
+ // If the key is the key of the fetched object :
+ // the counter is shifted to the right and it's MSB is set to 1
+ // else
+ // the counter is shifted to the left
+ void onRelease(const DT& key)
+ {
+ std::for_each(EH::m_mHitCount.begin(), EH::m_mHitCount.end(), updateCounter< typename HitMap::value_type >(key));
+ }
+
+ void onDestroy(const DT& key)
+ {
+ EH::m_mHitCount.erase(key);
+ }
+
+ // this function is implemented in Cache and redirected
+ // to the Storage Policy
+ virtual void remove(DT const key)=0;
+
+ // LRU with Aging Eviction policy
+ void evict()
+ {
+ remove(EH::getLowerBound());
+ }
+ const char* name() {return "LRU with aging";}
+};
+
+/**
+ * \class EvictRandom
+ * \ingroup EvictionPolicyCachedFactoryGroup
+ * \brief Evicts a random object
+ *
+ * Implementation of the Random algorithm as
+ * described in http://en.wikipedia.org/wiki/Page_replacement_algorithms .
+ */
+template
+<
+typename DT, // Data Type (AbstractProduct*)
+ typename ST = void // Score Type not used by this policy
+ >
+class EvictRandom
+{
+private:
+ std::vector< DT > m_vKeys;
+ typedef typename std::vector< DT >::size_type size_type;
+ typedef typename std::vector< DT >::iterator iterator;
+
+protected:
+
+ virtual ~EvictRandom() {}
+
+ void onCreate(const DT&)
+ {
+ }
+
+ void onFetch(const DT& )
+ {
+ }
+
+ void onRelease(const DT& key)
+ {
+ m_vKeys.push_back(key);
+ }
+
+ void onDestroy(const DT& key)
+ {
+ using namespace std;
+ m_vKeys.erase(remove_if(m_vKeys.begin(), m_vKeys.end(), bind2nd(equal_to< DT >(), key)), m_vKeys.end());
+ }
+
+ // Implemented in Cache and redirected to the Storage Policy
+ virtual void remove(DT const key)=0;
+
+ // Random Eviction policy
+ void evict()
+ {
+ if(m_vKeys.empty())
+ throw EvictionException();
+ size_type random = static_cast<size_type>((m_vKeys.size()*rand())/(static_cast<size_type>(RAND_MAX) + 1));
+ remove(*(m_vKeys.begin()+random));
+ }
+ const char* name() {return "random";}
+};
/**
* \defgroup StatisticPolicyCachedFactoryGroup Statistic policies
* \ingroup CachedFactoryGroup
* \brief Gathers information about the cache.
- *
+ *
* For debugging purpose this policy proposes to gather informations
* about the cache. This could be useful to determine whether the cache is
* mandatory or if the policies are well suited to the application.
*/
- /**
- * \class NoStatisticPolicy
- * \ingroup StatisticPolicyCachedFactoryGroup
- * \brief Do nothing
- *
- * Should be used in release code for better performances
- */
- class NoStatisticPolicy
- {
- protected:
- void onDebug(){}
- void onFetch(){}
- void onRelease(){}
- void onCreate(){}
- void onDestroy(){}
- const char* name(){return "no";}
- };
-
- /**
- * \class SimpleStatisticPolicy
- * \ingroup StatisticPolicyCachedFactoryGroup
- * \brief Simple statistics
- *
- * Provides the following informations about the cache :
- * - Created objects
- * - Fetched objects
- * - Destroyed objects
- * - Cache hit
- * - Cache miss
- * - Currently allocated
- * - Currently out
- * - Cache overall efficiency
- */
- class SimpleStatisticPolicy
+/**
+ * \class NoStatisticPolicy
+ * \ingroup StatisticPolicyCachedFactoryGroup
+ * \brief Do nothing
+ *
+ * Should be used in release code for better performances
+ */
+class NoStatisticPolicy
+{
+protected:
+ void onDebug() {}
+ void onFetch() {}
+ void onRelease() {}
+ void onCreate() {}
+ void onDestroy() {}
+ const char* name() {return "no";}
+};
+
+/**
+ * \class SimpleStatisticPolicy
+ * \ingroup StatisticPolicyCachedFactoryGroup
+ * \brief Simple statistics
+ *
+ * Provides the following informations about the cache :
+ * - Created objects
+ * - Fetched objects
+ * - Destroyed objects
+ * - Cache hit
+ * - Cache miss
+ * - Currently allocated
+ * - Currently out
+ * - Cache overall efficiency
+ */
+class SimpleStatisticPolicy
+{
+private:
+ unsigned allocated, created, hit, out, fetched;
+protected:
+ SimpleStatisticPolicy() : allocated(0), created(0), hit(0), out(0), fetched(0)
{
- private:
- unsigned allocated, created, hit, out, fetched;
- protected:
- SimpleStatisticPolicy() : allocated(0), created(0), hit(0), out(0), fetched(0)
- {
- }
-
- void onDebug()
+ }
+
+ void onDebug()
+ {
+ using namespace std;
+ cout << "############################" << endl;
+ cout << "## About this cache " << this << endl;
+ cout << "## + Created objects : " << created << endl;
+ cout << "## + Fetched objects : " << fetched << endl;
+ cout << "## + Destroyed objects : " << created - allocated << endl;
+ cout << "## + Cache hit : " << hit << endl;
+ cout << "## + Cache miss : " << fetched - hit << endl;
+ cout << "## + Currently allocated : " << allocated << endl;
+ cout << "## + Currently out : " << out << endl;
+ cout << "############################" << endl;
+ if(fetched!=0)
{
- using namespace std;
- cout << "############################" << endl;
- cout << "## About this cache " << this << endl;
- cout << "## + Created objects : " << created << endl;
- cout << "## + Fetched objects : " << fetched << endl;
- cout << "## + Destroyed objects : " << created - allocated << endl;
- cout << "## + Cache hit : " << hit << endl;
- cout << "## + Cache miss : " << fetched - hit << endl;
- cout << "## + Currently allocated : " << allocated << endl;
- cout << "## + Currently out : " << out << endl;
+ cout << "## Overall efficiency " << 100*double(hit)/fetched <<"%"<< endl;
cout << "############################" << endl;
- if(fetched!=0){
- cout << "## Overall efficiency " << 100*double(hit)/fetched <<"%"<< endl;
- cout << "############################" << endl;
- }
- cout << endl;
}
-
- void onFetch()
- {
- ++fetched;
- ++out;
- ++hit;
- }
- void onRelease()
- {
- --out;
- }
- void onCreate()
+ cout << endl;
+ }
+
+ void onFetch()
+ {
+ ++fetched;
+ ++out;
+ ++hit;
+ }
+ void onRelease()
+ {
+ --out;
+ }
+ void onCreate()
+ {
+ ++created;
+ ++allocated;
+ --hit;
+ }
+ void onDestroy()
+ {
+ --allocated;
+ }
+
+ const char* name() {return "simple";}
+public:
+ unsigned getCreated() {return created;}
+ unsigned getFetched() {return fetched;}
+ unsigned getHit() {return hit;}
+ unsigned getMissed() {return fetched - hit;}
+ unsigned getAllocated() {return allocated;}
+ unsigned getOut() {return out;}
+ unsigned getDestroyed() {return created-allocated;}
+};
+
+///////////////////////////////////////////////////////////////////////////
+// Cache Factory definition
+///////////////////////////////////////////////////////////////////////////
+class CacheException : public std::exception
+{
+public:
+ const char* what() const throw() { return "Internal Cache Error"; }
+};
+
+/**
+ * \class CachedFactory
+ * \ingroup CachedFactoryGroup
+ * \brief Factory with caching support
+ *
+ * This class acts as a Factory (it creates objects)
+ * but also keeps the already created objects to prevent
+ * long constructions time.
+ *
+ * Note this implementation do not retain ownership.
+ */
+template
+<
+class AbstractProduct,
+ typename IdentifierType,
+ typename CreatorParmTList = NullType,
+ template<class> class EncapsulationPolicy = SimplePointer,
+ class CreationPolicy = AlwaysCreate,
+ template <typename , typename> class EvictionPolicy = EvictRandom,
+ class StatisticPolicy = NoStatisticPolicy,
+ template<typename, class> class FactoryErrorPolicy = DefaultFactoryError,
+ class ObjVector = std::vector<AbstractProduct*>
+ >
+class CachedFactory :
+ protected EncapsulationPolicy<AbstractProduct>,
+ public CreationPolicy, public StatisticPolicy, EvictionPolicy< AbstractProduct* , unsigned >
+{
+private:
+ typedef Factory< AbstractProduct, IdentifierType, CreatorParmTList, FactoryErrorPolicy> MyFactory;
+ typedef FactoryImpl< AbstractProduct, IdentifierType, CreatorParmTList > Impl;
+ typedef Functor< AbstractProduct* , CreatorParmTList > ProductCreator;
+ typedef EncapsulationPolicy<AbstractProduct> NP;
+ typedef CreationPolicy CP;
+ typedef StatisticPolicy SP;
+ typedef EvictionPolicy< AbstractProduct* , unsigned > EP;
+
+ typedef typename Impl::Parm1 Parm1;
+ typedef typename Impl::Parm2 Parm2;
+ typedef typename Impl::Parm3 Parm3;
+ typedef typename Impl::Parm4 Parm4;
+ typedef typename Impl::Parm5 Parm5;
+ typedef typename Impl::Parm6 Parm6;
+ typedef typename Impl::Parm7 Parm7;
+ typedef typename Impl::Parm8 Parm8;
+ typedef typename Impl::Parm9 Parm9;
+ typedef typename Impl::Parm10 Parm10;
+ typedef typename Impl::Parm11 Parm11;
+ typedef typename Impl::Parm12 Parm12;
+ typedef typename Impl::Parm13 Parm13;
+ typedef typename Impl::Parm14 Parm14;
+ typedef typename Impl::Parm15 Parm15;
+
+public:
+ typedef typename NP::ProductReturn ProductReturn;
+private:
+ typedef Key< Impl, IdentifierType > MyKey;
+ typedef std::map< MyKey, ObjVector > KeyToObjVectorMap;
+ typedef std::map< AbstractProduct*, MyKey > FetchedObjToKeyMap;
+
+ MyFactory factory;
+ KeyToObjVectorMap fromKeyToObjVector;
+ FetchedObjToKeyMap providedObjects;
+ unsigned outObjects;
+
+ ObjVector& getContainerFromKey(MyKey key)
+ {
+ return fromKeyToObjVector[key];
+ }
+
+ AbstractProduct* const getPointerToObjectInContainer(ObjVector& entry)
+ {
+ if(entry.empty()) // No object available
{
- ++created;
- ++allocated;
- --hit;
+ // the object will be created in the calling function.
+ // It has to be created in the calling function because of
+ // the variable number of parameters for CreateObject(...) method
+ return NULL;
}
- void onDestroy()
+ else
{
- --allocated;
+ // returning the found object
+ AbstractProduct* pObject(entry.back());
+ assert(pObject!=NULL);
+ entry.pop_back();
+ return pObject;
}
+ }
+
+ bool shouldCreateObject(AbstractProduct* const pProduct)
+ {
+ if(pProduct!=NULL) // object already exists
+ return false;
+ if(CP::canCreate()==false) // Are we allowed to Create ?
+ EP::evict(); // calling Eviction Policy to clean up
+ return true;
+ }
+
+ void ReleaseObjectFromContainer(ObjVector& entry, AbstractProduct* const object)
+ {
+ entry.push_back(object);
+ }
+
+ void onFetch(AbstractProduct* const pProduct)
+ {
+ SP::onFetch();
+ EP::onFetch(pProduct);
+ ++outObjects;
+ }
+
+ void onRelease(AbstractProduct* const pProduct)
+ {
+ SP::onRelease();
+ EP::onRelease(pProduct);
+ --outObjects;
+ }
+
+ void onCreate(AbstractProduct* const pProduct)
+ {
+ CP::onCreate();
+ SP::onCreate();
+ EP::onCreate(pProduct);
+ }
- const char* name(){return "simple";}
- public:
- unsigned getCreated(){return created;}
- unsigned getFetched(){return fetched;}
- unsigned getHit(){return hit;}
- unsigned getMissed(){return fetched - hit;}
- unsigned getAllocated(){return allocated;}
- unsigned getOut(){return out;}
- unsigned getDestroyed(){return created-allocated;}
- };
-
- ///////////////////////////////////////////////////////////////////////////
- // Cache Factory definition
- ///////////////////////////////////////////////////////////////////////////
- class CacheException : public std::exception
- {
- public:
- const char* what() const throw() { return "Internal Cache Error"; }
+ void onDestroy(AbstractProduct* const pProduct)
+ {
+ CP::onDestroy();
+ SP::onDestroy();
+ EP::onDestroy(pProduct);
+ }
+
+ // delete the object
+ template<class T> struct deleteObject : public std::unary_function<T, void>
+ {
+ void operator()(T x) { delete x; }
};
-
- /**
- * \class CachedFactory
- * \ingroup CachedFactoryGroup
- * \brief Factory with caching support
- *
- * This class acts as a Factory (it creates objects)
- * but also keeps the already created objects to prevent
- * long constructions time.
- *
- * Note this implementation do not retain ownership.
- */
- template
- <
- class AbstractProduct,
- typename IdentifierType,
- typename CreatorParmTList = NullType,
- template<class> class EncapsulationPolicy = SimplePointer,
- class CreationPolicy = AlwaysCreate,
- template <typename , typename> class EvictionPolicy = EvictRandom,
- class StatisticPolicy = NoStatisticPolicy,
- template<typename, class> class FactoryErrorPolicy = DefaultFactoryError,
- class ObjVector = std::vector<AbstractProduct*>
- >
- class CachedFactory :
- protected EncapsulationPolicy<AbstractProduct>,
- public CreationPolicy, public StatisticPolicy, EvictionPolicy< AbstractProduct * , unsigned >
- {
- private:
- typedef Factory< AbstractProduct, IdentifierType, CreatorParmTList, FactoryErrorPolicy> MyFactory;
- typedef FactoryImpl< AbstractProduct, IdentifierType, CreatorParmTList > Impl;
- typedef Functor< AbstractProduct* , CreatorParmTList > ProductCreator;
- typedef EncapsulationPolicy<AbstractProduct> NP;
- typedef CreationPolicy CP;
- typedef StatisticPolicy SP;
- typedef EvictionPolicy< AbstractProduct* , unsigned > EP;
-
- typedef typename Impl::Parm1 Parm1;
- typedef typename Impl::Parm2 Parm2;
- typedef typename Impl::Parm3 Parm3;
- typedef typename Impl::Parm4 Parm4;
- typedef typename Impl::Parm5 Parm5;
- typedef typename Impl::Parm6 Parm6;
- typedef typename Impl::Parm7 Parm7;
- typedef typename Impl::Parm8 Parm8;
- typedef typename Impl::Parm9 Parm9;
- typedef typename Impl::Parm10 Parm10;
- typedef typename Impl::Parm11 Parm11;
- typedef typename Impl::Parm12 Parm12;
- typedef typename Impl::Parm13 Parm13;
- typedef typename Impl::Parm14 Parm14;
- typedef typename Impl::Parm15 Parm15;
-
- public:
- typedef typename NP::ProductReturn ProductReturn;
- private:
- typedef Key< Impl, IdentifierType > MyKey;
- typedef std::map< MyKey, ObjVector > KeyToObjVectorMap;
- typedef std::map< AbstractProduct*, MyKey > FetchedObjToKeyMap;
-
- MyFactory factory;
- KeyToObjVectorMap fromKeyToObjVector;
- FetchedObjToKeyMap providedObjects;
- unsigned outObjects;
-
- ObjVector& getContainerFromKey(MyKey key){
- return fromKeyToObjVector[key];
- }
- AbstractProduct* const getPointerToObjectInContainer(ObjVector &entry)
- {
- if(entry.empty()) // No object available
- { // the object will be created in the calling function.
- // It has to be created in the calling function because of
- // the variable number of parameters for CreateObject(...) method
- return NULL;
- }
- else
- { // returning the found object
- AbstractProduct* pObject(entry.back());
- assert(pObject!=NULL);
- entry.pop_back();
- return pObject;
- }
- }
-
- bool shouldCreateObject(AbstractProduct * const pProduct){
- if(pProduct!=NULL) // object already exists
- return false;
- if(CP::canCreate()==false) // Are we allowed to Create ?
- EP::evict(); // calling Eviction Policy to clean up
- return true;
- }
-
- void ReleaseObjectFromContainer(ObjVector &entry, AbstractProduct * const object)
- {
- entry.push_back(object);
- }
-
- void onFetch(AbstractProduct * const pProduct)
- {
- SP::onFetch();
- EP::onFetch(pProduct);
- ++outObjects;
- }
-
- void onRelease(AbstractProduct * const pProduct)
- {
- SP::onRelease();
- EP::onRelease(pProduct);
- --outObjects;
- }
-
- void onCreate(AbstractProduct * const pProduct)
- {
- CP::onCreate();
- SP::onCreate();
- EP::onCreate(pProduct);
- }
-
- void onDestroy(AbstractProduct * const pProduct)
+ // delete the objects in the vector
+ template<class T> struct deleteVectorObjects : public std::unary_function<T, void>
+ {
+ void operator()(T x)
{
- CP::onDestroy();
- SP::onDestroy();
- EP::onDestroy(pProduct);
+ ObjVector& vec(x.second);
+ std::for_each(vec.begin(), vec.end(), deleteObject< typename ObjVector::value_type>());
}
-
- // delete the object
- template<class T> struct deleteObject : public std::unary_function<T, void>
- {
- void operator()(T x){ delete x; }
- };
-
- // delete the objects in the vector
- template<class T> struct deleteVectorObjects : public std::unary_function<T, void>
- {
- void operator()(T x){
- ObjVector &vec(x.second);
- std::for_each(vec.begin(), vec.end(), deleteObject< typename ObjVector::value_type>());
- }
- };
-
- // delete the keys of the map
- template<class T> struct deleteMapKeys : public std::unary_function<T, void>
- {
- void operator()(T x){ delete x.first; }
- };
-
- protected:
- virtual void remove(AbstractProduct * const pProduct)
+ };
+
+ // delete the keys of the map
+ template<class T> struct deleteMapKeys : public std::unary_function<T, void>
+ {
+ void operator()(T x) { delete x.first; }
+ };
+
+protected:
+ virtual void remove(AbstractProduct* const pProduct)
+ {
+ typename FetchedObjToKeyMap::iterator fetchedItr = providedObjects.find(pProduct);
+ if(fetchedItr!=providedObjects.end()) // object is unreleased.
+ throw CacheException();
+ bool productRemoved = false;
+ typename KeyToObjVectorMap::iterator objVectorItr;
+ typename ObjVector::iterator objItr;
+ for(objVectorItr=fromKeyToObjVector.begin(); objVectorItr!=fromKeyToObjVector.end(); ++objVectorItr)
{
- typename FetchedObjToKeyMap::iterator fetchedItr = providedObjects.find(pProduct);
- if(fetchedItr!=providedObjects.end()) // object is unreleased.
- throw CacheException();
- bool productRemoved = false;
- typename KeyToObjVectorMap::iterator objVectorItr;
- typename ObjVector::iterator objItr;
- for(objVectorItr=fromKeyToObjVector.begin();objVectorItr!=fromKeyToObjVector.end();++objVectorItr)
+ ObjVector& v((*objVectorItr).second);
+ objItr = remove_if(v.begin(), v.end(), std::bind2nd(std::equal_to<AbstractProduct*>(), pProduct));
+ if(objItr != v.end()) // we found the vector containing pProduct and removed it
{
- ObjVector &v((*objVectorItr).second);
- objItr = remove_if(v.begin(), v.end(), std::bind2nd(std::equal_to<AbstractProduct*>(), pProduct));
- if(objItr != v.end()) // we found the vector containing pProduct and removed it
- {
- onDestroy(pProduct); // warning policies we are about to destroy an object
- v.erase(objItr, v.end()); // real removing
- productRemoved = true;
- break;
- }
+ onDestroy(pProduct); // warning policies we are about to destroy an object
+ v.erase(objItr, v.end()); // real removing
+ productRemoved = true;
+ break;
}
- if(productRemoved==false)
- throw CacheException(); // the product is not in the cache ?!
- delete pProduct; // deleting it
}
+ if(productRemoved==false)
+ throw CacheException(); // the product is not in the cache ?!
+ delete pProduct; // deleting it
+ }
- public:
- CachedFactory() : factory(), fromKeyToObjVector(), providedObjects(), outObjects(0)
- {
- }
+public:
+ CachedFactory() : factory(), fromKeyToObjVector(), providedObjects(), outObjects(0)
+ {
+ }
- ~CachedFactory()
- {
- using namespace std;
- // debug information
- SP::onDebug();
- // cleaning the Cache
- for_each(fromKeyToObjVector.begin(), fromKeyToObjVector.end(),
- deleteVectorObjects< typename KeyToObjVectorMap::value_type >()
- );
- if(!providedObjects.empty())
- {
- // The factory is responsible for the creation and destruction of objects.
- // If objects are out during the destruction of the Factory : deleting anyway.
- // This might not be a good idea. But throwing an exception in a destructor is
- // considered as a bad pratice and asserting might be too much.
- // What to do ? Leaking memory or corrupting in use pointers ? hmm...
- D( cout << "====>> Cache destructor : deleting "<< providedObjects.size()<<" in use objects <<====" << endl << endl; )
- for_each(providedObjects.begin(), providedObjects.end(),
- deleteMapKeys< typename FetchedObjToKeyMap::value_type >()
+ ~CachedFactory()
+ {
+ using namespace std;
+ // debug information
+ SP::onDebug();
+ // cleaning the Cache
+ for_each(fromKeyToObjVector.begin(), fromKeyToObjVector.end(),
+ deleteVectorObjects< typename KeyToObjVectorMap::value_type >()
);
- }
- }
-
- ///////////////////////////////////
- // Acts as the proxy pattern and //
- // forwards factory methods //
- ///////////////////////////////////
-
- bool Register(const IdentifierType& id, ProductCreator creator)
+ if(!providedObjects.empty())
{
- return factory.Register(id, creator);
- }
-
- template <class PtrObj, typename CreaFn>
- bool Register(const IdentifierType& id, const PtrObj& p, CreaFn fn)
- {
- return factory.Register(id, p, fn);
- }
-
- bool Unregister(const IdentifierType& id)
- {
- return factory.Unregister(id);
+ // The factory is responsible for the creation and destruction of objects.
+ // If objects are out during the destruction of the Factory : deleting anyway.
+ // This might not be a good idea. But throwing an exception in a destructor is
+ // considered as a bad pratice and asserting might be too much.
+ // What to do ? Leaking memory or corrupting in use pointers ? hmm...
+ D( cout << "====>> Cache destructor : deleting "<< providedObjects.size()<<" in use objects <<====" << endl << endl; )
+ for_each(providedObjects.begin(), providedObjects.end(),
+ deleteMapKeys< typename FetchedObjToKeyMap::value_type >()
+ );
}
+ }
- /// Return the registered ID in this Factory
- std::vector<IdentifierType>& RegisteredIds()
- {
- return factory.RegisteredIds();
- }
+ ///////////////////////////////////
+ // Acts as the proxy pattern and //
+ // forwards factory methods //
+ ///////////////////////////////////
- ProductReturn CreateObject(const IdentifierType& id)
- {
- MyKey key(id);
- AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
- if(shouldCreateObject(pProduct))
- {
- pProduct = factory.CreateObject(key.id);
- onCreate(pProduct);
- }
- onFetch(pProduct);
- providedObjects[pProduct] = key;
- return NP::encapsulate(pProduct);
- }
-
- ProductReturn CreateObject(const IdentifierType& id,
- Parm1 p1)
- {
- MyKey key(id,p1);
- AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
- if(shouldCreateObject(pProduct))
- {
- pProduct = factory.CreateObject(key.id,key.p1);
- onCreate(pProduct);
- }
- onFetch(pProduct);
- providedObjects[pProduct] = key;
- return NP::encapsulate(pProduct);
- }
+ bool Register(const IdentifierType& id, ProductCreator creator)
+ {
+ return factory.Register(id, creator);
+ }
+
+ template <class PtrObj, typename CreaFn>
+ bool Register(const IdentifierType& id, const PtrObj& p, CreaFn fn)
+ {
+ return factory.Register(id, p, fn);
+ }
+
+ bool Unregister(const IdentifierType& id)
+ {
+ return factory.Unregister(id);
+ }
- ProductReturn CreateObject(const IdentifierType& id,
- Parm1 p1, Parm2 p2)
+ /// Return the registered ID in this Factory
+ std::vector<IdentifierType>& RegisteredIds()
+ {
+ return factory.RegisteredIds();
+ }
+
+ ProductReturn CreateObject(const IdentifierType& id)
+ {
+ MyKey key(id);
+ AbstractProduct* pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
+ if(shouldCreateObject(pProduct))
{
- MyKey key(id,p1,p2);
- AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
- if(shouldCreateObject(pProduct))
- {
- pProduct = factory.CreateObject(key.id,key.p1,key.p2);
- onCreate(pProduct);
- }
- onFetch(pProduct);
- providedObjects[pProduct] = key;
- return NP::encapsulate(pProduct);
+ pProduct = factory.CreateObject(key.id);
+ onCreate(pProduct);
}
+ onFetch(pProduct);
+ providedObjects[pProduct] = key;
+ return NP::encapsulate(pProduct);
+ }
- ProductReturn CreateObject(const IdentifierType& id,
- Parm1 p1, Parm2 p2, Parm3 p3)
+ ProductReturn CreateObject(const IdentifierType& id,
+ Parm1 p1)
+ {
+ MyKey key(id,p1);
+ AbstractProduct* pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
+ if(shouldCreateObject(pProduct))
{
- MyKey key(id,p1,p2,p3);
- AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
- if(shouldCreateObject(pProduct))
- {
- pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3);
- onCreate(pProduct);
- }
- onFetch(pProduct);
- providedObjects[pProduct] = key;
- return NP::encapsulate(pProduct);
+ pProduct = factory.CreateObject(key.id,key.p1);
+ onCreate(pProduct);
}
+ onFetch(pProduct);
+ providedObjects[pProduct] = key;
+ return NP::encapsulate(pProduct);
+ }
- ProductReturn CreateObject(const IdentifierType& id,
- Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4)
+ ProductReturn CreateObject(const IdentifierType& id,
+ Parm1 p1, Parm2 p2)
+ {
+ MyKey key(id,p1,p2);
+ AbstractProduct* pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
+ if(shouldCreateObject(pProduct))
{
- MyKey key(id,p1,p2,p3,p4);
- AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
- if(shouldCreateObject(pProduct))
- {
- pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
- ,key.p4);
- onCreate(pProduct);
- }
- onFetch(pProduct);
- providedObjects[pProduct] = key;
- return NP::encapsulate(pProduct);
+ pProduct = factory.CreateObject(key.id,key.p1,key.p2);
+ onCreate(pProduct);
}
+ onFetch(pProduct);
+ providedObjects[pProduct] = key;
+ return NP::encapsulate(pProduct);
+ }
- ProductReturn CreateObject(const IdentifierType& id,
- Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5)
+ ProductReturn CreateObject(const IdentifierType& id,
+ Parm1 p1, Parm2 p2, Parm3 p3)
+ {
+ MyKey key(id,p1,p2,p3);
+ AbstractProduct* pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
+ if(shouldCreateObject(pProduct))
{
- MyKey key(id,p1,p2,p3,p4,p5);
- AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
- if(shouldCreateObject(pProduct))
- {
- pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
- ,key.p4,key.p5);
- onCreate(pProduct);
- }
- onFetch(pProduct);
- providedObjects[pProduct] = key;
- return NP::encapsulate(pProduct);
+ pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3);
+ onCreate(pProduct);
}
+ onFetch(pProduct);
+ providedObjects[pProduct] = key;
+ return NP::encapsulate(pProduct);
+ }
- ProductReturn CreateObject(const IdentifierType& id,
- Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
- Parm6 p6)
+ ProductReturn CreateObject(const IdentifierType& id,
+ Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4)
+ {
+ MyKey key(id,p1,p2,p3,p4);
+ AbstractProduct* pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
+ if(shouldCreateObject(pProduct))
{
- MyKey key(id,p1,p2,p3,p4,p5,p6);
- AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
- if(shouldCreateObject(pProduct))
- {
- pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
- ,key.p4,key.p5,key.p6);
- onCreate(pProduct);
- }
- onFetch(pProduct);
- providedObjects[pProduct] = key;
- return NP::encapsulate(pProduct);
+ pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
+ ,key.p4);
+ onCreate(pProduct);
}
+ onFetch(pProduct);
+ providedObjects[pProduct] = key;
+ return NP::encapsulate(pProduct);
+ }
- ProductReturn CreateObject(const IdentifierType& id,
- Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
- Parm6 p6, Parm7 p7 )
+ ProductReturn CreateObject(const IdentifierType& id,
+ Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5)
+ {
+ MyKey key(id,p1,p2,p3,p4,p5);
+ AbstractProduct* pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
+ if(shouldCreateObject(pProduct))
{
- MyKey key(id,p1,p2,p3,p4,p5,p6,p7);
- AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
- if(shouldCreateObject(pProduct))
- {
- pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
- ,key.p4,key.p5,key.p6,key.p7);
- onCreate(pProduct);
- }
- onFetch(pProduct);
- providedObjects[pProduct] = key;
- return NP::encapsulate(pProduct);
+ pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
+ ,key.p4,key.p5);
+ onCreate(pProduct);
}
+ onFetch(pProduct);
+ providedObjects[pProduct] = key;
+ return NP::encapsulate(pProduct);
+ }
- ProductReturn CreateObject(const IdentifierType& id,
- Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
- Parm6 p6, Parm7 p7, Parm8 p8)
+ ProductReturn CreateObject(const IdentifierType& id,
+ Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6)
+ {
+ MyKey key(id,p1,p2,p3,p4,p5,p6);
+ AbstractProduct* pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
+ if(shouldCreateObject(pProduct))
{
- MyKey key(id,p1,p2,p3,p4,p5,p6,p7,p8);
- AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
- if(shouldCreateObject(pProduct))
- {
- pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
- ,key.p4,key.p5,key.p6,key.p7,key.p8);
- onCreate(pProduct);
- }
- onFetch(pProduct);
- providedObjects[pProduct] = key;
- return NP::encapsulate(pProduct);
+ pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
+ ,key.p4,key.p5,key.p6);
+ onCreate(pProduct);
}
+ onFetch(pProduct);
+ providedObjects[pProduct] = key;
+ return NP::encapsulate(pProduct);
+ }
- ProductReturn CreateObject(const IdentifierType& id,
- Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
- Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9)
+ ProductReturn CreateObject(const IdentifierType& id,
+ Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7 )
+ {
+ MyKey key(id,p1,p2,p3,p4,p5,p6,p7);
+ AbstractProduct* pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
+ if(shouldCreateObject(pProduct))
{
- MyKey key(id,p1,p2,p3,p4,p5,p6,p7,p8,p9);
- AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
- if(shouldCreateObject(pProduct))
- {
- pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
- ,key.p4,key.p5,key.p6,key.p7,key.p8,key.p9);
- onCreate(pProduct);
- }
- onFetch(pProduct);
- providedObjects[pProduct] = key;
- return NP::encapsulate(pProduct);
+ pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
+ ,key.p4,key.p5,key.p6,key.p7);
+ onCreate(pProduct);
}
-
- ProductReturn CreateObject(const IdentifierType& id,
- Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
- Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9,Parm10 p10)
+ onFetch(pProduct);
+ providedObjects[pProduct] = key;
+ return NP::encapsulate(pProduct);
+ }
+
+ ProductReturn CreateObject(const IdentifierType& id,
+ Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8)
+ {
+ MyKey key(id,p1,p2,p3,p4,p5,p6,p7,p8);
+ AbstractProduct* pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
+ if(shouldCreateObject(pProduct))
{
- MyKey key(id,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10);
- AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
- if(shouldCreateObject(pProduct))
- {
- pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
- ,key.p4,key.p5,key.p6,key.p7,key.p8,key.p9,key.p10);
- onCreate(pProduct);
- }
- onFetch(pProduct);
- providedObjects[pProduct] = key;
- return NP::encapsulate(pProduct);
+ pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
+ ,key.p4,key.p5,key.p6,key.p7,key.p8);
+ onCreate(pProduct);
}
+ onFetch(pProduct);
+ providedObjects[pProduct] = key;
+ return NP::encapsulate(pProduct);
+ }
- ProductReturn CreateObject(const IdentifierType& id,
- Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
- Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10,
- Parm11 p11)
+ ProductReturn CreateObject(const IdentifierType& id,
+ Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9)
+ {
+ MyKey key(id,p1,p2,p3,p4,p5,p6,p7,p8,p9);
+ AbstractProduct* pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
+ if(shouldCreateObject(pProduct))
{
- MyKey key(id,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11);
- AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
- if(shouldCreateObject(pProduct))
- {
- pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
- ,key.p4,key.p5,key.p6,key.p7,key.p8,key.p9,key.p10,key.p11);
- onCreate(pProduct);
- }
- onFetch(pProduct);
- providedObjects[pProduct] = key;
- return NP::encapsulate(pProduct);
+ pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
+ ,key.p4,key.p5,key.p6,key.p7,key.p8,key.p9);
+ onCreate(pProduct);
}
+ onFetch(pProduct);
+ providedObjects[pProduct] = key;
+ return NP::encapsulate(pProduct);
+ }
- ProductReturn CreateObject(const IdentifierType& id,
- Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
- Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10,
- Parm11 p11, Parm12 p12)
+ ProductReturn CreateObject(const IdentifierType& id,
+ Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9,Parm10 p10)
+ {
+ MyKey key(id,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10);
+ AbstractProduct* pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
+ if(shouldCreateObject(pProduct))
{
- MyKey key(id,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12);
- AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
- if(shouldCreateObject(pProduct))
- {
- pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
- ,key.p4,key.p5,key.p6,key.p7,key.p8,key.p9,key.p10,key.p11,key.p12);
- onCreate(pProduct);
- }
- onFetch(pProduct);
- providedObjects[pProduct] = key;
- return NP::encapsulate(pProduct);
+ pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
+ ,key.p4,key.p5,key.p6,key.p7,key.p8,key.p9,key.p10);
+ onCreate(pProduct);
}
+ onFetch(pProduct);
+ providedObjects[pProduct] = key;
+ return NP::encapsulate(pProduct);
+ }
- ProductReturn CreateObject(const IdentifierType& id,
- Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
- Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10,
- Parm11 p11, Parm12 p12, Parm13 p13)
+ ProductReturn CreateObject(const IdentifierType& id,
+ Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10,
+ Parm11 p11)
+ {
+ MyKey key(id,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11);
+ AbstractProduct* pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
+ if(shouldCreateObject(pProduct))
{
- MyKey key(id,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13);
- AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
- if(shouldCreateObject(pProduct))
- {
- pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
- ,key.p4,key.p5,key.p6,key.p7,key.p8,key.p9,key.p10,key.p11,key.p12
- ,key.p13);
- onCreate(pProduct);
- }
- onFetch(pProduct);
- providedObjects[pProduct] = key;
- return NP::encapsulate(pProduct);
+ pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
+ ,key.p4,key.p5,key.p6,key.p7,key.p8,key.p9,key.p10,key.p11);
+ onCreate(pProduct);
}
+ onFetch(pProduct);
+ providedObjects[pProduct] = key;
+ return NP::encapsulate(pProduct);
+ }
- ProductReturn CreateObject(const IdentifierType& id,
- Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
- Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10,
- Parm11 p11, Parm12 p12, Parm13 p13, Parm14 p14)
+ ProductReturn CreateObject(const IdentifierType& id,
+ Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10,
+ Parm11 p11, Parm12 p12)
+ {
+ MyKey key(id,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12);
+ AbstractProduct* pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
+ if(shouldCreateObject(pProduct))
{
- MyKey key(id,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14);
- AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
- if(shouldCreateObject(pProduct))
- {
- pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
- ,key.p4,key.p5,key.p6,key.p7,key.p8,key.p9,key.p10,key.p11,key.p12
- ,key.p13,key.p14);
- onCreate(pProduct);
- }
- onFetch(pProduct);
- providedObjects[pProduct] = key;
- return NP::encapsulate(pProduct);
+ pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
+ ,key.p4,key.p5,key.p6,key.p7,key.p8,key.p9,key.p10,key.p11,key.p12);
+ onCreate(pProduct);
}
+ onFetch(pProduct);
+ providedObjects[pProduct] = key;
+ return NP::encapsulate(pProduct);
+ }
- ProductReturn CreateObject(const IdentifierType& id,
- Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
- Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10,
- Parm11 p11, Parm12 p12, Parm13 p13, Parm14 p14, Parm15 p15)
+ ProductReturn CreateObject(const IdentifierType& id,
+ Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10,
+ Parm11 p11, Parm12 p12, Parm13 p13)
+ {
+ MyKey key(id,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13);
+ AbstractProduct* pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
+ if(shouldCreateObject(pProduct))
{
- MyKey key(id,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14,p15);
- AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
- if(shouldCreateObject(pProduct))
- {
- pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
- ,key.p4,key.p5,key.p6,key.p7,key.p8,key.p9,key.p10,key.p11,key.p12
- ,key.p13,key.p14,key.p15);
- onCreate(pProduct);
- }
- onFetch(pProduct);
- providedObjects[pProduct] = key;
- return NP::encapsulate(pProduct);
+ pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
+ ,key.p4,key.p5,key.p6,key.p7,key.p8,key.p9,key.p10,key.p11,key.p12
+ ,key.p13);
+ onCreate(pProduct);
}
+ onFetch(pProduct);
+ providedObjects[pProduct] = key;
+ return NP::encapsulate(pProduct);
+ }
- /// Use this function to release the object
- /**
- * if execution brakes in this function then you tried
- * to release an object that wasn't provided by this Cache
- * ... which is bad :-)
- */
- void ReleaseObject(ProductReturn &object)
+ ProductReturn CreateObject(const IdentifierType& id,
+ Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10,
+ Parm11 p11, Parm12 p12, Parm13 p13, Parm14 p14)
+ {
+ MyKey key(id,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14);
+ AbstractProduct* pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
+ if(shouldCreateObject(pProduct))
{
- AbstractProduct* pProduct(NP::release(object));
- typename FetchedObjToKeyMap::iterator itr = providedObjects.find(pProduct);
- if(itr == providedObjects.end())
- throw CacheException();
- onRelease(pProduct);
- ReleaseObjectFromContainer(getContainerFromKey((*itr).second), pProduct);
- providedObjects.erase(itr);
+ pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
+ ,key.p4,key.p5,key.p6,key.p7,key.p8,key.p9,key.p10,key.p11,key.p12
+ ,key.p13,key.p14);
+ onCreate(pProduct);
}
-
- /// display the cache configuration
- void displayCacheType()
+ onFetch(pProduct);
+ providedObjects[pProduct] = key;
+ return NP::encapsulate(pProduct);
+ }
+
+ ProductReturn CreateObject(const IdentifierType& id,
+ Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10,
+ Parm11 p11, Parm12 p12, Parm13 p13, Parm14 p14, Parm15 p15)
+ {
+ MyKey key(id,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14,p15);
+ AbstractProduct* pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
+ if(shouldCreateObject(pProduct))
{
- using namespace std;
- cout << "############################" << endl;
- cout << "## Cache configuration" << endl;
- cout << "## + Encapsulation " << NP::name() << endl;
- cout << "## + Creating " << CP::name() << endl;
- cout << "## + Eviction " << EP::name() << endl;
- cout << "## + Statistics " << SP::name() << endl;
- cout << "############################" << endl;
+ pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
+ ,key.p4,key.p5,key.p6,key.p7,key.p8,key.p9,key.p10,key.p11,key.p12
+ ,key.p13,key.p14,key.p15);
+ onCreate(pProduct);
}
- };
+ onFetch(pProduct);
+ providedObjects[pProduct] = key;
+ return NP::encapsulate(pProduct);
+ }
+
+ /// Use this function to release the object
+ /**
+ * if execution brakes in this function then you tried
+ * to release an object that wasn't provided by this Cache
+ * ... which is bad :-)
+ */
+ void ReleaseObject(ProductReturn& object)
+ {
+ AbstractProduct* pProduct(NP::release(object));
+ typename FetchedObjToKeyMap::iterator itr = providedObjects.find(pProduct);
+ if(itr == providedObjects.end())
+ throw CacheException();
+ onRelease(pProduct);
+ ReleaseObjectFromContainer(getContainerFromKey((*itr).second), pProduct);
+ providedObjects.erase(itr);
+ }
+
+ /// display the cache configuration
+ void displayCacheType()
+ {
+ using namespace std;
+ cout << "############################" << endl;
+ cout << "## Cache configuration" << endl;
+ cout << "## + Encapsulation " << NP::name() << endl;
+ cout << "## + Creating " << CP::name() << endl;
+ cout << "## + Eviction " << EP::name() << endl;
+ cout << "## + Statistics " << SP::name() << endl;
+ cout << "############################" << endl;
+ }
+};
} // namespace Loki
#endif // end file guardian
bgstack15