00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
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
00100
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 & ) 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 & ) 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
00316
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
00429
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