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