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 class FactoryMap : public std::map<std::string, PFactoryBase *>
00121 {
00122 public:
00123 FactoryMap() { }
00124 ~FactoryMap();
00125 };
00126
00127 static FactoryMap & GetFactories();
00128 static PMutex & GetFactoriesMutex();
00129
00130 PMutex mutex;
00131
00132 private:
00133 PFactoryBase(const PFactoryBase &) {}
00134 void operator=(const PFactoryBase &) {}
00135 };
00136
00137
00140 template <class AbstractClass, typename KeyType = PDefaultPFactoryKey>
00141 class PFactory : PFactoryBase
00142 {
00143 public:
00144 typedef KeyType Key_T;
00145 typedef AbstractClass Abstract_T;
00146
00147 class WorkerBase
00148 {
00149 protected:
00150 WorkerBase(bool singleton = false)
00151 : isDynamic(false),
00152 isSingleton(singleton),
00153 singletonInstance(NULL),
00154 deleteSingleton(false)
00155 { }
00156 WorkerBase(Abstract_T * instance, bool delSingleton = true)
00157 : isDynamic(true),
00158 isSingleton(true),
00159 singletonInstance(instance),
00160 deleteSingleton(delSingleton)
00161 { }
00162
00163 virtual ~WorkerBase()
00164 {
00165 if (deleteSingleton)
00166 delete singletonInstance;
00167 }
00168
00169 Abstract_T * CreateInstance(const Key_T & key)
00170 {
00171 if (!isSingleton)
00172 return Create(key);
00173
00174 if (singletonInstance == NULL)
00175 singletonInstance = Create(key);
00176 return singletonInstance;
00177 }
00178
00179 virtual Abstract_T * Create(const Key_T & ) const { return singletonInstance; }
00180
00181 bool isDynamic;
00182 bool isSingleton;
00183 Abstract_T * singletonInstance;
00184 bool deleteSingleton;
00185
00186 friend class PFactory<Abstract_T, Key_T>;
00187 };
00188
00189 template <class ConcreteClass>
00190 class Worker : WorkerBase
00191 {
00192 public:
00193 Worker(const Key_T & key, bool singleton = false)
00194 : WorkerBase(singleton)
00195 {
00196 PMEMORY_IGNORE_ALLOCATIONS_FOR_SCOPE;
00197 PFactory<Abstract_T, Key_T>::Register(key, this);
00198 }
00199
00200 protected:
00201 virtual Abstract_T * Create(const Key_T & ) const
00202 {
00203 #if PMEMORY_HEAP
00204
00205 PBoolean previousIgnoreAllocations = PMemoryHeap::SetIgnoreAllocations(WorkerBase::isSingleton);
00206 #endif
00207 Abstract_T * instance = new ConcreteClass;
00208 #if PMEMORY_HEAP
00209 PMemoryHeap::SetIgnoreAllocations(previousIgnoreAllocations);
00210 #endif
00211 return instance;
00212 }
00213 };
00214
00215 typedef std::map<Key_T, WorkerBase *> KeyMap_T;
00216 typedef std::vector<Key_T> KeyList_T;
00217
00218 static void Register(const Key_T & key, WorkerBase * worker)
00219 {
00220 GetInstance().Register_Internal(key, worker);
00221 }
00222
00223 static void Register(const Key_T & key, Abstract_T * instance, bool autoDeleteInstance = true)
00224 {
00225 WorkerBase * w = PNEW WorkerBase(instance, autoDeleteInstance);
00226 GetInstance().Register_Internal(key, w);
00227 }
00228
00229 static PBoolean RegisterAs(const Key_T & newKey, const Key_T & oldKey)
00230 {
00231 return GetInstance().RegisterAs_Internal(newKey, oldKey);
00232 }
00233
00234 static void Unregister(const Key_T & key)
00235 {
00236 GetInstance().Unregister_Internal(key);
00237 }
00238
00239 static void UnregisterAll()
00240 {
00241 GetInstance().UnregisterAll_Internal();
00242 }
00243
00244 static bool IsRegistered(const Key_T & key)
00245 {
00246 return GetInstance().IsRegistered_Internal(key);
00247 }
00248
00249 static Abstract_T * CreateInstance(const Key_T & key)
00250 {
00251 return GetInstance().CreateInstance_Internal(key);
00252 }
00253
00254 template <class Derived_T>
00255 static Derived_T * CreateInstanceAs(const Key_T & key)
00256 {
00257 return dynamic_cast<Derived_T *>(GetInstance().CreateInstance_Internal(key));
00258 }
00259
00260 static PBoolean IsSingleton(const Key_T & key)
00261 {
00262 return GetInstance().IsSingleton_Internal(key);
00263 }
00264
00265 static KeyList_T GetKeyList()
00266 {
00267 return GetInstance().GetKeyList_Internal();
00268 }
00269
00270 static KeyMap_T & GetKeyMap()
00271 {
00272 return GetInstance().keyMap;
00273 }
00274
00275 static PMutex & GetMutex()
00276 {
00277 return GetInstance().mutex;
00278 }
00279
00280 protected:
00281 PFactory()
00282 { }
00283
00284 ~PFactory()
00285 {
00286 typename KeyMap_T::const_iterator entry;
00287 for (entry = keyMap.begin(); entry != keyMap.end(); ++entry) {
00288 if (entry->second->isDynamic)
00289 delete entry->second;
00290 }
00291 }
00292
00293 static PFactory & GetInstance()
00294 {
00295 std::string className = typeid(PFactory).name();
00296 PWaitAndSignal m(GetFactoriesMutex());
00297 FactoryMap & factories = GetFactories();
00298 FactoryMap::const_iterator entry = factories.find(className);
00299 if (entry != factories.end()) {
00300 PAssert(entry->second != NULL, "Factory map returned NULL for existing key");
00301 PFactoryBase * b = entry->second;
00302
00303
00304 return *(PFactory *)b;
00305 }
00306
00307 PMEMORY_IGNORE_ALLOCATIONS_FOR_SCOPE;
00308 PFactory * factory = new PFactory;
00309 factories[className] = factory;
00310 return *factory;
00311 }
00312
00313
00314 void Register_Internal(const Key_T & key, WorkerBase * worker)
00315 {
00316 PWaitAndSignal m(mutex);
00317 if (keyMap.find(key) == keyMap.end()) {
00318 keyMap[key] = worker;
00319 if (worker->isSingleton)
00320 worker->CreateInstance(key);
00321 }
00322 }
00323
00324 PBoolean RegisterAs_Internal(const Key_T & newKey, const Key_T & oldKey)
00325 {
00326 PWaitAndSignal m(mutex);
00327 if (keyMap.find(oldKey) == keyMap.end())
00328 return PFalse;
00329 keyMap[newKey] = keyMap[oldKey];
00330 return PTrue;
00331 }
00332
00333 void Unregister_Internal(const Key_T & key)
00334 {
00335 PWaitAndSignal m(mutex);
00336 typename KeyMap_T::iterator r = keyMap.find(key);
00337 if (r != keyMap.end()) {
00338 if (r->second->isDynamic)
00339 delete r->second;
00340 keyMap.erase(r);
00341 }
00342 }
00343
00344 void UnregisterAll_Internal()
00345 {
00346 PWaitAndSignal m(mutex);
00347 while (keyMap.size() > 0)
00348 keyMap.erase(keyMap.begin());
00349 }
00350
00351 bool IsRegistered_Internal(const Key_T & key)
00352 {
00353 PWaitAndSignal m(mutex);
00354 return keyMap.find(key) != keyMap.end();
00355 }
00356
00357 Abstract_T * CreateInstance_Internal(const Key_T & key)
00358 {
00359 PWaitAndSignal m(mutex);
00360 typename KeyMap_T::const_iterator entry = keyMap.find(key);
00361 if (entry != keyMap.end())
00362 return entry->second->CreateInstance(key);
00363 return NULL;
00364 }
00365
00366 bool IsSingleton_Internal(const Key_T & key)
00367 {
00368 PWaitAndSignal m(mutex);
00369 if (keyMap.find(key) == keyMap.end())
00370 return false;
00371 return keyMap[key]->isSingleton;
00372 }
00373
00374 KeyList_T GetKeyList_Internal()
00375 {
00376 PWaitAndSignal m(mutex);
00377 KeyList_T list;
00378 typename KeyMap_T::const_iterator entry;
00379 for (entry = keyMap.begin(); entry != keyMap.end(); ++entry)
00380 list.push_back(entry->first);
00381 return list;
00382 }
00383
00384 KeyMap_T keyMap;
00385
00386 private:
00387 PFactory(const PFactory &) {}
00388 void operator=(const PFactory &) {}
00389 };
00390
00391
00392
00393
00394 #define PLOAD_FACTORY(AbstractType, KeyType) \
00395 namespace PWLibFactoryLoader { \
00396 extern int AbstractType##_##KeyType##_loader; \
00397 static int AbstractType##_##KeyType##_loader_instance = AbstractType##_##KeyType##_loader; \
00398 };
00399
00400
00401
00402
00403
00404
00405 #define PINSTANTIATE_FACTORY(AbstractType, KeyType) \
00406 namespace PWLibFactoryLoader { int AbstractType##_##KeyType##_loader; }
00407
00408
00420 #define PFACTORY_CREATE(factory, ConcreteType, keyValue, singleton) \
00421 namespace PFactoryLoader { \
00422 int ConcreteType##_link() { return 0; } \
00423 factory::Worker<ConcreteType> ConcreteType##_instance(keyValue, singleton); \
00424 }
00425
00426
00427
00428
00429 #define PFACTORY_LOAD(ConcreteType) \
00430 namespace PFactoryLoader { \
00431 extern int ConcreteType##_link(); \
00432 int const ConcreteType##_loader = ConcreteType##_link(); \
00433 }
00434
00435
00436 #endif // PTLIB_FACTORY_H
00437
00438
00439