Dune Core Modules (2.9.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 // 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 
11 #include <dune/common/parallel/future.hh>
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 
112  ~MPIFuture() {
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 
122  MPIFuture(MPIFuture&& f)
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 
131  MPIFuture& operator=(MPIFuture&& f){
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 
160  S get_send_data(){
161  wait();
162  return send_data_.get();
163  }
164 
165  auto get_mpidata(){
166  return getMPIData(*data_);
167  }
168 
169  auto get_send_mpidata(){
170  return getMPIData(*send_data_);
171  }
172  };
173 
174 }
175 #endif
176 #endif
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
Provides a future-like object for MPI communication. It contains the object that will be received and...
Definition: mpifuture.hh:85
Implements an utility class that provides collective communication methods for sequential programs.
#define DUNE_THROW(E, m)
Definition: exceptions.hh:218
Interface class to translate objects to a MPI_Datatype, void* and size used for MPI calls.
Dune namespace.
Definition: alignedallocator.hh:13
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.80.0 (Apr 27, 22:29, 2024)