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
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131 #ifndef _PFACTORY_H
00132 #define _PFACTORY_H
00133
00134 #ifdef P_USE_PRAGMA
00135 #pragma interface
00136 #endif
00137
00138 #ifndef _PTLIB_H
00139 #include <ptlib.h>
00140 #endif
00141
00142 #include <string>
00143 #include <map>
00144 #include <vector>
00145
00146 #if defined(_MSC_VER)
00147 #pragma warning(disable:4786)
00148 #endif
00149
00201
00202
00203 typedef std::string PDefaultPFactoryKey;
00204
00205
00213 class PFactoryBase
00214 {
00215 protected:
00216 PFactoryBase()
00217 { }
00218 public:
00219 virtual ~PFactoryBase()
00220 { }
00221
00222 class FactoryMap : public std::map<std::string, PFactoryBase *>
00223 {
00224 public:
00225 FactoryMap() { }
00226 ~FactoryMap();
00227 };
00228
00229 static FactoryMap & GetFactories();
00230 static PMutex & GetFactoriesMutex();
00231
00232 PMutex mutex;
00233
00234 private:
00235 PFactoryBase(const PFactoryBase &) {}
00236 void operator=(const PFactoryBase &) {}
00237 };
00238
00239
00242 template <class _Abstract_T, typename _Key_T = PDefaultPFactoryKey>
00243 class PFactory : PFactoryBase
00244 {
00245 public:
00246 typedef _Key_T Key_T;
00247 typedef _Abstract_T Abstract_T;
00248
00249 class WorkerBase
00250 {
00251 protected:
00252 WorkerBase(bool singleton = false)
00253 : isDynamic(false),
00254 isSingleton(singleton),
00255 singletonInstance(NULL),
00256 deleteSingleton(false)
00257 { }
00258 WorkerBase(Abstract_T * instance)
00259 : isDynamic(true),
00260 isSingleton(true),
00261 singletonInstance(instance),
00262 deleteSingleton(true)
00263 { }
00264
00265 virtual ~WorkerBase()
00266 {
00267 if (deleteSingleton)
00268 delete singletonInstance;
00269 }
00270
00271 Abstract_T * CreateInstance(const Key_T & key)
00272 {
00273 if (!isSingleton)
00274 return Create(key);
00275
00276 if (singletonInstance == NULL)
00277 singletonInstance = Create(key);
00278 return singletonInstance;
00279 }
00280
00281 virtual Abstract_T * Create(const Key_T & ) const { return singletonInstance; }
00282
00283 bool isDynamic;
00284 bool isSingleton;
00285 Abstract_T * singletonInstance;
00286 bool deleteSingleton;
00287
00288 friend class PFactory<_Abstract_T, _Key_T>;
00289 };
00290
00291 template <class _Concrete_T>
00292 class Worker : WorkerBase
00293 {
00294 public:
00295 Worker(const Key_T & key, bool singleton = false)
00296 : WorkerBase(singleton)
00297 {
00298 PMEMORY_IGNORE_ALLOCATIONS_FOR_SCOPE;
00299 PFactory<_Abstract_T, _Key_T>::Register(key, this);
00300 }
00301
00302 protected:
00303 virtual Abstract_T * Create(const Key_T & ) const
00304 {
00305 #if PMEMORY_HEAP
00306
00307 BOOL previousIgnoreAllocations = PMemoryHeap::SetIgnoreAllocations(isSingleton);
00308 #endif
00309 Abstract_T * instance = new _Concrete_T;
00310 #if PMEMORY_HEAP
00311 PMemoryHeap::SetIgnoreAllocations(previousIgnoreAllocations);
00312 #endif
00313 return instance;
00314 }
00315 };
00316
00317 typedef std::map<_Key_T, WorkerBase *> KeyMap_T;
00318 typedef std::vector<_Key_T> KeyList_T;
00319
00320 static void Register(const _Key_T & key, WorkerBase * worker)
00321 {
00322 GetInstance().Register_Internal(key, worker);
00323 }
00324
00325 static void Register(const _Key_T & key, Abstract_T * instance)
00326 {
00327 GetInstance().Register_Internal(key, PNEW WorkerBase(instance));
00328 }
00329
00330 static BOOL RegisterAs(const _Key_T & newKey, const _Key_T & oldKey)
00331 {
00332 return GetInstance().RegisterAs_Internal(newKey, oldKey);
00333 }
00334
00335 static void Unregister(const _Key_T & key)
00336 {
00337 GetInstance().Unregister_Internal(key);
00338 }
00339
00340 static void UnregisterAll()
00341 {
00342 GetInstance().UnregisterAll_Internal();
00343 }
00344
00345 static bool IsRegistered(const _Key_T & key)
00346 {
00347 return GetInstance().IsRegistered_Internal(key);
00348 }
00349
00350 static _Abstract_T * CreateInstance(const _Key_T & key)
00351 {
00352 return GetInstance().CreateInstance_Internal(key);
00353 }
00354
00355 static BOOL IsSingleton(const _Key_T & key)
00356 {
00357 return GetInstance().IsSingleton_Internal(key);
00358 }
00359
00360 static KeyList_T GetKeyList()
00361 {
00362 return GetInstance().GetKeyList_Internal();
00363 }
00364
00365 static KeyMap_T & GetKeyMap()
00366 {
00367 return GetInstance().keyMap;
00368 }
00369
00370 static PMutex & GetMutex()
00371 {
00372 return GetInstance().mutex;
00373 }
00374
00375 protected:
00376 PFactory()
00377 { }
00378
00379 ~PFactory()
00380 {
00381 typename KeyMap_T::const_iterator entry;
00382 for (entry = keyMap.begin(); entry != keyMap.end(); ++entry) {
00383 if (entry->second->isDynamic)
00384 delete entry->second;
00385 }
00386 }
00387
00388 static PFactory & GetInstance()
00389 {
00390 std::string className = typeid(PFactory).name();
00391 PWaitAndSignal m(GetFactoriesMutex());
00392 FactoryMap & factories = GetFactories();
00393 FactoryMap::const_iterator entry = factories.find(className);
00394 if (entry != factories.end()) {
00395 PAssert(entry->second != NULL, "Factory map returned NULL for existing key");
00396 PFactoryBase * b = entry->second;
00397
00398
00399 return *(PFactory *)b;
00400 }
00401
00402 PMEMORY_IGNORE_ALLOCATIONS_FOR_SCOPE;
00403 PFactory * factory = new PFactory;
00404 factories[className] = factory;
00405 return *factory;
00406 }
00407
00408
00409 void Register_Internal(const _Key_T & key, WorkerBase * worker)
00410 {
00411 PWaitAndSignal m(mutex);
00412 if (keyMap.find(key) == keyMap.end())
00413 keyMap[key] = worker;
00414 }
00415
00416 BOOL RegisterAs_Internal(const _Key_T & newKey, const _Key_T & oldKey)
00417 {
00418 PWaitAndSignal m(mutex);
00419 if (keyMap.find(oldKey) == keyMap.end())
00420 return FALSE;
00421 keyMap[newKey] = keyMap[oldKey];
00422 return TRUE;
00423 }
00424
00425 void Unregister_Internal(const _Key_T & key)
00426 {
00427 PWaitAndSignal m(mutex);
00428 keyMap.erase(key);
00429 }
00430
00431 void UnregisterAll_Internal()
00432 {
00433 PWaitAndSignal m(mutex);
00434 keyMap.erase(keyMap.begin(), keyMap.end());
00435 }
00436
00437 bool IsRegistered_Internal(const _Key_T & key)
00438 {
00439 PWaitAndSignal m(mutex);
00440 return keyMap.find(key) != keyMap.end();
00441 }
00442
00443 _Abstract_T * CreateInstance_Internal(const _Key_T & key)
00444 {
00445 PWaitAndSignal m(mutex);
00446 typename KeyMap_T::const_iterator entry = keyMap.find(key);
00447 if (entry != keyMap.end())
00448 return entry->second->CreateInstance(key);
00449 return NULL;
00450 }
00451
00452 bool IsSingleton_Internal(const _Key_T & key)
00453 {
00454 PWaitAndSignal m(mutex);
00455 if (keyMap.find(key) == keyMap.end())
00456 return false;
00457 return keyMap[key]->isSingleton;
00458 }
00459
00460 KeyList_T GetKeyList_Internal()
00461 {
00462 PWaitAndSignal m(mutex);
00463 KeyList_T list;
00464 typename KeyMap_T::const_iterator entry;
00465 for (entry = keyMap.begin(); entry != keyMap.end(); ++entry)
00466 list.push_back(entry->first);
00467 return list;
00468 }
00469
00470 KeyMap_T keyMap;
00471
00472 private:
00473 PFactory(const PFactory &) {}
00474 void operator=(const PFactory &) {}
00475 };
00476
00477
00478
00479
00480 #define PLOAD_FACTORY(AbstractType, KeyType) \
00481 namespace PWLibFactoryLoader { \
00482 extern int AbstractType##_##KeyType##_loader; \
00483 static int AbstractType##_##KeyType##_loader_instance = AbstractType##_##KeyType##_loader; \
00484 };
00485
00486
00487
00488
00489
00490
00491 #define PINSTANTIATE_FACTORY(AbstractType, KeyType) \
00492 namespace PWLibFactoryLoader { int AbstractType##_##KeyType##_loader; }
00493
00494
00495 #endif // _PFACTORY_H