PTLib  Version 2.18.8
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
pfactory.h
Go to the documentation of this file.
1 /*
2  * factory.h
3  *
4  * Abstract Factory Classes
5  *
6  * Portable Windows Library
7  *
8  * Copyright (C) 2004 Post Increment
9  *
10  * The contents of this file are subject to the Mozilla Public License
11  * Version 1.0 (the "License"); you may not use this file except in
12  * compliance with the License. You may obtain a copy of the License at
13  * http://www.mozilla.org/MPL/
14  *
15  * Software distributed under the License is distributed on an "AS IS"
16  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
17  * the License for the specific language governing rights and limitations
18  * under the License.
19  *
20  * The Original Code is Portable Windows Library.
21  *
22  * The Initial Developer of the Original Code is Post Increment
23  *
24  * Contributor(s): ______________________________________.
25  */
26 
27 #ifndef PTLIB_FACTORY_H
28 #define PTLIB_FACTORY_H
29 
30 #ifdef P_USE_PRAGMA
31 #pragma interface
32 #endif
33 
34 #include <ptlib.h>
35 
36 #include <typeinfo>
37 #include <string>
38 #include <map>
39 #include <vector>
40 
41 #if defined(_MSC_VER)
42 #pragma warning(disable:4786)
43 #endif
44 
112 {
113  protected:
115  { }
116  public:
117  virtual ~PFactoryBase()
118  { }
119 
120  virtual void DestroySingletons() = 0;
121 
122  class FactoryMap : public std::map<std::string, PFactoryBase *>, public PCriticalSection
123  {
124  public:
125  ~FactoryMap();
126  void DestroySingletons();
127  };
128 
129  static FactoryMap & GetFactories();
130 
131  protected:
132  static PFactoryBase & InternalGetFactory(const std::string & className, PFactoryBase * (*createFactory)());
133 
134  template <class TheFactory> static PFactoryBase * CreateFactory() { return new TheFactory; }
135 
136  template <class TheFactory> static TheFactory & GetFactoryAs()
137  {
138  return dynamic_cast<TheFactory&>(InternalGetFactory(typeid(TheFactory).name(), CreateFactory<TheFactory>));
139  }
140 
141  protected:
142  PDECLARE_MUTEX(m_mutex, "PFactoryBase");
143 
144  private:
145  PFactoryBase(const PFactoryBase &) {}
146  void operator=(const PFactoryBase &) {}
147 };
148 
149 
152 template <class AbstractClass, typename ParamType, typename KeyType>
154 {
155  public:
156  class WorkerBase;
157 
158  typedef AbstractClass Abstract_T;
159  typedef ParamType Param_T;
160  typedef KeyType Key_T;
161  typedef std::vector<Key_T> KeyList_T;
162 
163  struct WorkerWrap
164  {
165  WorkerWrap(WorkerBase * worker, bool autoDelete) : m_worker(worker), m_autoDelete(autoDelete) { }
168  };
169  typedef std::map<Key_T, WorkerWrap> WorkerMap_T;
170  typedef typename WorkerMap_T::iterator WorkerIter_T;
171 
173  {
174  public:
175  enum Types {
179  };
180 
181  WorkerBase(bool singleton = false)
182  : m_type(singleton ? DynamicSingleton : NonSingleton)
183  , m_singletonInstance(NULL)
184  {
185  }
186 
187  WorkerBase(Abstract_T * instance, bool delSingleton = true)
188  : m_type(delSingleton ? DynamicSingleton : StaticSingleton)
189  , m_singletonInstance(instance)
190  {
191  }
192 
193  virtual ~WorkerBase()
194  {
196  }
197 
199  {
200  if (m_type == NonSingleton)
201  return Create(param);
202 
203  if (m_singletonInstance == NULL)
204  m_singletonInstance = Create(param);
205  return m_singletonInstance;
206  }
207 
208  virtual void DestroySingleton()
209  {
210  if (m_type == DynamicSingleton) {
211  delete m_singletonInstance;
212  m_singletonInstance = NULL;
213  }
214  }
215 
216  bool IsSingleton() const { return m_type != NonSingleton; }
217 
218  protected:
219  virtual Abstract_T * Create(Param_T /*param*/) const
220  {
221  PAssert(this->m_type == StaticSingleton, "Incorrect factory worker descendant");
222  return this->m_singletonInstance;
223  }
224 
227 
228  private:
229  WorkerBase(const WorkerBase &) { }
230  void operator=(const WorkerBase &) { }
231 
232  friend class PFactoryTemplate;
233  };
234 
235  virtual void DestroySingletons()
236  {
237  for (WorkerIter_T it = m_workers.begin(); it != m_workers.end(); ++it)
238  it->second.m_worker->DestroySingleton();
239  }
240 
241  protected:
243  { }
244 
246  {
249  }
250 
251  bool InternalRegister(const Key_T & key, WorkerBase * worker, bool autoDeleteWorker)
252  {
253  PWaitAndSignal mutex(m_mutex);
254  typename WorkerMap_T::iterator it = m_workers.find(key);
255  if (it != m_workers.end()) {
256  return it->second.m_worker == worker;
257  }
258 
260  m_workers.insert(make_pair(key, WorkerWrap(PAssertNULL(worker), autoDeleteWorker)));
261  return true;
262  }
263 
264  bool InternalRegister(const Key_T & key, Abstract_T * instance, bool autoDeleteInstance)
265  {
266  PWaitAndSignal mutex(m_mutex);
267  typename WorkerMap_T::iterator it = m_workers.find(key);
268  if (it != m_workers.end())
269  return it->second.m_worker->m_singletonInstance == instance;
270 
272  m_workers.insert(make_pair(key, WorkerWrap(PNEW WorkerBase(instance, autoDeleteInstance), true)));
273  return true;
274  }
275 
276  PBoolean InternalRegisterAs(const Key_T & newKey, const Key_T & oldKey)
277  {
278  PWaitAndSignal mutex(m_mutex);
279  typename WorkerMap_T::iterator itOld = m_workers.find(oldKey);
280  if (itOld == m_workers.end())
281  return false;
282 
283  typename WorkerMap_T::iterator itNew = m_workers.find(newKey);
284  if (itNew != m_workers.end())
285  return itNew->second.m_worker == itOld->second.m_worker;
286 
287  m_workers.insert(make_pair(newKey, WorkerWrap(itOld->second.m_worker, false)));
288  return true;
289  }
290 
291  void InternalUnregister(const Key_T & key)
292  {
293  m_mutex.Wait();
294  typename WorkerMap_T::iterator it = m_workers.find(key);
295  if (it != m_workers.end()) {
296  if (it->second.m_autoDelete)
297  delete it->second.m_worker;
298  m_workers.erase(it);
299  }
300  m_mutex.Signal();
301  }
302 
303  void InternalUnregister(WorkerBase * instance)
304  {
305  m_mutex.Wait();
306  for (WorkerIter_T it = m_workers.begin(); it != m_workers.end(); ++it) {
307  if (it->second == instance) {
308  InternalUnregister(it->first);
309  break;
310  }
311  }
312  m_mutex.Signal();
313  }
314 
316  {
317  m_mutex.Wait();
318  for (typename WorkerMap_T::iterator it = m_workers.begin(); it != m_workers.end(); ++it) {
319  if (it->second.m_autoDelete)
320  delete it->second.m_worker;
321  }
322  m_workers.clear();
323  m_mutex.Signal();
324  }
325 
326  bool InternalIsRegistered(const Key_T & key)
327  {
328  PWaitAndSignal mutex(m_mutex);
329  return m_workers.find(key) != m_workers.end();
330  }
331 
333  {
334  PWaitAndSignal mutex(m_mutex);
335  WorkerIter_T entry = m_workers.find(key);
336  return entry == m_workers.end() ? NULL : entry->second.m_worker->CreateInstance(param);
337  }
338 
339  void InternalDestroy(const Key_T & key, Abstract_T * instance)
340  {
341  PWaitAndSignal mutex(m_mutex);
342  WorkerIter_T entry = m_workers.find(key);
343  if (entry != m_workers.end() && !entry->second.m_worker->IsSingleton())
344  delete instance;
345  }
346 
347  bool InternalIsSingleton(const Key_T & key)
348  {
349  PWaitAndSignal mutex(m_mutex);
350  WorkerIter_T entry = m_workers.find(key);
351  return entry != m_workers.end() && entry->second.m_worker->IsSingleton();
352  }
353 
355  {
356  PWaitAndSignal mutex(m_mutex);
357  KeyList_T list;
358  for (WorkerIter_T entry = m_workers.begin(); entry != m_workers.end(); ++entry)
359  list.push_back(entry->first);
360  return list;
361  }
362 
363  protected:
365 
366  private:
368  void operator=(const PFactoryTemplate &) {}
369 
370  friend class PFactoryBase;
371 };
372 
373 
375 typedef std::string PDefaultPFactoryKey;
376 
377 
378 #define PFACTORY_STATICS(cls) \
379  static cls & GetFactory() { return PFactoryBase::GetFactoryAs<cls>(); } \
380  static bool Register(const Key_T & k, WorkerBase_T *w, bool a=false) { return GetFactory().InternalRegister(k, w, a); } \
381  static bool Register(const Key_T & k, Abstract_T * i, bool a = true) { return GetFactory().InternalRegister(k, i, a); } \
382  static bool RegisterAs(const Key_T & synonym, const Key_T & original){ return GetFactory().InternalRegisterAs(synonym, original); } \
383  static void Unregister(const Key_T & k) { GetFactory().InternalUnregister(k); } \
384  static void Unregister(WorkerBase_T * a) { GetFactory().InternalUnregister(a); } \
385  static void UnregisterAll() { GetFactory().InternalUnregisterAll(); } \
386  static bool IsRegistered(const Key_T & k) { return GetFactory().InternalIsRegistered(k); } \
387  static bool IsSingleton(const Key_T & k) { return GetFactory().InternalIsSingleton(k); } \
388  static typename Base_T::KeyList_T GetKeyList() { return GetFactory().InternalGetKeyList(); } \
389  static PMutex & GetMutex() { return GetFactory().m_mutex; } \
390 
391 
395 template <class AbstractClass, typename KeyType = PDefaultPFactoryKey>
396 class PFactory : public PFactoryTemplate<AbstractClass, const KeyType &, KeyType>
397 {
398  public:
400  typedef typename Base_T::WorkerBase WorkerBase_T;
401  typedef typename Base_T::Abstract_T Abstract_T;
402  typedef typename Base_T::Param_T Param_T;
403  typedef typename Base_T::Key_T Key_T;
404 
406 
407  template <class ConcreteClass>
408  class Worker : protected WorkerBase_T
409  {
410  private:
411  Key_T * m_key;
412  public:
413  Worker(const Key_T & key, bool singleton = false)
414  : WorkerBase_T(singleton)
415  , m_key(new Key_T(key))
416  {
417  PAssert(Register(key, this), "Factory Worker already registered");
418  }
419 
421  {
422  if (m_key == NULL)
423  return;
424  Unregister(*m_key);
425  delete m_key;
426  m_key = NULL;
427  }
428 
429  const Key_T & GetKey() const { return *m_key; }
430 
431  protected:
432  virtual Abstract_T * Create(Param_T) const
433  {
434  return new ConcreteClass();
435  }
436  };
437 
438  static Abstract_T * CreateInstance(const Key_T & key)
439  {
440  return GetFactory().InternalCreateInstance(key, key);
441  }
442 
443  template <class Derived_T>
444  static Derived_T * CreateInstanceAs(const Key_T & key)
445  {
446  Abstract_T * instance = GetFactory().InternalCreateInstance(key, key);
447  Derived_T * derived = dynamic_cast<Derived_T *>(instance);
448  if (derived != NULL)
449  return derived;
450 
451  GetFactory().InternalDestroy(key, instance);
452  return NULL;
453  }
454 };
455 
456 
460 template <class AbstractClass, typename ParamType, typename KeyType = PDefaultPFactoryKey>
461 class PParamFactory : public PFactoryTemplate<AbstractClass, ParamType, KeyType>
462 {
463  public:
466  typedef typename Base_T::Abstract_T Abstract_T;
467  typedef typename Base_T::Param_T Param_T;
468  typedef typename Base_T::Key_T Key_T;
469 
471 
472  template <class ConcreteClass>
473  class Worker : protected WorkerBase_T
474  {
475  private:
476  Key_T * m_key;
477  public:
478  Worker(const Key_T & key, bool singleton = false)
479  : WorkerBase_T(singleton)
480  , m_key(new Key_T(key))
481  {
482  PAssert(Register(key, this), "Factory Worker already registered");
483  }
484 
486  {
487  if (m_key == NULL)
488  return;
489  Unregister(*m_key);
490  delete m_key;
491  m_key = NULL;
492  }
493 
494  const Key_T & GetKey() const { return *m_key; }
495 
496  protected:
497  virtual Abstract_T * Create(Param_T param) const
498  {
499  return new ConcreteClass(param);
500  }
501  };
502 
503  static Abstract_T * CreateInstance(const Key_T & key, Param_T param)
504  {
505  return GetFactory().InternalCreateInstance(key, param);
506  }
507 
508  template <class Derived_T>
509  static Derived_T * CreateInstanceAs(const Key_T & key, Param_T param)
510  {
511  Abstract_T * instance = GetFactory().InternalCreateInstance(key, param);
512  Derived_T * derived = dynamic_cast<Derived_T *>(instance);
513  if (derived != NULL)
514  return derived;
515  GetFactory().InternalDestroy(key, instance);
516  return NULL;
517  }
518 };
519 
520 
532 #define PFACTORY_CREATE(factory, ConcreteClass, ...) \
533  namespace PFactoryLoader { \
534  int ConcreteClass##_link(int const *) { return 0; } \
535  factory::Worker<ConcreteClass> ConcreteClass##_instance(__VA_ARGS__); \
536  }
537 
538 #define PFACTORY_SYNONYM(factory, ConcreteClass, name, key) \
539  namespace PFactoryLoader { \
540  bool ConcreteClass##name##_synonym = factory::RegisterAs(key, ConcreteClass##_instance.GetKey()); \
541  }
542 
543 #define PFACTORY_CREATE_SINGLETON(factory, ConcreteClass) \
544  PFACTORY_CREATE(factory, ConcreteClass, typeid(ConcreteClass).name(), true)
545 
546 #define PFACTORY_GET_SINGLETON(factory, ConcreteClass) \
547  static ConcreteClass & GetInstance() { \
548  return *factory::CreateInstanceAs<ConcreteClass>(typeid(ConcreteClass).name()); \
549  }
550 
551 
552 
553 
554 /* This macro is used to force linking of factories.
555  See PFACTORY_CREATE() for more information
556  */
557 #define PFACTORY_LOAD(ConcreteType) \
558  namespace PFactoryLoader { \
559  extern int ConcreteType##_link(int const *); \
560  static int const ConcreteType##_loader = ConcreteType##_link(&ConcreteType##_loader); \
561  }
562 
563 
564 #endif // PTLIB_FACTORY_H
565 
566 
567 // End Of File ///////////////////////////////////////////////////////////////
static Abstract_T * CreateInstance(const Key_T &key, Param_T param)
Definition: pfactory.h:503
WorkerWrap(WorkerBase *worker, bool autoDelete)
Definition: pfactory.h:165
Definition: pfactory.h:163
This class waits for the semaphore on construction and automatically signals the semaphore on destruc...
Definition: psync.h:115
Base_T::Key_T Key_T
Definition: pfactory.h:403
Base_T::Key_T Key_T
Definition: pfactory.h:468
void InternalUnregister(WorkerBase *instance)
Definition: pfactory.h:303
Template class for generic factories of an abstract class.
Definition: pfactory.h:153
static PFactoryBase & InternalGetFactory(const std::string &className, PFactoryBase *(*createFactory)())
Definition: pfactory.h:122
virtual void DestroySingletons()=0
virtual Abstract_T * Create(Param_T) const
Definition: pfactory.h:219
void InternalUnregister(const Key_T &key)
Definition: pfactory.h:291
This class implements critical section mutexes using the most efficient mechanism available on the ho...
Definition: mutex.h:270
Base_T::Param_T Param_T
Definition: pfactory.h:402
virtual Abstract_T * Create(Param_T param) const
Definition: pfactory.h:497
WorkerBase(bool singleton=false)
Definition: pfactory.h:181
bool InternalIsRegistered(const Key_T &key)
Definition: pfactory.h:326
KeyList_T InternalGetKeyList()
Definition: pfactory.h:354
WorkerBase(Abstract_T *instance, bool delSingleton=true)
Definition: pfactory.h:187
PFactoryTemplate< AbstractClass, ParamType, KeyType > Base_T
Definition: pfactory.h:464
WorkerMap_T m_workers
Definition: pfactory.h:364
Base_T::WorkerBase WorkerBase_T
Definition: pfactory.h:400
virtual Abstract_T * Create(Param_T) const
Definition: pfactory.h:432
std::vector< Key_T > KeyList_T
Definition: pfactory.h:161
std::map< Key_T, WorkerWrap > WorkerMap_T
Definition: pfactory.h:169
static TheFactory & GetFactoryAs()
Definition: pfactory.h:136
std::string PDefaultPFactoryKey
this define the default class to be used for keys into PFactories
Definition: pfactory.h:375
Definition: pfactory.h:172
Definition: pfactory.h:473
virtual void DestroySingletons()
Definition: pfactory.h:235
Worker(const Key_T &key, bool singleton=false)
Definition: pfactory.h:413
Types m_type
Definition: pfactory.h:225
static Abstract_T * CreateInstance(const Key_T &key)
Definition: pfactory.h:438
Class for a factory to create concrete class instances which have a single parameter during construct...
Definition: pfactory.h:461
virtual void DestroySingleton()
Definition: pfactory.h:208
void InternalDestroy(const Key_T &key, Abstract_T *instance)
Definition: pfactory.h:339
PFactoryTemplate< AbstractClass, const KeyType &, KeyType > Base_T
Definition: pfactory.h:399
Abstract_T * InternalCreateInstance(const Key_T &key, Param_T param)
Definition: pfactory.h:332
static FactoryMap & GetFactories()
Base_T::Param_T Param_T
Definition: pfactory.h:467
AbstractClass Abstract_T
Definition: pfactory.h:156
bool InternalIsSingleton(const Key_T &key)
Definition: pfactory.h:347
#define PAssertNULL(ptr)
This macro is used to assert that a pointer must be non-null.
Definition: object.h:428
~Worker()
Definition: pfactory.h:420
PDECLARE_MUTEX(m_mutex,"PFactoryBase")
bool PBoolean
Definition: object.h:174
Definition: pfactory.h:408
Worker(const Key_T &key, bool singleton=false)
Definition: pfactory.h:478
virtual ~PFactoryBase()
Definition: pfactory.h:117
#define PMEMORY_IGNORE_ALLOCATIONS_FOR_SCOPE
Definition: object.h:1961
Base_T::Abstract_T Abstract_T
Definition: pfactory.h:466
PFactoryBase()
Definition: pfactory.h:114
Abstract_T * CreateInstance(Param_T param)
Definition: pfactory.h:198
const Key_T & GetKey() const
Definition: pfactory.h:429
Base_T::WorkerBase WorkerBase_T
Definition: pfactory.h:465
PFactoryTemplate()
Definition: pfactory.h:242
void InternalUnregisterAll()
Definition: pfactory.h:315
static Derived_T * CreateInstanceAs(const Key_T &key, Param_T param)
Definition: pfactory.h:509
static PFactoryBase * CreateFactory()
Definition: pfactory.h:134
bool IsSingleton() const
Definition: pfactory.h:216
const Key_T & GetKey() const
Definition: pfactory.h:494
Class for a factory to create concrete class instances without parameters during construction.
Definition: pfactory.h:396
Base_T::Abstract_T Abstract_T
Definition: pfactory.h:401
ParamType Param_T
Definition: pfactory.h:159
Abstract_T * m_singletonInstance
Definition: pfactory.h:226
virtual ~WorkerBase()
Definition: pfactory.h:193
PBoolean InternalRegisterAs(const Key_T &newKey, const Key_T &oldKey)
Definition: pfactory.h:276
~Worker()
Definition: pfactory.h:485
#define PAssert(b, msg)
This macro is used to assert that a condition must be true.
Definition: object.h:400
bool InternalRegister(const Key_T &key, WorkerBase *worker, bool autoDeleteWorker)
Definition: pfactory.h:251
Base class for generic factories.
Definition: pfactory.h:111
bool m_autoDelete
Definition: pfactory.h:167
~PFactoryTemplate()
Definition: pfactory.h:245
WorkerMap_T::iterator WorkerIter_T
Definition: pfactory.h:170
PFACTORY_STATICS(PParamFactory)
bool InternalRegister(const Key_T &key, Abstract_T *instance, bool autoDeleteInstance)
Definition: pfactory.h:264
static Derived_T * CreateInstanceAs(const Key_T &key)
Definition: pfactory.h:444
PFACTORY_STATICS(PFactory)
Types
Definition: pfactory.h:175
#define PNEW
Macro for overriding system default new operator.
Definition: object.h:1896
KeyType Key_T
Definition: pfactory.h:160
WorkerBase * m_worker
Definition: pfactory.h:166