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