KaMPIng 0.1.0
(Near) zero-overhead C++ MPI bindings.
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>
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.
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>
152 auto const& get_recv_buffer() const {
153 return internal::select_parameter_type_in_tuple<internal::ParameterType::recv_buf>(_data).underlying();
154 }
155
156 /// @brief Get the \c send_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 elements to send.
163 template <
164 typename T = std::tuple<Args...>,
165 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::send_buf, T>(), bool> = true>
166 auto const& get_send_buffer() const {
167 return internal::select_parameter_type_in_tuple<internal::ParameterType::send_buf>(_data).underlying();
168 }
169
170 /// @brief Extracts the \c recv_buffer from the MPIResult object.
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 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>
181 return internal::select_parameter_type_in_tuple<internal::ParameterType::recv_buf>(_data).extract();
182 }
183
184 /// @brief Get the \c send_recv_buffer from the MPIResult object. @todo discuss this
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 received elements.
191 template <
192 typename T = std::tuple<Args...>,
193 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::send_recv_buf, T>(), bool> =
194 true>
196 return internal::select_parameter_type_in_tuple<internal::ParameterType::send_recv_buf>(_data).underlying();
197 }
198
199 /// @brief Get the \c send_recv_buffer from the MPIResult object. @todo discuss this
200 ///
201 /// This function is only available if the underlying memory is owned by the
202 /// MPIResult object.
203 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
204 /// the result object.
205 /// @return Returns a reference to the underlying storage containing the received elements.
206 template <
207 typename T = std::tuple<Args...>,
208 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::send_recv_buf, T>(), bool> =
209 true>
210 auto const& get_recv_buffer() const {
211 return internal::select_parameter_type_in_tuple<internal::ParameterType::send_recv_buf>(_data).underlying();
212 }
213
214 /// @brief Extracts the \c send_recv_buffer from the MPIResult object. @todo discuss this
215 ///
216 /// This function is only available if the underlying memory is owned by the
217 /// MPIResult object.
218 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
219 /// the result object.
220 /// @return Returns the underlying storage containing the received elements.
221 template <
222 typename T = std::tuple<Args...>,
223 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::send_recv_buf, T>(), bool> =
224 true>
226 return internal::select_parameter_type_in_tuple<internal::ParameterType::send_recv_buf>(_data).extract();
227 }
228
229 /// @brief Get the \c recv_counts from the MPIResult object.
230 ///
231 /// This function is only available if the corresponding data is part of the result object.
232 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
233 /// the result object.
234 /// @return Returns a reference to the underlying storage containing the receive counts.
235 template <
236 typename T = std::tuple<Args...>,
237 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::recv_counts, T>(), bool> = true>
239 return internal::select_parameter_type_in_tuple<internal::ParameterType::recv_counts>(_data).underlying();
240 }
241
242 /// @brief Get the \c recv_counts from the MPIResult object.
243 ///
244 /// This function is only available if the corresponding data is part of the result object.
245 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
246 /// the result object.
247 /// @return Returns a reference to the underlying storage containing the receive counts.
248 template <
249 typename T = std::tuple<Args...>,
250 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::recv_counts, T>(), bool> = true>
251 auto const& get_recv_counts() const {
252 return internal::select_parameter_type_in_tuple<internal::ParameterType::recv_counts>(_data).underlying();
253 }
254
255 /// @brief Extracts the \c recv_counts from the MPIResult object.
256 ///
257 /// This function is only available if the corresponding data is part of the result 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 the underlying storage containing the receive counts.
261 template <
262 typename T = std::tuple<Args...>,
263 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::recv_counts, T>(), bool> = true>
265 return internal::select_parameter_type_in_tuple<internal::ParameterType::recv_counts>(_data).extract();
266 }
267
268 /// @brief Gets the \c recv_count from the MPIResult object.
269 ///
270 /// This function is only available if the corresponding data is part of the result object.
271 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
272 /// the result object.
273 /// @return Returns a reference to the underlying storage containing the recv count.
274 template <
275 typename T = std::tuple<Args...>,
276 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::recv_count, T>(), bool> = true>
278 return internal::select_parameter_type_in_tuple<internal::ParameterType::recv_count>(_data).underlying();
279 }
280
281 /// @brief Gets the \c recv_count from the MPIResult object.
282 ///
283 /// This function is only available if the corresponding data is part of the result object.
284 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
285 /// the result object.
286 /// @return Returns a reference to the underlying storage containing the recv count.
287 template <
288 typename T = std::tuple<Args...>,
289 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::recv_count, T>(), bool> = true>
290 auto const& get_recv_count() const {
291 return internal::select_parameter_type_in_tuple<internal::ParameterType::recv_count>(_data).underlying();
292 }
293
294 /// @brief Extracts the \c recv_count from the MPIResult object.
295 ///
296 /// This function is only available if the corresponding data is part of the result object.
297 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
298 /// the result object.
299 /// @return Returns the underlying storage containing the recv count.
300 template <
301 typename T = std::tuple<Args...>,
302 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::recv_count, T>(), bool> = true>
304 return internal::select_parameter_type_in_tuple<internal::ParameterType::recv_count>(_data).extract();
305 }
306
307 /// @brief Gets the \c recv_displs from the MPIResult object.
308 ///
309 /// This function is only available if the corresponding data is part of the result object.
310 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
311 /// the result object.
312 /// @return Returns a reference to the underlying storage containing the receive displacements.
313 template <
314 typename T = std::tuple<Args...>,
315 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::recv_displs, T>(), bool> = true>
317 return internal::select_parameter_type_in_tuple<internal::ParameterType::recv_displs>(_data).underlying();
318 }
319
320 /// @brief Gets the \c recv_displs from the MPIResult object.
321 ///
322 /// This function is only available if the corresponding data is part of the result object.
323 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
324 /// the result object.
325 /// @return Returns a reference to the underlying storage containing the receive displacements.
326 template <
327 typename T = std::tuple<Args...>,
328 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::recv_displs, T>(), bool> = true>
329 auto const& get_recv_displs() const {
330 return internal::select_parameter_type_in_tuple<internal::ParameterType::recv_displs>(_data).underlying();
331 }
332
333 /// @brief Extracts the \c recv_displs from the MPIResult object.
334 ///
335 /// This function is only available if the corresponding data is part of the result 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 receive displacements.
339 template <
340 typename T = std::tuple<Args...>,
341 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::recv_displs, T>(), bool> = true>
343 return internal::select_parameter_type_in_tuple<internal::ParameterType::recv_displs>(_data).extract();
344 }
345
346 /// @brief Gets the \c send_counts from the MPIResult object.
347 ///
348 /// This function is only available if the corresponding data is part of the result object.
349 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
350 /// the result object.
351 /// @return Returns a reference to the underlying storage containing the send counts.
352 template <
353 typename T = std::tuple<Args...>,
354 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::send_counts, T>(), bool> = true>
356 return internal::select_parameter_type_in_tuple<internal::ParameterType::send_counts>(_data).underlying();
357 }
358
359 /// @brief Gets the \c send_counts from the MPIResult object.
360 ///
361 /// This function is only available if the corresponding data is part of the result object.
362 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
363 /// the result object.
364 /// @return Returns a reference to the underlying storage containing the send counts.
365 template <
366 typename T = std::tuple<Args...>,
367 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::send_counts, T>(), bool> = true>
368 auto const& get_send_counts() const {
369 return internal::select_parameter_type_in_tuple<internal::ParameterType::send_counts>(_data).underlying();
370 }
371
372 /// @brief Extracts the \c send_counts from the MPIResult object.
373 ///
374 /// This function is only available if the corresponding data is part of the result object.
375 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
376 /// the result object.
377 /// @return Returns the underlying storage containing the send counts.
378 template <
379 typename T = std::tuple<Args...>,
380 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::send_counts, T>(), bool> = true>
382 return internal::select_parameter_type_in_tuple<internal::ParameterType::send_counts>(_data).extract();
383 }
384
385 /// @brief Gets the \c send_count from the MPIResult object.
386 ///
387 /// This function is only available if the corresponding data is part of the result object.
388 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
389 /// the result object.
390 /// @return Returns a reference to the underlying storage containing the send counts.
391 template <
392 typename T = std::tuple<Args...>,
393 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::send_count, T>(), bool> = true>
395 return internal::select_parameter_type_in_tuple<internal::ParameterType::send_count>(_data).underlying();
396 }
397
398 /// @brief Gets the \c send_count from the MPIResult object.
399 ///
400 /// This function is only available if the corresponding data is part of the result object.
401 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
402 /// the result object.
403 /// @return Returns a reference to the underlying storage containing the send counts.
404 template <
405 typename T = std::tuple<Args...>,
406 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::send_count, T>(), bool> = true>
407 auto const& get_send_count() const {
408 return internal::select_parameter_type_in_tuple<internal::ParameterType::send_count>(_data).underlying();
409 }
410
411 /// @brief Extracts the \c send_count from the MPIResult object.
412 ///
413 /// This function is only available if the corresponding data is part of the result object.
414 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
415 /// the result object.
416 /// @return Returns the underlying storage containing the send counts.
417 template <
418 typename T = std::tuple<Args...>,
419 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::send_count, T>(), bool> = true>
421 return internal::select_parameter_type_in_tuple<internal::ParameterType::send_count>(_data).extract();
422 }
423
424 /// @brief Gets the \c send_displs from the MPIResult object.
425 ///
426 /// This function is only available if the corresponding data is part of the result object.
427 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
428 /// the result object.
429 /// @return Returns a reference to the underlying storage containing the send displacements.
430 template <
431 typename T = std::tuple<Args...>,
432 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::send_displs, T>(), bool> = true>
434 return internal::select_parameter_type_in_tuple<internal::ParameterType::send_displs>(_data).underlying();
435 }
436
437 /// @brief Gets the \c send_displs from the MPIResult object.
438 ///
439 /// This function is only available if the corresponding data is part of the result object.
440 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
441 /// the result object.
442 /// @return Returns a reference to the underlying storage containing the send displacements.
443 template <
444 typename T = std::tuple<Args...>,
445 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::send_displs, T>(), bool> = true>
446 auto const& get_send_displs() const {
447 return internal::select_parameter_type_in_tuple<internal::ParameterType::send_displs>(_data).underlying();
448 }
449
450 /// @brief Extracts the \c send_displs from the MPIResult object.
451 ///
452 /// This function is only available if the corresponding data is part of the result object.
453 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
454 /// the result object.
455 /// @return Returns the underlying storage containing the send displacements.
456 template <
457 typename T = std::tuple<Args...>,
458 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::send_displs, T>(), bool> = true>
460 return internal::select_parameter_type_in_tuple<internal::ParameterType::send_displs>(_data).extract();
461 }
462
463 /// @brief Gets the \c send_recv_count from the MPIResult object.
464 ///
465 /// This function is only available if the corresponding data is part of the result object.
466 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
467 /// the result object.
468 /// @return Returns a reference to the underlying storage containing the send_recv_count.
469 template <
470 typename T = std::tuple<Args...>,
471 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::send_recv_count, T>(), bool> =
472 true>
474 return internal::select_parameter_type_in_tuple<internal::ParameterType::send_recv_count>(_data).underlying();
475 }
476
477 /// @brief Gets the \c send_recv_count 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_recv_count.
483 template <
484 typename T = std::tuple<Args...>,
485 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::send_recv_count, T>(), bool> =
486 true>
487 auto const& get_send_recv_count() const {
488 return internal::select_parameter_type_in_tuple<internal::ParameterType::send_recv_count>(_data).underlying();
489 }
490
491 /// @brief Extracts the \c send_recv_count from the MPIResult object.
492 ///
493 /// This function is only available if the corresponding data is part of the result object.
494 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
495 /// the result object.
496 /// @return Returns the underlying storage containing the send_recv_count.
497 template <
498 typename T = std::tuple<Args...>,
499 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::send_recv_count, T>(), bool> =
500 true>
502 return internal::select_parameter_type_in_tuple<internal::ParameterType::send_recv_count>(_data).extract();
503 }
504
505 /// @brief Gets the \c send_type from the MPIResult object.
506 ///
507 /// This function is only available if the corresponding data is part of the result object.
508 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
509 /// the result object.
510 /// @return Returns a reference to the underlying storage containing the send_type.
511 template <
512 typename T = std::tuple<Args...>,
513 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::send_type, T>(), bool> = true>
515 return internal::select_parameter_type_in_tuple<internal::ParameterType::send_type>(_data).underlying();
516 }
517
518 /// @brief Gets the \c send_type from the MPIResult object.
519 ///
520 /// This function is only available if the corresponding data is part of the result object.
521 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
522 /// the result object.
523 /// @return Returns a reference to the underlying storage containing the send_type.
524 template <
525 typename T = std::tuple<Args...>,
526 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::send_type, T>(), bool> = true>
527 auto const& get_send_type() const {
528 return internal::select_parameter_type_in_tuple<internal::ParameterType::send_type>(_data).underlying();
529 }
530
531 /// @brief Extracts the \c send_type from the MPIResult object.
532 ///
533 /// This function is only available if the corresponding data is part of the result object.
534 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
535 /// the result object.
536 /// @return Returns the underlying storage containing the send_type.
537 template <
538 typename T = std::tuple<Args...>,
539 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::send_type, T>(), bool> = true>
541 return internal::select_parameter_type_in_tuple<internal::ParameterType::send_type>(_data).extract();
542 }
543
544 /// @brief Gets the \c recv_type from the MPIResult object.
545 ///
546 /// This function is only available if the corresponding data is part of the result object.
547 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
548 /// the result object.
549 /// @return Returns a reference to the underlying storage containing the send_type.
550 template <
551 typename T = std::tuple<Args...>,
552 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::recv_type, T>(), bool> = true>
554 return internal::select_parameter_type_in_tuple<internal::ParameterType::recv_type>(_data).underlying();
555 }
556
557 /// @brief Gets the \c recv_type from the MPIResult object.
558 ///
559 /// This function is only available if the corresponding data is part of the result object.
560 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
561 /// the result object.
562 /// @return Returns a reference to the underlying storage containing the send_type.
563 template <
564 typename T = std::tuple<Args...>,
565 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::recv_type, T>(), bool> = true>
566 auto const& get_recv_type() const {
567 return internal::select_parameter_type_in_tuple<internal::ParameterType::recv_type>(_data).underlying();
568 }
569
570 /// @brief Extracts the \c recv_type from the MPIResult object.
571 ///
572 /// This function is only available if the corresponding data is part of the result object.
573 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
574 /// the result object.
575 /// @return Returns the underlying storage containing the send_type.
576 template <
577 typename T = std::tuple<Args...>,
578 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::recv_type, T>(), bool> = true>
580 return internal::select_parameter_type_in_tuple<internal::ParameterType::recv_type>(_data).extract();
581 }
582
583 /// @brief Gets the \c send_recv_type from the MPIResult object.
584 ///
585 /// This function is only available if the corresponding data is part of the result object.
586 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
587 /// the result object.
588 /// @return Returns the underlying storage containing the send_recv_type.
589 template <
590 typename T = std::tuple<Args...>,
591 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::send_recv_type, T>(), bool> =
592 true>
594 return internal::select_parameter_type_in_tuple<internal::ParameterType::send_recv_type>(_data).underlying();
595 }
596
597 /// @brief Gets the \c send_recv_type from the MPIResult object.
598 ///
599 /// This function is only available if the corresponding data is part of the result object.
600 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
601 /// the result object.
602 /// @return Returns the underlying storage containing the send_recv_type.
603 template <
604 typename T = std::tuple<Args...>,
605 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::send_recv_type, T>(), bool> =
606 true>
607 auto const& get_send_recv_type() const {
608 return internal::select_parameter_type_in_tuple<internal::ParameterType::send_recv_type>(_data).underlying();
609 }
610
611 /// @brief Extracts the \c send_recv_type from the MPIResult object.
612 ///
613 /// This function is only available if the corresponding data is part of the result object.
614 /// @tparam T Template parameter helper only needed to remove this function if the corresponding data is not part of
615 /// the result object.
616 /// @return Returns the underlying storage containing the send_recv_type.
617 template <
618 typename T = std::tuple<Args...>,
619 std::enable_if_t<internal::has_parameter_type_in_tuple<internal::ParameterType::send_recv_type, T>(), bool> =
620 true>
622 return internal::select_parameter_type_in_tuple<internal::ParameterType::send_recv_type>(_data).extract();
623 }
624
625 /// @brief Get the underlying data from the i-th buffer in the result object. This method is part of the
626 /// structured binding enabling machinery.
627 ///
628 /// @tparam i Index of the data buffer to extract.
629 /// @return Returns a reference to the underlying data of the i-th data buffer.
630 template <std::size_t i>
631 auto& get() {
632 return std::get<i>(_data).underlying();
633 }
634
635 /// @brief Get the underlying data from the i-th buffer in the result object. This method is part of the
636 /// structured binding enabling machinery.
637 ///
638 /// @tparam i Index of the data buffer to extract.
639 /// @return Returns a reference to the underlying data of the i-th data buffer.
640 template <std::size_t i>
641 auto const& get() const {
642 return std::get<i>(_data).underlying();
643 }
644
645private:
646 std::tuple<Args...> _data; ///< tuple storing the data buffers
647};
648
649/// @brief Trait for checking whether a type is an \ref MPIResult.
650template <typename>
651constexpr bool is_mpi_result_v = false;
652
653/// @brief Trait for checking whether a type is an \ref MPIResult.
654template <typename... Args>
655constexpr bool is_mpi_result_v<MPIResult<Args...>> = true;
656
657/// @brief Primary template for result trait indicates whether the result object is empty.
658template <typename T>
659constexpr bool is_result_empty_v = false;
660
661/// @brief Template specialization for result trait indicates whether the result object is
662/// empty.
663template <typename... Args>
664constexpr bool is_result_empty_v<MPIResult<Args...>> = MPIResult<Args...>::is_empty;
665
666/// @brief Template specialization for result trait indicates whether the result object is
667/// empty.
668template <>
669inline constexpr bool is_result_empty_v<void> = true;
670
671} // namespace kamping
672
673namespace std {
674
675/// @brief Specialization of the std::tuple_size for \ref kamping::MPIResult. Part of the structured binding machinery.
676///
677/// @tparam Args Automatically deducted template parameters.
678template <typename... Args>
679struct tuple_size<kamping::MPIResult<Args...>> {
680 static constexpr size_t value = sizeof...(Args); ///< Number of data buffers in the \ref kamping::MPIResult.
681};
682
683/// @brief Specialization of the std::tuple_element for \ref kamping::MPIResult. Part of the structured binding
684/// machinery.
685///
686/// @param index Index of the entry of \ref kamping::MPIResult for which the underlying data type shall be deduced.
687/// @tparam Args Automatically deducted template parameters.
688template <size_t index, typename... Args>
689struct tuple_element<index, kamping::MPIResult<Args...>> {
690 using type = std::remove_reference_t<decltype(declval<kamping::MPIResult<Args...>>().template get<index>()
691 )>; ///< Type of the underlying data of the i-th data buffer in the result object.
692};
693
694} // namespace std
695
696namespace kamping {
697
698/// @brief NonBlockingResult contains the result of a non-blocking \c MPI call wrapped by KaMPIng. It encapsulates a
699/// \ref kamping::MPIResult and a \ref kamping::Request.
700///
701///
702/// @tparam MPIResultType The underlying result type.
703/// @tparam RequestDataBuffer Container encapsulating the underlying request.
704template <typename MPIResultType, typename RequestDataBuffer>
706public:
707 /// @brief Constructor for \c NonBlockingResult.
708 /// @param result The underlying \ref kamping::MPIResult.
709 /// @param request A \ref kamping::internal::DataBuffer containing the associated \ref kamping::Request.
710 NonBlockingResult(std::unique_ptr<MPIResultType> result, RequestDataBuffer request)
711 : _mpi_result(std::move(result)),
712 _request(std::move(request)) {}
713
714 /// @brief \c true if the result object owns the underlying \ref kamping::Request.
715 static constexpr bool owns_request = internal::has_extract_v<RequestDataBuffer>;
716
717 /// @brief Extracts the components of this results, leaving the user responsible.
718 ///
719 /// If this result owns the underlying request:
720 /// - returns a \c std::pair containing the \ref Request and \ref
721 /// MPIResult if the result object contains owning out buffers.
722 /// - returns only the \ref Request object otherwise.
723 ///
724 /// If the request is owned by the user
725 /// - return the underlying \ref MPIResult if the result object contains any owning out buffers.
726 /// - returns nothing otherwise.
727 ///
728 /// Note that the result may be in an undefined state because the associated operations is still underway and it
729 /// is the user's responsibilty to ensure that the corresponding request has been completed before accessing the
730 /// result.
731 auto extract() {
732 if constexpr (owns_request) {
733 if constexpr (is_result_empty_v<decltype(extract_result())>) {
734 return _request.extract();
735 } else {
736 auto result =
737 extract_result(); // we try to extract the result first, so that we get a nice error message
738 // TODO: return a named struct
739 return std::pair(_request.extract(), std::move(result));
740 }
741 } else {
742 if constexpr (is_result_empty_v<decltype(extract_result())>) {
743 return;
744 } else {
745 return extract_result();
746 }
747 }
748 }
749
750 /// @brief Waits for the underlying \ref Request to complete by calling \ref Request::wait() and upon completion
751 /// returns:
752 ///
753 /// If \p status is an out-parameter:
754 /// - If the result is not empty (see \ref is_result_empty_v), an \c std::pair containing an \ref MPIResult
755 /// and the status.
756 /// - If the result is empty, only the status is returned.
757 ///
758 /// If \p is \c kamping::status(ignore<>), or not an out-paramter:
759 /// - If the result is not empty (see \ref is_result_empty_v), only the result is returned.
760 /// - If the result is empty, nothing is returned.
761 ///
762 /// This method is only available if this result owns the underlying request. If this is not the case, the user
763 /// must manually wait on the request that they own and manually obtain the result via \ref extract().
764 ///
765 /// @param status A parameter created by \ref kamping::status() or \ref kamping::status_out().
766 /// Defaults to \c kamping::status(ignore<>).
767 template <
768 typename StatusParamObjectType = decltype(status(ignore<>)),
770 typename std::enable_if<NonBlockingResulType_::owns_request, bool>::type = true>
772 static_assert(
773 StatusParamObjectType::parameter_type == internal::ParameterType::status,
774 "Only status parameters are allowed."
775 );
776 kassert_not_extracted("The result of this request has already been extracted.");
777 constexpr bool return_status = internal::is_extractable<StatusParamObjectType>;
778 if constexpr (!is_result_empty_v<MPIResultType>) {
779 if constexpr (return_status) {
780 auto status_return = _request.underlying().wait(std::move(status));
781 return std::make_pair(extract_result(), std::move(status_return));
782 } else {
783 _request.underlying().wait(std::move(status));
784 return extract_result();
785 }
786 } else {
787 return _request.underlying().wait(std::move(status));
788 }
789 }
790
791 /// @brief Tests the underlying \ref Request for completion by calling \ref
792 /// Request::test() and returns a value convertible to \c bool indicating if the request is complete.
793 ///
794 /// The type of the return value depends on the encapsulated result and the \p status parameter and follows the
795 /// same semantics as \ref wait(), but its return value is wrapped in an \c std::optional. The optional only
796 /// contains a value if the request is complete, i.e. \c test() succeeded.
797 ///
798 /// If both the result is empty and no status returned, returns a \c bool indicating completion instead of an \c
799 /// std::optional.
800 ///
801 /// This method is only available if this result owns the underlying request. If this is not the case, the user
802 /// must manually test the request that they own and manually obtain the result via \ref extract().
803 ///
804 /// @param status A parameter created by \ref kamping::status() or \ref kamping::status_out().
805 /// Defaults to \c kamping::status(ignore<>).
806 template <
807 typename StatusParamObjectType = decltype(status(ignore<>)),
809 typename std::enable_if<NonBlockingResulType_::owns_request, bool>::type = true>
811 static_assert(
812 StatusParamObjectType::parameter_type == internal::ParameterType::status,
813 "Only status parameters are allowed."
814 );
815 kassert_not_extracted("The result of this request has already been extracted.");
816 constexpr bool return_status = internal::is_extractable<StatusParamObjectType>;
817 if constexpr (!is_result_empty_v<MPIResultType>) {
818 if constexpr (return_status) {
819 auto status_return = _request.underlying().test(std::move(status));
820 if (status_return) {
821 return std::optional{std::pair{extract_result(), std::move(*status_return)}};
822 } else {
823 return std::optional<std::pair<MPIResultType, typename decltype(status_return)::value_type>>{};
824 }
825 } else {
826 if (_request.underlying().test(std::move(status))) {
827 return std::optional{extract_result()};
828 } else {
829 return std::optional<MPIResultType>{};
830 }
831 }
832 } else {
833 return _request.underlying().test(std::move(status));
834 }
835 }
836
837 /// @brief Provides access to the underlying result object.
839 kassert_not_extracted("The result of this request has already been extracted.");
840 return *_mpi_result;
841 }
842
843 /// @brief Returns a pointer to the underlying request.
845 return _request.underlying().request_ptr();
846 }
847
848private:
849 /// @brief Moves the wrapped \ref MPIResult out of this object.
850 MPIResultType extract_result() {
851 kassert_not_extracted("The result of this request has already been extracted.");
852 auto extracted = std::move(*_mpi_result);
853 set_extracted();
854 return extracted;
855 }
856
857 void set_extracted() {
858#if KASSERT_ENABLED(KAMPING_ASSERTION_LEVEL_NORMAL)
859 is_extracted = true;
860#endif
861 }
862
863 /// @brief Throws an assertion if the extracted flag is set, i.e. the underlying status has been moved out.
864 ///
865 /// @param message The message for the assertion.
866 void kassert_not_extracted(std::string const message [[maybe_unused]]) const {
867#if KASSERT_ENABLED(KAMPING_ASSERTION_LEVEL_NORMAL)
868 KASSERT(!is_extracted, message, assert::normal);
869#endif
870 }
871 std::unique_ptr<MPIResultType> _mpi_result; ///< The wrapped \ref MPIResult.
872 RequestDataBuffer _request; ///< DataBuffer containing the wrapped \ref Request.
873#if KASSERT_ENABLED(KAMPING_ASSERTION_LEVEL_NORMAL)
874 bool is_extracted = false; ///< Has the status been extracted and is therefore in an invalid state?
875#endif
876};
877} // namespace kamping
878
879namespace kamping::internal {
880
881/// @brief Determines whether only the recv (send_recv) buffer or multiple different buffers will be returned.
882/// @tparam CallerProvidedOwningOutBuffers An std::tuple containing the types of the owning, out buffers explicitly
883/// requested by the caller of the wrapped MPI call.
884/// @returns \c True if the recv (send_recv) buffer is either not mentioned explicitly and no other (owning) out buffers
885/// are requested or the only explicitly requested owning out buffer is the recv_buf. \c False otherwise.
886template <typename CallerProvidedOwningOutBuffers>
888 constexpr std::size_t num_caller_provided_owning_out_buffers = std::tuple_size_v<CallerProvidedOwningOutBuffers>;
889 if constexpr (num_caller_provided_owning_out_buffers == 0) {
890 return true;
891 } else if constexpr (num_caller_provided_owning_out_buffers == 1 && std::tuple_element_t<0, CallerProvidedOwningOutBuffers>::value == ParameterType::recv_buf) {
892 return true;
893 } else if constexpr (num_caller_provided_owning_out_buffers == 1 && std::tuple_element_t<0, CallerProvidedOwningOutBuffers>::value == ParameterType::send_recv_buf) {
894 return true;
895 } else {
896 return false;
897 }
898}
899
900/// @brief Determines whether only the send buffer should be returned.
901/// This may happen if ownership of the send buffer is transfered to the call.
902template <typename CallerProvidedOwningOutBuffers>
903constexpr bool return_send_buf_out_only() {
904 constexpr std::size_t num_caller_provided_owning_out_buffers = std::tuple_size_v<CallerProvidedOwningOutBuffers>;
905 if constexpr (num_caller_provided_owning_out_buffers == 1) {
906 return std::tuple_element_t<0, CallerProvidedOwningOutBuffers>::value == ParameterType::send_buf;
907 } else {
908 return false;
909 }
910}
911
912/// @brief Checks whether a buffer with parameter type recv_buf or a buffer with type send_recv_buf is present and
913/// returns the found parameter type. Note that we require that either a recv_buf or a send_recv_buf is present.
914///
915/// @tparam Buffers All buffer types to be searched for type `recv_buf` or `send_recv_buf`.
916/// @returns The parameter type of the first buffer whose parameter type is recv_buf or send_recv_buf.
917template <typename... Buffers>
919 constexpr bool has_recv_buffer = internal::has_parameter_type<internal::ParameterType::recv_buf, Buffers...>();
920 constexpr bool has_send_recv_buffer =
921 internal::has_parameter_type<internal::ParameterType::send_recv_buf, Buffers...>();
922 static_assert(has_recv_buffer ^ has_send_recv_buffer, "either a recv or a send_recv buffer must be present");
923 if constexpr (has_recv_buffer) {
924 return ParameterType::recv_buf;
925 } else {
926 return ParameterType::send_recv_buf;
927 }
928}
929
930/// @brief List of parameter type (entries) which should not be included in the result object.
941
942///@brief Predicate to check whether a buffer provided to \ref make_mpi_result() shall be discard or returned in the
943/// result object.
945 ///@brief Discard function to check whether a buffer provided to \ref make_mpi_result() shall be discard or returned
946 /// in the result object.
947 /// call.
948 ///
949 ///@tparam BufferType BufferType to be checked.
950 ///@return \c True (i.e. discard) iff Arg's parameter_type is `sparse_send_buf`, `on_message` or `destination`.
951 template <typename BufferType>
952 static constexpr bool discard() {
954 if constexpr (parameter_types_to_ignore_for_result_object::contains<ptype_entry>) {
955 return true;
956 } else {
957 return !BufferType::is_owning
958 || !BufferType::is_out_buffer; ///< Predicate which Head has to fulfill to be kept.
959 }
960 }
961};
962
963/// @brief Helper to check if a type `T` has a member type `T::DataBufferType`.
964template <typename, typename = void>
965constexpr bool has_data_buffer_type_member = false;
966
967/// @brief Helper to check if a type `T` has a member type `T::DataBufferType`.
968template <typename T>
970
971///@brief Predicate to check whether a buffer provided to \ref make_mpi_result() shall be discard or returned in the
972/// result object, including a hotfix for serialization.
974 /// @brief Discard function to check whether a buffer provided to \ref make_mpi_result() shall be discard or
975 /// returned in the result object. call.
976 ///
977 /// @tparam BufferType BufferType to be checked.
978 /// @return \c True (i.e. discard) iff \ref PredicateForResultObject discards this, or if the parameter uses
979 /// serialization, so we don't expose serialization buffers to the user.
980 ///
981 /// @todo this a quick and dirty hack, in the future we want to select which parameters to return based on a flag.
982 /// Currently we assume that we want to return everything that is out and owning.
983 template <typename BufferType>
984 static constexpr bool discard() {
985 if (PredicateForResultObject::discard<BufferType>()) {
986 return true;
987 }
988 // we sometimes call this with DataBuffers and sometimes with DataBufferBuilder, so we need a case distinction
989 // here.
991 if constexpr (ptype_entry::parameter_type == internal::ParameterType::recv_buf || ptype_entry::parameter_type == internal::ParameterType::send_recv_buf) {
994 } else {
996 }
997 }
998 return false;
999 }
1000};
1001
1002/// @brief Returns True iff only a recv or send_recv buffer is present.
1003/// Communicator::ibarrier()).
1004///
1005/// @tparam Buffers All buffer types to be searched for type `status`.
1006template <typename... Buffers>
1008 constexpr bool has_recv_buffer = internal::has_parameter_type<internal::ParameterType::recv_buf, Buffers...>();
1009 constexpr bool has_send_recv_buffer =
1010 internal::has_parameter_type<internal::ParameterType::send_recv_buf, Buffers...>();
1011 return has_recv_buffer || has_send_recv_buffer;
1012}
1013
1014/// @brief Template class to prepend the ParameterTypeEntry<ParameterType::ptype> type to a given std::tuple.
1015/// @tparam ptype ParameterType to prepend
1016/// @tparam Tuple An std::tuple.
1017template <ParameterType ptype, typename Tuple>
1020 type; ///< Concatenated tuple, i.e. type = std::tuple<TypeToPrepend, (Type contained in Tuple)... >.
1021};
1022
1023/// @brief Construct result object for a wrapped MPI call. Four different cases are handled:
1024/// a) The recv_buffer owns its underlying data (i.e. the received data has to be returned via the result object):
1025///
1026/// a.1) The recv_buffer is the only buffer to be returned, i.e. the only caller provided owning out buffer:
1027/// In this case, the recv_buffers's underlying data is extracted and returned directly (by value).
1028///
1029/// a.2) There are multiple buffers to be returned and recv_buffer is explicitly provided by the caller:
1030/// In this case a \ref kamping::MPIResult object is created, which stores the buffers to return (owning out buffers)
1031/// in a std::tuple respecting the order in which these buffers where provided to the wrapped MPI call. This enables
1032/// unpacking the object via structured binding.
1033///
1034/// a.3) There are more data buffers to be returned and recv_buffer is *not* explicitly provided by the caller:
1035/// In this case a \ref kamping::MPIResult object is created, which stores the buffers to return. The
1036/// recv_buffer is always the first entry in the result object followed by the other buffers respecting the order in
1037/// which these buffers where provided to the wrapped MPI call.
1038///
1039/// b) There is no recv buffer (see \ref Communicator::probe() for example) or the recv_buffer only references its
1040/// underlying data (i.e. it is a non-owning out buffer): In this case recv_buffer is not part of the result object. The
1041/// \ref kamping::MPIResult object stores the buffer to return (owning buffers for which a *_out() named parameter was
1042/// passed to the wrapped MPI call) in a std::tuple respecting the order in which these buffers where provided to the
1043/// wrapped MPI call.
1044///
1045/// @tparam CallerProvidedArgs Types of arguments passed to the wrapped MPI call.
1046/// @tparam Buffers Types of data buffers created/filled within the wrapped MPI call.
1047/// @param buffers data buffers created/filled within the wrapped MPI call.
1048/// @return result object as specified above.
1049///
1050/// @see \ref docs/parameter_handling.md
1051template <typename CallerProvidedArgs, typename... Buffers>
1053 // filter named parameters provided to the wrapped MPI function and keep only owning out parameters (=owning out
1054 // buffers)
1059 constexpr std::size_t num_caller_provided_owning_out_buffers =
1060 std::tuple_size_v<CallerProvidedOwningOutParametersWithoutSerializationBuffers>;
1062 auto& send_buffer = internal::select_parameter_type<ParameterType::send_buf>(buffers...);
1063 return send_buffer.extract();
1064 } else if constexpr (!has_recv_or_send_recv_buf<Buffers...>()) {
1065 // do no special handling for receive buffer at all, since there is none.
1067 } else {
1068 // receive (send-receive) buffer needs (potentially) a special treatment (if it is an owning (out) buffer
1069 // and provided by the caller)
1071 auto& recv_or_send_recv_buffer = internal::select_parameter_type<recv_parameter_type>(buffers...);
1072 constexpr bool recv_or_send_recv_buf_is_owning =
1073 std::remove_reference_t<decltype(recv_or_send_recv_buffer)>::is_owning;
1076
1077 // special case 1: recv (send_recv) buffer is not owning
1078 if constexpr (!recv_or_send_recv_buf_is_owning) {
1079 if constexpr (num_caller_provided_owning_out_buffers == 0) {
1080 // there are no buffers to return
1081 return;
1082 } else {
1083 // no special treatment of recv buffer is needed as the recv_buffer is not part of the result
1084 // object anyway.
1086 }
1087 }
1088 // specialcase 2: recv (send_recv) buffer is the only owning out parameter
1090 // if only the receive buffer shall be returned, its underlying data is returned directly instead of a
1091 // wrapping result object
1092 return recv_or_send_recv_buffer.extract();
1093 }
1094
1095 // case A: recv (send_recv) buffer is provided by caller (and owning)
1098 }
1099 // case B: recv buffer is not provided by caller -> recv buffer will be stored as first entry in
1100 // underlying result object
1101 else {
1102 using ParametersToReturn =
1105 }
1106 }
1107}
1108
1109/// @brief Factory for creating a \ref kamping::NonBlockingResult.
1110///
1111/// Makes an \ref kamping::NonBlockingResult from all arguments passed and inserts internal::ResultCategoryNotUsed
1112/// when no fitting parameter type is passed as argument.
1113///
1114/// Note that an argument of with type \ref kamping::internal::ParameterType::request is required.
1115///
1116/// @tparam CallerProvidedArgs Types of arguments passed to the wrapped MPI call.
1117/// @tparam Args Automatically deducted template parameters.
1118/// @param args All parameter that should be included in the MPIResult.
1119/// @return \ref kamping::NonBlockingResult encapsulating all passed parameters.
1120template <typename CallerProvidedArgsInTuple, typename... Args>
1122 auto&& request = internal::select_parameter_type<internal::ParameterType::request>(args...);
1123 using result_type = decltype(make_mpi_result<CallerProvidedArgsInTuple>(std::forward<Args>(args)...));
1124 if constexpr (is_result_empty_v<result_type>) {
1125 return NonBlockingResult(std::make_unique<MPIResult<>>(std::tuple<>{}), std::move(request));
1126 } else {
1127 auto construct_result_object = [&]() {
1128 auto result = make_mpi_result<CallerProvidedArgsInTuple>(std::forward<Args>(args)...);
1129 return std::make_unique<decltype(result)>(std::move(result));
1130 };
1132 }
1133}
1134
1135} // namespace kamping::internal
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:290
auto extract_recv_buffer()
Extracts the recv_buffer from the MPIResult object.
Definition result.hpp:180
auto & get_send_type()
Gets the send_type from the MPIResult object.
Definition result.hpp:514
auto const & get_recv_type() const
Gets the recv_type from the MPIResult object.
Definition result.hpp:566
auto & get_send_recv_type()
Gets the send_recv_type from the MPIResult object.
Definition result.hpp:593
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.
Definition result.hpp:138
auto const & get_recv_displs() const
Gets the recv_displs from the MPIResult object.
Definition result.hpp:329
auto extract_send_counts()
Extracts the send_counts from the MPIResult object.
Definition result.hpp:381
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:264
auto extract_recv_count()
Extracts the recv_count from the MPIResult object.
Definition result.hpp:303
auto const & get_send_type() const
Gets the send_type from the MPIResult object.
Definition result.hpp:527
auto extract_send_count()
Extracts the send_count from the MPIResult object.
Definition result.hpp:420
auto & get_send_count()
Gets the send_count from the MPIResult object.
Definition result.hpp:394
auto & get_recv_counts()
Get the recv_counts from the MPIResult object.
Definition result.hpp:238
auto extract_recv_displs()
Extracts the recv_displs from the MPIResult object.
Definition result.hpp:342
auto const & get_send_counts() const
Gets the send_counts from the MPIResult object.
Definition result.hpp:368
auto & get_recv_displs()
Gets the recv_displs from the MPIResult object.
Definition result.hpp:316
auto & get_send_displs()
Gets the send_displs from the MPIResult object.
Definition result.hpp:433
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:641
auto & get_recv_count()
Gets the recv_count from the MPIResult object.
Definition result.hpp:277
auto const & get_recv_buffer() const
Get the recv_buffer from the MPIResult object.
Definition result.hpp:152
static constexpr bool has_send_recv_buffer
true, if the result encapsulates a send_recv_buf.
Definition result.hpp:74
auto extract_send_recv_type()
Extracts the send_recv_type from the MPIResult object.
Definition result.hpp:621
auto extract_send_recv_count()
Extracts the send_recv_count from the MPIResult object.
Definition result.hpp:501
auto const & get_send_recv_count() const
Gets the send_recv_count from the MPIResult object.
Definition result.hpp:487
auto extract_recv_type()
Extracts the recv_type from the MPIResult object.
Definition result.hpp:579
auto & get_send_counts()
Gets the send_counts from the MPIResult object.
Definition result.hpp:355
auto const & get_send_buffer() const
Get the send_buffer from the MPIResult object.
Definition result.hpp:166
auto & get_recv_type()
Gets the recv_type from the MPIResult object.
Definition result.hpp:553
auto extract_send_type()
Extracts the send_type from the MPIResult object.
Definition result.hpp:540
auto extract_send_displs()
Extracts the send_displs from the MPIResult object.
Definition result.hpp:459
auto const & get_recv_counts() const
Get the recv_counts from the MPIResult object.
Definition result.hpp:251
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:473
auto const & get_send_displs() const
Gets the send_displs from the MPIResult object.
Definition result.hpp:446
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:631
auto const & get_send_recv_type() const
Gets the send_recv_type from the MPIResult object.
Definition result.hpp:607
auto const & get_send_count() const
Gets the send_count from the MPIResult object.
Definition result.hpp:407
MPIResult(std::tuple< Args... > &&data)
Constructor for MPIResult.
Definition result.hpp:84
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:705
NonBlockingResult(std::unique_ptr< MPIResultType > result, RequestDataBuffer request)
Constructor for NonBlockingResult.
Definition result.hpp:710
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:810
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:771
static constexpr bool owns_request
true if the result object owns the underlying kamping::Request.
Definition result.hpp:715
MPIResultType & get_result()
Provides access to the underlying result object.
Definition result.hpp:838
MPI_Request * get_request_ptr()
Returns a pointer to the underlying request.
Definition result.hpp:844
auto extract()
Extracts the components of this results, leaving the user responsible.
Definition result.hpp:731
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
auto request(Request &request)
Passes a request handle to the underlying MPI call.
Definition named_parameters.hpp:1095
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:887
constexpr bool has_extract_v
has_extract_v is true iff type T has a member function extract().
Definition result.hpp:40
constexpr bool has_data_buffer_type_member
Helper to check if a type T has a member type T::DataBufferType.
Definition result.hpp:965
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:903
auto make_nonblocking_result(Args... args)
Factory for creating a kamping::NonBlockingResult.
Definition result.hpp:1121
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:1052
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:1007
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:918
STL namespace.
constexpr bool is_mpi_result_v
Trait for checking whether a type is an MPIResult.
Definition result.hpp:651
constexpr bool is_result_empty_v
Primary template for result trait indicates whether the result object is empty.
Definition result.hpp:659
Predicate to check whether a buffer provided to make_mpi_result() shall be discard or returned in the...
Definition result.hpp:973
static constexpr bool discard()
Discard function to check whether a buffer provided to make_mpi_result() shall be discard or returned...
Definition result.hpp:984
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:944
static constexpr bool discard()
Discard function to check whether a buffer provided to make_mpi_result() shall be discard or returned...
Definition result.hpp:952
Template class to prepend the ParameterTypeEntry<ParameterType::ptype> type to a given std::tuple.
Definition result.hpp:1018
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:1019
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:690