From 23744d1d35db16473e143b0dd326b270f8704a63 Mon Sep 17 00:00:00 2001
From: Stephane Del Pino <stephane.delpino44@gmail.com>
Date: Mon, 24 Sep 2018 11:53:12 +0200
Subject: [PATCH] Begin Messenger infrastructure

The goal of this class is to encapsulate MPI calls and to provide a same API for
non-parallel and parallel builds
---
 src/utils/CMakeLists.txt  |  1 +
 src/utils/Messenger.cpp   | 50 +++++++++++++++++++++++++++++++++++++
 src/utils/Messenger.hpp   | 34 +++++++++++++++++++++++++
 src/utils/PastisUtils.cpp | 52 ++++-----------------------------------
 4 files changed, 90 insertions(+), 47 deletions(-)
 create mode 100644 src/utils/Messenger.cpp
 create mode 100644 src/utils/Messenger.hpp

diff --git a/src/utils/CMakeLists.txt b/src/utils/CMakeLists.txt
index 5152bf528..d21584923 100644
--- a/src/utils/CMakeLists.txt
+++ b/src/utils/CMakeLists.txt
@@ -9,6 +9,7 @@ add_library(
   BacktraceManager.cpp
   ConsoleManager.cpp
   FPEManager.cpp
+  Messenger.cpp
   PastisOStream.cpp
   PastisUtils.cpp
   RevisionInfo.cpp
diff --git a/src/utils/Messenger.cpp b/src/utils/Messenger.cpp
new file mode 100644
index 000000000..027f5bb3f
--- /dev/null
+++ b/src/utils/Messenger.cpp
@@ -0,0 +1,50 @@
+#include <Messenger.hpp>
+#include <PastisOStream.hpp>
+
+#include <pastis_config.hpp>
+
+#ifdef PASTIS_HAS_MPI
+#include <mpi.h>
+#endif // PASTIS_HAS_MPI
+
+Messenger* Messenger::m_instance = nullptr;
+
+void Messenger::create(int& argc, char* argv[])
+{
+  if (Messenger::m_instance == nullptr) {
+    Messenger::m_instance = new Messenger(argc, argv);
+  } else {
+    std::cerr << "Messenger already created\n";
+    std::exit(1);
+  }
+}
+
+void Messenger::destroy()
+{
+  // One allows multiple destruction to handle unexpected code exit
+  if (Messenger::m_instance != nullptr) {
+    delete Messenger::m_instance;
+    Messenger::m_instance = nullptr;
+  }
+}
+
+Messenger::
+Messenger(int& argc, char* argv[])
+{
+#ifdef PASTIS_HAS_MPI
+  MPI_Init(&argc, &argv);
+  MPI_Comm_rank(MPI_COMM_WORLD, &m_rank);
+  MPI_Comm_size(MPI_COMM_WORLD, &m_size);
+
+  if (m_rank != 0) {
+    pout.setOutput(null_stream);
+    perr.setOutput(null_stream);
+  }
+#endif // PASTIS_HAS_MPI
+}
+
+Messenger::
+~Messenger()
+{
+  MPI_Finalize();
+}
diff --git a/src/utils/Messenger.hpp b/src/utils/Messenger.hpp
new file mode 100644
index 000000000..275840eef
--- /dev/null
+++ b/src/utils/Messenger.hpp
@@ -0,0 +1,34 @@
+#ifndef MESSENGER_HPP
+#define MESSENGER_HPP
+
+#include <PastisMacros.hpp>
+
+class Messenger
+{
+ private:
+  static Messenger* m_instance;
+  Messenger(int& argc, char* argv[]);
+
+  int m_rank{0};
+  int m_size{1};
+ public:
+  static void create(int& argc, char* argv[]);
+  static void destroy();
+
+  PASTIS_INLINE
+  const int& rank() const
+  {
+    return m_rank;
+  }
+
+  PASTIS_INLINE
+  const int& size() const
+  {
+    return m_size;
+  }
+
+  Messenger(const Messenger&) = delete;
+  ~Messenger();
+};
+
+#endif // MESSENGER_HPP
diff --git a/src/utils/PastisUtils.cpp b/src/utils/PastisUtils.cpp
index 9494c68a7..66aa50b49 100644
--- a/src/utils/PastisUtils.cpp
+++ b/src/utils/PastisUtils.cpp
@@ -6,6 +6,8 @@
 #include <RevisionInfo.hpp>
 #include <BuildInfo.hpp>
 
+#include <Messenger.hpp>
+
 #include <rang.hpp>
 
 #include <FPEManager.hpp>
@@ -14,30 +16,9 @@
 
 #include <CLI/CLI.hpp>
 
-#include <pastis_config.hpp>
-
-#ifdef PASTIS_HAS_MPI
-#include <mpi.h>
-#endif // PASTIS_HAS_MPI
-
 std::string initialize(int& argc, char* argv[])
 {
-#ifdef PASTIS_HAS_MPI
-  MPI_Init(&argc, &argv);
-
-  {
-    const int mpi_rank
-        =[](){
-           int mpi_rank;
-           MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
-           return mpi_rank;
-         }();
-    if (mpi_rank != 0) {
-      pout.setOutput(null_stream);
-      perr.setOutput(null_stream);
-    }
-  }
-#endif // PASTIS_HAS_MPI
+  Messenger::create(argc, argv);
 
   long unsigned number = 10;
   std::string filename;
@@ -97,6 +78,7 @@ std::string initialize(int& argc, char* argv[])
     try {
       app.parse(argc, argv);
     } catch (const CLI::ParseError &e) {
+      Messenger::destroy();
       std::exit(app.exit(e, pout(), perr()));
     }
 
@@ -124,30 +106,6 @@ std::string initialize(int& argc, char* argv[])
 
 void finalize()
 {
-#ifdef PASTIS_HAS_MPI
-  MPI_Barrier(MPI_COMM_WORLD);
-  const int mpi_rank
-      =[](){
-         int mpi_rank;
-         MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
-         return mpi_rank;
-       }();
-
-  const int mpi_size
-      =[](){
-         int mpi_size;
-         MPI_Comm_size(MPI_COMM_WORLD, &mpi_size);
-         return mpi_size;
-       }();
-
-  pout() << rang::fgB::green << "Terminating process " << rang::fg::reset
-         << rang::fgB::yellow << mpi_rank << rang::fg::reset << " of "
-         << rang::style::bold << mpi_size << rang::style::reset << '\n';;
-#endif // PASTIS_HAS_MPI
-
   Kokkos::finalize();
-
-#ifdef PASTIS_HAS_MPI
-  MPI_Finalize();
-#endif // PASTIS_HAS_MPI
+  Messenger::destroy();
 }
-- 
GitLab