pfactory.h
Go to the documentation of this file.
/*
* factory.h
*
* Abstract Factory Classes
*
* Portable Windows Library
*
* Copyright (C) 2004 Post Increment
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Portable Windows Library.
*
* The Initial Developer of the Original Code is Post Increment
*
* Contributor(s): ______________________________________.
*
* $Revision: 26567 $
* $Author: rjongbloed $
* $Date: 2011-10-08 01:17:56 -0500 (Sat, 08 Oct 2011) $
*/
#ifndef PTLIB_FACTORY_H
#define PTLIB_FACTORY_H
#ifdef P_USE_PRAGMA
#pragma interface
#endif
#include <ptlib.h>
#include <string>
#include <map>
#include <vector>
#if defined(_MSC_VER)
#pragma warning(disable:4786)
#endif
// this define the default class to be used for keys into PFactories
//typedef PString PDefaultPFactoryKey;
typedef std::string PDefaultPFactoryKey;
class PFactoryBase
{
protected:
PFactoryBase()
{ }
public:
virtual ~PFactoryBase()
{ }
virtual void DestroySingletons() = 0;
class FactoryMap : public std::map<std::string, PFactoryBase *>
{
public:
FactoryMap() { }
~FactoryMap();
};
static FactoryMap & GetFactories();
static PMutex & GetFactoriesMutex();
protected:
PMutex m_mutex;
private:
PFactoryBase(const PFactoryBase &) {}
void operator=(const PFactoryBase &) {}
};
template <class AbstractClass, typename KeyType = PDefaultPFactoryKey>
class PFactory : PFactoryBase
{
public:
typedef KeyType Key_T;
typedef AbstractClass Abstract_T;
class WorkerBase
{
protected:
enum Types {
NonSingleton,
StaticSingleton,
DynamicSingleton
} m_type;
Abstract_T * m_singletonInstance;
WorkerBase(bool singleton = false)
: m_type(singleton ? DynamicSingleton : NonSingleton)
, m_singletonInstance(NULL)
{ }
WorkerBase(Abstract_T * instance, bool delSingleton = true)
: m_type(delSingleton ? DynamicSingleton : StaticSingleton)
, m_singletonInstance(instance)
{ }
virtual ~WorkerBase()
{
DestroySingleton();
}
Abstract_T * CreateInstance(const Key_T & key)
{
if (m_type == NonSingleton)
return Create(key);
if (m_singletonInstance == NULL)
m_singletonInstance = Create(key);
return m_singletonInstance;
}
virtual Abstract_T * Create(const Key_T & /*key*/) const
{
PAssert(this->m_type == StaticSingleton, "Incorrect factory worker descendant");
return this->m_singletonInstance;
}
virtual void DestroySingleton()
{
if (m_type == DynamicSingleton) {
delete m_singletonInstance;
m_singletonInstance = NULL;
}
}
bool IsSingleton() const { return m_type != NonSingleton; }
friend class PFactory<Abstract_T, Key_T>;
};
template <class ConcreteClass>
class Worker : WorkerBase
{
public:
Worker(const Key_T & key, bool singleton = false)
: WorkerBase(singleton)
{
PMEMORY_IGNORE_ALLOCATIONS_FOR_SCOPE;
PFactory<Abstract_T, Key_T>::Register(key, this);
}
protected:
virtual Abstract_T * Create(const Key_T & /*key*/) const
{
return new ConcreteClass;
}
};
typedef std::map<Key_T, WorkerBase *> KeyMap_T;
typedef std::vector<Key_T> KeyList_T;
static bool Register(const Key_T & key, WorkerBase * worker)
{
return GetInstance().Register_Internal(key, worker);
}
static bool Register(const Key_T & key, Abstract_T * instance, bool autoDeleteInstance = true)
{
WorkerBase * worker = PNEW WorkerBase(instance, autoDeleteInstance);
if (GetInstance().Register_Internal(key, worker))
return true;
delete worker;
return false;
}
static PBoolean RegisterAs(const Key_T & newKey, const Key_T & oldKey)
{
return GetInstance().RegisterAs_Internal(newKey, oldKey);
}
static void Unregister(const Key_T & key)
{
GetInstance().Unregister_Internal(key);
}
static void UnregisterAll()
{
GetInstance().UnregisterAll_Internal();
}
static bool IsRegistered(const Key_T & key)
{
return GetInstance().IsRegistered_Internal(key);
}
static Abstract_T * CreateInstance(const Key_T & key)
{
return GetInstance().CreateInstance_Internal(key);
}
template <class Derived_T>
static Derived_T * CreateInstanceAs(const Key_T & key)
{
return dynamic_cast<Derived_T *>(GetInstance().CreateInstance_Internal(key));
}
static PBoolean IsSingleton(const Key_T & key)
{
return GetInstance().IsSingleton_Internal(key);
}
static KeyList_T GetKeyList()
{
return GetInstance().GetKeyList_Internal();
}
static KeyMap_T & GetKeyMap()
{
return GetInstance().m_keyMap;
}
static PMutex & GetMutex()
{
return GetInstance().m_mutex;
}
virtual void DestroySingletons()
{
for (typename KeyMap_T::const_iterator it = m_keyMap.begin(); it != m_keyMap.end(); ++it)
it->second->DestroySingleton();
}
protected:
PFactory()
{ }
~PFactory()
{
DestroySingletons();
}
static PFactory & GetInstance()
{
std::string className = typeid(PFactory).name();
PWaitAndSignal m(GetFactoriesMutex());
FactoryMap & factories = GetFactories();
FactoryMap::const_iterator entry = factories.find(className);
if (entry != factories.end()) {
PAssert(entry->second != NULL, "Factory map returned NULL for existing key");
PFactoryBase * b = entry->second;
// don't use the following dynamic cast, because gcc does not like it
//PFactory * f = dynamic_cast<PFactory*>(b);
return *(PFactory *)b;
}
PMEMORY_IGNORE_ALLOCATIONS_FOR_SCOPE;
PFactory * factory = new PFactory;
factories[className] = factory;
return *factory;
}
bool Register_Internal(const Key_T & key, WorkerBase * worker)
{
PWaitAndSignal mutex(m_mutex);
if (m_keyMap.find(key) != m_keyMap.end())
return false;
m_keyMap[key] = PAssertNULL(worker);
return true;
}
PBoolean RegisterAs_Internal(const Key_T & newKey, const Key_T & oldKey)
{
PWaitAndSignal mutex(m_mutex);
if (m_keyMap.find(oldKey) == m_keyMap.end())
return false;
m_keyMap[newKey] = m_keyMap[oldKey];
return true;
}
void Unregister_Internal(const Key_T & key)
{
m_mutex.Wait();
m_keyMap.erase(key);
m_mutex.Signal();
}
void UnregisterAll_Internal()
{
m_mutex.Wait();
m_keyMap.clear();
m_mutex.Signal();
}
bool IsRegistered_Internal(const Key_T & key)
{
PWaitAndSignal mutex(m_mutex);
return m_keyMap.find(key) != m_keyMap.end();
}
Abstract_T * CreateInstance_Internal(const Key_T & key)
{
PWaitAndSignal mutex(m_mutex);
typename KeyMap_T::const_iterator entry = m_keyMap.find(key);
if (entry != m_keyMap.end())
return entry->second->CreateInstance(key);
return NULL;
}
bool IsSingleton_Internal(const Key_T & key)
{
PWaitAndSignal mutex(m_mutex);
if (m_keyMap.find(key) == m_keyMap.end())
return false;
return m_keyMap[key]->IsSingleton();
}
KeyList_T GetKeyList_Internal()
{
PWaitAndSignal mutex(m_mutex);
KeyList_T list;
typename KeyMap_T::const_iterator entry;
for (entry = m_keyMap.begin(); entry != m_keyMap.end(); ++entry)
list.push_back(entry->first);
return list;
}
KeyMap_T m_keyMap;
private:
PFactory(const PFactory &) {}
void operator=(const PFactory &) {}
};
#define PFACTORY_CREATE(factory, ConcreteClass, ...) \
namespace PFactoryLoader { \
int ConcreteClass##_link() { return 0; } \
factory::Worker<ConcreteClass> ConcreteClass##_instance(__VA_ARGS__); \
}
#define PFACTORY_CREATE_SINGLETON(factory, ConcreteClass) \
PFACTORY_CREATE(factory, ConcreteClass, typeid(ConcreteClass).name(), true)
#define PFACTORY_GET_SINGLETON(factory, ConcreteClass) \
static ConcreteClass & GetInstance() { \
return *factory::CreateInstanceAs<ConcreteClass>(typeid(ConcreteClass).name()); \
}
/* This macro is used to force linking of factories.
See PFACTORY_CREATE() for more information
*/
#define PFACTORY_LOAD(ConcreteType) \
namespace PFactoryLoader { \
extern int ConcreteType##_link(); \
int const ConcreteType##_loader = ConcreteType##_link(); \
}
#endif // PTLIB_FACTORY_H
// End Of File ///////////////////////////////////////////////////////////////
PFactory::RegisterAs
static PBoolean RegisterAs(const Key_T &newKey, const Key_T &oldKey)
Definition: pfactory.h:240
PFactory::WorkerBase::Types
Types
Definition: pfactory.h:153
PWaitAndSignal
This class waits for the semaphore on construction and automatically signals the semaphore on destruc...
Definition: psync.h:86
PFactory::KeyMap_T
std::map< Key_T, WorkerBase * > KeyMap_T
Definition: pfactory.h:223
PFactory::PFactory
PFactory()
Definition: pfactory.h:298
PFactory::WorkerBase::WorkerBase
WorkerBase(bool singleton=false)
Definition: pfactory.h:161
PFactory::GetKeyMap
static KeyMap_T & GetKeyMap()
Definition: pfactory.h:281
PFactoryBase::FactoryMap
Definition: pfactory.h:122
PFactoryBase::FactoryMap::~FactoryMap
~FactoryMap()
PFactory::WorkerBase::StaticSingleton
Definition: pfactory.h:155
PFactory::GetMutex
static PMutex & GetMutex()
Definition: pfactory.h:286
PFactoryBase::DestroySingletons
virtual void DestroySingletons()=0
PFactory::IsRegistered_Internal
bool IsRegistered_Internal(const Key_T &key)
Definition: pfactory.h:359
PFactory::UnregisterAll_Internal
void UnregisterAll_Internal()
Definition: pfactory.h:352
PFactory::Unregister
static void Unregister(const Key_T &key)
Definition: pfactory.h:245
PFactory::CreateInstance_Internal
Abstract_T * CreateInstance_Internal(const Key_T &key)
Definition: pfactory.h:365
PFactory::Abstract_T
AbstractClass Abstract_T
Definition: pfactory.h:148
PFactory::WorkerBase::m_singletonInstance
Abstract_T * m_singletonInstance
Definition: pfactory.h:159
PFactory::Register_Internal
bool Register_Internal(const Key_T &key, WorkerBase *worker)
Definition: pfactory.h:327
PFactory::m_keyMap
KeyMap_T m_keyMap
Definition: pfactory.h:392
PFactoryBase::m_mutex
PMutex m_mutex
Definition: pfactory.h:133
PDefaultPFactoryKey
std::string PDefaultPFactoryKey
These templates implement an Abstract Factory that allows creation of a class "factory" that can be u...
Definition: pfactory.h:101
PFactory::Worker::Worker
Worker(const Key_T &key, bool singleton=false)
Definition: pfactory.h:209
PFactory::~PFactory
~PFactory()
Definition: pfactory.h:301
PBoolean
BOOL PBoolean
Definition: object.h:102
PFactory::CreateInstance
static Abstract_T * CreateInstance(const Key_T &key)
Definition: pfactory.h:260
PFactory::IsSingleton_Internal
bool IsSingleton_Internal(const Key_T &key)
Definition: pfactory.h:374
PFactory::GetKeyList_Internal
KeyList_T GetKeyList_Internal()
Definition: pfactory.h:382
PFactory::DestroySingletons
virtual void DestroySingletons()
Definition: pfactory.h:291
PFactory::UnregisterAll
static void UnregisterAll()
Definition: pfactory.h:250
PFactoryBase::GetFactories
static FactoryMap & GetFactories()
PFactory::WorkerBase::WorkerBase
WorkerBase(Abstract_T *instance, bool delSingleton=true)
Definition: pfactory.h:166
PAssertNULL
#define PAssertNULL(ptr)
This macro is used to assert that a pointer must be non-null.
Definition: object.h:220
PFactory::Worker
Definition: pfactory.h:206
PFactoryBase::~PFactoryBase
virtual ~PFactoryBase()
Definition: pfactory.h:117
PMEMORY_IGNORE_ALLOCATIONS_FOR_SCOPE
#define PMEMORY_IGNORE_ALLOCATIONS_FOR_SCOPE
Definition: object.h:953
PFactory::Register
static bool Register(const Key_T &key, WorkerBase *worker)
Definition: pfactory.h:226
PFactoryBase::PFactoryBase
PFactoryBase()
Definition: pfactory.h:114
PFactoryBase::FactoryMap::FactoryMap
FactoryMap()
Definition: pfactory.h:125
PFactory::IsRegistered
static bool IsRegistered(const Key_T &key)
Definition: pfactory.h:255
PFactory::Key_T
KeyType Key_T
Definition: pfactory.h:147
PFactory
Template class for generic factories of an abstract class.
Definition: pfactory.h:144
PFactory::WorkerBase::CreateInstance
Abstract_T * CreateInstance(const Key_T &key)
Definition: pfactory.h:176
PFactory::WorkerBase::Create
virtual Abstract_T * Create(const Key_T &) const
Definition: pfactory.h:186
PFactory::GetKeyList
static KeyList_T GetKeyList()
Definition: pfactory.h:276
PMutex
Synonym for PTimedMutex.
PAssert
#define PAssert(b, msg)
This macro is used to assert that a condition must be true.
Definition: object.h:192
PFactory::IsSingleton
static PBoolean IsSingleton(const Key_T &key)
Definition: pfactory.h:271
PFactory::WorkerBase::IsSingleton
bool IsSingleton() const
Definition: pfactory.h:200
PFactoryBase
Base class for generic factories.
Definition: pfactory.h:111
PFactory::WorkerBase::NonSingleton
Definition: pfactory.h:154
PFactory::Register
static bool Register(const Key_T &key, Abstract_T *instance, bool autoDeleteInstance=true)
Definition: pfactory.h:231
PFactory::GetInstance
static PFactory & GetInstance()
Definition: pfactory.h:306
PFactory::WorkerBase
Definition: pfactory.h:150
PFactory::Unregister_Internal
void Unregister_Internal(const Key_T &key)
Definition: pfactory.h:345
PFactory::WorkerBase::~WorkerBase
virtual ~WorkerBase()
Definition: pfactory.h:171
PFactory::KeyList_T
std::vector< Key_T > KeyList_T
Definition: pfactory.h:224
PFactoryBase::GetFactoriesMutex
static PMutex & GetFactoriesMutex()
PFactory::WorkerBase::DestroySingleton
virtual void DestroySingleton()
Definition: pfactory.h:192
PFactory::CreateInstanceAs
static Derived_T * CreateInstanceAs(const Key_T &key)
Definition: pfactory.h:266
PNEW
#define PNEW
Macro for overriding system default new operator.
Definition: object.h:890
PFactory::Worker::Create
virtual Abstract_T * Create(const Key_T &) const
Definition: pfactory.h:217
PFactory::RegisterAs_Internal
PBoolean RegisterAs_Internal(const Key_T &newKey, const Key_T &oldKey)
Definition: pfactory.h:336