PTLib  Version 2.10.10
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  * $Revision: 26567 $
27  * $Author: rjongbloed $
28  * $Date: 2011-10-08 01:17:56 -0500 (Sat, 08 Oct 2011) $
29  */
30 
31 #ifndef PTLIB_FACTORY_H
32 #define PTLIB_FACTORY_H
33 
34 #ifdef P_USE_PRAGMA
35 #pragma interface
36 #endif
37 
38 #include <ptlib.h>
39 
40 #include <string>
41 #include <map>
42 #include <vector>
43 
44 #if defined(_MSC_VER)
45 #pragma warning(disable:4786)
46 #endif
47 
99 // this define the default class to be used for keys into PFactories
100 //typedef PString PDefaultPFactoryKey;
101 typedef std::string PDefaultPFactoryKey;
102 
103 
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 *>
123  {
124  public:
126  ~FactoryMap();
127  };
128 
129  static FactoryMap & GetFactories();
130  static PMutex & GetFactoriesMutex();
131 
132  protected:
134 
135  private:
136  PFactoryBase(const PFactoryBase &) {}
137  void operator=(const PFactoryBase &) {}
138 };
139 
140 
143 template <class AbstractClass, typename KeyType = PDefaultPFactoryKey>
145 {
146  public:
147  typedef KeyType Key_T;
148  typedef AbstractClass Abstract_T;
149 
151  {
152  protected:
153  enum Types {
157  } m_type;
158 
159  Abstract_T * m_singletonInstance;
160 
161  WorkerBase(bool singleton = false)
162  : m_type(singleton ? DynamicSingleton : NonSingleton)
163  , m_singletonInstance(NULL)
164  { }
165 
166  WorkerBase(Abstract_T * instance, bool delSingleton = true)
167  : m_type(delSingleton ? DynamicSingleton : StaticSingleton)
168  , m_singletonInstance(instance)
169  { }
170 
171  virtual ~WorkerBase()
172  {
174  }
175 
176  Abstract_T * CreateInstance(const Key_T & key)
177  {
178  if (m_type == NonSingleton)
179  return Create(key);
180 
181  if (m_singletonInstance == NULL)
182  m_singletonInstance = Create(key);
183  return m_singletonInstance;
184  }
185 
186  virtual Abstract_T * Create(const Key_T & /*key*/) const
187  {
188  PAssert(this->m_type == StaticSingleton, "Incorrect factory worker descendant");
189  return this->m_singletonInstance;
190  }
191 
192  virtual void DestroySingleton()
193  {
194  if (m_type == DynamicSingleton) {
195  delete m_singletonInstance;
196  m_singletonInstance = NULL;
197  }
198  }
199 
200  bool IsSingleton() const { return m_type != NonSingleton; }
201 
202  friend class PFactory<Abstract_T, Key_T>;
203  };
204 
205  template <class ConcreteClass>
207  {
208  public:
209  Worker(const Key_T & key, bool singleton = false)
210  : WorkerBase(singleton)
211  {
214  }
215 
216  protected:
217  virtual Abstract_T * Create(const Key_T & /*key*/) const
218  {
219  return new ConcreteClass;
220  }
221  };
222 
223  typedef std::map<Key_T, WorkerBase *> KeyMap_T;
224  typedef std::vector<Key_T> KeyList_T;
225 
226  static bool Register(const Key_T & key, WorkerBase * worker)
227  {
228  return GetInstance().Register_Internal(key, worker);
229  }
230 
231  static bool Register(const Key_T & key, Abstract_T * instance, bool autoDeleteInstance = true)
232  {
233  WorkerBase * worker = PNEW WorkerBase(instance, autoDeleteInstance);
234  if (GetInstance().Register_Internal(key, worker))
235  return true;
236  delete worker;
237  return false;
238  }
239 
240  static PBoolean RegisterAs(const Key_T & newKey, const Key_T & oldKey)
241  {
242  return GetInstance().RegisterAs_Internal(newKey, oldKey);
243  }
244 
245  static void Unregister(const Key_T & key)
246  {
248  }
249 
250  static void UnregisterAll()
251  {
253  }
254 
255  static bool IsRegistered(const Key_T & key)
256  {
257  return GetInstance().IsRegistered_Internal(key);
258  }
259 
260  static Abstract_T * CreateInstance(const Key_T & key)
261  {
262  return GetInstance().CreateInstance_Internal(key);
263  }
264 
265  template <class Derived_T>
266  static Derived_T * CreateInstanceAs(const Key_T & key)
267  {
268  return dynamic_cast<Derived_T *>(GetInstance().CreateInstance_Internal(key));
269  }
270 
271  static PBoolean IsSingleton(const Key_T & key)
272  {
273  return GetInstance().IsSingleton_Internal(key);
274  }
275 
276  static KeyList_T GetKeyList()
277  {
278  return GetInstance().GetKeyList_Internal();
279  }
280 
281  static KeyMap_T & GetKeyMap()
282  {
283  return GetInstance().m_keyMap;
284  }
285 
286  static PMutex & GetMutex()
287  {
288  return GetInstance().m_mutex;
289  }
290 
291  virtual void DestroySingletons()
292  {
293  for (typename KeyMap_T::const_iterator it = m_keyMap.begin(); it != m_keyMap.end(); ++it)
294  it->second->DestroySingleton();
295  }
296 
297  protected:
299  { }
300 
302  {
304  }
305 
307  {
308  std::string className = typeid(PFactory).name();
310  FactoryMap & factories = GetFactories();
311  FactoryMap::const_iterator entry = factories.find(className);
312  if (entry != factories.end()) {
313  PAssert(entry->second != NULL, "Factory map returned NULL for existing key");
314  PFactoryBase * b = entry->second;
315  // don't use the following dynamic cast, because gcc does not like it
316  //PFactory * f = dynamic_cast<PFactory*>(b);
317  return *(PFactory *)b;
318  }
319 
321  PFactory * factory = new PFactory;
322  factories[className] = factory;
323  return *factory;
324  }
325 
326 
327  bool Register_Internal(const Key_T & key, WorkerBase * worker)
328  {
329  PWaitAndSignal mutex(m_mutex);
330  if (m_keyMap.find(key) != m_keyMap.end())
331  return false;
332  m_keyMap[key] = PAssertNULL(worker);
333  return true;
334  }
335 
336  PBoolean RegisterAs_Internal(const Key_T & newKey, const Key_T & oldKey)
337  {
338  PWaitAndSignal mutex(m_mutex);
339  if (m_keyMap.find(oldKey) == m_keyMap.end())
340  return false;
341  m_keyMap[newKey] = m_keyMap[oldKey];
342  return true;
343  }
344 
345  void Unregister_Internal(const Key_T & key)
346  {
347  m_mutex.Wait();
348  m_keyMap.erase(key);
349  m_mutex.Signal();
350  }
351 
353  {
354  m_mutex.Wait();
355  m_keyMap.clear();
356  m_mutex.Signal();
357  }
358 
359  bool IsRegistered_Internal(const Key_T & key)
360  {
361  PWaitAndSignal mutex(m_mutex);
362  return m_keyMap.find(key) != m_keyMap.end();
363  }
364 
365  Abstract_T * CreateInstance_Internal(const Key_T & key)
366  {
367  PWaitAndSignal mutex(m_mutex);
368  typename KeyMap_T::const_iterator entry = m_keyMap.find(key);
369  if (entry != m_keyMap.end())
370  return entry->second->CreateInstance(key);
371  return NULL;
372  }
373 
374  bool IsSingleton_Internal(const Key_T & key)
375  {
376  PWaitAndSignal mutex(m_mutex);
377  if (m_keyMap.find(key) == m_keyMap.end())
378  return false;
379  return m_keyMap[key]->IsSingleton();
380  }
381 
383  {
384  PWaitAndSignal mutex(m_mutex);
385  KeyList_T list;
386  typename KeyMap_T::const_iterator entry;
387  for (entry = m_keyMap.begin(); entry != m_keyMap.end(); ++entry)
388  list.push_back(entry->first);
389  return list;
390  }
391 
392  KeyMap_T m_keyMap;
393 
394  private:
395  PFactory(const PFactory &) {}
396  void operator=(const PFactory &) {}
397 };
398 
399 
411 #define PFACTORY_CREATE(factory, ConcreteClass, ...) \
412  namespace PFactoryLoader { \
413  int ConcreteClass##_link() { return 0; } \
414  factory::Worker<ConcreteClass> ConcreteClass##_instance(__VA_ARGS__); \
415  }
416 
417 #define PFACTORY_CREATE_SINGLETON(factory, ConcreteClass) \
418  PFACTORY_CREATE(factory, ConcreteClass, typeid(ConcreteClass).name(), true)
419 
420 #define PFACTORY_GET_SINGLETON(factory, ConcreteClass) \
421  static ConcreteClass & GetInstance() { \
422  return *factory::CreateInstanceAs<ConcreteClass>(typeid(ConcreteClass).name()); \
423  }
424 
425 
426 
427 
428 /* This macro is used to force linking of factories.
429  See PFACTORY_CREATE() for more information
430  */
431 #define PFACTORY_LOAD(ConcreteType) \
432  namespace PFactoryLoader { \
433  extern int ConcreteType##_link(); \
434  int const ConcreteType##_loader = ConcreteType##_link(); \
435  }
436 
437 
438 #endif // PTLIB_FACTORY_H
439 
440 
441 // End Of File ///////////////////////////////////////////////////////////////
enum PFactory::WorkerBase::Types m_type
static PBoolean RegisterAs(const Key_T &newKey, const Key_T &oldKey)
Definition: pfactory.h:240
Types
Definition: pfactory.h:153
This class waits for the semaphore on construction and automatically signals the semaphore on destruc...
Definition: psync.h:86
std::map< Key_T, WorkerBase * > KeyMap_T
Definition: pfactory.h:223
PFactory()
Definition: pfactory.h:298
WorkerBase(bool singleton=false)
Definition: pfactory.h:161
static KeyMap_T & GetKeyMap()
Definition: pfactory.h:281
Definition: pfactory.h:122
Definition: pfactory.h:155
static PMutex & GetMutex()
Definition: pfactory.h:286
virtual void DestroySingletons()=0
bool IsRegistered_Internal(const Key_T &key)
Definition: pfactory.h:359
void UnregisterAll_Internal()
Definition: pfactory.h:352
static void Unregister(const Key_T &key)
Definition: pfactory.h:245
Abstract_T * CreateInstance_Internal(const Key_T &key)
Definition: pfactory.h:365
AbstractClass Abstract_T
Definition: pfactory.h:148
Abstract_T * m_singletonInstance
Definition: pfactory.h:159
Definition: pfactory.h:156
bool Register_Internal(const Key_T &key, WorkerBase *worker)
Definition: pfactory.h:327
KeyMap_T m_keyMap
Definition: pfactory.h:392
PMutex m_mutex
Definition: pfactory.h:133
std::string PDefaultPFactoryKey
These templates implement an Abstract Factory that allows creation of a class "factory" that can be u...
Definition: pfactory.h:101
Worker(const Key_T &key, bool singleton=false)
Definition: pfactory.h:209
~PFactory()
Definition: pfactory.h:301
BOOL PBoolean
Definition: object.h:102
static Abstract_T * CreateInstance(const Key_T &key)
Definition: pfactory.h:260
bool IsSingleton_Internal(const Key_T &key)
Definition: pfactory.h:374
KeyList_T GetKeyList_Internal()
Definition: pfactory.h:382
virtual void DestroySingletons()
Definition: pfactory.h:291
static void UnregisterAll()
Definition: pfactory.h:250
static FactoryMap & GetFactories()
WorkerBase(Abstract_T *instance, bool delSingleton=true)
Definition: pfactory.h:166
#define PAssertNULL(ptr)
This macro is used to assert that a pointer must be non-null.
Definition: object.h:220
Definition: pfactory.h:206
virtual ~PFactoryBase()
Definition: pfactory.h:117
#define PMEMORY_IGNORE_ALLOCATIONS_FOR_SCOPE
Definition: object.h:953
static bool Register(const Key_T &key, WorkerBase *worker)
Definition: pfactory.h:226
PFactoryBase()
Definition: pfactory.h:114
FactoryMap()
Definition: pfactory.h:125
static bool IsRegistered(const Key_T &key)
Definition: pfactory.h:255
KeyType Key_T
Definition: pfactory.h:147
bool IsSingleton() const
Definition: pfactory.h:200
Template class for generic factories of an abstract class.
Definition: pfactory.h:144
Abstract_T * CreateInstance(const Key_T &key)
Definition: pfactory.h:176
static KeyList_T GetKeyList()
Definition: pfactory.h:276
Synonym for PTimedMutex.
#define PAssert(b, msg)
This macro is used to assert that a condition must be true.
Definition: object.h:192
static PBoolean IsSingleton(const Key_T &key)
Definition: pfactory.h:271
Base class for generic factories.
Definition: pfactory.h:111
Definition: pfactory.h:154
static bool Register(const Key_T &key, Abstract_T *instance, bool autoDeleteInstance=true)
Definition: pfactory.h:231
static PFactory & GetInstance()
Definition: pfactory.h:306
virtual Abstract_T * Create(const Key_T &) const
Definition: pfactory.h:217
Definition: pfactory.h:150
void Unregister_Internal(const Key_T &key)
Definition: pfactory.h:345
virtual ~WorkerBase()
Definition: pfactory.h:171
std::vector< Key_T > KeyList_T
Definition: pfactory.h:224
static PMutex & GetFactoriesMutex()
virtual void DestroySingleton()
Definition: pfactory.h:192
virtual Abstract_T * Create(const Key_T &) const
Definition: pfactory.h:186
static Derived_T * CreateInstanceAs(const Key_T &key)
Definition: pfactory.h:266
#define PNEW
Macro for overriding system default new operator.
Definition: object.h:890
PBoolean RegisterAs_Internal(const Key_T &newKey, const Key_T &oldKey)
Definition: pfactory.h:336