Loading...
Searching...
No Matches
mpifuture.hh
Go to the documentation of this file.
// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
// vi: set et ts=4 sw=2 sts=2:
// SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root
// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception
#ifndef DUNE_COMMON_PARALLEL_MPIFUTURE_HH
#define DUNE_COMMON_PARALLEL_MPIFUTURE_HH
#if HAVE_MPI
#include <functional>
#include <memory>
#include <optional>
#include <type_traits>
#include <utility>
#include <mpi.h>
#include <dune/common/exceptions.hh>
#include <dune/common/parallel/communication.hh>
#include <dune/common/parallel/future.hh>
#include <dune/common/parallel/mpidata.hh>
namespace Dune{
namespace Impl{
template<class T>
struct Buffer{
Buffer(bool valid){
if(valid)
value = std::make_unique<T>();
}
template<class V>
Buffer(V&& t)
: value(std::make_unique<T>(std::forward<V>(t)))
{}
std::unique_ptr<T> value;
T get(){
T tmp = std::move(*value);
value.reset();
return tmp;
}
operator bool () const {
return (bool)value;
}
T& operator *() const{
return *value;
}
};
template<class T>
struct Buffer<T&>{
Buffer(bool valid = false)
{
if(valid)
value = T();
}
template<class V>
Buffer(V&& t)
: value(std::forward<V>(t))
{}
std::optional<std::reference_wrapper<T>> value;
T& get(){
T& tmp = *value;
value.reset();
return tmp;
}
operator bool () const{
return (bool)value;
}
T& operator *() const{
return *value;
}
};
template<>
struct Buffer<void>{
bool valid_;
Buffer(bool valid = false)
: valid_(valid)
{}
operator bool () const{
return valid_;
}
void get(){}
};
}
template<class R, class S = void>
class MPIFuture{
mutable MPI_Request req_;
mutable MPI_Status status_;
Impl::Buffer<R> data_;
Impl::Buffer<S> send_data_;
friend class Communication<MPI_Comm>;
public:
MPIFuture(bool valid = false)
: req_(MPI_REQUEST_NULL)
, data_(valid)
{}
// Hide this constructor if R or S is void
template<class V = R, class U = S>
MPIFuture(V&& recv_data, U&& send_data, typename std::enable_if_t<!std::is_void<V>::value && !std::is_void<U>::value>* = 0) :
req_(MPI_REQUEST_NULL)
, data_(std::forward<R>(recv_data))
, send_data_(std::forward<S>(send_data))
{}
// hide this constructor if R is void
template<class V = R>
MPIFuture(V&& recv_data, typename std::enable_if_t<!std::is_void<V>::value>* = 0)
: req_(MPI_REQUEST_NULL)
, data_(std::forward<V>(recv_data))
{}
~MPIFuture() {
if(req_ != MPI_REQUEST_NULL){
try{ // might fail when it is a collective communication
MPI_Cancel(&req_);
MPI_Request_free(&req_);
}catch(...){
}
}
}
MPIFuture(MPIFuture&& f)
: req_(MPI_REQUEST_NULL)
, data_(std::move(f.data_))
, send_data_(std::move(f.send_data_))
{
std::swap(req_, f.req_);
std::swap(status_, f.status_);
}
MPIFuture& operator=(MPIFuture&& f){
std::swap(req_, f.req_);
std::swap(status_, f.status_);
std::swap(data_, f.data_);
std::swap(send_data_, f.send_data_);
return *this;
}
bool valid() const{
return (bool)data_;
}
void wait(){
if(!valid())
DUNE_THROW(InvalidFutureException, "The MPIFuture is not valid!");
MPI_Wait(&req_, &status_);
}
bool ready() const{
int flag = -1;
MPI_Test(&req_, &flag, &status_);
return flag;
}
R get() {
wait();
return data_.get();
}
S get_send_data(){
wait();
return send_data_.get();
}
auto get_mpidata(){
return getMPIData(*data_);
}
auto get_send_mpidata(){
return getMPIData(*send_data_);
}
};
}
#endif // HAVE_MPI
#endif // DUNE_COMMON_PARALLEL_MPIFUTURE_HH
communication.hh
Implements an utility class that provides collective communication methods for sequential programs.
mpidata.hh
Interface class to translate objects to a MPI_Datatype, void* and size used for MPI calls.
future.hh
exceptions.hh
A few common exception classes.
DUNE_THROW
#define DUNE_THROW(E,...)
Definition exceptions.hh:314
Dune::operator*
constexpr decltype(auto) operator*() const
Dereferencing operator.
Definition iteratorfacades.hh:1119
std
STL namespace.
Dune
Dune namespace
Definition alignedallocator.hh:13
Dune::getMPIData
auto getMPIData(T &t)
Definition mpidata.hh:44
Dune::get
constexpr auto get(std::integer_sequence< T, II... >, std::integral_constant< std::size_t, pos >={})
Return the entry at position pos of the given sequence.
Definition integersequence.hh:22
Dune::Communication
Collective communication interface and sequential default implementation.
Definition communication.hh:100
Dune::InvalidFutureException
This exception is thrown when ready(), wait() or get() is called on an invalid future....
Definition future.hh:20
Dune::MPIFuture::MPIFuture
MPIFuture(V &&recv_data, typename std::enable_if_t<!std::is_void< V >::value > *=0)
Definition mpifuture.hh:115
Dune::MPIFuture::ready
bool ready() const
Definition mpifuture.hh:157
Dune::MPIFuture::valid
bool valid() const
Definition mpifuture.hh:147
Dune::MPIFuture::~MPIFuture
~MPIFuture()
Definition mpifuture.hh:120
Dune::MPIFuture::MPIFuture
MPIFuture(bool valid=false)
Definition mpifuture.hh:100
Dune::MPIFuture::operator=
MPIFuture & operator=(MPIFuture &&f)
Definition mpifuture.hh:139
Dune::MPIFuture::get_send_mpidata
auto get_send_mpidata()
Definition mpifuture.hh:177
Dune::MPIFuture::wait
void wait()
Definition mpifuture.hh:151
Dune::MPIFuture::get_mpidata
auto get_mpidata()
Definition mpifuture.hh:173
Dune::MPIFuture::get
R get()
Definition mpifuture.hh:163
Dune::MPIFuture::MPIFuture
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:107
Dune::MPIFuture::get_send_data
S get_send_data()
Definition mpifuture.hh:168
Dune::MPIFuture::MPIFuture
MPIFuture(MPIFuture &&f)
Definition mpifuture.hh:130