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(WorkerBase::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 if (worker->isSingleton)
00322 worker->CreateInstance(key);
00323 }
00324 }
00325
00326 PBoolean RegisterAs_Internal(const _Key_T & newKey, const _Key_T & oldKey)
00327 {
00328 PWaitAndSignal m(mutex);
00329 if (keyMap.find(oldKey) == keyMap.end())
00330 return PFalse;
00331 keyMap[newKey] = keyMap[oldKey];
00332 return PTrue;
00333 }
00334
00335 void Unregister_Internal(const _Key_T & key)
00336 {
00337 PWaitAndSignal m(mutex);
00338 typename KeyMap_T::iterator r = keyMap.find(key);
00339 if (r != keyMap.end()) {
00340 if (r->second->isDynamic)
00341 delete r->second;
00342 keyMap.erase(r);
00343 }
00344 }
00345
00346 void UnregisterAll_Internal()
00347 {
00348 PWaitAndSignal m(mutex);
00349 while (keyMap.size() > 0)
00350 keyMap.erase(keyMap.begin());
00351 }
00352
00353 bool IsRegistered_Internal(const _Key_T & key)
00354 {
00355 PWaitAndSignal m(mutex);
00356 return keyMap.find(key) != keyMap.end();
00357 }
00358
00359 _Abstract_T * CreateInstance_Internal(const _Key_T & key)
00360 {
00361 PWaitAndSignal m(mutex);
00362 typename KeyMap_T::const_iterator entry = keyMap.find(key);
00363 if (entry != keyMap.end())
00364 return entry->second->CreateInstance(key);
00365 return NULL;
00366 }
00367
00368 bool IsSingleton_Internal(const _Key_T & key)
00369 {
00370 PWaitAndSignal m(mutex);
00371 if (keyMap.find(key) == keyMap.end())
00372 return false;
00373 return keyMap[key]->isSingleton;
00374 }
00375
00376 KeyList_T GetKeyList_Internal()
00377 {
00378 PWaitAndSignal m(mutex);
00379 KeyList_T list;
00380 typename KeyMap_T::const_iterator entry;
00381 for (entry = keyMap.begin(); entry != keyMap.end(); ++entry)
00382 list.push_back(entry->first);
00383 return list;
00384 }
00385
00386 KeyMap_T keyMap;
00387
00388 private:
00389 PFactory(const PFactory &) {}
00390 void operator=(const PFactory &) {}
00391 };
00392
00393
00394
00395
00396 #define PLOAD_FACTORY(AbstractType, KeyType) \
00397 namespace PWLibFactoryLoader { \
00398 extern int AbstractType##_##KeyType##_loader; \
00399 static int AbstractType##_##KeyType##_loader_instance = AbstractType##_##KeyType##_loader; \
00400 };
00401
00402
00403
00404
00405
00406
00407 #define PINSTANTIATE_FACTORY(AbstractType, KeyType) \
00408 namespace PWLibFactoryLoader { int AbstractType##_##KeyType##_loader; }
00409
00410
00411 #endif // _PFACTORY_H