# 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 ///////////////////////////////////////////////////////////////