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 <cassert>
|
---|
12 | #include <boost/thread.hpp>
|
---|
13 |
|
---|
14 | #include "defs.hpp"
|
---|
15 |
|
---|
16 | /**
|
---|
17 | * This template produces the generic singleton pattern using the CRTP idiom.
|
---|
18 | *
|
---|
19 | * <h1> Singleton Howto </h1>
|
---|
20 | * <h2> Introduction </h2>
|
---|
21 | *
|
---|
22 | * A Singleton is a class of which there can only be a single Object in the programm. It is
|
---|
23 | * described as an design-pattern in Gof:96 (the famous design-pattern book). In the
|
---|
24 | * molecuilder there are so far several Singletons serving a wide range of purposes:
|
---|
25 | *
|
---|
26 | * - the World, which handles all atoms, molecules and bonds
|
---|
27 | * - the ActionRegistry, which stores all created actions by name for later use
|
---|
28 | * - the UIFactory, which is an AbstractFactory (another design-pattern from Gof:96) and
|
---|
29 | * handles all creation of gui elements to ensure a single type throughout the programm
|
---|
30 | * - the logger and errorLogger classes, that can be used to output messages on the screen
|
---|
31 | * depending on certain conditions
|
---|
32 | *
|
---|
33 | * Because those classes can only be instantiated once you cannot simply call <code>new World()</code>
|
---|
34 | * or <code>delete</code> on them. Rather they have to be constructed and accessed using the singleton
|
---|
35 | * mechanism. This mechanism consists of four static functions (and a fifth that is used internally,
|
---|
36 | * but we will get to that later). These functions are:
|
---|
37 | *
|
---|
38 | * - <code>Singleton& Singleton::getInstance()</code> : returns the instance of the singleton as
|
---|
39 | * a reference
|
---|
40 | * - <code>Singleton* Singleton::getPointer()</code> : returns the instance of the singleton as a
|
---|
41 | * pointer
|
---|
42 | * - <code>void Singleton::purgeInstance()</code> : destroys the single Instance of the singleton
|
---|
43 | * - <code>Singleton& Singleton::resetInstance()</code> : resets the Singleton, i.e. destroys the
|
---|
44 | * old instance and creates a new one
|
---|
45 | *
|
---|
46 | * If you need the instance of the singleton it is usually fine just to use one off the accessor
|
---|
47 | * functions (i.e. <code>getInstance()</code> or <code>getPointer()</code>. Any creation of the
|
---|
48 | * Singleton is then handled by these functions, so that the same object will be returned whenever
|
---|
49 | * one of these functions is called. This easy process is true for most singletons you will need
|
---|
50 | * to use. The only special singleton is the UIFactory.
|
---|
51 | *
|
---|
52 | * <h3>Special functions of the UIFactory</h3>
|
---|
53 | *
|
---|
54 | * If you simply call the <code>getInstance()</code> method of the UIFactory class the program
|
---|
55 | * will crash. This happens, because the UIFactory in itself is abstract and needs to know what
|
---|
56 | * kind of user interface it should produce later on. You need to tell the class the type of UI
|
---|
57 | * using the void <code>UIFactory::makeUserInterface(InterfaceTypes type)</code> method. This will
|
---|
58 | * also take care of creating the sole instance, so that the accessor functions will work afterwards.
|
---|
59 | * What this also means is, that you cannot <code>reset()</code> the UIFactory, because at that
|
---|
60 | * point it wont know anymore what to construct. A sequence of <code>UIFactory::purgeInstance()</code>,
|
---|
61 | * <code>UIFactory::makeUserInterface()</code> and <code>UIFactory::getInstance()</code> will work
|
---|
62 | * though.
|
---|
63 | *
|
---|
64 | * In order to make life easier and propagate changes to the singleton mechanism to all those
|
---|
65 | * classes, there is a simple framework class that can be used to make any other class a
|
---|
66 | * singleton through inheritance. This class can be found in the Pattern directory.
|
---|
67 | *
|
---|
68 | * <h2>How to make a class Singleton</h2>
|
---|
69 | *
|
---|
70 | * Most of the time you will only need singletons that don't require additional
|
---|
71 | * information for creation. So I will cover the basic case for constructing singletons
|
---|
72 | * first and then explain what has to be changed to make it accept special parameters.
|
---|
73 | * Singletons are created by inheriting from the <code>Singleton<class T></code> template
|
---|
74 | * using the Curiously recurring template pattern (CRTP). What this means is, that the
|
---|
75 | * class they inherit from carries the inheriting class as a template parameter. For example
|
---|
76 | * <code>class MySingletonExaple : public Singleton<MySingletonExample>{...}</code>. If you
|
---|
77 | * want to know more about this idiom have a look at the
|
---|
78 | * <A HREF="http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern">wikipedia
|
---|
79 | * page for this idiom</A>, but don't worry if you don't quite get how this works for now, for
|
---|
80 | * the use of the singleton framework this is not important.
|
---|
81 | *
|
---|
82 | * If you want to make a class a singleton you can use the following sequence of steps.
|
---|
83 | *
|
---|
84 | * - Inherit from the singleton pattern using the CRTP as above:<br>
|
---|
85 | * @code
|
---|
86 | * class MySingletonExaple : public Singleton<MySingletonExample>{ ...}
|
---|
87 | * @endcode
|
---|
88 | * - Make constructor and destructor private to avoid creation or destruction from
|
---|
89 | * outside the class:<br>
|
---|
90 | * @code
|
---|
91 | * class MySingletonExaple : public Singleton<MySingletonExample>{
|
---|
92 | * private:
|
---|
93 | * MySingletonExample();
|
---|
94 | * ~MySingletonExample();
|
---|
95 | * ...}
|
---|
96 | * @endcode
|
---|
97 | * - give the inherited class access to the class internals using a friend declaration:<br>
|
---|
98 | * @code
|
---|
99 | * class MySingletonExaple : public Singleton<MySingletonExample>{
|
---|
100 | * friend class Singleton<MySingletonExample>; // don't forget the template parameters here
|
---|
101 | * private:
|
---|
102 | * MySingletonExample();
|
---|
103 | * ~MySingletonExample();
|
---|
104 | * ...}
|
---|
105 | * @endcode
|
---|
106 | *
|
---|
107 | * - include the file "Patterns/Singleton_impl.hpp" that carries the implementation details of
|
---|
108 | * the singleton functions in your implementation file of the class.
|
---|
109 | * - make the compiler construct the template instantiations. For this you can use the defined
|
---|
110 | * keyword <code>CONSTRUCT_SINGLETON(name)</code> at any toplevel point in the implementation
|
---|
111 | * file:<br>
|
---|
112 | * @code
|
---|
113 | * void MySingletonExample::foo(){...}
|
---|
114 | * void MySingletonExample::bar(){...}
|
---|
115 | * CONSTRUCT_SINGLETON(MySingletonExample) // no ; after this
|
---|
116 | * @endcode
|
---|
117 | *
|
---|
118 | * <h3>Singleton with initialization parameters</h3>
|
---|
119 | *
|
---|
120 | * Sometimes it is necessary for a singleton to be passed some initilization parameters. For
|
---|
121 | * example the UIFactory mentioned above needs to know what kind of user interface it has to
|
---|
122 | * produce. Making a singleton that takes initialization parameters is only sligtly different
|
---|
123 | * from the steps lined out above. Here are all the differences:
|
---|
124 | *
|
---|
125 | * - pass an extra <code>false</code> to the template to deactivate the standard instantiation
|
---|
126 | * mechanism
|
---|
127 | * - write a method that handles the special parameters and instantiation. In this method you
|
---|
128 | * can use the <code>setInstance(T*)</code> method inherited from the singleton pattern to set
|
---|
129 | * the created instance. The <code>setInstance()</code> method will only work when the
|
---|
130 | * <code>false<code> template parameter has been set and produce errors otherwise.
|
---|
131 | *
|
---|
132 | */
|
---|
133 | template <class T, bool _may_create=true>
|
---|
134 | class Singleton
|
---|
135 | {
|
---|
136 | private:
|
---|
137 | /**
|
---|
138 | * simple auto_ptr that is used by Singleton template
|
---|
139 | *
|
---|
140 | * This ptr_t allows destruction of the object using a private destructor,
|
---|
141 | * when only the Singleton pattern is friend with the class
|
---|
142 | *
|
---|
143 | * All methods have similar sematics to auto_ptr
|
---|
144 | */
|
---|
145 | class ptr_t {
|
---|
146 | public:
|
---|
147 | ptr_t();
|
---|
148 | ptr_t(T* _content);
|
---|
149 | ~ptr_t();
|
---|
150 | T& operator*();
|
---|
151 | T* get();
|
---|
152 | void reset(T* _content);
|
---|
153 | void reset();
|
---|
154 | ptr_t& operator=(const ptr_t& rhs);
|
---|
155 | private:
|
---|
156 | mutable T* content;
|
---|
157 | };
|
---|
158 |
|
---|
159 | /**
|
---|
160 | * This object handles the actual creation inside the singleton
|
---|
161 | *
|
---|
162 | * Using template specialization this will allways know what it can
|
---|
163 | * do or cannot do at compile time
|
---|
164 | */
|
---|
165 | template<class creator_T, bool creator_may_create>
|
---|
166 | struct creator_t {
|
---|
167 | inline static creator_T* make();
|
---|
168 | inline static void set(creator_T*&,creator_T*);
|
---|
169 | };
|
---|
170 |
|
---|
171 | // specialization to allow fast creations
|
---|
172 |
|
---|
173 | /**
|
---|
174 | * Specialized template that allows automatic construction only
|
---|
175 | */
|
---|
176 | template<class creator_T>
|
---|
177 | struct creator_t<creator_T,true>{
|
---|
178 | inline static creator_T* make(){
|
---|
179 | return new creator_T();
|
---|
180 | }
|
---|
181 |
|
---|
182 | inline static void set(creator_T*&,creator_T*){
|
---|
183 | assert(0 && "Cannot set the Instance for a singleton of this type");
|
---|
184 | }
|
---|
185 | };
|
---|
186 |
|
---|
187 | /**
|
---|
188 | * specialized template that allows setting only
|
---|
189 | */
|
---|
190 | template<class creator_T>
|
---|
191 | struct creator_t<creator_T,false>{
|
---|
192 | inline static creator_T* make(){
|
---|
193 | assert(0 && "Cannot create a singleton of this type directly");
|
---|
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 |
|
---|
203 | public:
|
---|
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 |
|
---|
247 | protected:
|
---|
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 |
|
---|
265 | private:
|
---|
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_ */
|
---|