Made some subtle changes to the way the static variables are instantiated in
[pwlib.git] / include / ptlib / pfactory.h
blob03bc79b9147bbe420a7789758eabcd8f9464d33c
1 /*
2 * factory.h
4 * Abstract Factory Classes
6 * Portable Windows Library
8 * Copyright (C) 2004 Post Increment
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/
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.
20 * The Original Code is Portable Windows Library.
22 * The Initial Developer of the Original Code is Post Increment
24 * Contributor(s): ______________________________________.
26 * $Log$
27 * Revision 1.7 2004/05/23 12:33:56 rjongbloed
28 * Made some subtle changes to the way the static variables are instantiated in
29 * the factoris to fix problems with DLL's under windows. May not be final solution.
31 * Revision 1.6 2004/05/19 06:48:39 csoutheren
32 * Added new functions to allow handling of singletons without concrete classes
34 * Revision 1.5 2004/05/18 06:01:06 csoutheren
35 * Deferred plugin loading until after main has executed by using abstract factory classes
37 * Revision 1.4 2004/05/18 02:32:08 csoutheren
38 * Fixed linking problems with PGenericFactory classes
40 * Revision 1.3 2004/05/13 15:10:51 csoutheren
41 * Removed warnings under Windows
43 * Revision 1.2 2004/05/13 14:59:00 csoutheren
44 * Removed warning under gcc
46 * Revision 1.1 2004/05/13 14:53:35 csoutheren
47 * Add "abstract factory" template classes
51 #ifndef _PFACTORY_H
52 #define _PFACTORY_H
54 #ifdef P_USE_PRAGMA
55 #pragma interface
56 #endif
58 #include <ptlib.h>
59 #include <string>
60 #include <map>
61 #include <vector>
63 #ifdef _WIN32
64 #pragma warning(disable:4786)
65 #endif
67 /**
69 * These templates implement an Abstract Factory that allows
70 * creation of a class "factory" that can be used to create
71 * "concrete" instance that are descended from a abstract case class
73 * Given an abstract class A with a descendant concrete class B, the
74 * concrete class is registered by instantiating the PAbstractFactory
75 * class as follows:
77 * PAbstractFactory<A, B> aFactory("B");
79 * To instantiate the an object of type B, use the following
81 * A * b = PGenericFactory<A>::CreateInstance("B");
83 * A vector containing the names of all of the concrete classes for an
84 * abstract type can be obtained as follows:
86 * std::vector<PString> list = PGenericFactory<A>::GetKeyList()
88 * Note that these example assumes that the "key" type for the factory
89 * registration is of the default type PString. If a different key type
90 * is needed, then it is necessary to specify the key type:
92 * PAbstractFactory<C, D, unsigned> aFactory(42);
93 * C * d = PGenericFactory<C, unsigned>::CreateInstance(42);
94 * std::vector<unsigned> list = PGenericFactory<C, unsigned>::GetKeyList()
96 * Finally, note that the factory lists are all thread safe for addition,
97 * creation, and obtaining the key lists
101 template <class AbstractType, typename TypeKey = PString>
102 class PGenericFactory
104 public:
105 typedef AbstractType * (*CreatorFunctionType)();
106 class AbstractInfo {
107 public:
108 AbstractInfo()
109 : creator(NULL), isSingleton(FALSE), instance(NULL)
111 AbstractInfo(CreatorFunctionType creat, BOOL single)
112 : creator(creat), isSingleton(single), instance(NULL)
114 AbstractInfo(AbstractType * inst, BOOL single)
115 : creator(NULL), isSingleton(single), instance(inst)
117 CreatorFunctionType creator;
118 BOOL isSingleton;
119 AbstractType * instance;
122 typedef std::map<TypeKey, AbstractInfo> KeyMap;
123 typedef std::vector<TypeKey> KeyList;
125 static AbstractType * CreateInstance(const TypeKey & key)
127 PWaitAndSignal m(GetMutex());
128 KeyMap & keyMap = GetKeyMap();
129 AbstractType * instance = NULL;
130 typename KeyMap::const_iterator entry = keyMap.find(key);
131 if (entry != keyMap.end()) {
132 if (entry->second.isSingleton && entry->second.instance != NULL)
133 instance = entry->second.instance;
134 else if (entry->second.creator != NULL)
135 instance = (*(entry->second.creator))();
137 return instance;
140 static void Register(const TypeKey & key, CreatorFunctionType func, BOOL isSingleton)
142 Register(key, AbstractInfo(func, isSingleton));
145 static void Register(const TypeKey & key, AbstractType * instance, BOOL isSingleton)
147 Register(key, AbstractInfo(instance, isSingleton));
150 static void Register(const TypeKey & key, const AbstractInfo & info)
152 PWaitAndSignal m(GetMutex());
153 KeyMap & keyMap = GetKeyMap();
154 if (keyMap.find(key) == keyMap.end())
155 keyMap[key] = info;
158 static BOOL IsSingleton(const TypeKey & key)
160 PWaitAndSignal m(GetMutex());
161 KeyMap & keyMap = GetKeyMap();
162 if (keyMap.find(key) == keyMap.end())
163 return FALSE;
164 return keyMap[key].isSingleton;
167 static KeyList GetKeyList()
169 PWaitAndSignal m(GetMutex());
170 KeyMap & keyMap = GetKeyMap();
171 KeyList list;
172 typename KeyMap::const_iterator entry;
173 for (entry = keyMap.begin(); entry != keyMap.end(); ++entry)
174 list.push_back(entry->first);
175 return list;
178 static PMutex & GetMutex()
180 return GetFactory().mutex;
183 static KeyMap & GetKeyMap()
185 return GetFactory().keyMap;
188 protected:
189 PGenericFactory()
193 static PGenericFactory & GetFactory()
195 static PGenericFactory factory;
196 return factory;
199 PMutex mutex;
200 KeyMap keyMap;
202 private:
203 PGenericFactory(const PGenericFactory &) {}
204 void operator=(const PGenericFactory &) {}
208 template <class AbstractType, class ConcreteType, typename TypeKey = PString>
209 class PAbstractFactory
211 public:
212 PAbstractFactory(const TypeKey & key)
214 PGenericFactory<AbstractType>::Register(key, &CreateInstance, FALSE);
217 static AbstractType * CreateInstance()
219 return new ConcreteType;
222 private:
223 PAbstractFactory(const PAbstractFactory &) {}
224 void operator=(const PAbstractFactory &) {}
228 template <class AbstractType, class ConcreteType, typename TypeKey = PString>
229 class PAbstractSingletonFactory
231 public:
232 PAbstractSingletonFactory(const TypeKey & key)
234 PGenericFactory<AbstractType>::Register(key, &GetInstance(), TRUE);
237 static ConcreteType & GetInstance()
239 static ConcreteType instance;
240 return instance;
243 private:
244 PAbstractSingletonFactory(const PAbstractSingletonFactory &) {}
245 void operator=(const PAbstractSingletonFactory &) {}
249 #endif // _PFACTORY_H