Mercurial > hg > vamp-build-and-test
comparison DEPENDENCIES/generic/include/boost/mpi/skeleton_and_content.hpp @ 16:2665513ce2d3
Add boost headers
author | Chris Cannam |
---|---|
date | Tue, 05 Aug 2014 11:11:38 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
15:663ca0da4350 | 16:2665513ce2d3 |
---|---|
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 | |
37 namespace 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 */ | |
54 template <class T> | |
55 struct 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 */ | |
82 template <class T> | |
83 inline const skeleton_proxy<T> skeleton(T& x) | |
84 { | |
85 return skeleton_proxy<T>(x); | |
86 } | |
87 | |
88 namespace 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 */ | |
142 class BOOST_MPI_DECL content | |
143 { | |
144 public: | |
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 | |
199 private: | |
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 */ | |
228 template <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 */ | |
243 class BOOST_MPI_DECL packed_skeleton_iarchive | |
244 : public detail::ignore_iprimitive, | |
245 public detail::forward_skeleton_iarchive<packed_skeleton_iarchive,packed_iarchive> | |
246 { | |
247 public: | |
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 | |
294 private: | |
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 */ | |
313 class BOOST_MPI_DECL packed_skeleton_oarchive | |
314 : public detail::ignore_oprimitive, | |
315 public detail::forward_skeleton_oarchive<packed_skeleton_oarchive,packed_oarchive> | |
316 { | |
317 public: | |
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 | |
355 private: | |
356 /// Store the actual archive that holds the structure. | |
357 packed_oarchive skeleton_archive_; | |
358 }; | |
359 | |
360 namespace 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 | |
384 BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::mpi::packed_skeleton_oarchive) | |
385 BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::mpi::packed_skeleton_iarchive) | |
386 BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::mpi::detail::type1) | |
387 BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::mpi::detail::type2) | |
388 | |
389 BOOST_SERIALIZATION_USE_ARRAY_OPTIMIZATION(boost::mpi::packed_skeleton_oarchive) | |
390 BOOST_SERIALIZATION_USE_ARRAY_OPTIMIZATION(boost::mpi::packed_skeleton_iarchive) | |
391 | |
392 #endif // BOOST_MPI_SKELETON_AND_CONTENT_HPP |