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
15namespace 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
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
STL namespace.
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Dec 21, 23:30, 2024)