Dune Core Modules (2.7.0)

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