diff options
author | Daniel Wilhelm <daniel@wili.li> | 2014-04-18 17:15:16 +0200 |
---|---|---|
committer | Daniel Wilhelm <daniel@wili.li> | 2014-04-18 17:15:16 +0200 |
commit | bd6336c629841c6db3a6ca53a936d629d34db53b (patch) | |
tree | 3721ef997864108df175ce677a8a7d4342a6f1d2 /shared/loki/CachedFactory.h | |
parent | 4.0 (diff) | |
download | FreeFileSync-bd6336c629841c6db3a6ca53a936d629d34db53b.tar.gz FreeFileSync-bd6336c629841c6db3a6ca53a936d629d34db53b.tar.bz2 FreeFileSync-bd6336c629841c6db3a6ca53a936d629d34db53b.zip |
4.1
Diffstat (limited to 'shared/loki/CachedFactory.h')
-rw-r--r-- | shared/loki/CachedFactory.h | 1179 |
1 files changed, 0 insertions, 1179 deletions
diff --git a/shared/loki/CachedFactory.h b/shared/loki/CachedFactory.h deleted file mode 100644 index dc5a76ae..00000000 --- a/shared/loki/CachedFactory.h +++ /dev/null @@ -1,1179 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// The Loki Library -// Copyright (c) 2006 by Guillaume Chatelet -// -// 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 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 -// Patterns Applied". Copyright (c) 2001. Addison-Wesley. -// -//////////////////////////////////////////////////////////////////////////////// -#ifndef LOKI_CACHEDFACTORY_INC_ -#define LOKI_CACHEDFACTORY_INC_ - -// $Id: CachedFactory.h 950 2009-01-26 19:45:54Z syntheticpp $ - -#include <functional> -#include <algorithm> -#include <iostream> -#include <vector> -#include <iterator> -#include <map> -#include <cassert> -#include <loki/Key.h> - -#ifdef DO_EXTRA_LOKI_TESTS -#define D( x ) x -#else -#define D( x ) ; -#endif - -#if defined(_MSC_VER) || defined(__CYGWIN__) -#include <time.h> -#endif - -/** - * \defgroup FactoriesGroup Factories - * \defgroup CachedFactoryGroup Cached Factory - * \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 - * CachedFactory will surely speedup the execution. - */ -namespace Loki -{ -/** - * \defgroup EncapsulationPolicyCachedFactoryGroup Encapsulation policies - * \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";} -}; - -/** - * \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; - } - - 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; - } - - 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; ) - } -}; - -/** - * \defgroup EvictionPolicyCachedFactoryGroup Eviction policies - * \ingroup CachedFactoryGroup - * \brief Gathers informations about the stored objects and choose a - * candidate for eviction. - */ - -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() - { - 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 > -{ -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]); - } - - 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: - 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 -{ -private: - unsigned allocated, created, hit, out, fetched; -protected: - SimpleStatisticPolicy() : allocated(0), created(0), hit(0), out(0), fetched(0) - { - } - - 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) - { - cout << "## Overall efficiency " << 100 * double(hit) / fetched << "%" << endl; - cout << "############################" << endl; - } - 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 - { - // 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) - { - 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; } - }; - - // 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) - { - 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 - { - 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 - } - -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 >() - ); - } - } - - /////////////////////////////////// - // Acts as the proxy pattern and // - // forwards factory methods // - /////////////////////////////////// - - 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); - } - - /// 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)) - { - 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); - } - - ProductReturn CreateObject(const IdentifierType& id, - Parm1 p1, Parm2 p2) - { - 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); - } - - 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)) - { - 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) - { - 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); - } - - 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)) - { - 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) - { - 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); - } - - 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)) - { - 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); - } - - 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)) - { - 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) - { - 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); - } - - 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)) - { - 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) - { - 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); - } - - 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)) - { - 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) - { - 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); - } - - 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)) - { - 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); - } - - 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)) - { - 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 - |