PTLib  Version 2.10.4
pfactory.h
Go to the documentation of this file.
00001 /*
00002  * factory.h
00003  *
00004  * Abstract Factory Classes
00005  *
00006  * Portable Windows Library
00007  *
00008  * Copyright (C) 2004 Post Increment
00009  *
00010  * The contents of this file are subject to the Mozilla Public License
00011  * Version 1.0 (the "License"); you may not use this file except in
00012  * compliance with the License. You may obtain a copy of the License at
00013  * http://www.mozilla.org/MPL/
00014  *
00015  * Software distributed under the License is distributed on an "AS IS"
00016  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
00017  * the License for the specific language governing rights and limitations
00018  * under the License.
00019  *
00020  * The Original Code is Portable Windows Library.
00021  *
00022  * The Initial Developer of the Original Code is Post Increment
00023  *
00024  * Contributor(s): ______________________________________.
00025  *
00026  * $Revision: 26567 $
00027  * $Author: rjongbloed $
00028  * $Date: 2011-10-08 01:17:56 -0500 (Sat, 08 Oct 2011) $
00029  */
00030 
00031 #ifndef PTLIB_FACTORY_H
00032 #define PTLIB_FACTORY_H
00033 
00034 #ifdef P_USE_PRAGMA
00035 #pragma interface
00036 #endif
00037 
00038 #include <ptlib.h>
00039 
00040 #include <string>
00041 #include <map>
00042 #include <vector>
00043 
00044 #if defined(_MSC_VER)
00045 #pragma warning(disable:4786)
00046 #endif
00047 
00099 // this define the default class to be used for keys into PFactories
00100 //typedef PString PDefaultPFactoryKey;
00101 typedef std::string PDefaultPFactoryKey;
00102 
00103 
00111 class PFactoryBase
00112 {
00113   protected:
00114     PFactoryBase()
00115     { }
00116   public:
00117     virtual ~PFactoryBase()
00118     { }
00119 
00120     virtual void DestroySingletons() = 0;
00121 
00122     class FactoryMap : public std::map<std::string, PFactoryBase *>
00123     {
00124       public:
00125         FactoryMap() { }
00126         ~FactoryMap();
00127     };
00128 
00129     static FactoryMap & GetFactories();
00130     static PMutex & GetFactoriesMutex();
00131 
00132   protected:
00133     PMutex m_mutex;
00134 
00135   private:
00136     PFactoryBase(const PFactoryBase &) {}
00137     void operator=(const PFactoryBase &) {}
00138 };
00139 
00140 
00143 template <class AbstractClass, typename KeyType = PDefaultPFactoryKey>
00144 class PFactory : PFactoryBase
00145 {
00146   public:
00147     typedef KeyType       Key_T;
00148     typedef AbstractClass Abstract_T;
00149 
00150     class WorkerBase
00151     {
00152       protected:
00153         enum Types {
00154           NonSingleton,
00155           StaticSingleton,
00156           DynamicSingleton
00157         } m_type;
00158 
00159         Abstract_T * m_singletonInstance;
00160 
00161         WorkerBase(bool singleton = false)
00162           : m_type(singleton ? DynamicSingleton : NonSingleton)
00163           , m_singletonInstance(NULL)
00164         { }
00165 
00166         WorkerBase(Abstract_T * instance, bool delSingleton = true)
00167           : m_type(delSingleton ? DynamicSingleton : StaticSingleton)
00168           , m_singletonInstance(instance)
00169         { }
00170 
00171         virtual ~WorkerBase()
00172         {
00173           DestroySingleton();
00174         }
00175 
00176         Abstract_T * CreateInstance(const Key_T & key)
00177         {
00178           if (m_type == NonSingleton)
00179             return Create(key);
00180 
00181           if (m_singletonInstance == NULL)
00182             m_singletonInstance = Create(key);
00183           return m_singletonInstance;
00184         }
00185 
00186         virtual Abstract_T * Create(const Key_T & /*key*/) const
00187         {
00188           PAssert(this->m_type == StaticSingleton, "Incorrect factory worker descendant");
00189           return this->m_singletonInstance;
00190         }
00191 
00192         virtual void DestroySingleton()
00193         {
00194           if (m_type == DynamicSingleton) {
00195             delete m_singletonInstance;
00196             m_singletonInstance = NULL;
00197           }
00198         }
00199 
00200         bool IsSingleton() const { return m_type != NonSingleton; }
00201 
00202       friend class PFactory<Abstract_T, Key_T>;
00203     };
00204 
00205     template <class ConcreteClass>
00206     class Worker : WorkerBase
00207     {
00208       public:
00209         Worker(const Key_T & key, bool singleton = false)
00210           : WorkerBase(singleton)
00211         {
00212           PMEMORY_IGNORE_ALLOCATIONS_FOR_SCOPE;
00213           PFactory<Abstract_T, Key_T>::Register(key, this);
00214         }
00215 
00216       protected:
00217         virtual Abstract_T * Create(const Key_T & /*key*/) const
00218         {
00219           return new ConcreteClass;
00220         }
00221     };
00222 
00223     typedef std::map<Key_T, WorkerBase *> KeyMap_T;
00224     typedef std::vector<Key_T> KeyList_T;
00225 
00226     static bool Register(const Key_T & key, WorkerBase * worker)
00227     {
00228       return GetInstance().Register_Internal(key, worker);
00229     }
00230 
00231     static bool Register(const Key_T & key, Abstract_T * instance, bool autoDeleteInstance = true)
00232     {
00233       WorkerBase * worker = PNEW WorkerBase(instance, autoDeleteInstance);
00234       if (GetInstance().Register_Internal(key, worker))
00235         return true;
00236       delete worker;
00237       return false;
00238     }
00239 
00240     static PBoolean RegisterAs(const Key_T & newKey, const Key_T & oldKey)
00241     {
00242       return GetInstance().RegisterAs_Internal(newKey, oldKey);
00243     }
00244 
00245     static void Unregister(const Key_T & key)
00246     {
00247       GetInstance().Unregister_Internal(key);
00248     }
00249 
00250     static void UnregisterAll()
00251     {
00252       GetInstance().UnregisterAll_Internal();
00253     }
00254 
00255     static bool IsRegistered(const Key_T & key)
00256     {
00257       return GetInstance().IsRegistered_Internal(key);
00258     }
00259 
00260     static Abstract_T * CreateInstance(const Key_T & key)
00261     {
00262       return GetInstance().CreateInstance_Internal(key);
00263     }
00264 
00265     template <class Derived_T>
00266     static Derived_T * CreateInstanceAs(const Key_T & key)
00267     {
00268       return dynamic_cast<Derived_T *>(GetInstance().CreateInstance_Internal(key));
00269     }
00270 
00271     static PBoolean IsSingleton(const Key_T & key)
00272     {
00273       return GetInstance().IsSingleton_Internal(key);
00274     }
00275 
00276     static KeyList_T GetKeyList()
00277     { 
00278       return GetInstance().GetKeyList_Internal();
00279     }
00280 
00281     static KeyMap_T & GetKeyMap()
00282     { 
00283       return GetInstance().m_keyMap;
00284     }
00285 
00286     static PMutex & GetMutex()
00287     {
00288       return GetInstance().m_mutex;
00289     }
00290 
00291     virtual void DestroySingletons()
00292     {
00293       for (typename KeyMap_T::const_iterator it = m_keyMap.begin(); it != m_keyMap.end(); ++it)
00294         it->second->DestroySingleton();
00295     }
00296 
00297   protected:
00298     PFactory()
00299     { }
00300 
00301     ~PFactory()
00302     {
00303       DestroySingletons();
00304     }
00305 
00306     static PFactory & GetInstance()
00307     {
00308       std::string className = typeid(PFactory).name();
00309       PWaitAndSignal m(GetFactoriesMutex());
00310       FactoryMap & factories = GetFactories();
00311       FactoryMap::const_iterator entry = factories.find(className);
00312       if (entry != factories.end()) {
00313         PAssert(entry->second != NULL, "Factory map returned NULL for existing key");
00314         PFactoryBase * b = entry->second;
00315         // don't use the following dynamic cast, because gcc does not like it
00316         //PFactory * f = dynamic_cast<PFactory*>(b);
00317         return *(PFactory *)b;
00318       }
00319 
00320       PMEMORY_IGNORE_ALLOCATIONS_FOR_SCOPE;
00321       PFactory * factory = new PFactory;
00322       factories[className] = factory;
00323       return *factory;
00324     }
00325 
00326 
00327     bool Register_Internal(const Key_T & key, WorkerBase * worker)
00328     {
00329       PWaitAndSignal mutex(m_mutex);
00330       if (m_keyMap.find(key) != m_keyMap.end())
00331         return false;
00332       m_keyMap[key] = PAssertNULL(worker);
00333       return true;
00334     }
00335 
00336     PBoolean RegisterAs_Internal(const Key_T & newKey, const Key_T & oldKey)
00337     {
00338       PWaitAndSignal mutex(m_mutex);
00339       if (m_keyMap.find(oldKey) == m_keyMap.end())
00340         return false;
00341       m_keyMap[newKey] = m_keyMap[oldKey];
00342       return true;
00343     }
00344 
00345     void Unregister_Internal(const Key_T & key)
00346     {
00347       m_mutex.Wait();
00348       m_keyMap.erase(key);
00349       m_mutex.Signal();
00350     }
00351 
00352     void UnregisterAll_Internal()
00353     {
00354       m_mutex.Wait();
00355       m_keyMap.clear();
00356       m_mutex.Signal();
00357     }
00358 
00359     bool IsRegistered_Internal(const Key_T & key)
00360     {
00361       PWaitAndSignal mutex(m_mutex);
00362       return m_keyMap.find(key) != m_keyMap.end();
00363     }
00364 
00365     Abstract_T * CreateInstance_Internal(const Key_T & key)
00366     {
00367       PWaitAndSignal mutex(m_mutex);
00368       typename KeyMap_T::const_iterator entry = m_keyMap.find(key);
00369       if (entry != m_keyMap.end())
00370         return entry->second->CreateInstance(key);
00371       return NULL;
00372     }
00373 
00374     bool IsSingleton_Internal(const Key_T & key)
00375     {
00376       PWaitAndSignal mutex(m_mutex);
00377       if (m_keyMap.find(key) == m_keyMap.end())
00378         return false;
00379       return m_keyMap[key]->IsSingleton();
00380     }
00381 
00382     KeyList_T GetKeyList_Internal()
00383     { 
00384       PWaitAndSignal mutex(m_mutex);
00385       KeyList_T list;
00386       typename KeyMap_T::const_iterator entry;
00387       for (entry = m_keyMap.begin(); entry != m_keyMap.end(); ++entry)
00388         list.push_back(entry->first);
00389       return list;
00390     }
00391 
00392     KeyMap_T m_keyMap;
00393 
00394   private:
00395     PFactory(const PFactory &) {}
00396     void operator=(const PFactory &) {}
00397 };
00398 
00399 
00411 #define PFACTORY_CREATE(factory, ConcreteClass, ...) \
00412   namespace PFactoryLoader { \
00413     int ConcreteClass##_link() { return 0; } \
00414     factory::Worker<ConcreteClass> ConcreteClass##_instance(__VA_ARGS__); \
00415   }
00416 
00417 #define PFACTORY_CREATE_SINGLETON(factory, ConcreteClass) \
00418         PFACTORY_CREATE(factory, ConcreteClass, typeid(ConcreteClass).name(), true)
00419 
00420 #define PFACTORY_GET_SINGLETON(factory, ConcreteClass) \
00421         static ConcreteClass & GetInstance() { \
00422           return *factory::CreateInstanceAs<ConcreteClass>(typeid(ConcreteClass).name()); \
00423         }
00424 
00425 
00426 
00427 
00428 /* This macro is used to force linking of factories.
00429    See PFACTORY_CREATE() for more information
00430  */
00431 #define PFACTORY_LOAD(ConcreteType) \
00432   namespace PFactoryLoader { \
00433     extern int ConcreteType##_link(); \
00434     int const ConcreteType##_loader = ConcreteType##_link(); \
00435   }
00436 
00437 
00438 #endif // PTLIB_FACTORY_H
00439 
00440 
00441 // End Of File ///////////////////////////////////////////////////////////////
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines