00001
00002
00003
00011 #ifndef DUNE_COMMON_MPIGUARD_HH
00012 #define DUNE_COMMON_MPIGUARD_HH
00013
00014 #include "mpihelper.hh"
00015 #include "collectivecommunication.hh"
00016 #include "mpicollectivecommunication.hh"
00017 #include <dune/common/exceptions.hh>
00018
00019 namespace Dune
00020 {
00021
00022 #ifndef DOXYGEN
00023
00024
00025
00026
00027 struct GuardCommunicator
00028 {
00029
00030 virtual ~GuardCommunicator() {};
00031
00032 virtual int rank() = 0;
00033 virtual int size() = 0;
00034 virtual int sum(int i) = 0;
00035
00036 template <class C>
00037 static GuardCommunicator * create(const C & c);
00038 };
00039
00040 namespace {
00041
00042
00043
00044
00045 template <class Imp>
00046 struct GenericGuardCommunicator
00047 : public GuardCommunicator
00048 {};
00049
00050 template <class T>
00051 struct GenericGuardCommunicator< CollectiveCommunication<T> >
00052 : public GuardCommunicator
00053 {
00054 const CollectiveCommunication<T> comm;
00055 GenericGuardCommunicator(const CollectiveCommunication<T> & c) :
00056 comm(c) {}
00057 virtual int rank() { return comm.rank(); };
00058 virtual int size() { return comm.size(); };
00059 virtual int sum(int i) { return comm.sum(i); }
00060 };
00061
00062 #if HAVE_MPI
00063
00064 template <>
00065 struct GenericGuardCommunicator<MPI_Comm>
00066 : public GenericGuardCommunicator< CollectiveCommunication<MPI_Comm> >
00067 {
00068 GenericGuardCommunicator(const MPI_Comm & c) :
00069 GenericGuardCommunicator< CollectiveCommunication<MPI_Comm> >(
00070 CollectiveCommunication<MPI_Comm>(c)) {}
00071 };
00072 #endif
00073 }
00074
00075 template<class C>
00076 GuardCommunicator * GuardCommunicator::create(const C & comm)
00077 {
00078 return new GenericGuardCommunicator<C>(comm);
00079 }
00080 #endif
00081
00085 class MPIGuardError : public ParallelError {};
00086
00119 class MPIGuard
00120 {
00121 GuardCommunicator * comm_;
00122 bool active_;
00123
00124
00125 MPIGuard (const MPIGuard &);
00126
00127 public:
00132 MPIGuard (bool active=true) :
00133 comm_(GuardCommunicator::create(
00134 MPIHelper::getCollectiveCommunication())),
00135 active_(active)
00136 {}
00137
00143 MPIGuard (MPIHelper & m, bool active=true) :
00144 comm_(GuardCommunicator::create(
00145 m.getCollectiveCommunication())),
00146 active_(active)
00147 {}
00148
00159 template <class C>
00160 MPIGuard (const C & comm, bool active=true) :
00161 comm_(GuardCommunicator::create(comm)),
00162 active_(active)
00163 {}
00164
00167 ~MPIGuard()
00168 {
00169 if (active_)
00170 {
00171 active_ = false;
00172 finalize(false);
00173 }
00174 delete comm_;
00175 }
00176
00181 void reactivate() {
00182 if (active_ == true)
00183 finalize();
00184 active_ = true;
00185 }
00186
00197 void finalize(bool success = true)
00198 {
00199 int result = success ? 0 : 1;
00200 bool was_active = active_;
00201 active_ = false;
00202 result = comm_->sum(result);
00203 if (result>0 && was_active)
00204 {
00205 DUNE_THROW(MPIGuardError, "Terminating process "
00206 << comm_->rank() << " due to "
00207 << result << " remote error(s)");
00208 }
00209 }
00210 };
00211
00212 }
00213
00214 #endif // DUNE_COMMON_MPIGUARD_HH