Dune Core Modules (2.7.1)

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
12 namespace 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 
119  MPIFuture(MPIFuture&& f)
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
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.80.0 (May 16, 22:29, 2024)