| 1 | /*
 | 
|---|
| 2 |  * Project: MoleCuilder
 | 
|---|
| 3 |  * Description: creates and alters molecular systems
 | 
|---|
| 4 |  * Copyright (C)  2010 University of Bonn. All rights reserved.
 | 
|---|
| 5 |  * Please see the LICENSE file or "Copyright notice" in builder.cpp for details.
 | 
|---|
| 6 |  */
 | 
|---|
| 7 | 
 | 
|---|
| 8 | /**
 | 
|---|
| 9 |  * \file serialization.dox
 | 
|---|
| 10 |  *
 | 
|---|
| 11 |  *  Here, we explain what serialization is and how it is used within MoleCuilder.
 | 
|---|
| 12 |  *
 | 
|---|
| 13 |  * Created on: Oct 11, 2011
 | 
|---|
| 14 |  *    Author: heber
 | 
|---|
| 15 |  */
 | 
|---|
| 16 | 
 | 
|---|
| 17 | /** \page serialization Serialization
 | 
|---|
| 18 |  *
 | 
|---|
| 19 |  *  Serialization is a mighty concept. The is only possible within an object-
 | 
|---|
| 20 |  *  oriented framework. The member variables of a class make up its internal
 | 
|---|
| 21 |  *  state. By storing this state, creating another instance and restoring
 | 
|---|
| 22 |  *  the variables to this state, we may in essence clone the instance. However,
 | 
|---|
| 23 |  *  we obtain additional control as to the moment of restoration because the
 | 
|---|
| 24 |  *  internal state is stored temporarily. To allow for this storage all of
 | 
|---|
| 25 |  *  these variables have to be \e serialized.
 | 
|---|
| 26 |  *
 | 
|---|
| 27 |  *  Serialization refers to putting one after another into a writable form
 | 
|---|
| 28 |  *  (e.g. convert to string and write into a stringstream) and eventually
 | 
|---|
| 29 |  *  in reverse order to read them one by one from this writable form and
 | 
|---|
| 30 |  *  cast them back into their original type.
 | 
|---|
| 31 |  *
 | 
|---|
| 32 |  *  Here, this is done via boost::serialization.
 | 
|---|
| 33 |  *
 | 
|---|
| 34 |  *  \attention The serialization headers do not mingle well with \b MemDebug.hpp.
 | 
|---|
| 35 |  *  Hence, place them before MemDebug.hpp as they do funny stuff with the
 | 
|---|
| 36 |  *  new() operator.
 | 
|---|
| 37 |  *
 | 
|---|
| 38 |  *  Serialization is so powerful because the stored state can be stored to
 | 
|---|
| 39 |  *  disk, transfered to another thread or even to another computer. If received
 | 
|---|
| 40 |  *  by a compatible code, the instance is recreated and computation can be
 | 
|---|
| 41 |  *  continued elsewhere.
 | 
|---|
| 42 |  *
 | 
|---|
| 43 |  *  For the moment we use it for creating an undo state within the Action's.
 | 
|---|
| 44 |  *  I.e. we store the state of all instances that are modified by an Action's
 | 
|---|
| 45 |  *  doings and may in Action::performUndo() just re-create the unmodified
 | 
|---|
| 46 |  *  instance by loading them from the serializing archive.
 | 
|---|
| 47 |  *
 | 
|---|
| 48 |  *  \section serialization-add How to make your class serializable.
 | 
|---|
| 49 |  *
 | 
|---|
| 50 |  *  \subsection serialization-add-simple The simple case
 | 
|---|
| 51 |  *
 | 
|---|
| 52 |  *  All you need to do with your newly created class foo is this:
 | 
|---|
| 53 |  *  \code
 | 
|---|
| 54 |  *  class foo {
 | 
|---|
| 55 |  *  ...
 | 
|---|
| 56 |  *  private:
 | 
|---|
| 57 |  *    friend class boost::serialization::access;
 | 
|---|
| 58 |  *    template<class Archive>
 | 
|---|
| 59 |  *    void serialize(Archive & ar, const unsigned int version) const
 | 
|---|
| 60 |  *    {
 | 
|---|
| 61 |  *      ar & content;
 | 
|---|
| 62 |  *    }
 | 
|---|
| 63 |  *    ...
 | 
|---|
| 64 |  *    double content;
 | 
|---|
| 65 |  *  };
 | 
|---|
| 66 |  *  \endcode
 | 
|---|
| 67 |  *  This will implement a serialization function for both directions for the
 | 
|---|
| 68 |  *  member variable content. I.e. we may now store a class instance as this:
 | 
|---|
| 69 |  *  \code
 | 
|---|
| 70 |  *  #include <boost/archive/text_oarchive.hpp>
 | 
|---|
| 71 |  *  std::stringstream stream;
 | 
|---|
| 72 |  *  boost::archive::text_oarchive oa(stream);
 | 
|---|
| 73 |  *  oa << diagonal;
 | 
|---|
| 74 |  *  \endcode
 | 
|---|
| 75 |  *  This will store the state of the class in the stringstream \a stream.
 | 
|---|
| 76 |  *  Getting the instance back is then as easy as
 | 
|---|
| 77 |  *  \code
 | 
|---|
| 78 |  *  #include <boost/archive/text_iarchive.hpp>
 | 
|---|
| 79 |  *  boost::archive::text_iarchive ia(stream);
 | 
|---|
| 80 |  *  RealSpaceMatrix *newm;
 | 
|---|
| 81 |  *  ia >> newm;
 | 
|---|
| 82 |  *  \endcode
 | 
|---|
| 83 |  *
 | 
|---|
| 84 |  *  \subsection serialization-add-complicated The more complicated case
 | 
|---|
| 85 |  *
 | 
|---|
| 86 |  *  It gets trickier when load and store need to be done differently, e.h.
 | 
|---|
| 87 |  *  \code
 | 
|---|
| 88 |  *  class foo {
 | 
|---|
| 89 |  *  ...
 | 
|---|
| 90 |  *  private:
 | 
|---|
| 91 |  *    friend class boost::serialization::access;
 | 
|---|
| 92 |  *    // serialization
 | 
|---|
| 93 |  *    template<class Archive>
 | 
|---|
| 94 |  *    void save(Archive & ar, const unsigned int version) const
 | 
|---|
| 95 |  *    {
 | 
|---|
| 96 |  *      ar & content;
 | 
|---|
| 97 |  *    }
 | 
|---|
| 98 |  *    template<class Archive>
 | 
|---|
| 99 |  *    void load(Archive & ar, const unsigned int version)
 | 
|---|
| 100 |  *    {
 | 
|---|
| 101 |  *      ar & content;
 | 
|---|
| 102 |  *      createViews();
 | 
|---|
| 103 |  *    }
 | 
|---|
| 104 |  *    BOOST_SERIALIZATION_SPLIT_MEMBER()
 | 
|---|
| 105 |  *    ...
 | 
|---|
| 106 |  *  }
 | 
|---|
| 107 |  *  \endcode
 | 
|---|
| 108 |  *  Here, we split serialize() function into distinct load() and save() because
 | 
|---|
| 109 |  *  we have to call an additional function to fully re-store the instance, i.e.
 | 
|---|
| 110 |  *  it creates some internal reference arrays (Views) in a specific manner.
 | 
|---|
| 111 |  *
 | 
|---|
| 112 |  *  The serialize functions can also be added externally, i.e. outside of the
 | 
|---|
| 113 |  *  scope of the class, but can then access only public members (except we
 | 
|---|
| 114 |  *  again make it a friend).
 | 
|---|
| 115 |  *
 | 
|---|
| 116 |  *  \subsection serialization-important notes Some important notes
 | 
|---|
| 117 |  *
 | 
|---|
| 118 |  *  There are a few things that one needs to be aware of: Otherwise easily
 | 
|---|
| 119 |  *  a stupid mistake is introduced that is trivial once understand but hard
 | 
|---|
| 120 |  *  to find otherwise. This is especially so because compiler errors with
 | 
|---|
| 121 |  *  respect to the serialization part are always length (whole page) and
 | 
|---|
| 122 |  *  very hard to read:
 | 
|---|
| 123 |  *  \li Always obtain the same type from an archive that you put into it!
 | 
|---|
| 124 |  *    If it's been an instance, get an instance, not a ref(&) or a pointer(*)
 | 
|---|
| 125 |  *    and also the other way round.
 | 
|---|
| 126 |  *  \li boost::serialization always uses the default constructor of your class
 | 
|---|
| 127 |  *    that is afterwards filled with state information stored. If your default
 | 
|---|
| 128 |  *    constructor is unusable, something goes wrong here. There are two ways
 | 
|---|
| 129 |  *    out:
 | 
|---|
| 130 |  *    -# Write a private default constructor. Also you might have to split
 | 
|---|
| 131 |  *      serialize() into load() and save() and do some additional stuff in
 | 
|---|
| 132 |  *      load().
 | 
|---|
| 133 |  *    -# one can write save_construct_data() and load_construct_data() directly
 | 
|---|
| 134 |  *      as is explained in the boost::serialization documentation on
 | 
|---|
| 135 |  *      constructors (as of 1.47).
 | 
|---|
| 136 |  *  \li Const members are a problem as they can only be written during the
 | 
|---|
| 137 |  *    constructor and as always the default cstor is used ... however, wiggle
 | 
|---|
| 138 |  *    around by casting it to non-const, e.g.
 | 
|---|
| 139 |  *    \code
 | 
|---|
| 140 |  *    const foo foo_instance;
 | 
|---|
| 141 |  *    ...
 | 
|---|
| 142 |  *    const_cast<foo &>(foo_instance);
 | 
|---|
| 143 |  *    \endcode
 | 
|---|
| 144 |  *    Alternatively, you could place const variables in an extra class (and
 | 
|---|
| 145 |  *    non-const there), make them available only via a getter. Hence, they
 | 
|---|
| 146 |  *    would still be const in your main class but could be serialized without
 | 
|---|
| 147 |  *    any trouble.
 | 
|---|
| 148 |  *  \li When you want to serialize a derived class, also the base class state
 | 
|---|
| 149 |  *    has to be serialized, this is done via
 | 
|---|
| 150 |  *    \code
 | 
|---|
| 151 |  *    boost::serialization::base_object<base type>(*this);
 | 
|---|
| 152 |  *    \endcode
 | 
|---|
| 153 |  *
 | 
|---|
| 154 |  * 
 | 
|---|
| 155 |  * \date 2011-11-01
 | 
|---|
| 156 |  */
 | 
|---|