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: 19008 $
00027  * $Author: rjongbloed $
00028  * $Date: 2007-11-29 09:17:41 +0000 (Thu, 29 Nov 2007) $
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)
00159           : isDynamic(true),
00160             isSingleton(true),
00161             singletonInstance(instance),
00162             deleteSingleton(true)
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(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)
00226     {
00227       GetInstance().Register_Internal(key, PNEW WorkerBase(instance));
00228     }
00229 
00230     static PBoolean RegisterAs(const _Key_T & newKey, const _Key_T & oldKey)
00231     {
00232       return GetInstance().RegisterAs_Internal(newKey, oldKey);
00233     }
00234 
00235     static void Unregister(const _Key_T & key)
00236     {
00237       GetInstance().Unregister_Internal(key);
00238     }
00239 
00240     static void UnregisterAll()
00241     {
00242       GetInstance().UnregisterAll_Internal();
00243     }
00244 
00245     static bool IsRegistered(const _Key_T & key)
00246     {
00247       return GetInstance().IsRegistered_Internal(key);
00248     }
00249 
00250     static _Abstract_T * CreateInstance(const _Key_T & key)
00251     {
00252       return GetInstance().CreateInstance_Internal(key);
00253     }
00254 
00255     static PBoolean IsSingleton(const _Key_T & key)
00256     {
00257       return GetInstance().IsSingleton_Internal(key);
00258     }
00259 
00260     static KeyList_T GetKeyList()
00261     { 
00262       return GetInstance().GetKeyList_Internal();
00263     }
00264 
00265     static KeyMap_T & GetKeyMap()
00266     { 
00267       return GetInstance().keyMap;
00268     }
00269 
00270     static PMutex & GetMutex()
00271     {
00272       return GetInstance().mutex;
00273     }
00274 
00275   protected:
00276     PFactory()
00277     { }
00278 
00279     ~PFactory()
00280     {
00281       typename KeyMap_T::const_iterator entry;
00282       for (entry = keyMap.begin(); entry != keyMap.end(); ++entry) {
00283         if (entry->second->isDynamic)
00284           delete entry->second;
00285       }
00286     }
00287 
00288     static PFactory & GetInstance()
00289     {
00290       std::string className = typeid(PFactory).name();
00291       PWaitAndSignal m(GetFactoriesMutex());
00292       FactoryMap & factories = GetFactories();
00293       FactoryMap::const_iterator entry = factories.find(className);
00294       if (entry != factories.end()) {
00295         PAssert(entry->second != NULL, "Factory map returned NULL for existing key");
00296         PFactoryBase * b = entry->second;
00297         // don't use the following dynamic cast, because gcc does not like it
00298         //PFactory * f = dynamic_cast<PFactory*>(b);
00299         return *(PFactory *)b;
00300       }
00301 
00302       PMEMORY_IGNORE_ALLOCATIONS_FOR_SCOPE;
00303       PFactory * factory = new PFactory;
00304       factories[className] = factory;
00305       return *factory;
00306     }
00307 
00308 
00309     void Register_Internal(const _Key_T & key, WorkerBase * worker)
00310     {
00311       PWaitAndSignal m(mutex);
00312       if (keyMap.find(key) == keyMap.end())
00313         keyMap[key] = worker;
00314     }
00315 
00316     PBoolean RegisterAs_Internal(const _Key_T & newKey, const _Key_T & oldKey)
00317     {
00318       PWaitAndSignal m(mutex);
00319       if (keyMap.find(oldKey) == keyMap.end())
00320         return PFalse;
00321       keyMap[newKey] = keyMap[oldKey];
00322       return PTrue;
00323     }
00324 
00325     void Unregister_Internal(const _Key_T & key)
00326     {
00327       PWaitAndSignal m(mutex);
00328       keyMap.erase(key);
00329     }
00330 
00331     void UnregisterAll_Internal()
00332     {
00333       PWaitAndSignal m(mutex);
00334       keyMap.erase(keyMap.begin(), keyMap.end());
00335     }
00336 
00337     bool IsRegistered_Internal(const _Key_T & key)
00338     {
00339       PWaitAndSignal m(mutex);
00340       return keyMap.find(key) != keyMap.end();
00341     }
00342 
00343     _Abstract_T * CreateInstance_Internal(const _Key_T & key)
00344     {
00345       PWaitAndSignal m(mutex);
00346       typename KeyMap_T::const_iterator entry = keyMap.find(key);
00347       if (entry != keyMap.end())
00348         return entry->second->CreateInstance(key);
00349       return NULL;
00350     }
00351 
00352     bool IsSingleton_Internal(const _Key_T & key)
00353     {
00354       PWaitAndSignal m(mutex);
00355       if (keyMap.find(key) == keyMap.end())
00356         return false;
00357       return keyMap[key]->isSingleton;
00358     }
00359 
00360     KeyList_T GetKeyList_Internal()
00361     { 
00362       PWaitAndSignal m(mutex);
00363       KeyList_T list;
00364       typename KeyMap_T::const_iterator entry;
00365       for (entry = keyMap.begin(); entry != keyMap.end(); ++entry)
00366         list.push_back(entry->first);
00367       return list;
00368     }
00369 
00370     KeyMap_T keyMap;
00371 
00372   private:
00373     PFactory(const PFactory &) {}
00374     void operator=(const PFactory &) {}
00375 };
00376 
00377 //
00378 //  this macro is used to initialise the static member variable used to force factories to instantiate
00379 //
00380 #define PLOAD_FACTORY(AbstractType, KeyType) \
00381   namespace PWLibFactoryLoader { \
00382     extern int AbstractType##_##KeyType##_loader; \
00383     static int AbstractType##_##KeyType##_loader_instance = AbstractType##_##KeyType##_loader; \
00384   };
00385 
00386 
00387 //
00388 //  this macro is used to instantiate a static variable that accesses the static member variable 
00389 //  in a factory forcing it to load
00390 //
00391 #define PINSTANTIATE_FACTORY(AbstractType, KeyType) \
00392   namespace PWLibFactoryLoader { int AbstractType##_##KeyType##_loader; }
00393 
00394 
00395 #endif // _PFACTORY_H

Generated on Mon Dec 10 11:18:57 2007 for PTLib by  doxygen 1.5.1