Changeset c3dbe0 for src/Patterns


Ignore:
Timestamp:
Mar 11, 2010, 4:53:08 PM (15 years ago)
Author:
Tillmann Crueger <crueger@…>
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
Message:

Improved documentation for Singleton

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Patterns/Singleton.hpp

    r0f6f3a rc3dbe0  
    1616/**
    1717 * 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 *
    18132 */
    19133template <class T, bool _may_create=true>
     
    21135{
    22136private:
    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   */
    25145  class ptr_t {
    26146  public:
     
    38158
    39159  /**
    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
    41164   */
    42165  template<class creator_T, bool creator_may_create>
    43166  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*);
    46169  };
    47170
    48171  // specialization to allow fast creations
    49172
     173  /**
     174   * Specialized template that allows automatic construction only
     175   */
    50176  template<class creator_T>
    51177  struct creator_t<creator_T,true>{
    52     static creator_T* make(){
     178    inline static creator_T* make(){
    53179      return new creator_T();
    54180    }
    55181
    56     static void set(creator_T*&,creator_T*){
     182    inline static void set(creator_T*&,creator_T*){
    57183      assert(0 && "Cannot set the Instance for a singleton of this type");
    58184    }
    59185  };
    60186
     187  /**
     188   * specialized template that allows setting only
     189   */
    61190  template<class creator_T>
    62191  struct creator_t<creator_T,false>{
    63     static creator_T* make(){
     192    inline static creator_T* make(){
    64193      assert(0 && "Cannot create a singleton of this type directly");
    65194    }
    66     static void set(ptr_t& dest,creator_T* src){
     195    inline static void set(ptr_t& dest,creator_T* src){
    67196      dest.reset(src);
    68197    }
    69198  };
    70199
     200  // this is used for creation
     201  typedef creator_t<T,_may_create> creator; //< the creator used
     202
    71203public:
    72 
    73204  // 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   */
    79217  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   */
    80229  static T* getPointer();
    81230
     231  /**
     232   * destroys the current instance of this singleton
     233   */
    82234  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   */
    83245  static T&   resetInstance();
    84246
     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   */
    85257  static void setInstance(T*);
    86 protected:
    87   // constructor accessible by subclasses
     258
     259
     260  /**
     261   * empty constructor to allow creation of subclases
     262   */
    88263  Singleton();
    89264
    90265private:
    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   */
    92272  Singleton(const Singleton&);
    93273
    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
    96276};
    97277
Note: See TracChangeset for help on using the changeset viewer.