annotate DEPENDENCIES/generic/include/boost/mpi/skeleton_and_content.hpp @ 125:34e428693f5d vext

Vext -> Repoint
author Chris Cannam
date Thu, 14 Jun 2018 11:15:39 +0100
parents 2665513ce2d3
children
rev   line source
Chris@16 1 // (C) Copyright 2005 Matthias Troyer
Chris@16 2 // (C) Copyright 2006 Douglas Gregor <doug.gregor -at gmail.com>
Chris@16 3
Chris@16 4 // Use, modification and distribution is subject to the Boost Software
Chris@16 5 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
Chris@16 6 // http://www.boost.org/LICENSE_1_0.txt)
Chris@16 7
Chris@16 8 // Authors: Matthias Troyer
Chris@16 9 // Douglas Gregor
Chris@16 10
Chris@16 11 /** @file skeleton_and_content.hpp
Chris@16 12 *
Chris@16 13 * This header provides facilities that allow the structure of data
Chris@16 14 * types (called the "skeleton") to be transmitted and received
Chris@16 15 * separately from the content stored in those data types. These
Chris@16 16 * facilities are useful when the data in a stable data structure
Chris@16 17 * (e.g., a mesh or a graph) will need to be transmitted
Chris@16 18 * repeatedly. In this case, transmitting the skeleton only once
Chris@16 19 * saves both communication effort (it need not be sent again) and
Chris@16 20 * local computation (serialization need only be performed once for
Chris@16 21 * the content).
Chris@16 22 */
Chris@16 23 #ifndef BOOST_MPI_SKELETON_AND_CONTENT_HPP
Chris@16 24 #define BOOST_MPI_SKELETON_AND_CONTENT_HPP
Chris@16 25
Chris@16 26 #include <boost/mpi/config.hpp>
Chris@16 27 #include <boost/archive/detail/auto_link_archive.hpp>
Chris@16 28 #include <boost/mpi/packed_iarchive.hpp>
Chris@16 29 #include <boost/mpi/packed_oarchive.hpp>
Chris@16 30 #include <boost/mpi/detail/forward_skeleton_iarchive.hpp>
Chris@16 31 #include <boost/mpi/detail/forward_skeleton_oarchive.hpp>
Chris@16 32 #include <boost/mpi/detail/ignore_iprimitive.hpp>
Chris@16 33 #include <boost/mpi/detail/ignore_oprimitive.hpp>
Chris@16 34 #include <boost/shared_ptr.hpp>
Chris@16 35 #include <boost/archive/detail/register_archive.hpp>
Chris@16 36
Chris@16 37 namespace boost { namespace mpi {
Chris@16 38
Chris@16 39 /**
Chris@16 40 * @brief A proxy that requests that the skeleton of an object be
Chris@16 41 * transmitted.
Chris@16 42 *
Chris@16 43 * The @c skeleton_proxy is a lightweight proxy object used to
Chris@16 44 * indicate that the skeleton of an object, not the object itself,
Chris@16 45 * should be transmitted. It can be used with the @c send and @c recv
Chris@16 46 * operations of communicators or the @c broadcast collective. When a
Chris@16 47 * @c skeleton_proxy is sent, Boost.MPI generates a description
Chris@16 48 * containing the structure of the stored object. When that skeleton
Chris@16 49 * is received, the receiving object is reshaped to match the
Chris@16 50 * structure. Once the skeleton of an object as been transmitted, its
Chris@16 51 * @c content can be transmitted separately (often several times)
Chris@16 52 * without changing the structure of the object.
Chris@16 53 */
Chris@16 54 template <class T>
Chris@16 55 struct BOOST_MPI_DECL skeleton_proxy
Chris@16 56 {
Chris@16 57 /**
Chris@16 58 * Constructs a @c skeleton_proxy that references object @p x.
Chris@16 59 *
Chris@16 60 * @param x the object whose structure will be transmitted or
Chris@16 61 * altered.
Chris@16 62 */
Chris@16 63 skeleton_proxy(T& x)
Chris@16 64 : object(x)
Chris@16 65 {}
Chris@16 66
Chris@16 67 T& object;
Chris@16 68 };
Chris@16 69
Chris@16 70 /**
Chris@16 71 * @brief Create a skeleton proxy object.
Chris@16 72 *
Chris@16 73 * This routine creates an instance of the skeleton_proxy class. It
Chris@16 74 * will typically be used when calling @c send, @c recv, or @c
Chris@16 75 * broadcast, to indicate that only the skeleton (structure) of an
Chris@16 76 * object should be transmitted and not its contents.
Chris@16 77 *
Chris@16 78 * @param x the object whose structure will be transmitted.
Chris@16 79 *
Chris@16 80 * @returns a skeleton_proxy object referencing @p x
Chris@16 81 */
Chris@16 82 template <class T>
Chris@16 83 inline const skeleton_proxy<T> skeleton(T& x)
Chris@16 84 {
Chris@16 85 return skeleton_proxy<T>(x);
Chris@16 86 }
Chris@16 87
Chris@16 88 namespace detail {
Chris@16 89 /// @brief a class holding an MPI datatype
Chris@16 90 /// INTERNAL ONLY
Chris@16 91 /// the type is freed upon destruction
Chris@16 92 class BOOST_MPI_DECL mpi_datatype_holder : public boost::noncopyable
Chris@16 93 {
Chris@16 94 public:
Chris@16 95 mpi_datatype_holder()
Chris@16 96 : is_committed(false)
Chris@16 97 {}
Chris@16 98
Chris@16 99 mpi_datatype_holder(MPI_Datatype t, bool committed = true)
Chris@16 100 : d(t)
Chris@16 101 , is_committed(committed)
Chris@16 102 {}
Chris@16 103
Chris@16 104 void commit()
Chris@16 105 {
Chris@16 106 BOOST_MPI_CHECK_RESULT(MPI_Type_commit,(&d));
Chris@16 107 is_committed=true;
Chris@16 108 }
Chris@16 109
Chris@16 110 MPI_Datatype get_mpi_datatype() const
Chris@16 111 {
Chris@16 112 return d;
Chris@16 113 }
Chris@16 114
Chris@16 115 ~mpi_datatype_holder()
Chris@16 116 {
Chris@16 117 int finalized=0;
Chris@16 118 BOOST_MPI_CHECK_RESULT(MPI_Finalized,(&finalized));
Chris@16 119 if (!finalized && is_committed)
Chris@16 120 BOOST_MPI_CHECK_RESULT(MPI_Type_free,(&d));
Chris@16 121 }
Chris@16 122
Chris@16 123 private:
Chris@16 124 MPI_Datatype d;
Chris@16 125 bool is_committed;
Chris@16 126 };
Chris@16 127 } // end namespace detail
Chris@16 128
Chris@16 129 /** @brief A proxy object that transfers the content of an object
Chris@16 130 * without its structure.
Chris@16 131 *
Chris@16 132 * The @c content class indicates that Boost.MPI should transmit or
Chris@16 133 * receive the content of an object, but without any information
Chris@16 134 * about the structure of the object. It is only meaningful to
Chris@16 135 * transmit the content of an object after the receiver has already
Chris@16 136 * received the skeleton for the same object.
Chris@16 137 *
Chris@16 138 * Most users will not use @c content objects directly. Rather, they
Chris@16 139 * will invoke @c send, @c recv, or @c broadcast operations using @c
Chris@16 140 * get_content().
Chris@16 141 */
Chris@16 142 class BOOST_MPI_DECL content
Chris@16 143 {
Chris@16 144 public:
Chris@16 145 /**
Chris@16 146 * Constructs an empty @c content object. This object will not be
Chris@16 147 * useful for any Boost.MPI operations until it is reassigned.
Chris@16 148 */
Chris@16 149 content() {}
Chris@16 150
Chris@16 151 /**
Chris@16 152 * This routine initializes the @c content object with an MPI data
Chris@16 153 * type that refers to the content of an object without its structure.
Chris@16 154 *
Chris@16 155 * @param d the MPI data type referring to the content of the object.
Chris@16 156 *
Chris@16 157 * @param committed @c true indicates that @c MPI_Type_commit has
Chris@16 158 * already been excuted for the data type @p d.
Chris@16 159 */
Chris@16 160 content(MPI_Datatype d, bool committed=true)
Chris@16 161 : holder(new detail::mpi_datatype_holder(d,committed))
Chris@16 162 {}
Chris@16 163
Chris@16 164 /**
Chris@16 165 * Replace the MPI data type referencing the content of an object.
Chris@16 166 *
Chris@16 167 * @param d the new MPI data type referring to the content of the
Chris@16 168 * object.
Chris@16 169 *
Chris@16 170 * @returns *this
Chris@16 171 */
Chris@16 172 const content& operator=(MPI_Datatype d)
Chris@16 173 {
Chris@16 174 holder.reset(new detail::mpi_datatype_holder(d));
Chris@16 175 return *this;
Chris@16 176 }
Chris@16 177
Chris@16 178 /**
Chris@16 179 * Retrieve the MPI data type that refers to the content of the
Chris@16 180 * object.
Chris@16 181 *
Chris@16 182 * @returns the MPI data type, which should only be transmitted or
Chris@16 183 * received using @c MPI_BOTTOM as the address.
Chris@16 184 */
Chris@16 185 MPI_Datatype get_mpi_datatype() const
Chris@16 186 {
Chris@16 187 return holder->get_mpi_datatype();
Chris@16 188 }
Chris@16 189
Chris@16 190 /**
Chris@16 191 * Commit the MPI data type referring to the content of the
Chris@16 192 * object.
Chris@16 193 */
Chris@16 194 void commit()
Chris@16 195 {
Chris@16 196 holder->commit();
Chris@16 197 }
Chris@16 198
Chris@16 199 private:
Chris@16 200 boost::shared_ptr<detail::mpi_datatype_holder> holder;
Chris@16 201 };
Chris@16 202
Chris@16 203 /** @brief Returns the content of an object, suitable for transmission
Chris@16 204 * via Boost.MPI.
Chris@16 205 *
Chris@16 206 * The function creates an absolute MPI datatype for the object,
Chris@16 207 * where all offsets are counted from the address 0 (a.k.a. @c
Chris@16 208 * MPI_BOTTOM) instead of the address @c &x of the object. This
Chris@16 209 * allows the creation of MPI data types for complex data structures
Chris@16 210 * containing pointers, such as linked lists or trees.
Chris@16 211 *
Chris@16 212 * The disadvantage, compared to relative MPI data types is that for
Chris@16 213 * each object a new MPI data type has to be created.
Chris@16 214 *
Chris@16 215 * The contents of an object can only be transmitted when the
Chris@16 216 * receiver already has an object with the same structure or shape as
Chris@16 217 * the sender. To accomplish this, first transmit the skeleton of the
Chris@16 218 * object using, e.g., @c skeleton() or @c skeleton_proxy.
Chris@16 219 *
Chris@16 220 * The type @c T has to allow creation of an absolute MPI data type
Chris@16 221 * (content).
Chris@16 222 *
Chris@16 223 * @param x the object for which the content will be transmitted.
Chris@16 224 *
Chris@16 225 * @returns the content of the object @p x, which can be used for
Chris@16 226 * transmission via @c send, @c recv, or @c broadcast.
Chris@16 227 */
Chris@16 228 template <class T> const content get_content(const T& x);
Chris@16 229
Chris@16 230 /** @brief An archiver that reconstructs a data structure based on the
Chris@16 231 * binary skeleton stored in a buffer.
Chris@16 232 *
Chris@16 233 * The @c packed_skeleton_iarchive class is an Archiver (as in the
Chris@16 234 * Boost.Serialization library) that can construct the the shape of a
Chris@16 235 * data structure based on a binary skeleton stored in a buffer. The
Chris@16 236 * @c packed_skeleton_iarchive is typically used by the receiver of a
Chris@16 237 * skeleton, to prepare a data structure that will eventually receive
Chris@16 238 * content separately.
Chris@16 239 *
Chris@16 240 * Users will not generally need to use @c packed_skeleton_iarchive
Chris@16 241 * directly. Instead, use @c skeleton or @c get_skeleton.
Chris@16 242 */
Chris@16 243 class BOOST_MPI_DECL packed_skeleton_iarchive
Chris@16 244 : public detail::ignore_iprimitive,
Chris@16 245 public detail::forward_skeleton_iarchive<packed_skeleton_iarchive,packed_iarchive>
Chris@16 246 {
Chris@16 247 public:
Chris@16 248 /**
Chris@16 249 * Construct a @c packed_skeleton_iarchive for the given
Chris@16 250 * communicator.
Chris@16 251 *
Chris@16 252 * @param comm The communicator over which this archive will be
Chris@16 253 * transmitted.
Chris@16 254 *
Chris@16 255 * @param flags Control the serialization of the skeleton. Refer to
Chris@16 256 * the Boost.Serialization documentation before changing the
Chris@16 257 * default flags.
Chris@16 258 */
Chris@16 259 packed_skeleton_iarchive(MPI_Comm const & comm,
Chris@16 260 unsigned int flags = boost::archive::no_header)
Chris@16 261 : detail::forward_skeleton_iarchive<packed_skeleton_iarchive,packed_iarchive>(skeleton_archive_)
Chris@16 262 , skeleton_archive_(comm,flags)
Chris@16 263 {}
Chris@16 264
Chris@16 265 /**
Chris@16 266 * Construct a @c packed_skeleton_iarchive that unpacks a skeleton
Chris@16 267 * from the given @p archive.
Chris@16 268 *
Chris@16 269 * @param archive the archive from which the skeleton will be
Chris@16 270 * unpacked.
Chris@16 271 *
Chris@16 272 */
Chris@16 273 explicit packed_skeleton_iarchive(packed_iarchive & archive)
Chris@16 274 : detail::forward_skeleton_iarchive<packed_skeleton_iarchive,packed_iarchive>(archive)
Chris@16 275 , skeleton_archive_(MPI_COMM_WORLD, boost::archive::no_header)
Chris@16 276 {}
Chris@16 277
Chris@16 278 /**
Chris@16 279 * Retrieve the archive corresponding to this skeleton.
Chris@16 280 */
Chris@16 281 const packed_iarchive& get_skeleton() const
Chris@16 282 {
Chris@16 283 return this->implementation_archive;
Chris@16 284 }
Chris@16 285
Chris@16 286 /**
Chris@16 287 * Retrieve the archive corresponding to this skeleton.
Chris@16 288 */
Chris@16 289 packed_iarchive& get_skeleton()
Chris@16 290 {
Chris@16 291 return this->implementation_archive;
Chris@16 292 }
Chris@16 293
Chris@16 294 private:
Chris@16 295 /// Store the actual archive that holds the structure, unless the
Chris@16 296 /// user overrides this with their own archive.
Chris@16 297 packed_iarchive skeleton_archive_;
Chris@16 298 };
Chris@16 299
Chris@16 300 /** @brief An archiver that records the binary skeleton of a data
Chris@16 301 * structure into a buffer.
Chris@16 302 *
Chris@16 303 * The @c packed_skeleton_oarchive class is an Archiver (as in the
Chris@16 304 * Boost.Serialization library) that can record the shape of a data
Chris@16 305 * structure (called the "skeleton") into a binary representation
Chris@16 306 * stored in a buffer. The @c packed_skeleton_oarchive is typically
Chris@16 307 * used by the send of a skeleton, to pack the skeleton of a data
Chris@16 308 * structure for transmission separately from the content.
Chris@16 309 *
Chris@16 310 * Users will not generally need to use @c packed_skeleton_oarchive
Chris@16 311 * directly. Instead, use @c skeleton or @c get_skeleton.
Chris@16 312 */
Chris@16 313 class BOOST_MPI_DECL packed_skeleton_oarchive
Chris@16 314 : public detail::ignore_oprimitive,
Chris@16 315 public detail::forward_skeleton_oarchive<packed_skeleton_oarchive,packed_oarchive>
Chris@16 316 {
Chris@16 317 public:
Chris@16 318 /**
Chris@16 319 * Construct a @c packed_skeleton_oarchive for the given
Chris@16 320 * communicator.
Chris@16 321 *
Chris@16 322 * @param comm The communicator over which this archive will be
Chris@16 323 * transmitted.
Chris@16 324 *
Chris@16 325 * @param flags Control the serialization of the skeleton. Refer to
Chris@16 326 * the Boost.Serialization documentation before changing the
Chris@16 327 * default flags.
Chris@16 328 */
Chris@16 329 packed_skeleton_oarchive(MPI_Comm const & comm,
Chris@16 330 unsigned int flags = boost::archive::no_header)
Chris@16 331 : detail::forward_skeleton_oarchive<packed_skeleton_oarchive,packed_oarchive>(skeleton_archive_)
Chris@16 332 , skeleton_archive_(comm,flags)
Chris@16 333 {}
Chris@16 334
Chris@16 335 /**
Chris@16 336 * Construct a @c packed_skeleton_oarchive that packs a skeleton
Chris@16 337 * into the given @p archive.
Chris@16 338 *
Chris@16 339 * @param archive the archive to which the skeleton will be packed.
Chris@16 340 *
Chris@16 341 */
Chris@16 342 explicit packed_skeleton_oarchive(packed_oarchive & archive)
Chris@16 343 : detail::forward_skeleton_oarchive<packed_skeleton_oarchive,packed_oarchive>(archive)
Chris@16 344 , skeleton_archive_(MPI_COMM_WORLD, boost::archive::no_header)
Chris@16 345 {}
Chris@16 346
Chris@16 347 /**
Chris@16 348 * Retrieve the archive corresponding to this skeleton.
Chris@16 349 */
Chris@16 350 const packed_oarchive& get_skeleton() const
Chris@16 351 {
Chris@16 352 return this->implementation_archive;
Chris@16 353 }
Chris@16 354
Chris@16 355 private:
Chris@16 356 /// Store the actual archive that holds the structure.
Chris@16 357 packed_oarchive skeleton_archive_;
Chris@16 358 };
Chris@16 359
Chris@16 360 namespace detail {
Chris@16 361 typedef boost::mpi::detail::forward_skeleton_oarchive<boost::mpi::packed_skeleton_oarchive,boost::mpi::packed_oarchive> type1;
Chris@16 362 typedef boost::mpi::detail::forward_skeleton_iarchive<boost::mpi::packed_skeleton_iarchive,boost::mpi::packed_iarchive> type2;
Chris@16 363 }
Chris@16 364
Chris@16 365
Chris@16 366 } } // end namespace boost::mpi
Chris@16 367
Chris@16 368 #include <boost/mpi/detail/content_oarchive.hpp>
Chris@16 369
Chris@16 370 // For any headers that have provided declarations based on forward
Chris@16 371 // declarations of the contents of this header, include definitions
Chris@16 372 // for those declarations. This means that the inclusion of
Chris@16 373 // skeleton_and_content.hpp enables the use of skeleton/content
Chris@16 374 // transmission throughout the library.
Chris@16 375 #ifdef BOOST_MPI_BROADCAST_HPP
Chris@16 376 # include <boost/mpi/detail/broadcast_sc.hpp>
Chris@16 377 #endif
Chris@16 378
Chris@16 379 #ifdef BOOST_MPI_COMMUNICATOR_HPP
Chris@16 380 # include <boost/mpi/detail/communicator_sc.hpp>
Chris@16 381 #endif
Chris@16 382
Chris@16 383 // required by export
Chris@16 384 BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::mpi::packed_skeleton_oarchive)
Chris@16 385 BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::mpi::packed_skeleton_iarchive)
Chris@16 386 BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::mpi::detail::type1)
Chris@16 387 BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::mpi::detail::type2)
Chris@16 388
Chris@16 389 BOOST_SERIALIZATION_USE_ARRAY_OPTIMIZATION(boost::mpi::packed_skeleton_oarchive)
Chris@16 390 BOOST_SERIALIZATION_USE_ARRAY_OPTIMIZATION(boost::mpi::packed_skeleton_iarchive)
Chris@16 391
Chris@16 392 #endif // BOOST_MPI_SKELETON_AND_CONTENT_HPP