fix doc example typo
[boost.git] / boost / mpi / skeleton_and_content.hpp
blob87b1f4263c52a504575ade70a74d9c71ff502736
1 // (C) Copyright 2005 Matthias Troyer
2 // (C) Copyright 2006 Douglas Gregor <doug.gregor -at gmail.com>
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)
8 // Authors: Matthias Troyer
9 // Douglas Gregor
11 /** @file skeleton_and_content.hpp
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).
23 #ifndef BOOST_MPI_SKELETON_AND_CONTENT_HPP
24 #define BOOST_MPI_SKELETON_AND_CONTENT_HPP
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>
36 namespace boost { namespace mpi {
38 /**
39 * @brief A proxy that requests that the skeleton of an object be
40 * transmitted.
42 * The @c skeleton_proxy is a lightweight proxy object used to
43 * indicate that the skeleton of an object, not the object itself,
44 * should be transmitted. It can be used with the @c send and @c recv
45 * operations of communicators or the @c broadcast collective. When a
46 * @c skeleton_proxy is sent, Boost.MPI generates a description
47 * containing the structure of the stored object. When that skeleton
48 * is received, the receiving object is reshaped to match the
49 * structure. Once the skeleton of an object as been transmitted, its
50 * @c content can be transmitted separately (often several times)
51 * without changing the structure of the object.
53 template <class T>
54 struct BOOST_MPI_DECL skeleton_proxy
56 /**
57 * Constructs a @c skeleton_proxy that references object @p x.
59 * @param x the object whose structure will be transmitted or
60 * altered.
62 skeleton_proxy(T& x)
63 : object(x)
66 T& object;
69 /**
70 * @brief Create a skeleton proxy object.
72 * This routine creates an instance of the skeleton_proxy class. It
73 * will typically be used when calling @c send, @c recv, or @c
74 * broadcast, to indicate that only the skeleton (structure) of an
75 * object should be transmitted and not its contents.
77 * @param x the object whose structure will be transmitted.
79 * @returns a skeleton_proxy object referencing @p x
81 template <class T>
82 inline const skeleton_proxy<T> skeleton(T& x)
84 return skeleton_proxy<T>(x);
87 namespace detail {
88 /// @brief a class holding an MPI datatype
89 /// INTERNAL ONLY
90 /// the type is freed upon destruction
91 class BOOST_MPI_DECL mpi_datatype_holder : public boost::noncopyable
93 public:
94 mpi_datatype_holder()
95 : is_committed(false)
98 mpi_datatype_holder(MPI_Datatype t, bool committed = true)
99 : d(t)
100 , is_committed(committed)
103 void commit()
105 BOOST_MPI_CHECK_RESULT(MPI_Type_commit,(&d));
106 is_committed=true;
109 MPI_Datatype get_mpi_datatype() const
111 return d;
114 ~mpi_datatype_holder()
116 int finalized=0;
117 BOOST_MPI_CHECK_RESULT(MPI_Finalized,(&finalized));
118 if (!finalized && is_committed)
119 BOOST_MPI_CHECK_RESULT(MPI_Type_free,(&d));
122 private:
123 MPI_Datatype d;
124 bool is_committed;
126 } // end namespace detail
128 /** @brief A proxy object that transfers the content of an object
129 * without its structure.
131 * The @c content class indicates that Boost.MPI should transmit or
132 * receive the content of an object, but without any information
133 * about the structure of the object. It is only meaningful to
134 * transmit the content of an object after the receiver has already
135 * received the skeleton for the same object.
137 * Most users will not use @c content objects directly. Rather, they
138 * will invoke @c send, @c recv, or @c broadcast operations using @c
139 * get_content().
141 class BOOST_MPI_DECL content
143 public:
145 * Constructs an empty @c content object. This object will not be
146 * useful for any Boost.MPI operations until it is reassigned.
148 content() {}
151 * This routine initializes the @c content object with an MPI data
152 * type that refers to the content of an object without its structure.
154 * @param d the MPI data type referring to the content of the object.
156 * @param committed @c true indicates that @c MPI_Type_commit has
157 * already been excuted for the data type @p d.
159 content(MPI_Datatype d, bool committed=true)
160 : holder(new detail::mpi_datatype_holder(d,committed))
164 * Replace the MPI data type referencing the content of an object.
166 * @param d the new MPI data type referring to the content of the
167 * object.
169 * @returns *this
171 const content& operator=(MPI_Datatype d)
173 holder.reset(new detail::mpi_datatype_holder(d));
174 return *this;
178 * Retrieve the MPI data type that refers to the content of the
179 * object.
181 * @returns the MPI data type, which should only be transmitted or
182 * received using @c MPI_BOTTOM as the address.
184 MPI_Datatype get_mpi_datatype() const
186 return holder->get_mpi_datatype();
190 * Commit the MPI data type referring to the content of the
191 * object.
193 void commit()
195 holder->commit();
198 private:
199 boost::shared_ptr<detail::mpi_datatype_holder> holder;
202 /** @brief Returns the content of an object, suitable for transmission
203 * via Boost.MPI.
205 * The function creates an absolute MPI datatype for the object,
206 * where all offsets are counted from the address 0 (a.k.a. @c
207 * MPI_BOTTOM) instead of the address @c &x of the object. This
208 * allows the creation of MPI data types for complex data structures
209 * containing pointers, such as linked lists or trees.
211 * The disadvantage, compared to relative MPI data types is that for
212 * each object a new MPI data type has to be created.
214 * The contents of an object can only be transmitted when the
215 * receiver already has an object with the same structure or shape as
216 * the sender. To accomplish this, first transmit the skeleton of the
217 * object using, e.g., @c skeleton() or @c skeleton_proxy.
219 * The type @c T has to allow creation of an absolute MPI data type
220 * (content).
222 * @param x the object for which the content will be transmitted.
224 * @returns the content of the object @p x, which can be used for
225 * transmission via @c send, @c recv, or @c broadcast.
227 template <class T> const content get_content(const T& x);
229 /** @brief An archiver that reconstructs a data structure based on the
230 * binary skeleton stored in a buffer.
232 * The @c packed_skeleton_iarchive class is an Archiver (as in the
233 * Boost.Serialization library) that can construct the the shape of a
234 * data structure based on a binary skeleton stored in a buffer. The
235 * @c packed_skeleton_iarchive is typically used by the receiver of a
236 * skeleton, to prepare a data structure that will eventually receive
237 * content separately.
239 * Users will not generally need to use @c packed_skeleton_iarchive
240 * directly. Instead, use @c skeleton or @c get_skeleton.
242 class BOOST_MPI_DECL packed_skeleton_iarchive
243 : public detail::ignore_iprimitive,
244 public detail::forward_skeleton_iarchive<packed_skeleton_iarchive,packed_iarchive>
246 public:
248 * Construct a @c packed_skeleton_iarchive for the given
249 * communicator.
251 * @param comm The communicator over which this archive will be
252 * transmitted.
254 * @param flags Control the serialization of the skeleton. Refer to
255 * the Boost.Serialization documentation before changing the
256 * default flags.
258 packed_skeleton_iarchive(MPI_Comm const & comm,
259 unsigned int flags = boost::archive::no_header)
260 : detail::forward_skeleton_iarchive<packed_skeleton_iarchive,packed_iarchive>(skeleton_archive_)
261 , skeleton_archive_(comm,flags)
265 * Construct a @c packed_skeleton_iarchive that unpacks a skeleton
266 * from the given @p archive.
268 * @param archive the archive from which the skeleton will be
269 * unpacked.
272 explicit packed_skeleton_iarchive(packed_iarchive & archive)
273 : detail::forward_skeleton_iarchive<packed_skeleton_iarchive,packed_iarchive>(archive)
274 , skeleton_archive_(MPI_COMM_WORLD, boost::archive::no_header)
278 * Retrieve the archive corresponding to this skeleton.
280 const packed_iarchive& get_skeleton() const
282 return this->implementation_archive;
286 * Retrieve the archive corresponding to this skeleton.
288 packed_iarchive& get_skeleton()
290 return this->implementation_archive;
293 private:
294 /// Store the actual archive that holds the structure, unless the
295 /// user overrides this with their own archive.
296 packed_iarchive skeleton_archive_;
299 /** @brief An archiver that records the binary skeleton of a data
300 * structure into a buffer.
302 * The @c packed_skeleton_oarchive class is an Archiver (as in the
303 * Boost.Serialization library) that can record the shape of a data
304 * structure (called the "skeleton") into a binary representation
305 * stored in a buffer. The @c packed_skeleton_oarchive is typically
306 * used by the send of a skeleton, to pack the skeleton of a data
307 * structure for transmission separately from the content.
309 * Users will not generally need to use @c packed_skeleton_oarchive
310 * directly. Instead, use @c skeleton or @c get_skeleton.
312 class BOOST_MPI_DECL packed_skeleton_oarchive
313 : public detail::ignore_oprimitive,
314 public detail::forward_skeleton_oarchive<packed_skeleton_oarchive,packed_oarchive>
316 public:
318 * Construct a @c packed_skeleton_oarchive for the given
319 * communicator.
321 * @param comm The communicator over which this archive will be
322 * transmitted.
324 * @param flags Control the serialization of the skeleton. Refer to
325 * the Boost.Serialization documentation before changing the
326 * default flags.
328 packed_skeleton_oarchive(MPI_Comm const & comm,
329 unsigned int flags = boost::archive::no_header)
330 : detail::forward_skeleton_oarchive<packed_skeleton_oarchive,packed_oarchive>(skeleton_archive_)
331 , skeleton_archive_(comm,flags)
335 * Construct a @c packed_skeleton_oarchive that packs a skeleton
336 * into the given @p archive.
338 * @param archive the archive to which the skeleton will be packed.
341 explicit packed_skeleton_oarchive(packed_oarchive & archive)
342 : detail::forward_skeleton_oarchive<packed_skeleton_oarchive,packed_oarchive>(archive)
343 , skeleton_archive_(MPI_COMM_WORLD, boost::archive::no_header)
347 * Retrieve the archive corresponding to this skeleton.
349 const packed_oarchive& get_skeleton() const
351 return this->implementation_archive;
354 private:
355 /// Store the actual archive that holds the structure.
356 packed_oarchive skeleton_archive_;
359 namespace detail {
360 typedef boost::mpi::detail::forward_skeleton_oarchive<boost::mpi::packed_skeleton_oarchive,boost::mpi::packed_oarchive> type1;
361 typedef boost::mpi::detail::forward_skeleton_iarchive<boost::mpi::packed_skeleton_iarchive,boost::mpi::packed_iarchive> type2;
365 } } // end namespace boost::mpi
367 #include <boost/mpi/detail/content_oarchive.hpp>
369 // For any headers that have provided declarations based on forward
370 // declarations of the contents of this header, include definitions
371 // for those declarations. This means that the inclusion of
372 // skeleton_and_content.hpp enables the use of skeleton/content
373 // transmission throughout the library.
374 #ifdef BOOST_MPI_BROADCAST_HPP
375 # include <boost/mpi/detail/broadcast_sc.hpp>
376 #endif
378 #ifdef BOOST_MPI_COMMUNICATOR_HPP
379 # include <boost/mpi/detail/communicator_sc.hpp>
380 #endif
382 // required by export
383 BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::mpi::packed_skeleton_oarchive)
384 BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::mpi::packed_skeleton_iarchive)
385 BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::mpi::detail::type1)
386 BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::mpi::detail::type2)
388 BOOST_SERIALIZATION_USE_ARRAY_OPTIMIZATION(boost::mpi::packed_skeleton_oarchive)
389 BOOST_SERIALIZATION_USE_ARRAY_OPTIMIZATION(boost::mpi::packed_skeleton_iarchive)
391 #endif // BOOST_MPI_SKELETON_AND_CONTENT_HPP