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