source: src/Patterns/Singleton.hpp@ 6d574a

Action_Thermostats Add_AtomRandomPerturbation Add_FitFragmentPartialChargesAction Add_RotateAroundBondAction Add_SelectAtomByNameAction Added_ParseSaveFragmentResults AddingActions_SaveParseParticleParameters Adding_Graph_to_ChangeBondActions Adding_MD_integration_tests Adding_ParticleName_to_Atom Adding_StructOpt_integration_tests AtomFragments Automaking_mpqc_open AutomationFragmentation_failures Candidate_v1.5.4 Candidate_v1.6.0 Candidate_v1.6.1 ChangeBugEmailaddress ChangingTestPorts ChemicalSpaceEvaluator CombiningParticlePotentialParsing Combining_Subpackages Debian_Package_split Debian_package_split_molecuildergui_only Disabling_MemDebug Docu_Python_wait EmpiricalPotential_contain_HomologyGraph EmpiricalPotential_contain_HomologyGraph_documentation Enable_parallel_make_install Enhance_userguide Enhanced_StructuralOptimization Enhanced_StructuralOptimization_continued Example_ManyWaysToTranslateAtom Exclude_Hydrogens_annealWithBondGraph FitPartialCharges_GlobalError Fix_BoundInBox_CenterInBox_MoleculeActions Fix_ChargeSampling_PBC Fix_ChronosMutex Fix_FitPartialCharges Fix_FitPotential_needs_atomicnumbers Fix_ForceAnnealing Fix_IndependentFragmentGrids Fix_ParseParticles Fix_ParseParticles_split_forward_backward_Actions Fix_PopActions Fix_QtFragmentList_sorted_selection Fix_Restrictedkeyset_FragmentMolecule Fix_StatusMsg Fix_StepWorldTime_single_argument Fix_Verbose_Codepatterns Fix_fitting_potentials Fixes ForceAnnealing_goodresults ForceAnnealing_oldresults ForceAnnealing_tocheck ForceAnnealing_with_BondGraph ForceAnnealing_with_BondGraph_continued ForceAnnealing_with_BondGraph_continued_betteresults ForceAnnealing_with_BondGraph_contraction-expansion FragmentAction_writes_AtomFragments FragmentMolecule_checks_bonddegrees GeometryObjects Gui_Fixes Gui_displays_atomic_force_velocity ImplicitCharges IndependentFragmentGrids IndependentFragmentGrids_IndividualZeroInstances IndependentFragmentGrids_IntegrationTest IndependentFragmentGrids_Sole_NN_Calculation JobMarket_RobustOnKillsSegFaults JobMarket_StableWorkerPool JobMarket_unresolvable_hostname_fix MoreRobust_FragmentAutomation ODR_violation_mpqc_open PartialCharges_OrthogonalSummation PdbParser_setsAtomName PythonUI_with_named_parameters QtGui_reactivate_TimeChanged_changes Recreated_GuiChecks Rewrite_FitPartialCharges RotateToPrincipalAxisSystem_UndoRedo SaturateAtoms_findBestMatching SaturateAtoms_singleDegree StoppableMakroAction Subpackage_CodePatterns Subpackage_JobMarket Subpackage_LinearAlgebra Subpackage_levmar Subpackage_mpqc_open Subpackage_vmg Switchable_LogView ThirdParty_MPQC_rebuilt_buildsystem TrajectoryDependenant_MaxOrder TremoloParser_IncreasedPrecision TremoloParser_MultipleTimesteps TremoloParser_setsAtomName Ubuntu_1604_changes stable
Last change on this file since 6d574a was 6d574a, checked in by Tillmann Crueger <crueger@…>, 15 years ago

Replaced several old-style asserts with more usable ASSERTs

  • 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 "Helpers/Assert.hpp"
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 */
133template <class T, bool _may_create=true>
134class Singleton
135{
136private:
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 return 0;
195 }
196 inline static void set(ptr_t& dest,creator_T* src){
197 dest.reset(src);
198 }
199 };
200
201 // this is used for creation
202 typedef creator_t<T,_may_create> creator; //< the creator used
203
204public:
205 // make the state of this singleton accessible
206 static const bool may_create=_may_create; //!< the type of singleton that we have
207
208 /**
209 * returns the instance of this Singleton as a reference
210 *
211 * If no Singleton exists at this point and we are allowed to create one
212 * a new one is created and stored inside the singleton
213 *
214 * If no automatic creation is allowed, make sure to create an instance first
215 * using the appropriate methods of the derived class. Otherwise this method
216 * would fail.
217 */
218 static T& getInstance();
219
220 /**
221 * returns the instance of this singleton as a pointer
222 *
223 * If no Singleton exists at this point and we are allowed to create one
224 * a new one is created and stored inside the singleton.
225 *
226 * If no automatic creation is allowed, make sure to create an instance first
227 * using the appropriate methods of the derived class. Otherwise this method
228 * would fail.
229 */
230 static T* getPointer();
231
232 /**
233 * destroys the current instance of this singleton
234 */
235 static void purgeInstance();
236
237 /**
238 * destroys the current instance of the singleton and immidiately constructs
239 * a new one. Similar to using <code>purgeInstance()</code> and <code>getInstance()</code>
240 * but plays more nicely when observers are present. Especially the new instance is created
241 * before the old one is destroyed so observers can switch their targets, when they are notified
242 * of the destruction.
243 *
244 * If no automatic creation is allowed this method wont work.
245 */
246 static T& resetInstance();
247
248protected:
249 /**
250 * Method used to set the instance, when no automatic creation is allowed.
251 *
252 * Call this after the instantiation method in the derived class has created
253 * it's instance and want's the singleton mechanism to keep it around for later
254 * use.
255 *
256 * This method will always fail when automatic creation is enabled.
257 */
258 static void setInstance(T*);
259
260
261 /**
262 * empty constructor to allow creation of subclases
263 */
264 Singleton();
265
266private:
267 /**
268 * the copy constructor is private to avoid accidental copying of Singletons, for example
269 * when passing singletons to functions by value instead of by reference. If you
270 * need copying of singletons call the default constructor in the copy constructor
271 * of the derived object. The copyied object wont be known to the singleton mechanism.
272 */
273 Singleton(const Singleton&);
274
275 static boost::recursive_mutex instanceLock; //!< a lock for the pointer of the instance
276 static ptr_t theInstance; //!< the actual instance of the singleton
277};
278
279#endif /* SINGLETON_HPP_ */
Note: See TracBrowser for help on using the repository browser.