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: 20385 $
00027  * $Author: rjongbloed $
00028  * $Date: 2008-06-04 10:40:38 +0000 (Wed, 04 Jun 2008) $
00029  */
00030 
00031 #ifndef _PFACTORY_H
00032 #define _PFACTORY_H
00033 
00034 #ifdef P_USE_PRAGMA
00035 #pragma interface
00036 #endif
00037 
00038 #ifndef _PTLIB_H
00039 #include <ptlib.h>
00040 #endif
00041 
00042 #include <string>
00043 #include <map>
00044 #include <vector>
00045 
00046 #if defined(_MSC_VER)
00047 #pragma warning(disable:4786)
00048 #endif
00049 
00101 // this define the default class to be used for keys into PFactories
00102 //typedef PString PDefaultPFactoryKey;
00103 typedef std::string PDefaultPFactoryKey;
00104 
00105 
00113 class PFactoryBase
00114 {
00115   protected:
00116     PFactoryBase()
00117     { }
00118   public:
00119     virtual ~PFactoryBase()
00120     { }
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     PMutex mutex;
00133 
00134   private:
00135     PFactoryBase(const PFactoryBase &) {}
00136     void operator=(const PFactoryBase &) {}
00137 };
00138 
00139 
00142 template <class _Abstract_T, typename _Key_T = PDefaultPFactoryKey>
00143 class PFactory : PFactoryBase
00144 {
00145   public:
00146     typedef _Key_T      Key_T;
00147     typedef _Abstract_T Abstract_T;
00148 
00149     class WorkerBase
00150     {
00151       protected:
00152         WorkerBase(bool singleton = false)
00153           : isDynamic(false),
00154             isSingleton(singleton),
00155             singletonInstance(NULL),
00156             deleteSingleton(false)
00157         { }
00158         WorkerBase(Abstract_T * instance, bool _deleteSingleton = true)
00159           : isDynamic(true),
00160             isSingleton(true),
00161             singletonInstance(instance),
00162             deleteSingleton(_deleteSingleton)
00163         { }
00164 
00165         virtual ~WorkerBase()
00166         {
00167           if (deleteSingleton)
00168             delete singletonInstance;
00169         }
00170 
00171         Abstract_T * CreateInstance(const Key_T & key)
00172         {
00173           if (!isSingleton)
00174             return Create(key);
00175 
00176           if (singletonInstance == NULL)
00177             singletonInstance = Create(key);
00178           return singletonInstance;
00179         }
00180 
00181         virtual Abstract_T * Create(const Key_T & /*key*/) const { return singletonInstance; }
00182 
00183         bool         isDynamic;
00184         bool         isSingleton;
00185         Abstract_T * singletonInstance;
00186         bool         deleteSingleton;
00187 
00188       friend class PFactory<_Abstract_T, _Key_T>;
00189     };
00190 
00191     template <class _Concrete_T>
00192     class Worker : WorkerBase
00193     {
00194       public:
00195         Worker(const Key_T & key, bool singleton = false)
00196           : WorkerBase(singleton)
00197         {
00198           PMEMORY_IGNORE_ALLOCATIONS_FOR_SCOPE;
00199           PFactory<_Abstract_T, _Key_T>::Register(key, this);   // here
00200         }
00201 
00202       protected:
00203         virtual Abstract_T * Create(const Key_T & /*key*/) const
00204         {
00205 #if PMEMORY_HEAP
00206           // Singletons are never deallocated, so make sure they arenot reported as a leak
00207           PBoolean previousIgnoreAllocations = PMemoryHeap::SetIgnoreAllocations(WorkerBase::isSingleton);
00208 #endif
00209           Abstract_T * instance = new _Concrete_T;
00210 #if PMEMORY_HEAP
00211           PMemoryHeap::SetIgnoreAllocations(previousIgnoreAllocations);
00212 #endif
00213           return instance;
00214         }
00215     };
00216 
00217     typedef std::map<_Key_T, WorkerBase *> KeyMap_T;
00218     typedef std::vector<_Key_T> KeyList_T;
00219 
00220     static void Register(const _Key_T & key, WorkerBase * worker)
00221     {
00222       GetInstance().Register_Internal(key, worker);
00223     }
00224 
00225     static void Register(const _Key_T & key, Abstract_T * instance, bool autoDeleteInstance = true)
00226     {
00227       WorkerBase * w = PNEW WorkerBase(instance, autoDeleteInstance);
00228       GetInstance().Register_Internal(key, w);
00229     }
00230 
00231     static PBoolean RegisterAs(const _Key_T & newKey, const _Key_T & oldKey)
00232     {
00233       return GetInstance().RegisterAs_Internal(newKey, oldKey);
00234     }
00235 
00236     static void Unregister(const _Key_T & key)
00237     {
00238       GetInstance().Unregister_Internal(key);
00239     }
00240 
00241     static void UnregisterAll()
00242     {
00243       GetInstance().UnregisterAll_Internal();
00244     }
00245 
00246     static bool IsRegistered(const _Key_T & key)
00247     {
00248       return GetInstance().IsRegistered_Internal(key);
00249     }
00250 
00251     static _Abstract_T * CreateInstance(const _Key_T & key)
00252     {
00253       return GetInstance().CreateInstance_Internal(key);
00254     }
00255 
00256     template <class Derived_T>
00257     static Derived_T * CreateInstanceAs(const _Key_T & key)
00258     {
00259       return dynamic_cast<Derived_T *>(GetInstance().CreateInstance_Internal(key));
00260     }
00261 
00262     static PBoolean IsSingleton(const _Key_T & key)
00263     {
00264       return GetInstance().IsSingleton_Internal(key);
00265     }
00266 
00267     static KeyList_T GetKeyList()
00268     { 
00269       return GetInstance().GetKeyList_Internal();
00270     }
00271 
00272     static KeyMap_T & GetKeyMap()
00273     { 
00274       return GetInstance().keyMap;
00275     }
00276 
00277     static PMutex & GetMutex()
00278     {
00279       return GetInstance().mutex;
00280     }
00281 
00282   protected:
00283     PFactory()
00284     { }
00285 
00286     ~PFactory()
00287     {
00288       typename KeyMap_T::const_iterator entry;
00289       for (entry = keyMap.begin(); entry != keyMap.end(); ++entry) {
00290         if (entry->second->isDynamic)
00291           delete entry->second;
00292       }
00293     }
00294 
00295     static PFactory & GetInstance()
00296     {
00297       std::string className = typeid(PFactory).name();
00298       PWaitAndSignal m(GetFactoriesMutex());
00299       FactoryMap & factories = GetFactories();
00300       FactoryMap::const_iterator entry = factories.find(className);
00301       if (entry != factories.end()) {
00302         PAssert(entry->second != NULL, "Factory map returned NULL for existing key");
00303         PFactoryBase * b = entry->second;
00304         // don't use the following dynamic cast, because gcc does not like it
00305         //PFactory * f = dynamic_cast<PFactory*>(b);
00306         return *(PFactory *)b;
00307       }
00308 
00309       PMEMORY_IGNORE_ALLOCATIONS_FOR_SCOPE;
00310       PFactory * factory = new PFactory;
00311       factories[className] = factory;
00312       return *factory;
00313     }
00314 
00315 
00316     void Register_Internal(const _Key_T & key, WorkerBase * worker)
00317     {
00318       PWaitAndSignal m(mutex);
00319       if (keyMap.find(key) == keyMap.end()) {
00320         keyMap[key] = worker;
00321         if (worker->isSingleton)
00322           worker->CreateInstance(key);
00323       }
00324     }
00325 
00326     PBoolean RegisterAs_Internal(const _Key_T & newKey, const _Key_T & oldKey)
00327     {
00328       PWaitAndSignal m(mutex);
00329       if (keyMap.find(oldKey) == keyMap.end())
00330         return PFalse;
00331       keyMap[newKey] = keyMap[oldKey];
00332       return PTrue;
00333     }
00334 
00335     void Unregister_Internal(const _Key_T & key)
00336     {
00337       PWaitAndSignal m(mutex);
00338       typename KeyMap_T::iterator r = keyMap.find(key);
00339       if (r != keyMap.end()) {
00340         if (r->second->isDynamic)
00341           delete r->second;
00342         keyMap.erase(r);
00343       }
00344     }
00345 
00346     void UnregisterAll_Internal()
00347     {
00348       PWaitAndSignal m(mutex);
00349       while (keyMap.size() > 0)
00350         keyMap.erase(keyMap.begin());
00351     }
00352 
00353     bool IsRegistered_Internal(const _Key_T & key)
00354     {
00355       PWaitAndSignal m(mutex);
00356       return keyMap.find(key) != keyMap.end();
00357     }
00358 
00359     _Abstract_T * CreateInstance_Internal(const _Key_T & key)
00360     {
00361       PWaitAndSignal m(mutex);
00362       typename KeyMap_T::const_iterator entry = keyMap.find(key);
00363       if (entry != keyMap.end())
00364         return entry->second->CreateInstance(key);
00365       return NULL;
00366     }
00367 
00368     bool IsSingleton_Internal(const _Key_T & key)
00369     {
00370       PWaitAndSignal m(mutex);
00371       if (keyMap.find(key) == keyMap.end())
00372         return false;
00373       return keyMap[key]->isSingleton;
00374     }
00375 
00376     KeyList_T GetKeyList_Internal()
00377     { 
00378       PWaitAndSignal m(mutex);
00379       KeyList_T list;
00380       typename KeyMap_T::const_iterator entry;
00381       for (entry = keyMap.begin(); entry != keyMap.end(); ++entry)
00382         list.push_back(entry->first);
00383       return list;
00384     }
00385 
00386     KeyMap_T keyMap;
00387 
00388   private:
00389     PFactory(const PFactory &) {}
00390     void operator=(const PFactory &) {}
00391 };
00392 
00393 //
00394 //  this macro is used to initialise the static member variable used to force factories to instantiate
00395 //
00396 #define PLOAD_FACTORY(AbstractType, KeyType) \
00397   namespace PWLibFactoryLoader { \
00398     extern int AbstractType##_##KeyType##_loader; \
00399     static int AbstractType##_##KeyType##_loader_instance = AbstractType##_##KeyType##_loader; \
00400   };
00401 
00402 
00403 //
00404 //  this macro is used to instantiate a static variable that accesses the static member variable 
00405 //  in a factory forcing it to load
00406 //
00407 #define PINSTANTIATE_FACTORY(AbstractType, KeyType) \
00408   namespace PWLibFactoryLoader { int AbstractType##_##KeyType##_loader; }
00409 
00410 
00411 #endif // _PFACTORY_H

Generated on Mon Feb 23 01:57:54 2009 for PTLib by  doxygen 1.5.1