source: src/CodePatterns/Singleton.hpp@ 163eec

Last change on this file since 163eec was 163eec, checked in by Frederik Heber <heber@…>, 10 years ago

Added Singleton:getConstInstance() and ..Pointer() functions.

  • Property mode set to 100644
File size: 11.9 KB
Line 
1/*
2 * Singleton.hpp
3 *
4 * Created on: Mar 10, 2010
5 * Author: crueger
6 */
7
8#ifndef SINGLETON_HPP_
9#define SINGLETON_HPP_
10
11// include config.h
12#ifdef HAVE_CONFIG_H
13#include <config.h>
14#endif
15
16#include <boost/thread.hpp>
17
18#include "CodePatterns/Assert.hpp"
19
20/**
21 * This template produces the generic singleton pattern using the CRTP idiom.
22 *
23 * <h1> Singleton Howto </h1>
24 * <h2> Introduction </h2>
25 *
26 * A Singleton is a class of which there can only be a single Object in the programm. It is
27 * described as an design-pattern in Gof:96 (the famous design-pattern book). In the
28 * molecuilder there are so far several Singletons serving a wide range of purposes:
29 *
30 * - the World, which handles all atoms, molecules and bonds
31 * - the ActionRegistry, which stores all created actions by name for later use
32 * - the UIFactory, which is an AbstractFactory (another design-pattern from Gof:96) and
33 * handles all creation of gui elements to ensure a single type throughout the programm
34 * - the logger and errorLogger classes, that can be used to output messages on the screen
35 * depending on certain conditions
36 *
37 * Because those classes can only be instantiated once you cannot simply call <code>new World()</code>
38 * or <code>delete</code> on them. Rather they have to be constructed and accessed using the singleton
39 * mechanism. This mechanism consists of four static functions (and a fifth that is used internally,
40 * but we will get to that later). These functions are:
41 *
42 * - <code>Singleton& Singleton::getInstance()</code> : returns the instance of the singleton as
43 * a reference
44 * - <code>Singleton* Singleton::getPointer()</code> : returns the instance of the singleton as a
45 * pointer
46 * - <code>void Singleton::purgeInstance()</code> : destroys the single Instance of the singleton
47 * - <code>Singleton& Singleton::resetInstance()</code> : resets the Singleton, i.e. destroys the
48 * old instance and creates a new one
49 *
50 * If you need the instance of the singleton it is usually fine just to use one off the accessor
51 * functions (i.e. <code>getInstance()</code> or <code>getPointer()</code>. Any creation of the
52 * Singleton is then handled by these functions, so that the same object will be returned whenever
53 * one of these functions is called. This easy process is true for most singletons you will need
54 * to use. The only special singleton is the UIFactory.
55 *
56 * <h3>Special functions of the UIFactory</h3>
57 *
58 * If you simply call the <code>getInstance()</code> method of the UIFactory class the program
59 * will crash. This happens, because the UIFactory in itself is abstract and needs to know what
60 * kind of user interface it should produce later on. You need to tell the class the type of UI
61 * using the void <code>UIFactory::makeUserInterface(InterfaceTypes type)</code> method. This will
62 * also take care of creating the sole instance, so that the accessor functions will work afterwards.
63 * What this also means is, that you cannot <code>reset()</code> the UIFactory, because at that
64 * point it wont know anymore what to construct. A sequence of <code>UIFactory::purgeInstance()</code>,
65 * <code>UIFactory::makeUserInterface()</code> and <code>UIFactory::getInstance()</code> will work
66 * though.
67 *
68 * In order to make life easier and propagate changes to the singleton mechanism to all those
69 * classes, there is a simple framework class that can be used to make any other class a
70 * singleton through inheritance. This class can be found in the Pattern directory.
71 *
72 * <h2>How to make a class Singleton</h2>
73 *
74 * Most of the time you will only need singletons that don't require additional
75 * information for creation. So I will cover the basic case for constructing singletons
76 * first and then explain what has to be changed to make it accept special parameters.
77 * Singletons are created by inheriting from the <code>Singleton<class T></code> template
78 * using the Curiously recurring template pattern (CRTP). What this means is, that the
79 * class they inherit from carries the inheriting class as a template parameter. For example
80 * <code>class MySingletonExaple : public Singleton<MySingletonExample>{...}</code>. If you
81 * want to know more about this idiom have a look at the
82 * <A HREF="http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern">wikipedia
83 * page for this idiom</A>, but don't worry if you don't quite get how this works for now, for
84 * the use of the singleton framework this is not important.
85 *
86 * If you want to make a class a singleton you can use the following sequence of steps.
87 *
88 * - Inherit from the singleton pattern using the CRTP as above:<br>
89 * @code
90 * class MySingletonExaple : public Singleton<MySingletonExample>{ ...}
91 * @endcode
92 * - Make constructor and destructor private to avoid creation or destruction from
93 * outside the class:<br>
94 * @code
95 * class MySingletonExaple : public Singleton<MySingletonExample>{
96 * private:
97 * MySingletonExample();
98 * ~MySingletonExample();
99 * ...}
100 * @endcode
101 * - give the inherited class access to the class internals using a friend declaration:<br>
102 * @code
103 * class MySingletonExaple : public Singleton<MySingletonExample>{
104 * friend class Singleton<MySingletonExample>; // don't forget the template parameters here
105 * private:
106 * MySingletonExample();
107 * ~MySingletonExample();
108 * ...}
109 * @endcode
110 *
111 * - include the file "Singleton_impl.hpp" that carries the implementation details of
112 * the singleton functions in your implementation file of the class.
113 * - make the compiler construct the template instantiations. For this you can use the defined
114 * keyword <code>CONSTRUCT_SINGLETON(name)</code> at any toplevel point in the implementation
115 * file:<br>
116 * @code
117 * void MySingletonExample::foo(){...}
118 * void MySingletonExample::bar(){...}
119 * CONSTRUCT_SINGLETON(MySingletonExample) // no ; after this
120 * @endcode
121 *
122 * <h3>Singleton with initialization parameters</h3>
123 *
124 * Sometimes it is necessary for a singleton to be passed some initilization parameters. For
125 * example the UIFactory mentioned above needs to know what kind of user interface it has to
126 * produce. Making a singleton that takes initialization parameters is only sligtly different
127 * from the steps lined out above. Here are all the differences:
128 *
129 * - pass an extra <code>false</code> to the template to deactivate the standard instantiation
130 * mechanism
131 * - write a method that handles the special parameters and instantiation. In this method you
132 * can use the <code>setInstance(T*)</code> method inherited from the singleton pattern to set
133 * the created instance. The <code>setInstance()</code> method will only work when the
134 * <code>false<code> template parameter has been set and produce errors otherwise.
135 *
136 */
137template <class T, bool _may_create=true>
138class Singleton
139{
140private:
141 /**
142 * simple auto_ptr that is used by Singleton template
143 *
144 * This ptr_t allows destruction of the object using a private destructor,
145 * when only the Singleton pattern is friend with the class
146 *
147 * All methods have similar sematics to auto_ptr
148 */
149 class ptr_t {
150 public:
151 ptr_t();
152 ptr_t(T* _content);
153 ~ptr_t();
154 T& operator*();
155 T* get();
156 void reset(T* _content);
157 void reset();
158 ptr_t& operator=(const ptr_t& rhs);
159 private:
160 mutable T* content;
161 };
162
163 /**
164 * This object handles the actual creation inside the singleton
165 *
166 * Using template specialization this will allways know what it can
167 * do or cannot do at compile time
168 */
169 template<class creator_T, bool creator_may_create>
170 struct creator_t {
171 inline static creator_T* make();
172 inline static void set(creator_T*&,creator_T*);
173 };
174
175 // specialization to allow fast creations
176
177 /**
178 * Specialized template that allows automatic construction only
179 */
180 template<class creator_T>
181 struct creator_t<creator_T,true>{
182 inline static creator_T* make(){
183 return new creator_T();
184 }
185
186 inline static void set(creator_T*&,creator_T*){
187 ASSERT(0, "Cannot set the Instance for a singleton of this type");
188 }
189 };
190
191 /**
192 * specialized template that allows setting only
193 */
194 template<class creator_T>
195 struct creator_t<creator_T,false>{
196 inline static creator_T* make(){
197 ASSERT(0, "Cannot create a singleton of this type directly");
198 return 0;
199 }
200 inline static void set(ptr_t& dest,creator_T* src){
201 dest.reset(src);
202 }
203 };
204
205 // this is used for creation
206 typedef creator_t<T,_may_create> creator; //< the creator used
207
208public:
209 // make the state of this singleton accessible
210 static const bool may_create=_may_create; //!< the type of singleton that we have
211
212 /**
213 * returns the instance of this Singleton as a reference
214 *
215 * If no Singleton exists at this point and we are allowed to create one
216 * a new one is created and stored inside the singleton
217 *
218 * If no automatic creation is allowed, make sure to create an instance first
219 * using the appropriate methods of the derived class. Otherwise this method
220 * would fail.
221 */
222 static T& getInstance();
223
224 /**
225 * returns the instance of this Singleton as a reference
226 *
227 * If no Singleton exists at this point and we are allowed to create one
228 * a new one is created and stored inside the singleton
229 *
230 * If no automatic creation is allowed, make sure to create an instance first
231 * using the appropriate methods of the derived class. Otherwise this method
232 * would fail.
233 */
234 static const T& getConstInstance();
235
236 /**
237 * returns the instance of this singleton as a pointer
238 *
239 * If no Singleton exists at this point and we are allowed to create one
240 * a new one is created and stored inside the singleton.
241 *
242 * If no automatic creation is allowed, make sure to create an instance first
243 * using the appropriate methods of the derived class. Otherwise this method
244 * would fail.
245 */
246 static T* getPointer();
247
248 /**
249 * returns the instance of this singleton as a pointer
250 *
251 * If no Singleton exists at this point and we are allowed to create one
252 * a new one is created and stored inside the singleton.
253 *
254 * If no automatic creation is allowed, make sure to create an instance first
255 * using the appropriate methods of the derived class. Otherwise this method
256 * would fail.
257 */
258 static const T* getConstPointer();
259
260 /**
261 * destroys the current instance of this singleton
262 */
263 static void purgeInstance();
264
265 /**
266 * destroys the current instance of the singleton and immidiately constructs
267 * a new one. Similar to using <code>purgeInstance()</code> and <code>getInstance()</code>
268 * but plays more nicely when observers are present. Especially the new instance is created
269 * before the old one is destroyed so observers can switch their targets, when they are notified
270 * of the destruction.
271 *
272 * If no automatic creation is allowed this method wont work.
273 */
274 static T& resetInstance();
275
276protected:
277 /**
278 * Method used to set the instance, when no automatic creation is allowed.
279 *
280 * Call this after the instantiation method in the derived class has created
281 * it's instance and want's the singleton mechanism to keep it around for later
282 * use.
283 *
284 * This method will always fail when automatic creation is enabled.
285 */
286 static void setInstance(T*);
287
288
289 /**
290 * empty constructor to allow creation of subclases
291 */
292 Singleton();
293
294private:
295 /**
296 * the copy constructor is private to avoid accidental copying of Singletons, for example
297 * when passing singletons to functions by value instead of by reference. If you
298 * need copying of singletons call the default constructor in the copy constructor
299 * of the derived object. The copyied object wont be known to the singleton mechanism.
300 */
301 Singleton(const Singleton&);
302
303 static boost::recursive_mutex instanceLock; //!< a lock for the pointer of the instance
304 static ptr_t theInstance; //!< the actual instance of the singleton
305};
306
307#endif /* SINGLETON_HPP_ */
Note: See TracBrowser for help on using the repository browser.