dune-common  2.8.0
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 
11 #ifndef DUNE_COMMON_MPIGUARD_HH
12 #define DUNE_COMMON_MPIGUARD_HH
13 
14 #include "mpihelper.hh"
15 #include "communication.hh"
16 #include "mpicommunication.hh"
18 
19 namespace Dune
20 {
21 
22 #ifndef DOXYGEN
23 
24  /*
25  Interface class for the communication needed by MPIGuard
26  */
27  struct GuardCommunicator
28  {
29  // cleanup
30  virtual ~GuardCommunicator() {};
31  // all the communication methods we need
32  virtual int rank() = 0;
33  virtual int size() = 0;
34  virtual int sum(int i) = 0;
35  // create a new GuardCommunicator pointer
36  template <class C>
37  static GuardCommunicator * create(const CollectiveCommunication<C> & c);
38 #if HAVE_MPI
39  inline
40  static GuardCommunicator * create(const MPI_Comm & c);
41 #endif
42  };
43 
44  namespace {
45  /*
46  templated implementation of different communication classes
47  */
48  // the default class will always fail, due to the missing implementation of "sum"
49  template <class Imp>
50  struct GenericGuardCommunicator
51  : public GuardCommunicator
52  {};
53  // specialization for Communication
54  template <class T>
55  struct GenericGuardCommunicator< Communication<T> >
56  : public GuardCommunicator
57  {
58  const Communication<T> comm;
59  GenericGuardCommunicator(const Communication<T> & c) :
60  comm(c) {}
61  int rank() override { return comm.rank(); };
62  int size() override { return comm.size(); };
63  int sum(int i) override { return comm.sum(i); }
64  };
65 
66 #if HAVE_MPI
67  // specialization for MPI_Comm
68  template <>
69  struct GenericGuardCommunicator<MPI_Comm>
70  : public GenericGuardCommunicator< Communication<MPI_Comm> >
71  {
72  GenericGuardCommunicator(const MPI_Comm & c) :
73  GenericGuardCommunicator< Communication<MPI_Comm> >(
74  Communication<MPI_Comm>(c)) {}
75  };
76 #endif
77  } // anonymous namespace
78 
79  template<class C>
80  GuardCommunicator * GuardCommunicator::create(const CollectiveCommunication<C> & comm)
81  {
82  return new GenericGuardCommunicator< CollectiveCommunication<C> >(comm);
83  }
84 
85 #if HAVE_MPI
86  GuardCommunicator * GuardCommunicator::create(const MPI_Comm & comm)
87  {
88  return new GenericGuardCommunicator< CollectiveCommunication<MPI_Comm> >(comm);
89  }
90 #endif
91 
92 #endif
93 
97  class MPIGuardError : public ParallelError {};
98 
131  class MPIGuard
132  {
133  GuardCommunicator * comm_;
134  bool active_;
135 
136  // we don't want to copy this class
137  MPIGuard (const MPIGuard &);
138 
139  public:
144  MPIGuard (bool active=true) :
145  comm_(GuardCommunicator::create(
146  MPIHelper::getCommunication())),
147  active_(active)
148  {}
149 
155  MPIGuard (MPIHelper & m, bool active=true) :
156  comm_(GuardCommunicator::create(
157  m.getCommunication())),
158  active_(active)
159  {}
160 
171  template <class C>
172  MPIGuard (const C & comm, bool active=true) :
173  comm_(GuardCommunicator::create(comm)),
174  active_(active)
175  {}
176 
177 #if HAVE_MPI
178  MPIGuard (const MPI_Comm & comm, bool active=true) :
179  comm_(GuardCommunicator::create(comm)),
180  active_(active)
181  {}
182 #endif
183 
187  {
188  if (active_)
189  {
190  active_ = false;
191  finalize(false);
192  }
193  delete comm_;
194  }
195 
200  void reactivate() {
201  if (active_ == true)
202  finalize();
203  active_ = true;
204  }
205 
216  void finalize(bool success = true)
217  {
218  int result = success ? 0 : 1;
219  bool was_active = active_;
220  active_ = false;
221  result = comm_->sum(result);
222  if (result>0 && was_active)
223  {
224  DUNE_THROW(MPIGuardError, "Terminating process "
225  << comm_->rank() << " due to "
226  << result << " remote error(s)");
227  }
228  }
229  };
230 
231 }
232 
233 #endif // DUNE_COMMON_MPIGUARD_HH
A few common exception classes.
Implements an utility class that provides collective communication methods for sequential programs.
Implements an utility class that provides MPI's collective communication methods.
Helpers for dealing with MPI.
#define DUNE_THROW(E, m)
Definition: exceptions.hh:216
Dune namespace.
Definition: alignedallocator.hh:11
Default exception if an error in the parallel communication of the program occurred.
Definition: exceptions.hh:285
This exception is thrown if the MPIGuard detects an error on a remote process.
Definition: mpiguard.hh:97
detects a thrown exception and communicates to all other processes
Definition: mpiguard.hh:132
void reactivate()
reactivate the guard.
Definition: mpiguard.hh:200
void finalize(bool success=true)
stop the guard.
Definition: mpiguard.hh:216
~MPIGuard()
destroy the guard and check for undetected exceptions
Definition: mpiguard.hh:186
MPIGuard(const C &comm, bool active=true)
create an MPIGuard operating on an arbitrary communicator.
Definition: mpiguard.hh:172
MPIGuard(const MPI_Comm &comm, bool active=true)
Definition: mpiguard.hh:178
MPIGuard(bool active=true)
create an MPIGuard operating on the Communicator of the global Dune::MPIHelper
Definition: mpiguard.hh:144
MPIGuard(MPIHelper &m, bool active=true)
create an MPIGuard operating on the Communicator of a special Dune::MPIHelper m
Definition: mpiguard.hh:155
A real mpi helper.
Definition: mpihelper.hh:175