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