Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

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 * $Log: pfactory.h,v $ 00027 * Revision 1.18 2004/07/12 09:17:20 csoutheren 00028 * Fixed warnings and errors under Linux 00029 * 00030 * Revision 1.17 2004/07/06 10:12:52 csoutheren 00031 * Added static integer o factory template to assist in ensuring factories are instantiated 00032 * 00033 * Revision 1.16 2004/07/06 04:26:44 csoutheren 00034 * Fixed problem when using factory maps with non-standard keys 00035 * 00036 * Revision 1.15 2004/07/02 03:14:47 csoutheren 00037 * Made factories non-singleton, by default 00038 * Added more docs 00039 * 00040 * Revision 1.14 2004/07/01 11:41:28 csoutheren 00041 * Fixed compile and run problems on Linux 00042 * 00043 * Revision 1.13 2004/07/01 04:33:57 csoutheren 00044 * Updated documentation on PFactory classes 00045 * 00046 * Revision 1.12 2004/06/30 12:17:04 rjongbloed 00047 * Rewrite of plug in system to use single global variable for all factories to avoid all sorts 00048 * of issues with startup orders and Windows DLL multiple instances. 00049 * 00050 * Revision 1.11 2004/06/17 06:35:12 csoutheren 00051 * Use attribute (( constructor )) to guarantee that factories are 00052 * instantiated when loaded from a shared library 00053 * 00054 * Revision 1.10 2004/06/03 13:30:57 csoutheren 00055 * Renamed INSTANTIATE_FACTORY to avoid potential namespace collisions 00056 * Added documentaton on new PINSTANTIATE_FACTORY macro 00057 * Added generic form of PINSTANTIATE_FACTORY 00058 * 00059 * Revision 1.9 2004/06/03 12:47:58 csoutheren 00060 * Decomposed PFactory declarations to hopefully avoid problems with Windows DLLs 00061 * 00062 * Revision 1.8 2004/06/01 05:44:12 csoutheren 00063 * Added typedefs to allow access to types 00064 * Changed singleton class to use new so as to allow full cleanup 00065 * 00066 * Revision 1.7 2004/05/23 12:33:56 rjongbloed 00067 * Made some subtle changes to the way the static variables are instantiated in 00068 * the factoris to fix problems with DLL's under windows. May not be final solution. 00069 * 00070 * Revision 1.6 2004/05/19 06:48:39 csoutheren 00071 * Added new functions to allow handling of singletons without concrete classes 00072 * 00073 * Revision 1.5 2004/05/18 06:01:06 csoutheren 00074 * Deferred plugin loading until after main has executed by using abstract factory classes 00075 * 00076 * Revision 1.4 2004/05/18 02:32:08 csoutheren 00077 * Fixed linking problems with PGenericFactory classes 00078 * 00079 * Revision 1.3 2004/05/13 15:10:51 csoutheren 00080 * Removed warnings under Windows 00081 * 00082 * Revision 1.2 2004/05/13 14:59:00 csoutheren 00083 * Removed warning under gcc 00084 * 00085 * Revision 1.1 2004/05/13 14:53:35 csoutheren 00086 * Add "abstract factory" template classes 00087 * 00088 */ 00089 00090 #ifndef _PFACTORY_H 00091 #define _PFACTORY_H 00092 00093 #ifdef P_USE_PRAGMA 00094 #pragma interface 00095 #endif 00096 00097 #include <ptlib.h> 00098 #include <string> 00099 #include <map> 00100 #include <vector> 00101 00102 #ifdef _WIN32 00103 #pragma warning(disable:4786) 00104 #endif 00105 00164 class PFactoryBase 00165 { 00166 protected: 00167 PFactoryBase() 00168 { } 00169 public: 00170 virtual ~PFactoryBase() 00171 { } 00172 00173 class FactoryMap : public std::map<std::string, PFactoryBase *> 00174 { 00175 public: 00176 FactoryMap() { } 00177 ~FactoryMap(); 00178 }; 00179 00180 static FactoryMap & GetFactories(); 00181 static PMutex & GetFactoriesMutex(); 00182 00183 PMutex mutex; 00184 00185 private: 00186 PFactoryBase(const PFactoryBase &) {} 00187 void operator=(const PFactoryBase &) {} 00188 }; 00189 00190 00193 template <class _Abstract_T, typename _Key_T = PString> 00194 class PFactory : PFactoryBase 00195 { 00196 public: 00197 typedef _Key_T Key_T; 00198 typedef _Abstract_T Abstract_T; 00199 00200 class WorkerBase 00201 { 00202 protected: 00203 WorkerBase(bool singleton = false) 00204 : isDynamic(false), 00205 isSingleton(singleton), 00206 singletonInstance(NULL), 00207 deleteSingleton(false) 00208 { } 00209 WorkerBase(Abstract_T * instance) 00210 : isSingleton(true), 00211 singletonInstance(instance), 00212 deleteSingleton(true) 00213 { } 00214 00215 virtual ~WorkerBase() 00216 { 00217 if (deleteSingleton) 00218 delete singletonInstance; 00219 } 00220 00221 Abstract_T * CreateInstance() 00222 { 00223 if (!isSingleton) 00224 return Create(); 00225 00226 if (singletonInstance == NULL) 00227 singletonInstance = Create(); 00228 return singletonInstance; 00229 } 00230 00231 virtual Abstract_T * Create() const { return singletonInstance; } 00232 00233 bool isDynamic; 00234 bool isSingleton; 00235 Abstract_T * singletonInstance; 00236 bool deleteSingleton; 00237 00238 friend class PFactory<_Abstract_T, _Key_T>; 00239 }; 00240 00241 template <class _Concrete_T> 00242 class Worker : WorkerBase 00243 { 00244 public: 00245 Worker(const Key_T & key, bool singleton = false) 00246 : WorkerBase(singleton) 00247 { 00248 PFactory<_Abstract_T, _Key_T>::Register(key, this); // here 00249 } 00250 00251 protected: 00252 virtual Abstract_T * Create() const { return new _Concrete_T; } 00253 }; 00254 00255 typedef std::map<_Key_T, WorkerBase *> KeyMap_T; 00256 typedef std::vector<_Key_T> KeyList_T; 00257 00258 static void Register(const _Key_T & key, WorkerBase * worker) 00259 { 00260 GetInstance().Register_Internal(key, worker); 00261 } 00262 00263 static void Register(const _Key_T & key, Abstract_T * instance) 00264 { 00265 GetInstance().Register_Internal(key, new WorkerBase(instance)); 00266 } 00267 00268 static void Unregister(const _Key_T & key) 00269 { 00270 GetInstance().Unregister_Internal(key); 00271 } 00272 00273 static void UnregisterAll() 00274 { 00275 GetInstance().UnregisterAll_Internal(); 00276 } 00277 00278 static bool IsRegistered(const _Key_T & key) 00279 { 00280 return GetInstance().IsRegistered_Internal(key); 00281 } 00282 00283 static _Abstract_T * CreateInstance(const _Key_T & key) 00284 { 00285 return GetInstance().CreateInstance_Internal(key); 00286 } 00287 00288 static BOOL IsSingleton(const _Key_T & key) 00289 { 00290 return GetInstance().IsSingleton_Internal(key); 00291 } 00292 00293 static KeyList_T GetKeyList() 00294 { 00295 return GetInstance().GetKeyList_Internal(); 00296 } 00297 00298 static KeyMap_T & GetKeyMap() 00299 { 00300 return GetInstance().keyMap; 00301 } 00302 00303 static PMutex & GetMutex() 00304 { 00305 return GetInstance().mutex; 00306 } 00307 00308 protected: 00309 PFactory() 00310 { } 00311 00312 ~PFactory() 00313 { 00314 typename KeyMap_T::const_iterator entry; 00315 for (entry = keyMap.begin(); entry != keyMap.end(); ++entry) { 00316 if (entry->second->isDynamic) 00317 delete entry->second; 00318 } 00319 } 00320 00321 static PFactory & GetInstance() 00322 { 00323 std::string className = typeid(PFactory).name(); 00324 PWaitAndSignal m(GetFactoriesMutex()); 00325 FactoryMap & factories = GetFactories(); 00326 FactoryMap::const_iterator entry = factories.find(className); 00327 if (entry != factories.end()) { 00328 PAssert(entry->second != NULL, "Factory map returned NULL for existing key"); 00329 PFactoryBase * b = entry->second; 00330 // don't use the following dynamic cast, because gcc does not like it 00331 //PFactory * f = dynamic_cast<PFactory*>(b); 00332 return *(PFactory *)b; 00333 } 00334 00335 PFactory * factory = new PFactory; 00336 factories[className] = factory; 00337 return *factory; 00338 } 00339 00340 00341 void Register_Internal(const _Key_T & key, WorkerBase * worker) 00342 { 00343 PWaitAndSignal m(mutex); 00344 if (keyMap.find(key) == keyMap.end()) 00345 keyMap[key] = worker; 00346 } 00347 00348 void Unregister_Internal(const _Key_T & key) 00349 { 00350 PWaitAndSignal m(mutex); 00351 keyMap.erase(key); 00352 } 00353 00354 void UnregisterAll_Internal() 00355 { 00356 PWaitAndSignal m(mutex); 00357 keyMap.erase(keyMap.begin(), keyMap.end()); 00358 } 00359 00360 bool IsRegistered_Internal(const _Key_T & key) 00361 { 00362 PWaitAndSignal m(mutex); 00363 return keyMap.find(key) != keyMap.end(); 00364 } 00365 00366 _Abstract_T * CreateInstance_Internal(const _Key_T & key) 00367 { 00368 PWaitAndSignal m(mutex); 00369 typename KeyMap_T::const_iterator entry = keyMap.find(key); 00370 if (entry != keyMap.end()) 00371 return entry->second->CreateInstance(); 00372 return NULL; 00373 } 00374 00375 bool IsSingleton_Internal(const _Key_T & key) 00376 { 00377 PWaitAndSignal m(mutex); 00378 if (keyMap.find(key) == keyMap.end()) 00379 return false; 00380 return keyMap[key]->isSingleton; 00381 } 00382 00383 KeyList_T GetKeyList_Internal() 00384 { 00385 PWaitAndSignal m(mutex); 00386 KeyList_T list; 00387 typename KeyMap_T::const_iterator entry; 00388 for (entry = keyMap.begin(); entry != keyMap.end(); ++entry) 00389 list.push_back(entry->first); 00390 return list; 00391 } 00392 00393 KeyMap_T keyMap; 00394 00395 private: 00396 PFactory(const PFactory &) {} 00397 void operator=(const PFactory &) {} 00398 00399 #ifdef _WIN32 00400 public: 00401 static int factoryLoader; 00402 #endif 00403 }; 00404 00405 #ifdef _WIN32 00406 00407 namespace PWLibFactoryLoader { 00408 00409 template <class AbstractType, typename KeyType> 00410 class Loader 00411 { 00412 public: 00413 Loader() 00414 { PFactory<AbstractType, KeyType>::factoryLoader = 1; } 00415 }; 00416 }; 00417 00418 00419 // 00420 // this macro is used to declare the static member variable used to force factories to instantiate 00421 // 00422 #define PLOAD_FACTORY(AbstractType, KeyType) \ 00423 namespace PWLibFactoryLoader { \ 00424 static Loader<AbstractType, KeyType> AbstractType##_##KeyType##; \ 00425 }; 00426 00427 // 00428 // this macro is used to instantiate a static variable that accesses the static member variable 00429 // in a factory forcing it to load 00430 // 00431 #define PINSTANTIATE_FACTORY(AbstractType, KeyType) \ 00432 int PFactory<AbstractType, KeyType>::factoryLoader; 00433 00434 #endif // _WIN32 00435 00436 #endif // _PFACTORY_H

Generated on Sat Jul 24 15:35:56 2004 for PWLib by doxygen 1.3.7