source: src/Patterns/Singleton.hpp@ 9098f9

Last change on this file since 9098f9 was 9098f9, checked in by Frederik Heber <heber@…>, 15 years ago

All include files go into folder CodePatterns.

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