Dune Core Modules (unstable)

mpiguard.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 © DUNE Project contributors, see file LICENSE.md in module root
4 // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception
5 
13 #ifndef DUNE_COMMON_PARALLEL_MPIGUARD_HH
14 #define DUNE_COMMON_PARALLEL_MPIGUARD_HH
15 
16 #if HAVE_MPI
17 #include <mpi.h>
18 #endif
19 
24 
25 namespace Dune
26 {
27 
28 #ifndef DOXYGEN
29 
30  /*
31  Interface class for the communication needed by MPIGuard
32  */
33  struct GuardCommunicator
34  {
35  // cleanup
36  virtual ~GuardCommunicator() {};
37  // all the communication methods we need
38  virtual int rank() = 0;
39  virtual int size() = 0;
40  virtual int sum(int i) = 0;
41  // create a new GuardCommunicator pointer
42  template <class C>
43  static GuardCommunicator * create(const Communication<C> & c);
44 #if HAVE_MPI
45  inline
46  static GuardCommunicator * create(const MPI_Comm & c);
47 #endif
48  };
49 
50  namespace {
51  /*
52  templated implementation of different communication classes
53  */
54  // the default class will always fail, due to the missing implementation of "sum"
55  template <class Imp>
56  struct GenericGuardCommunicator
57  : public GuardCommunicator
58  {};
59  // specialization for Communication
60  template <class T>
61  struct GenericGuardCommunicator< Communication<T> >
62  : public GuardCommunicator
63  {
64  const Communication<T> comm;
65  GenericGuardCommunicator(const Communication<T> & c) :
66  comm(c) {}
67  int rank() override { return comm.rank(); };
68  int size() override { return comm.size(); };
69  int sum(int i) override { return comm.sum(i); }
70  };
71 
72 #if HAVE_MPI
73  // specialization for MPI_Comm
74  template <>
75  struct GenericGuardCommunicator<MPI_Comm>
76  : public GenericGuardCommunicator< Communication<MPI_Comm> >
77  {
78  GenericGuardCommunicator(const MPI_Comm & c) :
79  GenericGuardCommunicator< Communication<MPI_Comm> >(
80  Communication<MPI_Comm>(c)) {}
81  };
82 #endif
83  } // anonymous namespace
84 
85  template<class C>
86  GuardCommunicator * GuardCommunicator::create(const Communication<C> & comm)
87  {
88  return new GenericGuardCommunicator< Communication<C> >(comm);
89  }
90 
91 #if HAVE_MPI
92  GuardCommunicator * GuardCommunicator::create(const MPI_Comm & comm)
93  {
94  return new GenericGuardCommunicator< Communication<MPI_Comm> >(comm);
95  }
96 #endif
97 
98 #endif
99 
103  class MPIGuardError : public ParallelError {};
104 
137  class MPIGuard
138  {
139  GuardCommunicator * comm_;
140  bool active_;
141 
142  // we don't want to copy this class
143  MPIGuard (const MPIGuard &);
144 
145  public:
150  MPIGuard (bool active=true) :
151  comm_(GuardCommunicator::create(
152  MPIHelper::getCommunication())),
153  active_(active)
154  {}
155 
161  MPIGuard (MPIHelper & m, bool active=true) :
162  comm_(GuardCommunicator::create(
163  m.getCommunication())),
164  active_(active)
165  {}
166 
177  template <class C>
178  MPIGuard (const C & comm, bool active=true) :
179  comm_(GuardCommunicator::create(comm)),
180  active_(active)
181  {}
182 
183 #if HAVE_MPI
184  MPIGuard (const MPI_Comm & comm, bool active=true) :
185  comm_(GuardCommunicator::create(comm)),
186  active_(active)
187  {}
188 #endif
189 
193  {
194  if (active_)
195  {
196  active_ = false;
197  finalize(false);
198  }
199  delete comm_;
200  }
201 
206  void reactivate() {
207  if (active_ == true)
208  finalize();
209  active_ = true;
210  }
211 
222  void finalize(bool success = true)
223  {
224  int result = success ? 0 : 1;
225  bool was_active = active_;
226  active_ = false;
227  result = comm_->sum(result);
228  if (result>0 && was_active)
229  {
230  DUNE_THROW(MPIGuardError, "Terminating process "
231  << comm_->rank() << " due to "
232  << result << " remote error(s)");
233  }
234  }
235  };
236 
237 }
238 
239 #endif // DUNE_COMMON_PARALLEL_MPIGUARD_HH
This exception is thrown if the MPIGuard detects an error on a remote process.
Definition: mpiguard.hh:103
detects a thrown exception and communicates to all other processes
Definition: mpiguard.hh:138
void reactivate()
reactivate the guard.
Definition: mpiguard.hh:206
void finalize(bool success=true)
stop the guard.
Definition: mpiguard.hh:222
~MPIGuard()
destroy the guard and check for undetected exceptions
Definition: mpiguard.hh:192
MPIGuard(const C &comm, bool active=true)
create an MPIGuard operating on an arbitrary communicator.
Definition: mpiguard.hh:178
MPIGuard(bool active=true)
create an MPIGuard operating on the Communicator of the global Dune::MPIHelper
Definition: mpiguard.hh:150
MPIGuard(MPIHelper &m, bool active=true)
create an MPIGuard operating on the Communicator of a special Dune::MPIHelper m
Definition: mpiguard.hh:161
A real mpi helper.
Definition: mpihelper.hh:181
Default exception if an error in the parallel communication of the program occurred.
Definition: exceptions.hh:287
Implements an utility class that provides collective communication methods for sequential programs.
A few common exception classes.
#define DUNE_THROW(E, m)
Definition: exceptions.hh:218
Implements an utility class that provides MPI's collective communication methods.
Helpers for dealing with MPI.
Dune namespace.
Definition: alignedallocator.hh:13
constexpr std::integral_constant< std::size_t, sizeof...(II)> size(std::integer_sequence< T, II... >)
Return the size of the sequence.
Definition: integersequence.hh:75
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.80.0 (May 1, 22:29, 2024)