]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/mpi/include/boost/mpi/skeleton_and_content.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / mpi / include / boost / mpi / skeleton_and_content.hpp
CommitLineData
7c673cae
FG
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