Learn » Examples » Program Example Serialize To File

One potential application for this approach is to generate a restart file for a simulation.

The full code for this example can be found here: examples/checkpoint_example_to_file.cc

Example source code:

#include <checkpoint/checkpoint.h>

#include <iostream>
#include <vector>

namespace checkpoint { namespace intrusive { namespace examples {

static constexpr int const u_val = 934;

// \struct MyTestType
// \brief Simple structure with two variables of built-in types
struct MyTestType {

  // \brief Default constructor
  //
  // The default constructor is needed for the (de)serialization.
  // (required for serialization)
  MyTestType() = default;

  // \brief Constructor with two parameters
  //
  // \param[in] Initial value for `a`
  // \param[in] Initial value for `b`
  //
  explicit MyTestType(int len) : u_(), len_(len)
  {
    u_.resize(len_);
    for (int i = 0; i < len_; ++i)
      u_[i] = u_val + i;
  }

  // \brief Templated function for serializing/deserializing
  // a variable of type `MyTestType`
  //
  // \tparam <Serializer> { Type for storing the serialized result }
  // \param[in,out] Variable for storing the serialized result
  //
  // \note The routine `serialize` is actually a two-way routine:
  // - it creates the serialized result `s` by combining
  //   the variables `u_` and `len_`; this creation phase is run
  //   when the status of the serializer `s` is `Packing`.
  // - it can extract from a serialized result `s` the values
  //   to place in the variables `u_` and `len_`; this extraction phase is run
  //   when the status of the serializer `s` is `Unpacking`.
  //
  template <typename Serializer>
  void serialize(Serializer& s) {
    s | u_;
    s | len_;
  }

  //
  // Friend functions
  //
  friend bool operator== (const MyTestType &c1, const MyTestType &c2);

  //
  // Variables
  //

  std::vector<double> u_;
  int len_ = 0;

};


bool operator==(const MyTestType &c1, const MyTestType &c2)
{
  if (c1.len_ != c2.len_)
    return false;
  bool isEqual = true;
  for (int i = 0; i < c1.len_; ++i) {
    if (c1.u_[i] != c2.u_[i]) {
      isEqual = false;
      break;
    }
  }
  return isEqual;
}

}}} // end namespace checkpoint::intrusive::examples


int main(int, char**) {
  using namespace magistrate::intrusive::examples;

  // Define a variable of custom type `MyTestType`
  MyTestType my_test_inst(11);

  // Call the serialization routine for the variable `my_test_inst`
  // The output is a unique pointer: `std::unique_ptr<SerializedInfo>`
  // (defined in `src/checkpoint_api.h`)
  magistrate::serializeToFile(my_test_inst, "hello.txt");

  //
  // De-serializes from the file an object of type 'MyTestType'
  // out will be an object of type 'std::unique_ptr<MyTestType>'
  //
  auto out = magistrate::deserializeFromFile<MyTestType>("hello.txt");

  if (my_test_inst == *out)
    std::cout << " Serialization / Deserialization from file worked. \n";
  else
    std::cout << " Serialization / Deserialization from file failed. \n";

  //
  // Another option is to de-serialize into an existing object of type 'MyTestType'
  //
  MyTestType out_2;

  //
  // Here 'out_2' will contain an empty vector and an integer 'len_' set to 0.
  //

  magistrate::deserializeInPlaceFromFile<MyTestType>("hello.txt", &out_2);

  //
  // Now 'out_2' will contain:
  // - a resized vector filled with the values stored in the file;
  // - an integer 'len_' equal to the length of the vector stored in the file.
  //

  if (my_test_inst == out_2)
    std::cout << " Deserialization in-place from file worked. \n";
  else
    std::cout << " Deserialization in-place from file failed. \n";

  return 0;
}