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: 19525 $
00027  * $Author: rjongbloed $
00028  * $Date: 2008-02-16 05:59:37 +0000 (Sat, 16 Feb 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(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     }
00322 
00323     PBoolean RegisterAs_Internal(const _Key_T & newKey, const _Key_T & oldKey)
00324     {
00325       PWaitAndSignal m(mutex);
00326       if (keyMap.find(oldKey) == keyMap.end())
00327         return PFalse;
00328       keyMap[newKey] = keyMap[oldKey];
00329       return PTrue;
00330     }
00331 
00332     void Unregister_Internal(const _Key_T & key)
00333     {
00334       PWaitAndSignal m(mutex);
00335       typename KeyMap_T::iterator r = keyMap.find(key);
00336       if (r != keyMap.end()) {
00337         if (r->second->isDynamic)
00338           delete r->second;
00339         keyMap.erase(r);
00340       }
00341     }
00342 
00343     void UnregisterAll_Internal()
00344     {
00345       PWaitAndSignal m(mutex);
00346       while (keyMap.size() > 0)
00347         keyMap.erase(keyMap.begin());
00348     }
00349 
00350     bool IsRegistered_Internal(const _Key_T & key)
00351     {
00352       PWaitAndSignal m(mutex);
00353       return keyMap.find(key) != keyMap.end();
00354     }
00355 
00356     _Abstract_T * CreateInstance_Internal(const _Key_T & key)
00357     {
00358       PWaitAndSignal m(mutex);
00359       typename KeyMap_T::const_iterator entry = keyMap.find(key);
00360       if (entry != keyMap.end())
00361         return entry->second->CreateInstance(key);
00362       return NULL;
00363     }
00364 
00365     bool IsSingleton_Internal(const _Key_T & key)
00366     {
00367       PWaitAndSignal m(mutex);
00368       if (keyMap.find(key) == keyMap.end())
00369         return false;
00370       return keyMap[key]->isSingleton;
00371     }
00372 
00373     KeyList_T GetKeyList_Internal()
00374     { 
00375       PWaitAndSignal m(mutex);
00376       KeyList_T list;
00377       typename KeyMap_T::const_iterator entry;
00378       for (entry = keyMap.begin(); entry != keyMap.end(); ++entry)
00379         list.push_back(entry->first);
00380       return list;
00381     }
00382 
00383     KeyMap_T keyMap;
00384 
00385   private:
00386     PFactory(const PFactory &) {}
00387     void operator=(const PFactory &) {}
00388 };
00389 
00390 //
00391 //  this macro is used to initialise the static member variable used to force factories to instantiate
00392 //
00393 #define PLOAD_FACTORY(AbstractType, KeyType) \
00394   namespace PWLibFactoryLoader { \
00395     extern int AbstractType##_##KeyType##_loader; \
00396     static int AbstractType##_##KeyType##_loader_instance = AbstractType##_##KeyType##_loader; \
00397   };
00398 
00399 
00400 //
00401 //  this macro is used to instantiate a static variable that accesses the static member variable 
00402 //  in a factory forcing it to load
00403 //
00404 #define PINSTANTIATE_FACTORY(AbstractType, KeyType) \
00405   namespace PWLibFactoryLoader { int AbstractType##_##KeyType##_loader; }
00406 
00407 
00408 #endif // _PFACTORY_H

Generated on Wed May 7 00:47:56 2008 for PTLib by  doxygen 1.5.1