PTLib
Version 2.10.4
|
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 ///////////////////////////////////////////////////////////////