KaMPIng 0.1.1
Flexible and (near) zero-overhead C++ bindings for MPI
Loading...
Searching...
No Matches
result.hpp
Go to the documentation of this file.
1// This file is part of KaMPIng.
2//
3// Copyright 2021-2024 The KaMPIng Authors
4//
5// KaMPIng is free software : you can redistribute it and/or modify it under the terms of the GNU Lesser General Public
6// License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later
7// version. KaMPIng is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
8// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
9// for more details.
10//
11// You should have received a copy of the GNU Lesser General Public License along with KaMPIng. If not, see
12// <https://www.gnu.org/licenses/>.:
13
14#pragma once
15
16/// @file
17/// @brief Some functions and types simplifying/enabling the development of wrapped \c MPI calls in KaMPIng.
18
19#include <optional>
20#include <tuple>
21#include <utility>
22
25#include "kamping/named_parameter_filtering.hpp"
28#include "kamping/named_parameters_detail/status_parameters.hpp"
30
31namespace kamping {
32
33namespace internal {
34
36/// @brief has_extract_v is \c true iff type T has a member function \c extract().
37///
38/// @tparam T Type which is tested for the existence of a member function.
39template <typename T>
40inline constexpr bool has_extract_v = has_member_extract_v<T>;
41
42/// @brief Use this type if one of the template parameters of MPIResult is not used for a specific wrapped \c MPI call.
44
45/// @brief Helper for implementing the extract_* functions in \ref MPIResult. Is \c true if the passed buffer type owns
46/// its underlying storage and is an output buffer.
47template <typename Buffer>
48inline constexpr bool is_extractable = Buffer::is_owning&& Buffer::is_out_buffer;
49
50/// @brief Specialization of helper for implementing the extract_* functions in \ref MPIResult. Is always \c false;
51template <>
52inline constexpr bool is_extractable<internal::ResultCategoryNotUsed> = false;
53} // namespace internal
54/// @brief MPIResult contains the result of a \c MPI call wrapped by KaMPIng.
55///
56/// A wrapped \c MPI call can have multiple different results such as the \c
57/// recv_buffer, \c recv_counts, \c recv_displs etc. If the buffers where these
58/// results have been written to by the library call has been allocated
59/// by/transferred to KaMPIng, the content of the buffers can be extracted using
60/// extract_<result>.
61/// Note that not all below-listed buffer categories needs to be used by every
62/// wrapped \c MPI call. If a specific call does not use a buffer category, you
63/// have to provide ResultCategoryNotUsed instead.
64///
65/// @tparam Args Types of return data buffers.
66template <typename... Args>
67class MPIResult {
68public:
69 /// @brief \c true, if the result does not encapsulate any data.
70 static constexpr bool is_empty = (sizeof...(Args) == 0);
71 /// @brief \c true, if the result encapsulates a recv_buf.
73 /// @brief \c true, if the result encapsulates a send_recv_buf.
74 static constexpr bool has_send_recv_buffer =
76 static_assert(
78 "We cannot have a recv and a send_recv buffer contained in the result object."
79 );
80
81 /// @brief Constructor for MPIResult.
82 ///
83 /// @param data std::tuple containing all data buffers to be returned.
84 MPIResult(std::tuple<Args...>&& data) : _data(std::move(data)) {}
85
86 /// @brief Get the \c kamping::Status from the MPIResult object.
87 ///
88 /// This function is only available if the underlying status is owned by the
89 /// MPIResult object.
90 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
91 /// the result object.
92 /// @return Returns a reference to the underlying status object.
93 template <
94 typename T = std::tuple<Args...>,
95 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::status, T>(), bool> = true>
96 auto& get_status() {
97 return internal::select_parameter_type_in_tuple<internal::ParameterType::status>(_data).underlying();
98 }
99
100 /// @brief Get the \c kamping::Status from the MPIResult object.
101 ///
102 /// This function is only available if the underlying status is owned by the
103 /// MPIResult object.
104 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
105 /// the result object.
106 /// @return Returns a reference to the underlying status object.
107 template <
108 typename T = std::tuple<Args...>,
109 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::status, T>(), bool> = true>
110 auto const& get_status() const {
111 return internal::select_parameter_type_in_tuple<internal::ParameterType::status>(_data).underlying();
112 }
113
114 /// @brief Extracts the \c kamping::Status from the MPIResult object.
115 ///
116 /// This function is only available if the underlying status is owned by the
117 /// MPIResult object.
118 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
119 /// the result object.
120 /// @return Returns the underlying status object.
121 template <
122 typename T = std::tuple<Args...>,
123 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::status, T>(), bool> = true>
125 return internal::select_parameter_type_in_tuple<internal::ParameterType::status>(_data).extract();
126 }
127
128 /// @brief Get the \c recv_buffer from the MPIResult object.
129 ///
130 /// This function is only available if the underlying memory is owned by the
131 /// MPIResult object.
132 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
133 /// the result object.
134 /// @return Returns a reference to the underlying storage containing the received elements.
135 template <
136 typename T = std::tuple<Args...>,
137 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::recv_buf, T>(), bool> = true>
138 auto& get_recv_buf() {
139 return internal::select_parameter_type_in_tuple<internal::ParameterType::recv_buf>(_data).underlying();
140 }
141
142 /// @brief Get the \c recv_buffer from the MPIResult object. Alias for \ref get_recv_buf().
143 ///
144 /// This function is only available if the underlying memory is owned by the
145 /// MPIResult object.
146 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
147 /// the result object.
148 /// @return Returns a reference to the underlying storage containing the received elements.
149 template <
150 typename T = std::tuple<Args...>,
151 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::recv_buf, T>(), bool> = true>
153 return get_recv_buf();
154 }
155
156 /// @brief Get the \c recv_buffer from the MPIResult object.
157 ///
158 /// This function is only available if the underlying memory is owned by the
159 /// MPIResult object.
160 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
161 /// the result object.
162 /// @return Returns a reference to the underlying storage containing the received elements.
163 template <
164 typename T = std::tuple<Args...>,
165 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::recv_buf, T>(), bool> = true>
166 auto const& get_recv_buf() const {
167 return internal::select_parameter_type_in_tuple<internal::ParameterType::recv_buf>(_data).underlying();
168 }
169
170 /// @brief Get the \c recv_buffer from the MPIResult object. Alias for \ref get_recv_buf().
171 ///
172 /// This function is only available if the underlying memory is owned by the
173 /// MPIResult object.
174 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
175 /// the result object.
176 /// @return Returns a reference to the underlying storage containing the received elements.
177 template <
178 typename T = std::tuple<Args...>,
179 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::recv_buf, T>(), bool> = true>
180 auto const& get_recv_buffer() const {
181 return get_recv_buf();
182 }
183
184 /// @brief Get the \c send_buffer from the MPIResult object.
185 ///
186 /// This function is only available if the underlying memory is owned by the
187 /// MPIResult object.
188 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
189 /// the result object.
190 /// @return Returns a reference to the underlying storage containing the elements to send.
191 template <
192 typename T = std::tuple<Args...>,
193 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::send_buf, T>(), bool> = true>
194 auto const& get_send_buf() const {
195 return internal::select_parameter_type_in_tuple<internal::ParameterType::send_buf>(_data).underlying();
196 }
197
198 /// @brief Get the \c send_buffer from the MPIResult object. Alias for \ref get_send_buf().
199 ///
200 /// This function is only available if the underlying memory is owned by the
201 /// MPIResult object.
202 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
203 /// the result object.
204 /// @return Returns a reference to the underlying storage containing the elements to send.
205 template <
206 typename T = std::tuple<Args...>,
207 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::send_buf, T>(), bool> = true>
208 auto const& get_send_buffer() const {
209 return get_send_buf();
210 }
211
212 /// @brief Extracts the \c send_buffer from the MPIResult object.
213 ///
214 /// This function is only available if the underlying memory is owned by the
215 /// MPIResult object.
216 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
217 /// the result object.
218 /// @return Returns the underlying storage containing the elements to send.
219 template <
220 typename T = std::tuple<Args...>,
221 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::send_buf, T>(), bool> = true>
223 return internal::select_parameter_type_in_tuple<internal::ParameterType::send_buf>(_data).extract();
224 }
225
226 /// @brief Extracts the \c recv_buffer from the MPIResult object.
227 ///
228 /// This function is only available if the underlying memory is owned by the
229 /// MPIResult object.
230 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
231 /// the result object.
232 /// @return Returns the underlying storage containing the received elements.
233 template <
234 typename T = std::tuple<Args...>,
235 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::recv_buf, T>(), bool> = true>
237 return internal::select_parameter_type_in_tuple<internal::ParameterType::recv_buf>(_data).extract();
238 }
239
240 /// @brief Extracts the \c recv_buffer from the MPIResult object. Alias for \ref extract_recv_buf().
241 ///
242 /// This function is only available if the underlying memory is owned by the
243 /// MPIResult object.
244 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
245 /// the result object.
246 /// @return Returns the underlying storage containing the received elements.
247 template <
248 typename T = std::tuple<Args...>,
249 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::recv_buf, T>(), bool> = true>
251 return extract_recv_buf();
252 }
253
254 /// @brief Get the \c send_recv_buffer from the MPIResult object. @todo discuss this
255 ///
256 /// This function is only available if the underlying memory is owned by the
257 /// MPIResult object.
258 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
259 /// the result object.
260 /// @return Returns a reference to the underlying storage containing the received elements.
261 template <
262 typename T = std::tuple<Args...>,
263 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::send_recv_buf, T>(), bool> =
264 true>
265 auto& get_recv_buf() {
266 return internal::select_parameter_type_in_tuple<internal::ParameterType::send_recv_buf>(_data).underlying();
267 }
268
269 /// @brief Get the \c send_recv_buffer from the MPIResult object. @todo discuss this
270 /// Alias for \ref get_recv_buf().
271 ///
272 /// This function is only available if the underlying memory is owned by the
273 /// MPIResult object.
274 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
275 /// the result object.
276 /// @return Returns a reference to the underlying storage containing the received elements.
277 template <
278 typename T = std::tuple<Args...>,
279 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::send_recv_buf, T>(), bool> =
280 true>
282 return get_recv_buf();
283 }
284
285 /// @brief Get the \c send_recv_buffer from the MPIResult object. @todo discuss this
286 ///
287 /// This function is only available if the underlying memory is owned by the
288 /// MPIResult object.
289 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
290 /// the result object.
291 /// @return Returns a reference to the underlying storage containing the received elements.
292 template <
293 typename T = std::tuple<Args...>,
294 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::send_recv_buf, T>(), bool> =
295 true>
296 auto const& get_recv_buf() const {
297 return internal::select_parameter_type_in_tuple<internal::ParameterType::send_recv_buf>(_data).underlying();
298 }
299
300 /// @brief Get the \c send_recv_buffer from the MPIResult object. @todo discuss this
301 /// Alias for \ref get_recv_buf().
302 ///
303 /// This function is only available if the underlying memory is owned by the
304 /// MPIResult object.
305 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
306 /// the result object.
307 /// @return Returns a reference to the underlying storage containing the received elements.
308 template <
309 typename T = std::tuple<Args...>,
310 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::send_recv_buf, T>(), bool> =
311 true>
312 auto const& get_recv_buffer() const {
313 return get_recv_buf();
314 }
315
316 /// @brief Extracts the \c send_recv_buffer from the MPIResult object. @todo discuss this
317 ///
318 /// This function is only available if the underlying memory is owned by the
319 /// MPIResult object.
320 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
321 /// the result object.
322 /// @return Returns the underlying storage containing the received elements.
323 template <
324 typename T = std::tuple<Args...>,
325 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::send_recv_buf, T>(), bool> =
326 true>
328 return internal::select_parameter_type_in_tuple<internal::ParameterType::send_recv_buf>(_data).extract();
329 }
330
331 /// @brief Extracts the \c send_recv_buffer from the MPIResult object. @todo discuss this
332 /// Alias for \ref extract_recv_buf().
333 ///
334 /// This function is only available if the underlying memory is owned by the
335 /// MPIResult object.
336 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
337 /// the result object.
338 /// @return Returns the underlying storage containing the received elements.
339 template <
340 typename T = std::tuple<Args...>,
341 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::send_recv_buf, T>(), bool> =
342 true>
344 return extract_recv_buf();
345 }
346
347 /// @brief Get the \c recv_counts from the MPIResult object.
348 ///
349 /// This function is only available if the corresponding data is part of the result object.
350 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
351 /// the result object.
352 /// @return Returns a reference to the underlying storage containing the receive counts.
353 template <
354 typename T = std::tuple<Args...>,
355 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::recv_counts, T>(), bool> = true>
357 return internal::select_parameter_type_in_tuple<internal::ParameterType::recv_counts>(_data).underlying();
358 }
359
360 /// @brief Get the \c recv_counts from the MPIResult object.
361 ///
362 /// This function is only available if the corresponding data is part of the result object.
363 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
364 /// the result object.
365 /// @return Returns a reference to the underlying storage containing the receive counts.
366 template <
367 typename T = std::tuple<Args...>,
368 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::recv_counts, T>(), bool> = true>
369 auto const& get_recv_counts() const {
370 return internal::select_parameter_type_in_tuple<internal::ParameterType::recv_counts>(_data).underlying();
371 }
372
373 /// @brief Extracts the \c recv_counts from the MPIResult object.
374 ///
375 /// This function is only available if the corresponding data is part of the result object.
376 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
377 /// the result object.
378 /// @return Returns the underlying storage containing the receive counts.
379 template <
380 typename T = std::tuple<Args...>,
381 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::recv_counts, T>(), bool> = true>
383 return internal::select_parameter_type_in_tuple<internal::ParameterType::recv_counts>(_data).extract();
384 }
385
386 /// @brief Gets the \c recv_count from the MPIResult object.
387 ///
388 /// This function is only available if the corresponding data is part of the result object.
389 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
390 /// the result object.
391 /// @return Returns a reference to the underlying storage containing the recv count.
392 template <
393 typename T = std::tuple<Args...>,
394 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::recv_count, T>(), bool> = true>
396 return internal::select_parameter_type_in_tuple<internal::ParameterType::recv_count>(_data).underlying();
397 }
398
399 /// @brief Gets the \c recv_count from the MPIResult object.
400 ///
401 /// This function is only available if the corresponding data is part of the result object.
402 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
403 /// the result object.
404 /// @return Returns a reference to the underlying storage containing the recv count.
405 template <
406 typename T = std::tuple<Args...>,
407 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::recv_count, T>(), bool> = true>
408 auto const& get_recv_count() const {
409 return internal::select_parameter_type_in_tuple<internal::ParameterType::recv_count>(_data).underlying();
410 }
411
412 /// @brief Extracts the \c recv_count from the MPIResult object.
413 ///
414 /// This function is only available if the corresponding data is part of the result object.
415 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
416 /// the result object.
417 /// @return Returns the underlying storage containing the recv count.
418 template <
419 typename T = std::tuple<Args...>,
420 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::recv_count, T>(), bool> = true>
422 return internal::select_parameter_type_in_tuple<internal::ParameterType::recv_count>(_data).extract();
423 }
424
425 /// @brief Gets the \c recv_displs from the MPIResult object.
426 ///
427 /// This function is only available if the corresponding data is part of the result object.
428 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
429 /// the result object.
430 /// @return Returns a reference to the underlying storage containing the receive displacements.
431 template <
432 typename T = std::tuple<Args...>,
433 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::recv_displs, T>(), bool> = true>
435 return internal::select_parameter_type_in_tuple<internal::ParameterType::recv_displs>(_data).underlying();
436 }
437
438 /// @brief Gets the \c recv_displs from the MPIResult object.
439 ///
440 /// This function is only available if the corresponding data is part of the result object.
441 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
442 /// the result object.
443 /// @return Returns a reference to the underlying storage containing the receive displacements.
444 template <
445 typename T = std::tuple<Args...>,
446 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::recv_displs, T>(), bool> = true>
447 auto const& get_recv_displs() const {
448 return internal::select_parameter_type_in_tuple<internal::ParameterType::recv_displs>(_data).underlying();
449 }
450
451 /// @brief Extracts the \c recv_displs from the MPIResult object.
452 ///
453 /// This function is only available if the corresponding data is part of the result object.
454 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
455 /// the result object.
456 /// @return Returns the underlying storage containing the receive displacements.
457 template <
458 typename T = std::tuple<Args...>,
459 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::recv_displs, T>(), bool> = true>
461 return internal::select_parameter_type_in_tuple<internal::ParameterType::recv_displs>(_data).extract();
462 }
463
464 /// @brief Gets the \c send_counts from the MPIResult object.
465 ///
466 /// This function is only available if the corresponding data is part of the result object.
467 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
468 /// the result object.
469 /// @return Returns a reference to the underlying storage containing the send counts.
470 template <
471 typename T = std::tuple<Args...>,
472 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::send_counts, T>(), bool> = true>
474 return internal::select_parameter_type_in_tuple<internal::ParameterType::send_counts>(_data).underlying();
475 }
476
477 /// @brief Gets the \c send_counts from the MPIResult object.
478 ///
479 /// This function is only available if the corresponding data is part of the result object.
480 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
481 /// the result object.
482 /// @return Returns a reference to the underlying storage containing the send counts.
483 template <
484 typename T = std::tuple<Args...>,
485 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::send_counts, T>(), bool> = true>
486 auto const& get_send_counts() const {
487 return internal::select_parameter_type_in_tuple<internal::ParameterType::send_counts>(_data).underlying();
488 }
489
490 /// @brief Extracts the \c send_counts from the MPIResult object.
491 ///
492 /// This function is only available if the corresponding data is part of the result object.
493 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
494 /// the result object.
495 /// @return Returns the underlying storage containing the send counts.
496 template <
497 typename T = std::tuple<Args...>,
498 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::send_counts, T>(), bool> = true>
500 return internal::select_parameter_type_in_tuple<internal::ParameterType::send_counts>(_data).extract();
501 }
502
503 /// @brief Gets the \c send_count from the MPIResult object.
504 ///
505 /// This function is only available if the corresponding data is part of the result object.
506 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
507 /// the result object.
508 /// @return Returns a reference to the underlying storage containing the send counts.
509 template <
510 typename T = std::tuple<Args...>,
511 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::send_count, T>(), bool> = true>
513 return internal::select_parameter_type_in_tuple<internal::ParameterType::send_count>(_data).underlying();
514 }
515
516 /// @brief Gets the \c send_count from the MPIResult object.
517 ///
518 /// This function is only available if the corresponding data is part of the result object.
519 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
520 /// the result object.
521 /// @return Returns a reference to the underlying storage containing the send counts.
522 template <
523 typename T = std::tuple<Args...>,
524 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::send_count, T>(), bool> = true>
525 auto const& get_send_count() const {
526 return internal::select_parameter_type_in_tuple<internal::ParameterType::send_count>(_data).underlying();
527 }
528
529 /// @brief Extracts the \c send_count from the MPIResult object.
530 ///
531 /// This function is only available if the corresponding data is part of the result object.
532 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
533 /// the result object.
534 /// @return Returns the underlying storage containing the send counts.
535 template <
536 typename T = std::tuple<Args...>,
537 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::send_count, T>(), bool> = true>
539 return internal::select_parameter_type_in_tuple<internal::ParameterType::send_count>(_data).extract();
540 }
541
542 /// @brief Gets the \c send_displs from the MPIResult object.
543 ///
544 /// This function is only available if the corresponding data is part of the result object.
545 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
546 /// the result object.
547 /// @return Returns a reference to the underlying storage containing the send displacements.
548 template <
549 typename T = std::tuple<Args...>,
550 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::send_displs, T>(), bool> = true>
552 return internal::select_parameter_type_in_tuple<internal::ParameterType::send_displs>(_data).underlying();
553 }
554
555 /// @brief Gets the \c send_displs from the MPIResult object.
556 ///
557 /// This function is only available if the corresponding data is part of the result object.
558 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
559 /// the result object.
560 /// @return Returns a reference to the underlying storage containing the send displacements.
561 template <
562 typename T = std::tuple<Args...>,
563 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::send_displs, T>(), bool> = true>
564 auto const& get_send_displs() const {
565 return internal::select_parameter_type_in_tuple<internal::ParameterType::send_displs>(_data).underlying();
566 }
567
568 /// @brief Extracts the \c send_displs from the MPIResult object.
569 ///
570 /// This function is only available if the corresponding data is part of the result object.
571 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
572 /// the result object.
573 /// @return Returns the underlying storage containing the send displacements.
574 template <
575 typename T = std::tuple<Args...>,
576 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::send_displs, T>(), bool> = true>
578 return internal::select_parameter_type_in_tuple<internal::ParameterType::send_displs>(_data).extract();
579 }
580
581 /// @brief Gets the \c send_recv_count from the MPIResult object.
582 ///
583 /// This function is only available if the corresponding data is part of the result object.
584 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
585 /// the result object.
586 /// @return Returns a reference to the underlying storage containing the send_recv_count.
587 template <
588 typename T = std::tuple<Args...>,
589 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::send_recv_count, T>(), bool> =
590 true>
592 return internal::select_parameter_type_in_tuple<internal::ParameterType::send_recv_count>(_data).underlying();
593 }
594
595 /// @brief Gets the \c send_recv_count from the MPIResult object.
596 ///
597 /// This function is only available if the corresponding data is part of the result object.
598 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
599 /// the result object.
600 /// @return Returns a reference to the underlying storage containing the send_recv_count.
601 template <
602 typename T = std::tuple<Args...>,
603 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::send_recv_count, T>(), bool> =
604 true>
605 auto const& get_send_recv_count() const {
606 return internal::select_parameter_type_in_tuple<internal::ParameterType::send_recv_count>(_data).underlying();
607 }
608
609 /// @brief Extracts the \c send_recv_count from the MPIResult object.
610 ///
611 /// This function is only available if the corresponding data is part of the result object.
612 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
613 /// the result object.
614 /// @return Returns the underlying storage containing the send_recv_count.
615 template <
616 typename T = std::tuple<Args...>,
617 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::send_recv_count, T>(), bool> =
618 true>
620 return internal::select_parameter_type_in_tuple<internal::ParameterType::send_recv_count>(_data).extract();
621 }
622
623 /// @brief Gets the \c send_type from the MPIResult object.
624 ///
625 /// This function is only available if the corresponding data is part of the result object.
626 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
627 /// the result object.
628 /// @return Returns a reference to the underlying storage containing the send_type.
629 template <
630 typename T = std::tuple<Args...>,
631 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::send_type, T>(), bool> = true>
633 return internal::select_parameter_type_in_tuple<internal::ParameterType::send_type>(_data).underlying();
634 }
635
636 /// @brief Gets the \c send_type from the MPIResult object.
637 ///
638 /// This function is only available if the corresponding data is part of the result object.
639 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
640 /// the result object.
641 /// @return Returns a reference to the underlying storage containing the send_type.
642 template <
643 typename T = std::tuple<Args...>,
644 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::send_type, T>(), bool> = true>
645 auto const& get_send_type() const {
646 return internal::select_parameter_type_in_tuple<internal::ParameterType::send_type>(_data).underlying();
647 }
648
649 /// @brief Extracts the \c send_type from the MPIResult object.
650 ///
651 /// This function is only available if the corresponding data is part of the result object.
652 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
653 /// the result object.
654 /// @return Returns the underlying storage containing the send_type.
655 template <
656 typename T = std::tuple<Args...>,
657 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::send_type, T>(), bool> = true>
659 return internal::select_parameter_type_in_tuple<internal::ParameterType::send_type>(_data).extract();
660 }
661
662 /// @brief Gets the \c recv_type from the MPIResult object.
663 ///
664 /// This function is only available if the corresponding data is part of the result object.
665 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
666 /// the result object.
667 /// @return Returns a reference to the underlying storage containing the send_type.
668 template <
669 typename T = std::tuple<Args...>,
670 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::recv_type, T>(), bool> = true>
672 return internal::select_parameter_type_in_tuple<internal::ParameterType::recv_type>(_data).underlying();
673 }
674
675 /// @brief Gets the \c recv_type from the MPIResult object.
676 ///
677 /// This function is only available if the corresponding data is part of the result object.
678 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
679 /// the result object.
680 /// @return Returns a reference to the underlying storage containing the send_type.
681 template <
682 typename T = std::tuple<Args...>,
683 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::recv_type, T>(), bool> = true>
684 auto const& get_recv_type() const {
685 return internal::select_parameter_type_in_tuple<internal::ParameterType::recv_type>(_data).underlying();
686 }
687
688 /// @brief Extracts the \c recv_type from the MPIResult object.
689 ///
690 /// This function is only available if the corresponding data is part of the result object.
691 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
692 /// the result object.
693 /// @return Returns the underlying storage containing the send_type.
694 template <
695 typename T = std::tuple<Args...>,
696 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::recv_type, T>(), bool> = true>
698 return internal::select_parameter_type_in_tuple<internal::ParameterType::recv_type>(_data).extract();
699 }
700
701 /// @brief Gets the \c send_recv_type from the MPIResult object.
702 ///
703 /// This function is only available if the corresponding data is part of the result object.
704 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
705 /// the result object.
706 /// @return Returns the underlying storage containing the send_recv_type.
707 template <
708 typename T = std::tuple<Args...>,
709 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::send_recv_type, T>(), bool> =
710 true>
712 return internal::select_parameter_type_in_tuple<internal::ParameterType::send_recv_type>(_data).underlying();
713 }
714
715 /// @brief Gets the \c send_recv_type from the MPIResult object.
716 ///
717 /// This function is only available if the corresponding data is part of the result object.
718 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
719 /// the result object.
720 /// @return Returns the underlying storage containing the send_recv_type.
721 template <
722 typename T = std::tuple<Args...>,
723 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::send_recv_type, T>(), bool> =
724 true>
725 auto const& get_send_recv_type() const {
726 return internal::select_parameter_type_in_tuple<internal::ParameterType::send_recv_type>(_data).underlying();
727 }
728
729 /// @brief Extracts the \c send_recv_type from the MPIResult object.
730 ///
731 /// This function is only available if the corresponding data is part of the result object.
732 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
733 /// the result object.
734 /// @return Returns the underlying storage containing the send_recv_type.
735 template <
736 typename T = std::tuple<Args...>,
737 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::send_recv_type, T>(), bool> =
738 true>
740 return internal::select_parameter_type_in_tuple<internal::ParameterType::send_recv_type>(_data).extract();
741 }
742
743 /// @brief Gets the \c parameter with given parameter type from the MPIResult object.
744 ///
745 /// This function is only available if the corresponding data is part of the result object.
746 /// @tparam ptype Parameter type of the buffer to be retrieved.
747 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
748 /// the result object.
749 /// @return Returns the underlying storage containing the requested parameter.
750 template <
752 typename T = std::tuple<Args...>,
753 std::enable_if_t<internal::has_parameter_type_in_tuple<ptype, T>(), bool> = true>
754 auto& get() {
755 return internal::select_parameter_type_in_tuple<ptype>(_data).underlying();
756 }
757
758 /// @brief Gets the \c parameter with given parameter type from the MPIResult object.
759 ///
760 /// This function is only available if the corresponding data is part of the result object.
761 /// @tparam ptype Parameter type of the buffer to be retrieved.
762 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
763 /// the result object.
764 /// @return Returns the underlying storage containing the requested parameter.
765 template <
767 typename T = std::tuple<Args...>,
768 std::enable_if_t<internal::has_parameter_type_in_tuple<ptype, T>(), bool> = true>
769 auto const& get() const {
770 return internal::select_parameter_type_in_tuple<ptype>(_data).underlying();
771 }
772
773 /// @brief Get the underlying data from the i-th buffer in the result object. This method is part of the
774 /// structured binding enabling machinery.
775 ///
776 /// @tparam i Index of the data buffer to extract.
777 /// @return Returns a reference to the underlying data of the i-th data buffer.
778 template <std::size_t i>
779 auto& get() {
780 return std::get<i>(_data).underlying();
781 }
782
783 /// @brief Get the underlying data from the i-th buffer in the result object. This method is part of the
784 /// structured binding enabling machinery.
785 ///
786 /// @tparam i Index of the data buffer to extract.
787 /// @return Returns a reference to the underlying data of the i-th data buffer.
788 template <std::size_t i>
789 auto const& get() const {
790 return std::get<i>(_data).underlying();
791 }
792
793private:
794 std::tuple<Args...> _data; ///< tuple storing the data buffers
795};
796
797/// @brief Trait for checking whether a type is an \ref MPIResult.
798template <typename>
799constexpr bool is_mpi_result_v = false;
800
801/// @brief Trait for checking whether a type is an \ref MPIResult.
802template <typename... Args>
803constexpr bool is_mpi_result_v<MPIResult<Args...>> = true;
804
805/// @brief Primary template for result trait indicates whether the result object is empty.
806template <typename T>
807constexpr bool is_result_empty_v = false;
808
809/// @brief Template specialization for result trait indicates whether the result object is
810/// empty.
811template <typename... Args>
812constexpr bool is_result_empty_v<MPIResult<Args...>> = MPIResult<Args...>::is_empty;
813
814/// @brief Template specialization for result trait indicates whether the result object is
815/// empty.
816template <>
817inline constexpr bool is_result_empty_v<void> = true;
818
819} // namespace kamping
820
821namespace std {
822
823/// @brief Specialization of the std::tuple_size for \ref kamping::MPIResult. Part of the structured binding machinery.
824///
825/// @tparam Args Automatically deducted template parameters.
826template <typename... Args>
827struct tuple_size<kamping::MPIResult<Args...>> {
828 static constexpr size_t value = sizeof...(Args); ///< Number of data buffers in the \ref kamping::MPIResult.
829};
830
831/// @brief Specialization of the std::tuple_element for \ref kamping::MPIResult. Part of the structured binding
832/// machinery.
833///
834/// @param index Index of the entry of \ref kamping::MPIResult for which the underlying data type shall be deduced.
835/// @tparam Args Automatically deducted template parameters.
836template <size_t index, typename... Args>
837struct tuple_element<index, kamping::MPIResult<Args...>> {
838 using type = std::remove_reference_t<decltype(declval<kamping::MPIResult<Args...>>().template get<index>()
839 )>; ///< Type of the underlying data of the i-th data buffer in the result object.
840};
841
842} // namespace std
843
844namespace kamping::internal {
845
846/// @brief Determines whether only the recv (send_recv) buffer or multiple different buffers will be returned.
847/// @tparam CallerProvidedOwningOutBuffers An std::tuple containing the types of the owning, out buffers explicitly
848/// requested by the caller of the wrapped MPI call.
849/// @returns \c True if the recv (send_recv) buffer is either not mentioned explicitly and no other (owning) out buffers
850/// are requested or the only explicitly requested owning out buffer is the recv_buf. \c False otherwise.
851template <typename CallerProvidedOwningOutBuffers>
853 constexpr std::size_t num_caller_provided_owning_out_buffers = std::tuple_size_v<CallerProvidedOwningOutBuffers>;
854 if constexpr (num_caller_provided_owning_out_buffers == 0) {
855 return true;
856 } else if constexpr (num_caller_provided_owning_out_buffers == 1 && std::tuple_element_t<0, CallerProvidedOwningOutBuffers>::value == ParameterType::recv_buf) {
857 return true;
858 } else if constexpr (num_caller_provided_owning_out_buffers == 1 && std::tuple_element_t<0, CallerProvidedOwningOutBuffers>::value == ParameterType::send_recv_buf) {
859 return true;
860 } else {
861 return false;
862 }
863}
864
865/// @brief Checks whether a buffer with parameter type recv_buf or a buffer with type send_recv_buf is present and
866/// returns the found parameter type. Note that we require that either a recv_buf or a send_recv_buf is present.
867///
868/// @tparam Buffers All buffer types to be searched for type `recv_buf` or `send_recv_buf`.
869/// @returns The parameter type of the first buffer whose parameter type is recv_buf or send_recv_buf.
870template <typename... Buffers>
872 constexpr bool has_recv_buffer = internal::has_parameter_type<internal::ParameterType::recv_buf, Buffers...>();
873 constexpr bool has_send_recv_buffer =
875 static_assert(has_recv_buffer ^ has_send_recv_buffer, "either a recv or a send_recv buffer must be present");
876 if constexpr (has_recv_buffer) {
878 } else {
880 }
881}
882
883/// @brief List of parameter type (entries) which should not be included in the result object.
894
895///@brief Predicate to check whether a buffer provided to \ref make_mpi_result() shall be discard or returned in the
896/// result object.
898 ///@brief Discard function to check whether a buffer provided to \ref make_mpi_result() shall be discard or returned
899 /// in the result object.
900 /// call.
901 ///
902 ///@tparam BufferType BufferType to be checked.
903 ///@return \c True (i.e. discard) iff Arg's parameter_type is `sparse_send_buf`, `on_message` or `destination`.
904 template <typename BufferType>
905 static constexpr bool discard() {
907 if constexpr (parameter_types_to_ignore_for_result_object::contains<ptype_entry>) {
908 return true;
909 } else {
910 return !BufferType::is_owning
911 || !BufferType::is_out_buffer; ///< Predicate which Head has to fulfill to be kept.
912 }
913 }
914};
915
916/// @brief Helper to check if a type `T` has a member type `T::DataBufferType`.
917template <typename, typename = void>
918constexpr bool has_data_buffer_type_member = false;
919
920/// @brief Helper to check if a type `T` has a member type `T::DataBufferType`.
921template <typename T>
923
924///@brief Predicate to check whether a buffer provided to \ref make_mpi_result() shall be discard or returned in the
925/// result object, including a hotfix for serialization.
927 /// @brief Discard function to check whether a buffer provided to \ref make_mpi_result() shall be discard or
928 /// returned in the result object. call.
929 ///
930 /// @tparam BufferType BufferType to be checked.
931 /// @return \c True (i.e. discard) iff \ref PredicateForResultObject discards this, or if the parameter uses
932 /// serialization, so we don't expose serialization buffers to the user.
933 ///
934 /// @todo this a quick and dirty hack, in the future we want to select which parameters to return based on a flag.
935 /// Currently we assume that we want to return everything that is out and owning.
936 template <typename BufferType>
937 static constexpr bool discard() {
938 if (PredicateForResultObject::discard<BufferType>()) {
939 return true;
940 }
941 // we sometimes call this with DataBuffers and sometimes with DataBufferBuilder, so we need a case distinction
942 // here.
944 if constexpr (ptype_entry::parameter_type == internal::ParameterType::recv_buf || ptype_entry::parameter_type == internal::ParameterType::send_recv_buf) {
947 } else {
949 }
950 }
951 return false;
952 }
953};
954
955/// @brief Returns True iff only a recv or send_recv buffer is present.
956/// Communicator::ibarrier()).
957///
958/// @tparam Buffers All buffer types to be searched for type `status`.
959template <typename... Buffers>
961 constexpr bool has_recv_buffer = internal::has_parameter_type<internal::ParameterType::recv_buf, Buffers...>();
962 constexpr bool has_send_recv_buffer =
964 return has_recv_buffer || has_send_recv_buffer;
965}
966
967/// @brief Determines whether only the send buffer should be returned.
968/// This may happen if ownership of the send buffer is transfered to the call.
969template <typename CallerProvidedOwningOutBuffers, typename... Buffers>
970constexpr bool return_send_buf_out_only() {
971 constexpr std::size_t num_caller_provided_owning_out_buffers = std::tuple_size_v<CallerProvidedOwningOutBuffers>;
973 return std::tuple_element_t<0, CallerProvidedOwningOutBuffers>::value == ParameterType::send_buf;
974 } else {
975 return false;
976 }
977}
978
979/// @brief Template class to prepend the ParameterTypeEntry<ParameterType::ptype> type to a given std::tuple.
980/// @tparam ptype ParameterType to prepend
981/// @tparam Tuple An std::tuple.
982template <ParameterType ptype, typename Tuple>
985 type; ///< Concatenated tuple, i.e. type = std::tuple<TypeToPrepend, (Type contained in Tuple)... >.
986};
987
988/// @brief Construct result object for a wrapped MPI call. Four different cases are handled:
989/// a) The recv_buffer owns its underlying data (i.e. the received data has to be returned via the result object):
990///
991/// a.1) The recv_buffer is the only buffer to be returned, i.e. the only caller provided owning out buffer:
992/// In this case, the recv_buffers's underlying data is extracted and returned directly (by value).
993///
994/// a.2) There are multiple buffers to be returned and recv_buffer is explicitly provided by the caller:
995/// In this case a \ref kamping::MPIResult object is created, which stores the buffers to return (owning out buffers)
996/// in a std::tuple respecting the order in which these buffers where provided to the wrapped MPI call. This enables
997/// unpacking the object via structured binding.
998///
999/// a.3) There are more data buffers to be returned and recv_buffer is *not* explicitly provided by the caller:
1000/// In this case a \ref kamping::MPIResult object is created, which stores the buffers to return. The
1001/// recv_buffer is always the first entry in the result object followed by the other buffers respecting the order in
1002/// which these buffers where provided to the wrapped MPI call.
1003///
1004/// b) There is no recv buffer (see \ref Communicator::probe() for example) or the recv_buffer only references its
1005/// underlying data (i.e. it is a non-owning out buffer): In this case recv_buffer is not part of the result object. The
1006/// \ref kamping::MPIResult object stores the buffer to return (owning buffers for which a *_out() named parameter was
1007/// passed to the wrapped MPI call) in a std::tuple respecting the order in which these buffers where provided to the
1008/// wrapped MPI call.
1009///
1010/// @tparam CallerProvidedArgs Types of arguments passed to the wrapped MPI call.
1011/// @tparam Buffers Types of data buffers created/filled within the wrapped MPI call.
1012/// @param buffers data buffers created/filled within the wrapped MPI call.
1013/// @return result object as specified above.
1014///
1015/// @see \ref docs/parameter_handling.md
1016template <typename CallerProvidedArgs, typename... Buffers>
1018 // filter named parameters provided to the wrapped MPI function and keep only owning out parameters (=owning out
1019 // buffers)
1024 constexpr std::size_t num_caller_provided_owning_out_buffers =
1025 std::tuple_size_v<CallerProvidedOwningOutParametersWithoutSerializationBuffers>;
1027 auto& send_buffer = internal::select_parameter_type<ParameterType::send_buf>(buffers...);
1028 return send_buffer.extract();
1029 } else if constexpr (!has_recv_or_send_recv_buf<Buffers...>()) {
1030 // do no special handling for receive buffer at all, since there is none.
1032 } else {
1033 // receive (send-receive) buffer needs (potentially) a special treatment (if it is an owning (out) buffer
1034 // and provided by the caller)
1036 auto& recv_or_send_recv_buffer = internal::select_parameter_type<recv_parameter_type>(buffers...);
1037 constexpr bool recv_or_send_recv_buf_is_owning =
1038 std::remove_reference_t<decltype(recv_or_send_recv_buffer)>::is_owning;
1041
1042 // special case 1: recv (send_recv) buffer is not owning
1043 if constexpr (!recv_or_send_recv_buf_is_owning) {
1044 if constexpr (num_caller_provided_owning_out_buffers == 0) {
1045 // there are no buffers to return
1046 return;
1047 } else {
1048 // no special treatment of recv buffer is needed as the recv_buffer is not part of the result
1049 // object anyway.
1051 }
1052 }
1053 // specialcase 2: recv (send_recv) buffer is the only owning out parameter
1055 // if only the receive buffer shall be returned, its underlying data is returned directly instead of a
1056 // wrapping result object
1057 return recv_or_send_recv_buffer.extract();
1058 }
1059
1060 // case A: recv (send_recv) buffer is provided by caller (and owning)
1063 }
1064 // case B: recv buffer is not provided by caller -> recv buffer will be stored as first entry in
1065 // underlying result object
1066 else {
1067 using ParametersToReturn =
1070 }
1071 }
1072}
1073
1074namespace impl {
1075/// @brief Implementation helper function to enable the construction of an MPIResult object also if the buffers are
1076/// stored inside a std::tuple. See \ref make_mpi_result_from_tuple() for more details.
1077template <typename ParameterTypeTuple, typename... Buffers, std::size_t... i>
1079 std::tuple<Buffers...>& buffers, std::index_sequence<i...> /*index_sequence*/
1080) {
1081 return make_mpi_result<ParameterTypeTuple>(std::get<i>(buffers)...);
1082}
1083} // namespace impl
1084
1085/// @brief Wrapper function to enable the construction of an MPIResult object also if the buffers are stored inside a
1086/// std::tuple. See \ref make_mpi_result() for more details.
1087///
1088/// @tparam CallerProvidedArgs Types of arguments passed to the wrapped MPI call.
1089/// @tparam Buffers Types of data buffers created/filled within the wrapped MPI call.
1090/// @param buffers data buffers created/filled within the wrapped MPI call bundled within a std::tuple.
1091template <typename CallerProvidedArgs, typename... Buffers>
1092auto make_mpi_result_from_tuple(std::tuple<Buffers...>& buffers) {
1093 constexpr std::size_t num_buffers = sizeof...(Buffers);
1094 return impl::make_mpi_result_from_tuple<CallerProvidedArgs>(buffers, std::make_index_sequence<num_buffers>{});
1095}
1096} // namespace kamping::internal
1097
1098namespace kamping {
1099
1100/// @brief NonBlockingResult contains the result of a non-blocking \c MPI call wrapped by KaMPIng. It encapsulates a
1101/// \ref kamping::Request and stores the buffers associated with the non-blocking call. Upon completion the owning
1102/// out-buffers among all associated buffers are returned wrappend in an \ref MPIResult object.
1103///
1104/// @tparam CallerProvidedArgs Types of arguments passed to the wrapped MPI call.
1105/// @tparam RequestDataBuffer Container encapsulating the underlying request.
1106/// @tparam Buffers Types of buffers associated with the underlying non-blocking MPI call.
1107template <typename CallerProvidedArgs, typename RequestDataBuffer, typename... Buffers>
1109public:
1110 /// @brief Constructor for \c NonBlockingResult.
1111 /// @param buffers_on_heap Buffers stored on the heap which are required by the non-blocking mpi operation
1112 /// associated with the given request upon completition.
1113 /// @param request A \ref kamping::internal::DataBuffer containing the associated \ref kamping::Request.
1114 NonBlockingResult(std::unique_ptr<std::tuple<Buffers...>> buffers_on_heap, RequestDataBuffer request)
1115 : _buffers_on_heap(std::move(buffers_on_heap)),
1116 _request(std::move(request)) {}
1117
1118 /// @brief Constructor for \c NonBlockingResult.
1119 /// @param request A \ref kamping::internal::DataBuffer containing the associated \ref kamping::Request.
1121
1122 /// @brief \c true if the result object owns the underlying \ref kamping::Request.
1123 static constexpr bool owns_request = internal::has_extract_v<RequestDataBuffer>;
1124
1125 /// @brief Extracts the components of this results, leaving the user responsible.
1126 ///
1127 /// If this result owns the underlying request:
1128 /// - returns a \c std::pair containing the \ref Request and \ref
1129 /// MPIResult if the result object contains owning out buffers.
1130 /// - returns only the \ref Request object otherwise.
1131 ///
1132 /// If the request is owned by the user
1133 /// - return the underlying \ref MPIResult if the result object contains any owning out buffers.
1134 /// - returns nothing otherwise.
1135 ///
1136 /// Note that the result may be in an undefined state because the associated operations is still underway and it
1137 /// is the user's responsibilty to ensure that the corresponding request has been completed before accessing the
1138 /// result.
1139 auto extract() {
1140 if constexpr (owns_request) {
1141 if constexpr (is_result_empty_v<decltype(extract_result())>) {
1142 return _request.extract();
1143 } else {
1144 auto result =
1145 extract_result(); // we try to extract the result first, so that we get a nice error message
1146 // TODO: return a named struct
1147 return std::pair(_request.extract(), std::move(result));
1148 }
1149 } else {
1150 if constexpr (is_result_empty_v<decltype(extract_result())>) {
1151 return;
1152 } else {
1153 return extract_result();
1154 }
1155 }
1156 }
1157
1158 /// @brief Waits for the underlying \ref Request to complete by calling \ref Request::wait() and upon completion
1159 /// returns:
1160 ///
1161 /// If \p status is an out-parameter:
1162 /// - If the result is not empty (see \ref is_result_empty_v), an \c std::pair containing an \ref MPIResult
1163 /// and the status.
1164 /// - If the result is empty, only the status is returned.
1165 ///
1166 /// If \p is \c kamping::status(ignore<>), or not an out-paramter:
1167 /// - If the result is not empty (see \ref is_result_empty_v), only the result is returned.
1168 /// - If the result is empty, nothing is returned.
1169 ///
1170 /// This method is only available if this result owns the underlying request. If this is not the case, the user
1171 /// must manually wait on the request that they own and manually obtain the result via \ref extract().
1172 ///
1173 /// @param status A parameter created by \ref kamping::status() or \ref kamping::status_out().
1174 /// Defaults to \c kamping::status(ignore<>).
1175 template <
1176 typename StatusParamObjectType = decltype(status(ignore<>)),
1178 typename std::enable_if<NonBlockingResulType_::owns_request, bool>::type = true>
1180 static_assert(
1181 StatusParamObjectType::parameter_type == internal::ParameterType::status,
1182 "Only status parameters are allowed."
1183 );
1184 kassert_not_extracted("The result of this request has already been extracted.");
1185 constexpr bool return_status = internal::is_extractable<StatusParamObjectType>;
1186 using result_type = std::remove_reference_t<decltype(extract_result())>;
1187 if constexpr (!is_result_empty_v<result_type>) {
1188 if constexpr (return_status) {
1189 auto status_return = _request.underlying().wait(std::move(status));
1190 return std::make_pair(extract_result(), std::move(status_return));
1191 } else {
1192 _request.underlying().wait(std::move(status));
1193 return extract_result();
1194 }
1195 } else {
1196 return _request.underlying().wait(std::move(status));
1197 }
1198 }
1199
1200 /// @brief Tests the underlying \ref Request for completion by calling \ref
1201 /// Request::test() and returns a value convertible to \c bool indicating if the request is complete.
1202 ///
1203 /// The type of the return value depends on the encapsulated result and the \p status parameter and follows the
1204 /// same semantics as \ref wait(), but its return value is wrapped in an \c std::optional. The optional only
1205 /// contains a value if the request is complete, i.e. \c test() succeeded.
1206 ///
1207 /// If both the result is empty and no status returned, returns a \c bool indicating completion instead of an \c
1208 /// std::optional.
1209 ///
1210 /// This method is only available if this result owns the underlying request. If this is not the case, the user
1211 /// must manually test the request that they own and manually obtain the result via \ref extract().
1212 ///
1213 /// @param status A parameter created by \ref kamping::status() or \ref kamping::status_out().
1214 /// Defaults to \c kamping::status(ignore<>).
1215 template <
1216 typename StatusParamObjectType = decltype(status(ignore<>)),
1218 typename std::enable_if<NonBlockingResulType_::owns_request, bool>::type = true>
1220 static_assert(
1221 StatusParamObjectType::parameter_type == internal::ParameterType::status,
1222 "Only status parameters are allowed."
1223 );
1224 kassert_not_extracted("The result of this request has already been extracted.");
1225 constexpr bool return_status = internal::is_extractable<StatusParamObjectType>;
1226 using result_type = std::remove_reference_t<decltype(extract_result())>;
1227 if constexpr (!is_result_empty_v<result_type>) {
1228 if constexpr (return_status) {
1229 auto status_return = _request.underlying().test(std::move(status));
1230 if (status_return) {
1231 return std::optional{std::pair{extract_result(), std::move(*status_return)}};
1232 } else {
1233 return std::optional<std::pair<result_type, typename decltype(status_return)::value_type>>{};
1234 }
1235 } else {
1236 if (_request.underlying().test(std::move(status))) {
1237 return std::optional{extract_result()};
1238 } else {
1239 return std::optional<result_type>{};
1240 }
1241 }
1242 } else {
1243 return _request.underlying().test(std::move(status));
1244 }
1245 }
1246
1247 /// @brief Returns a pointer to the underlying request.
1249 return _request.underlying().request_ptr();
1250 }
1251
1252private:
1253 /// @brief Moves the wrapped \ref MPIResult out of this object.
1254 auto extract_result() {
1255 kassert_not_extracted("The result of this request has already been extracted.");
1256 set_extracted();
1257 return internal::make_mpi_result_from_tuple<CallerProvidedArgs>(*_buffers_on_heap.get());
1258 }
1259
1260 void set_extracted() {
1261#if KASSERT_ENABLED(KAMPING_ASSERTION_LEVEL_NORMAL)
1262 is_extracted = true;
1263#endif
1264 }
1265
1266 /// @brief Throws an assertion if the extracted flag is set, i.e. the underlying status has been moved out.
1267 ///
1268 /// @param message The message for the assertion.
1269 void kassert_not_extracted(std::string const message [[maybe_unused]]) const {
1270#if KASSERT_ENABLED(KAMPING_ASSERTION_LEVEL_NORMAL)
1271 KASSERT(!is_extracted, message, assert::normal);
1272#endif
1273 }
1274 std::unique_ptr<std::tuple<Buffers...>> _buffers_on_heap; ///< The wrapped \ref MPIResult.
1275 RequestDataBuffer _request; ///< DataBuffer containing the wrapped \ref Request.
1276#if KASSERT_ENABLED(KAMPING_ASSERTION_LEVEL_NORMAL)
1277 bool is_extracted = false; ///< Has the status been extracted and is therefore in an invalid state?
1278#endif
1279};
1280
1281namespace internal {
1282
1283/// @brief Moves given buffers into a std::tuple wrapped with an std::unique_ptr on the heap.
1284///
1285/// @tparam Buffers... Types of the buffers to be moved to the heap.
1286/// @param buffers Buffers to be moved to the heap.
1287/// @return std::unique_ptr wrapping a std::tuple containing the passed buffers.
1288template <typename... Buffers>
1290 using BufferTuple = std::tuple<std::remove_reference_t<Buffers>...>;
1291 return std::make_unique<BufferTuple>(std::move(buffers)...);
1292}
1293
1294/// @brief Factory for creating a \ref kamping::NonBlockingResult.
1295///
1296/// Makes an \ref kamping::NonBlockingResult from all arguments passed and inserts internal::ResultCategoryNotUsed
1297/// when no fitting parameter type is passed as argument.
1298///
1299/// Note that an argument of with type \ref kamping::internal::ParameterType::request is required.
1300///
1301/// @tparam CallerProvidedArgs Types of arguments passed to the wrapped MPI call.
1302/// @tparam RequestDataBuffer Container encapsulating the underlying request.
1303/// @tparam Buffers Types of buffers associated with the underlying non-blocking MPI call.
1304/// @param request Request associated with the non-blocking \c MPI call.
1305/// @param buffers_on_heap Buffers associated with the non-blocking \c MPI call stored in a tuple on the heap.
1306/// @return \ref kamping::NonBlockingResult encapsulating all passed parameters.
1307template <typename CallerProvidedArgsInTuple, typename RequestDataBuffer, typename... Buffers>
1308auto make_nonblocking_result(RequestDataBuffer&& request, std::unique_ptr<std::tuple<Buffers...>> buffers_on_heap) {
1310 std::move(buffers_on_heap),
1311 std::move(request)
1312 );
1313}
1314
1315/// @brief Factory for creating a \ref kamping::NonBlockingResult.
1316///
1317/// Makes an \ref kamping::NonBlockingResult from all arguments passed and inserts internal::ResultCategoryNotUsed
1318/// when no fitting parameter type is passed as argument.
1319///
1320/// Note that an argument of with type \ref kamping::internal::ParameterType::request is required.
1321///
1322/// @tparam RequestDataBuffer Container encapsulating the underlying request.
1323/// @param request Request associated with the non-blocking \c MPI call.
1324/// @return \ref kamping::NonBlockingResult encapsulating all passed parameters.
1325template <typename RequestDataBuffer>
1327 return NonBlockingResult<std::tuple<>, std::remove_reference_t<RequestDataBuffer>>(std::move(request));
1328}
1329} // namespace internal
1330} // namespace kamping
STL-compatible allocator for requesting memory using the builtin MPI allocator.
Definition allocator.hpp:32
MPIResult contains the result of a MPI call wrapped by KaMPIng.
Definition result.hpp:67
auto const & get_recv_count() const
Gets the recv_count from the MPIResult object.
Definition result.hpp:408
auto extract_recv_buffer()
Extracts the recv_buffer from the MPIResult object. Alias for extract_recv_buf().
Definition result.hpp:250
auto & get_send_type()
Gets the send_type from the MPIResult object.
Definition result.hpp:632
auto const & get_recv_type() const
Gets the recv_type from the MPIResult object.
Definition result.hpp:684
auto & get_send_recv_type()
Gets the send_recv_type from the MPIResult object.
Definition result.hpp:711
auto & get_status()
Get the kamping::Status from the MPIResult object.
Definition result.hpp:96
auto & get_recv_buffer()
Get the recv_buffer from the MPIResult object. Alias for get_recv_buf().
Definition result.hpp:152
auto const & get_recv_displs() const
Gets the recv_displs from the MPIResult object.
Definition result.hpp:447
auto extract_send_counts()
Extracts the send_counts from the MPIResult object.
Definition result.hpp:499
auto const & get_status() const
Get the kamping::Status from the MPIResult object.
Definition result.hpp:110
auto extract_recv_counts()
Extracts the recv_counts from the MPIResult object.
Definition result.hpp:382
auto extract_recv_count()
Extracts the recv_count from the MPIResult object.
Definition result.hpp:421
auto const & get_send_type() const
Gets the send_type from the MPIResult object.
Definition result.hpp:645
auto extract_send_count()
Extracts the send_count from the MPIResult object.
Definition result.hpp:538
auto & get_send_count()
Gets the send_count from the MPIResult object.
Definition result.hpp:512
auto & get_recv_counts()
Get the recv_counts from the MPIResult object.
Definition result.hpp:356
auto extract_recv_displs()
Extracts the recv_displs from the MPIResult object.
Definition result.hpp:460
auto const & get_send_counts() const
Gets the send_counts from the MPIResult object.
Definition result.hpp:486
auto & get_recv_displs()
Gets the recv_displs from the MPIResult object.
Definition result.hpp:434
auto & get()
Gets the parameter with given parameter type from the MPIResult object.
Definition result.hpp:754
auto & get_send_displs()
Gets the send_displs from the MPIResult object.
Definition result.hpp:551
auto const & get() const
Get the underlying data from the i-th buffer in the result object. This method is part of the structu...
Definition result.hpp:789
auto & get_recv_count()
Gets the recv_count from the MPIResult object.
Definition result.hpp:395
auto const & get_recv_buffer() const
Get the recv_buffer from the MPIResult object. Alias for get_recv_buf().
Definition result.hpp:180
static constexpr bool has_send_recv_buffer
true, if the result encapsulates a send_recv_buf.
Definition result.hpp:74
auto const & get_send_buf() const
Get the send_buffer from the MPIResult object.
Definition result.hpp:194
auto const & get_recv_buf() const
Get the recv_buffer from the MPIResult object.
Definition result.hpp:166
auto extract_send_recv_type()
Extracts the send_recv_type from the MPIResult object.
Definition result.hpp:739
auto extract_recv_buf()
Extracts the recv_buffer from the MPIResult object.
Definition result.hpp:236
auto extract_send_recv_count()
Extracts the send_recv_count from the MPIResult object.
Definition result.hpp:619
auto const & get_send_recv_count() const
Gets the send_recv_count from the MPIResult object.
Definition result.hpp:605
auto extract_recv_type()
Extracts the recv_type from the MPIResult object.
Definition result.hpp:697
auto & get_send_counts()
Gets the send_counts from the MPIResult object.
Definition result.hpp:473
auto const & get_send_buffer() const
Get the send_buffer from the MPIResult object. Alias for get_send_buf().
Definition result.hpp:208
auto & get_recv_type()
Gets the recv_type from the MPIResult object.
Definition result.hpp:671
auto extract_send_type()
Extracts the send_type from the MPIResult object.
Definition result.hpp:658
auto extract_send_displs()
Extracts the send_displs from the MPIResult object.
Definition result.hpp:577
auto const & get_recv_counts() const
Get the recv_counts from the MPIResult object.
Definition result.hpp:369
auto const & get() const
Gets the parameter with given parameter type from the MPIResult object.
Definition result.hpp:769
auto extract_status()
Extracts the kamping::Status from the MPIResult object.
Definition result.hpp:124
auto & get_send_recv_count()
Gets the send_recv_count from the MPIResult object.
Definition result.hpp:591
auto const & get_send_displs() const
Gets the send_displs from the MPIResult object.
Definition result.hpp:564
auto & get_recv_buf()
Get the recv_buffer from the MPIResult object.
Definition result.hpp:138
static constexpr bool is_empty
true, if the result does not encapsulate any data.
Definition result.hpp:70
auto & get()
Get the underlying data from the i-th buffer in the result object. This method is part of the structu...
Definition result.hpp:779
auto const & get_send_recv_type() const
Gets the send_recv_type from the MPIResult object.
Definition result.hpp:725
auto const & get_send_count() const
Gets the send_count from the MPIResult object.
Definition result.hpp:525
MPIResult(std::tuple< Args... > &&data)
Constructor for MPIResult.
Definition result.hpp:84
auto extract_send_buf()
Extracts the send_buffer from the MPIResult object.
Definition result.hpp:222
static constexpr bool has_recv_buffer
true, if the result encapsulates a recv_buf.
Definition result.hpp:72
NonBlockingResult contains the result of a non-blocking MPI call wrapped by KaMPIng....
Definition result.hpp:1108
auto test(StatusParamObjectType status=kamping::status(ignore<>))
Tests the underlying Request for completion by calling Request::test() and returns a value convertibl...
Definition result.hpp:1219
static constexpr bool owns_request
true if the result object owns the underlying kamping::Request.
Definition result.hpp:1123
NonBlockingResult(std::unique_ptr< std::tuple< Buffers... > > buffers_on_heap, RequestDataBuffer request)
Constructor for NonBlockingResult.
Definition result.hpp:1114
auto wait(StatusParamObjectType status=kamping::status(ignore<>))
Waits for the underlying Request to complete by calling Request::wait() and upon completion returns:
Definition result.hpp:1179
MPI_Request * get_request_ptr()
Returns a pointer to the underlying request.
Definition result.hpp:1248
NonBlockingResult(RequestDataBuffer request)
Constructor for NonBlockingResult.
Definition result.hpp:1120
auto extract()
Extracts the components of this results, leaving the user responsible.
Definition result.hpp:1139
constexpr int normal
Default assertion level. This level is used if no assertion level is specified.
Definition assertion_levels.hpp:19
auto status(internal::ignore_t< void >)
pass MPI_STATUS_IGNORE to the underlying MPI call.
Definition status_parameters.hpp:52
auto request()
Internally allocate a request object and return it to the user.
Definition named_parameters.hpp:1122
ParameterType
Each input parameter to one of the MPI calls wrapped by KaMPIng needs to has one of the following tag...
Definition named_parameter_types.hpp:33
constexpr bool has_parameter_type()
Checks if parameter with requested parameter type exists.
Definition named_parameter_selection.hpp:186
@ status
Tag used to represent the status in a MPI call.
Macros for generating concept-like type traits to check for member functions of objects.
#define KAMPING_MAKE_HAS_MEMBER(Member)
Macro for generating has_member_xxx and has_member_xxx_v templates. They return true if the type give...
Definition has_member.hpp:91
Template magic to check named parameters passed to wrappers at compile time.
Template magic to implement named parameters in cpp.
File containing the parameter types used by the KaMPIng library.
Internal namespace marking the code that is not user-facing.
Definition collectives_helpers.hpp:20
constexpr bool is_extractable
Helper for implementing the extract_* functions in MPIResult. Is true if the passed buffer type owns ...
Definition result.hpp:48
constexpr bool return_recv_or_send_recv_buffer_only()
Determines whether only the recv (send_recv) buffer or multiple different buffers will be returned.
Definition result.hpp:852
constexpr bool return_send_buf_out_only()
Determines whether only the send buffer should be returned. This may happen if ownership of the send ...
Definition result.hpp:970
constexpr bool has_extract_v
has_extract_v is true iff type T has a member function extract().
Definition result.hpp:40
auto move_buffer_to_heap(Buffers &&... buffers)
Moves given buffers into a std::tuple wrapped with an std::unique_ptr on the heap.
Definition result.hpp:1289
constexpr bool has_data_buffer_type_member
Helper to check if a type T has a member type T::DataBufferType.
Definition result.hpp:918
auto make_mpi_result(Buffers &&... buffers)
Construct result object for a wrapped MPI call. Four different cases are handled: a) The recv_buffer ...
Definition result.hpp:1017
constexpr bool has_recv_or_send_recv_buf()
Returns True iff only a recv or send_recv buffer is present. Communicator::ibarrier()).
Definition result.hpp:960
constexpr ParameterType determine_recv_buffer_type()
Checks whether a buffer with parameter type recv_buf or a buffer with type send_recv_buf is present a...
Definition result.hpp:871
auto make_mpi_result_from_tuple(std::tuple< Buffers... > &buffers)
Wrapper function to enable the construction of an MPIResult object also if the buffers are stored ins...
Definition result.hpp:1092
auto make_nonblocking_result(RequestDataBuffer &&request, std::unique_ptr< std::tuple< Buffers... > > buffers_on_heap)
Factory for creating a kamping::NonBlockingResult.
Definition result.hpp:1308
STL namespace.
auto make_mpi_result_from_tuple(std::tuple< Buffers... > &buffers, std::index_sequence< i... >)
Implementation helper function to enable the construction of an MPIResult object also if the buffers ...
Definition result.hpp:1078
constexpr bool is_mpi_result_v
Trait for checking whether a type is an MPIResult.
Definition result.hpp:799
constexpr bool is_result_empty_v
Primary template for result trait indicates whether the result object is empty.
Definition result.hpp:807
Predicate to check whether a buffer provided to make_mpi_result() shall be discard or returned in the...
Definition result.hpp:926
static constexpr bool discard()
Discard function to check whether a buffer provided to make_mpi_result() shall be discard or returned...
Definition result.hpp:937
Base template used to filter a list of types and only keep those whose types meet specified criteria....
Definition named_parameter_filtering.hpp:46
Predicate to check whether a buffer provided to make_mpi_result() shall be discard or returned in the...
Definition result.hpp:897
static constexpr bool discard()
Discard function to check whether a buffer provided to make_mpi_result() shall be discard or returned...
Definition result.hpp:905
Template class to prepend the ParameterTypeEntry<ParameterType::ptype> type to a given std::tuple.
Definition result.hpp:983
typename PrependType< std::integral_constant< internal::ParameterType, ptype >, Tuple >:: type type
Concatenated tuple, i.e. type = std::tuple<TypeToPrepend, (Type contained in Tuple)....
Definition result.hpp:984
Use this type if one of the template parameters of MPIResult is not used for a specific wrapped MPI c...
Definition result.hpp:43
Helper type for representing a type list.
Definition parameter_objects.hpp:326
std::remove_reference_t< decltype(declval< kamping::MPIResult< Args... > >().template get< index >())> type
Type of the underlying data of the i-th data buffer in the result object.
Definition result.hpp:838