PageRenderTime 48ms CodeModel.GetById 31ms app.highlight 13ms RepoModel.GetById 1ms app.codeStats 0ms

/Src/Dependencies/Boost/boost/mpi/skeleton_and_content.hpp

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