dune-common 2.10
Loading...
Searching...
No Matches
mpifuture.hh
Go to the documentation of this file.
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
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
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
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
169 wait();
170 return send_data_.get();
171 }
172
174 return getMPIData(*data_);
175 }
176
178 return getMPIData(*send_data_);
179 }
180 };
181
182}
183#endif // HAVE_MPI
184#endif // DUNE_COMMON_PARALLEL_MPIFUTURE_HH
Interface class to translate objects to a MPI_Datatype, void* and size used for MPI calls.
Implements an utility class that provides collective communication methods for sequential programs.
A few common exception classes.
bigunsignedint< k > operator*(const bigunsignedint< k > &x, std::uintmax_t y)
Definition bigunsignedint.hh:549
#define DUNE_THROW(E, m)
Definition exceptions.hh:218
STL namespace.
Dune namespace.
Definition alignedallocator.hh:13
auto getMPIData(T &t)
Definition mpidata.hh:44
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
Definition mpifuture.hh:27
std::unique_ptr< T > value
Definition mpifuture.hh:36
T & operator*() const
Definition mpifuture.hh:45
Buffer(V &&t)
Definition mpifuture.hh:33
T get()
Definition mpifuture.hh:37
Buffer(bool valid)
Definition mpifuture.hh:28
std::optional< std::reference_wrapper< T > > value
Definition mpifuture.hh:61
Buffer(bool valid=false)
Definition mpifuture.hh:52
T & get()
Definition mpifuture.hh:62
Buffer(V &&t)
Definition mpifuture.hh:58
bool valid_
Definition mpifuture.hh:77
void get()
Definition mpifuture.hh:84
Buffer(bool valid=false)
Definition mpifuture.hh:78
Provides a future-like object for MPI communication. It contains the object that will be received and...
Definition mpifuture.hh:93
MPIFuture(V &&recv_data, typename std::enable_if_t<!std::is_void< V >::value > *=0)
Definition mpifuture.hh:115
bool ready() const
Definition mpifuture.hh:157
bool valid() const
Definition mpifuture.hh:147
~MPIFuture()
Definition mpifuture.hh:120
MPIFuture(bool valid=false)
Definition mpifuture.hh:100
MPIFuture & operator=(MPIFuture &&f)
Definition mpifuture.hh:139
auto get_send_mpidata()
Definition mpifuture.hh:177
void wait()
Definition mpifuture.hh:151
auto get_mpidata()
Definition mpifuture.hh:173
R get()
Definition mpifuture.hh:163
MPIFuture(V &&recv_data, U &&send_data, typename std::enable_if_t<!std::is_void< V >::value &&!std::is_void< U >::value > *=0)
Definition mpifuture.hh:107
S get_send_data()
Definition mpifuture.hh:168
MPIFuture(MPIFuture &&f)
Definition mpifuture.hh:130