Changeset c3dbe0 for src/Patterns
- Timestamp:
- Mar 11, 2010, 4:53:08 PM (15 years ago)
- Branches:
- 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
- Children:
- ead4e6
- Parents:
- 0f6f3a
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Patterns/Singleton.hpp
r0f6f3a rc3dbe0 16 16 /** 17 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 * 18 132 */ 19 133 template <class T, bool _may_create=true> … … 21 135 { 22 136 private: 23 // simple auto_ptr that allows destruction of the object 24 // std::auto_ptr cannot do this because the destructor of T is ussually 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 */ 25 145 class ptr_t { 26 146 public: … … 38 158 39 159 /** 40 * this creator checks what it may or may not do 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 41 164 */ 42 165 template<class creator_T, bool creator_may_create> 43 166 struct creator_t { 44 static creator_T* make();45 static void set(creator_T*&,creator_T*);167 inline static creator_T* make(); 168 inline static void set(creator_T*&,creator_T*); 46 169 }; 47 170 48 171 // specialization to allow fast creations 49 172 173 /** 174 * Specialized template that allows automatic construction only 175 */ 50 176 template<class creator_T> 51 177 struct creator_t<creator_T,true>{ 52 static creator_T* make(){178 inline static creator_T* make(){ 53 179 return new creator_T(); 54 180 } 55 181 56 static void set(creator_T*&,creator_T*){182 inline static void set(creator_T*&,creator_T*){ 57 183 assert(0 && "Cannot set the Instance for a singleton of this type"); 58 184 } 59 185 }; 60 186 187 /** 188 * specialized template that allows setting only 189 */ 61 190 template<class creator_T> 62 191 struct creator_t<creator_T,false>{ 63 static creator_T* make(){192 inline static creator_T* make(){ 64 193 assert(0 && "Cannot create a singleton of this type directly"); 65 194 } 66 static void set(ptr_t& dest,creator_T* src){195 inline static void set(ptr_t& dest,creator_T* src){ 67 196 dest.reset(src); 68 197 } 69 198 }; 70 199 200 // this is used for creation 201 typedef creator_t<T,_may_create> creator; //< the creator used 202 71 203 public: 72 73 204 // make the state of this singleton accessible 74 static const bool may_create=_may_create; 75 76 // this is used for creation 77 typedef creator_t<T,_may_create> creator; 78 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 */ 79 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 */ 80 229 static T* getPointer(); 81 230 231 /** 232 * destroys the current instance of this singleton 233 */ 82 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 */ 83 245 static T& resetInstance(); 84 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 */ 85 257 static void setInstance(T*); 86 protected: 87 // constructor accessible by subclasses 258 259 260 /** 261 * empty constructor to allow creation of subclases 262 */ 88 263 Singleton(); 89 264 90 265 private: 91 // private copy constructor to avoid unintended copying 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 */ 92 272 Singleton(const Singleton&); 93 273 94 static boost::recursive_mutex instanceLock; 95 static ptr_t theInstance; 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 96 276 }; 97 277
Note:
See TracChangeset
for help on using the changeset viewer.