Dune Core Modules (unstable)

mpifuture.hh
1// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2// vi: set et ts=4 sw=2 sts=2:
3// SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root
4// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception
5#ifndef DUNE_COMMON_PARALLEL_MPIFUTURE_HH
6#define DUNE_COMMON_PARALLEL_MPIFUTURE_HH
7
8#if HAVE_MPI
9
10#include <functional>
11#include <memory>
12#include <optional>
13#include <type_traits>
14#include <utility>
15
16#include <mpi.h>
17
20#include <dune/common/parallel/future.hh>
22
23namespace Dune{
24
25 namespace impl{
26 template<class T>
27 struct Buffer{
28 Buffer(bool valid){
29 if(valid)
30 value = std::make_unique<T>();
31 }
32 template<class V>
33 Buffer(V&& t)
34 : value(std::make_unique<T>(std::forward<V>(t)))
35 {}
36 std::unique_ptr<T> value;
37 T get(){
38 T tmp = std::move(*value);
39 value.reset();
40 return tmp;
41 }
42 operator bool () const {
43 return (bool)value;
44 }
45 T& operator *() const{
46 return *value;
47 }
48 };
49
50 template<class T>
51 struct Buffer<T&>{
52 Buffer(bool valid = false)
53 {
54 if(valid)
55 value = T();
56 }
57 template<class V>
58 Buffer(V&& t)
59 : value(std::forward<V>(t))
60 {}
61 std::optional<std::reference_wrapper<T>> value;
62 T& get(){
63 T& tmp = *value;
64 value.reset();
65 return tmp;
66 }
67 operator bool () const{
68 return (bool)value;
69 }
70 T& operator *() const{
71 return *value;
72 }
73 };
74
75 template<>
76 struct Buffer<void>{
77 bool valid_;
78 Buffer(bool valid = false)
79 : valid_(valid)
80 {}
81 operator bool () const{
82 return valid_;
83 }
84 void get(){}
85 };
86 }
87
92 template<class R, class S = void>
93 class MPIFuture{
94 mutable MPI_Request req_;
95 mutable MPI_Status status_;
96 impl::Buffer<R> data_;
97 impl::Buffer<S> send_data_;
98 friend class Communication<MPI_Comm>;
99 public:
100 MPIFuture(bool valid = false)
101 : req_(MPI_REQUEST_NULL)
102 , data_(valid)
103 {}
104
105 // Hide this constructor if R or S is void
106 template<class V = R, class U = S>
107 MPIFuture(V&& recv_data, U&& send_data, typename std::enable_if_t<!std::is_void<V>::value && !std::is_void<U>::value>* = 0) :
108 req_(MPI_REQUEST_NULL)
109 , data_(std::forward<R>(recv_data))
110 , send_data_(std::forward<S>(send_data))
111 {}
112
113 // hide this constructor if R is void
114 template<class V = R>
115 MPIFuture(V&& recv_data, typename std::enable_if_t<!std::is_void<V>::value>* = 0)
116 : req_(MPI_REQUEST_NULL)
117 , data_(std::forward<V>(recv_data))
118 {}
119
120 ~MPIFuture() {
121 if(req_ != MPI_REQUEST_NULL){
122 try{ // might fail when it is a collective communication
123 MPI_Cancel(&req_);
124 MPI_Request_free(&req_);
125 }catch(...){
126 }
127 }
128 }
129
131 : req_(MPI_REQUEST_NULL)
132 , data_(std::move(f.data_))
133 , send_data_(std::move(f.send_data_))
134 {
135 std::swap(req_, f.req_);
136 std::swap(status_, f.status_);
137 }
138
139 MPIFuture& operator=(MPIFuture&& f){
140 std::swap(req_, f.req_);
141 std::swap(status_, f.status_);
142 std::swap(data_, f.data_);
143 std::swap(send_data_, f.send_data_);
144 return *this;
145 }
146
147 bool valid() const{
148 return (bool)data_;
149 }
150
151 void wait(){
152 if(!valid())
153 DUNE_THROW(InvalidFutureException, "The MPIFuture is not valid!");
154 MPI_Wait(&req_, &status_);
155 }
156
157 bool ready() const{
158 int flag = -1;
159 MPI_Test(&req_, &flag, &status_);
160 return flag;
161 }
162
163 R get() {
164 wait();
165 return data_.get();
166 }
167
168 S get_send_data(){
169 wait();
170 return send_data_.get();
171 }
172
173 auto get_mpidata(){
174 return getMPIData(*data_);
175 }
176
177 auto get_send_mpidata(){
178 return getMPIData(*send_data_);
179 }
180 };
181
182}
183#endif // HAVE_MPI
184#endif // DUNE_COMMON_PARALLEL_MPIFUTURE_HH
Collective communication interface and sequential default implementation.
Definition: communication.hh:100
This exception is thrown when ready(), wait() or get() is called on an invalid future....
Definition: future.hh:20
Provides a future-like object for MPI communication. It contains the object that will be received and...
Definition: mpifuture.hh:93
Implements an utility class that provides collective communication methods for sequential programs.
A few common exception classes.
#define DUNE_THROW(E,...)
Definition: exceptions.hh:312
Interface class to translate objects to a MPI_Datatype, void* and size used for MPI calls.
Dune namespace.
Definition: alignedallocator.hh:13
constexpr auto get(std::integer_sequence< T, II... >, std::integral_constant< std::size_t, pos >={})
Return the entry at position pos of the given sequence.
Definition: integersequence.hh:22
STL namespace.
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Dec 21, 23:30, 2024)