• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // (C) Copyright 2005 Matthias Troyer
2 // (C) Copyright 2006 Douglas Gregor <doug.gregor -at- gmail.com>
3 
4 // Use, modification and distribution is subject to the Boost Software
5 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
7 
8 //  Authors: Matthias Troyer
9 //           Douglas Gregor
10 
11 /** @file packed_iarchive.hpp
12  *
13  *  This header provides the facilities for packing Serializable data
14  *  types into a buffer using @c MPI_Pack. The buffers can then be
15  *  transmitted via MPI and then be unpacked either via the facilities
16  *  in @c packed_oarchive.hpp or @c MPI_Unpack.
17  */
18 #ifndef BOOST_MPI_PACKED_IARCHIVE_HPP
19 #define BOOST_MPI_PACKED_IARCHIVE_HPP
20 
21 #include <boost/mpi/datatype.hpp>
22 #include <boost/archive/detail/auto_link_archive.hpp>
23 #include <boost/archive/detail/common_iarchive.hpp>
24 #include <boost/archive/basic_archive.hpp>
25 #include <boost/mpi/detail/packed_iprimitive.hpp>
26 #include <boost/mpi/detail/binary_buffer_iprimitive.hpp>
27 #include <boost/serialization/string.hpp>
28 #include <boost/serialization/collection_size_type.hpp>
29 #include <boost/serialization/item_version_type.hpp>
30 #include <boost/assert.hpp>
31 
32 namespace boost { namespace mpi {
33 
34 #ifdef BOOST_MPI_HOMOGENEOUS
35   typedef binary_buffer_iprimitive iprimitive;
36 #else
37   typedef packed_iprimitive iprimitive;
38 #endif
39 
40 
41 /** @brief An archive that unpacks binary data from an MPI buffer.
42  *
43  *  The @c packed_oarchive class is an Archiver (as in the
44  *  Boost.Serialization library) that unpacks binary data from a
45  *  buffer received via MPI. It can operate on any Serializable data
46  *  type and will use the @c MPI_Unpack function of the underlying MPI
47  *  implementation to perform deserialization.
48  */
49 
50 class BOOST_MPI_DECL packed_iarchive
51   : public iprimitive
52   , public archive::detail::common_iarchive<packed_iarchive>
53 {
54 public:
55   /**
56    *  Construct a @c packed_iarchive to receive data over the given
57    *  MPI communicator and with an initial buffer.
58    *
59    *  @param comm The communicator over which this archive will be
60    *  received.
61    *
62    *  @param b A user-defined buffer that contains the binary
63    *  representation of serialized objects.
64    *
65    *  @param flags Control the serialization of the data types. Refer
66    *  to the Boost.Serialization documentation before changing the
67    *  default flags.
68    */
69 
packed_iarchive(MPI_Comm const & comm,buffer_type & b,unsigned int flags=boost::archive::no_header,int position=0)70   packed_iarchive(MPI_Comm const & comm, buffer_type & b, unsigned int flags = boost::archive::no_header, int position = 0)
71         : iprimitive(b,comm,position),
72           archive::detail::common_iarchive<packed_iarchive>(flags)
73         {}
74 
75   /**
76    *  Construct a @c packed_iarchive to receive data over the given
77    *  MPI communicator.
78    *
79    *  @param comm The communicator over which this archive will be
80    *  received.
81    *
82    *  @param flags Control the serialization of the data types. Refer
83    *  to the Boost.Serialization documentation before changing the
84    *  default flags.
85    */
86 
packed_iarchive(MPI_Comm const & comm,std::size_t s=0,unsigned int flags=boost::archive::no_header)87   packed_iarchive
88           ( MPI_Comm const & comm , std::size_t s=0,
89            unsigned int flags = boost::archive::no_header)
90          : iprimitive(internal_buffer_,comm)
91          , archive::detail::common_iarchive<packed_iarchive>(flags)
92          , internal_buffer_(s)
93         {}
94 
95   // Load everything else in the usual way, forwarding on to the Base class
96   template<class T>
load_override(T & x,mpl::false_)97   void load_override(T& x, mpl::false_)
98   {
99     archive::detail::common_iarchive<packed_iarchive>::load_override(x);
100   }
101 
102   // Load it directly using the primnivites
103   template<class T>
load_override(T & x,mpl::true_)104   void load_override(T& x, mpl::true_)
105   {
106     iprimitive::load(x);
107   }
108 
109   // Load all supported datatypes directly
110   template<class T>
load_override(T & x)111   void load_override(T& x)
112   {
113     typedef typename mpl::apply1<use_array_optimization
114       , BOOST_DEDUCED_TYPENAME remove_const<T>::type
115     >::type use_optimized;
116     load_override(x, use_optimized());
117   }
118 
119   // input archives need to ignore  the optional information
load_override(archive::class_id_optional_type &)120   void load_override(archive::class_id_optional_type & /*t*/){}
121 
load_override(archive::class_id_type & t)122   void load_override(archive::class_id_type & t){
123     int_least16_t x=0;
124     * this->This() >> x;
125     t = boost::archive::class_id_type(x);
126   }
127 
load_override(archive::version_type & t)128   void load_override(archive::version_type & t){
129     int_least8_t x=0;
130     * this->This() >> x;
131     t = boost::archive::version_type(x);
132   }
133 
load_override(archive::class_id_reference_type & t)134   void load_override(archive::class_id_reference_type & t){
135     load_override(static_cast<archive::class_id_type &>(t));
136   }
137 
load_override(archive::class_name_type & t)138   void load_override(archive::class_name_type & t)
139   {
140     std::string cn;
141     cn.reserve(BOOST_SERIALIZATION_MAX_KEY_SIZE);
142     * this->This() >> cn;
143     std::memcpy(t, cn.data(), cn.size());
144     // borland tweak
145     t.t[cn.size()] = '\0';
146   }
147 
148 private:
149   /// An internal buffer to be used when the user does not supply his
150   /// own buffer.
151   buffer_type internal_buffer_;
152 };
153 
154 } } // end namespace boost::mpi
155 
156 BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::mpi::packed_iarchive)
157 BOOST_SERIALIZATION_USE_ARRAY_OPTIMIZATION(boost::mpi::packed_iarchive)
158 
159 #endif // BOOST_MPI_PACKED_IARCHIVE_HPP
160