DUNE PDELab (2.8)

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#ifndef DUNE_COMMON_PARALLEL_MPIFUTURE_HH
4#define DUNE_COMMON_PARALLEL_MPIFUTURE_HH
5
6#include <optional>
7
9#include <dune/common/parallel/future.hh>
11
12#if HAVE_MPI
13namespace Dune{
14
15 namespace impl{
16 template<class T>
17 struct Buffer{
18 Buffer(bool valid){
19 if(valid)
20 value = std::make_unique<T>();
21 }
22 template<class V>
23 Buffer(V&& t)
24 : value(std::make_unique<T>(std::forward<V>(t)))
25 {}
26 std::unique_ptr<T> value;
27 T get(){
28 T tmp = std::move(*value);
29 value.reset();
30 return tmp;
31 }
32 operator bool () const {
33 return (bool)value;
34 }
35 T& operator *() const{
36 return *value;
37 }
38 };
39
40 template<class T>
41 struct Buffer<T&>{
42 Buffer(bool valid = false)
43 {
44 if(valid)
45 value = T();
46 }
47 template<class V>
48 Buffer(V&& t)
49 : value(std::forward<V>(t))
50 {}
51 std::optional<std::reference_wrapper<T>> value;
52 T& get(){
53 T& tmp = *value;
54 value.reset();
55 return tmp;
56 }
57 operator bool () const{
58 return (bool)value;
59 }
60 T& operator *() const{
61 return *value;
62 }
63 };
64
65 template<>
66 struct Buffer<void>{
67 bool valid_;
68 Buffer(bool valid = false)
69 : valid_(valid)
70 {}
71 operator bool () const{
72 return valid_;
73 }
74 void get(){}
75 };
76 }
77
82 template<class R, class S = void>
83 class MPIFuture{
84 mutable MPI_Request req_;
85 mutable MPI_Status status_;
86 impl::Buffer<R> data_;
87 impl::Buffer<S> send_data_;
88 friend class Communication<MPI_Comm>;
89 public:
90 MPIFuture(bool valid = false)
91 : req_(MPI_REQUEST_NULL)
92 , data_(valid)
93 {}
94
95 // Hide this constructor if R or S is void
96 template<class V = R, class U = S>
97 MPIFuture(V&& recv_data, U&& send_data, typename std::enable_if_t<!std::is_void<V>::value && !std::is_void<U>::value>* = 0) :
98 req_(MPI_REQUEST_NULL)
99 , data_(std::forward<R>(recv_data))
100 , send_data_(std::forward<S>(send_data))
101 {}
102
103 // hide this constructor if R is void
104 template<class V = R>
105 MPIFuture(V&& recv_data, typename std::enable_if_t<!std::is_void<V>::value>* = 0)
106 : req_(MPI_REQUEST_NULL)
107 , data_(std::forward<V>(recv_data))
108 {}
109
110 ~MPIFuture() {
111 if(req_ != MPI_REQUEST_NULL){
112 try{ // might fail when it is a collective communication
113 MPI_Cancel(&req_);
114 MPI_Request_free(&req_);
115 }catch(...){
116 }
117 }
118 }
119
121 : req_(MPI_REQUEST_NULL)
122 , data_(std::move(f.data_))
123 , send_data_(std::move(f.send_data_))
124 {
125 std::swap(req_, f.req_);
126 std::swap(status_, f.status_);
127 }
128
129 MPIFuture& operator=(MPIFuture&& f){
130 std::swap(req_, f.req_);
131 std::swap(status_, f.status_);
132 std::swap(data_, f.data_);
133 std::swap(send_data_, f.send_data_);
134 return *this;
135 }
136
137 bool valid() const{
138 return (bool)data_;
139 }
140
141 void wait(){
142 if(!valid())
143 DUNE_THROW(InvalidFutureException, "The MPIFuture is not valid!");
144 MPI_Wait(&req_, &status_);
145 }
146
147 bool ready() const{
148 int flag = -1;
149 MPI_Test(&req_, &flag, &status_);
150 return flag;
151 }
152
153 R get() {
154 wait();
155 return data_.get();
156 }
157
158 S get_send_data(){
159 wait();
160 return send_data_.get();
161 }
162
163 auto get_mpidata(){
164 return getMPIData(*data_);
165 }
166
167 auto get_send_mpidata(){
168 return getMPIData(*send_data_);
169 }
170 };
171
172}
173#endif
174#endif
Collective communication interface and sequential default implementation.
Definition: communication.hh:98
This exception is thrown when ready(), wait() or get() is called on an invalid future....
Definition: future.hh:16
Provides a future-like object for MPI communication. It contains the object that will be received and...
Definition: mpifuture.hh:83
Implements an utility class that provides collective communication methods for sequential programs.
#define DUNE_THROW(E, m)
Definition: exceptions.hh:216
Interface class to translate objects to a MPI_Datatype, void* and size used for MPI calls.
Dune namespace.
Definition: alignedallocator.hh:11
STL namespace.
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Dec 21, 23:30, 2024)