From d3e0fb798c2d5cfa159a7397e1b133c1aa8f5e02 Mon Sep 17 00:00:00 2001 From: Kai Germaschewski Date: Tue, 4 Jun 2019 15:22:47 -0400 Subject: [PATCH] mpiwrap: make mpwiwrap.h/mpidummy.h includable from plain C --- source/adios2/ADIOSMPI.h | 2 -- source/adios2/helper/mpidummy.h | 26 ++++++++------- source/adios2/helper/mpiwrap.cpp | 1 + source/adios2/helper/mpiwrap.h | 56 +++++++++++++++++++++++++++++--- 4 files changed, 67 insertions(+), 18 deletions(-) diff --git a/source/adios2/ADIOSMPI.h b/source/adios2/ADIOSMPI.h index 8190eb3ed1..185912599c 100644 --- a/source/adios2/ADIOSMPI.h +++ b/source/adios2/ADIOSMPI.h @@ -6,8 +6,6 @@ #ifndef ADIOS2_ADIOSMPI_H_ #define ADIOS2_ADIOSMPI_H_ -#include "adios2/ADIOSConfig.h" - #include "adios2/helper/mpiwrap.h" #include //UXXX_MAX diff --git a/source/adios2/helper/mpidummy.h b/source/adios2/helper/mpidummy.h index 1413b3a78b..bbaa555bbd 100644 --- a/source/adios2/helper/mpidummy.h +++ b/source/adios2/helper/mpidummy.h @@ -10,8 +10,8 @@ #ifndef ADIOS2_HELPER_MPIDUMMY_H_ #define ADIOS2_HELPER_MPIDUMMY_H_ -#include -#include +#include "stdint.h" +#include "stdio.h" #include "adios2/ADIOSConfig.h" @@ -21,15 +21,15 @@ #include #else -using MPI_Comm = int; -using MPI_Status = std::uint64_t; -using MPI_Request = std::uint64_t; -using MPI_File = std::FILE *; -using MPI_Info = int; -using MPI_Datatype = int; -using MPI_Offset = long int; -using MPI_Fint = int; -using MPI_Op = int; +typedef int MPI_Comm; +typedef uint64_t MPI_Status; +typedef uint64_t MPI_Request; +typedef FILE *MPI_File; +typedef int MPI_Info; +typedef int MPI_Datatype; +typedef long int MPI_Offset; +typedef int MPI_Fint; +typedef int MPI_Op; #define MPI_SUCCESS 0 #define MPI_ERR_BUFFER 1 /* Invalid buffer pointer */ @@ -101,8 +101,10 @@ namespace helper namespace mpidummy { #else +#ifdef __cplusplus extern "C" { #endif +#endif int MPI_Init(int *argc, char ***argv); int MPI_Finalize(); @@ -177,7 +179,9 @@ int MPI_Allreduce(const void *sendbuf, void *recvbuf, int count, } // end namespace helper } // end namespace adios #else +#ifdef __cplusplus } // end extern "C" #endif +#endif #endif /* ADIOS2_MPIDUMMY_H_ */ diff --git a/source/adios2/helper/mpiwrap.cpp b/source/adios2/helper/mpiwrap.cpp index 8de1f50198..e090d92ca1 100644 --- a/source/adios2/helper/mpiwrap.cpp +++ b/source/adios2/helper/mpiwrap.cpp @@ -6,6 +6,7 @@ */ #include "mpiwrap.h" +#include "mpidummy.h" static inline bool SMPI_Available() { diff --git a/source/adios2/helper/mpiwrap.h b/source/adios2/helper/mpiwrap.h index ca62ccab7c..403848b5bd 100644 --- a/source/adios2/helper/mpiwrap.h +++ b/source/adios2/helper/mpiwrap.h @@ -9,6 +9,50 @@ #ifndef ADIOS2_HELPER_MPIWRAP_H_ #define ADIOS2_HELPER_MPIWRAP_H_ +// Overview of the MPI wrapping: +// ============================= +// +// Including this header provides a unified way of dealing with the +// building against an actual MPI library (ADIOS2_HAVE_MPI) vs using +// a dummy implementation, and also deals with running serially +// when built against MPI, but not calling MPI_Init +// +// MPI types / constants +// --------------------- +// +// If ADIOS2_HAVE_MPI is defined, the actual MPI types (in particular MPI_Comm) +// from the real MPI are always used, even in the dummy implementations that are +// used when MPI hasn't been initialized. +// Otherwise, the definitions from mpidummy.h are used. These types are in the +// global namespace. +// +// MPI_* functions +// ------------- +// +// The usual MPI functions are always defined in the global namespace (extern +// "C"). If ADIOS2_HAVE_MPI is defined, the declarations come from mpi.h. +// Otherwise, these functions are declared in mpidummy.h, also extern "C". +// +// If ADIOS2_HAVE_MPI is defined, the declarations in mpidummy.h are put into +// adios2::helper::mpidummy in order to not interfere with the extern "C" ones, +// but this way they are still available to use in the SMPI_* wrappers +// +// SMPI_* wrappers +// --------------- +// The SMPI wrappers provide a way to write code that works in all three of the +// following cases: +// - If ADIOS2_HAVE_MPI is undefined, these wrappers call the corresponding +// extern "C" MPI functions, which in this case are the mpidummy +// implementations. +// - If ADIOS2_HAVE_MPI is defined, and MPI has been initialized, these wrappers +// call the corresponding extern "C" MPI functions, which in this case are the +// real MPI implementations. +// - If ADIOS2_HAVE_MPI is defined, and MPI has not been initialized, these +// wrappers call the corresponding adios2::helper::mpidummy MPI functions, +// which are serial only but don't require the real MPI to be initialized. + +#include "adios2/ADIOSConfig.h" + // Get either the real MPI or mpidummy into the global namespace #ifdef ADIOS2_HAVE_MPI #include @@ -16,11 +60,10 @@ #include "mpidummy.h" #endif -// SMPI_* work just as the original MPI_* functions, but will also -// work if MPI_Init has not been called, as long asssuming the communicator is a -// single-proc communicator, by falling back to mpidummy in that case - +#ifdef __cplusplus extern "C" { +#endif + int SMPI_Comm_dup(MPI_Comm comm, MPI_Comm *newcomm); int SMPI_Comm_free(MPI_Comm *newcomm); int SMPI_Comm_rank(MPI_Comm comm, int *rank); @@ -36,6 +79,9 @@ int SMPI_Gatherv(const void *sendbuf, int sendcount, MPI_Datatype sendtype, MPI_Datatype recvtype, int root, MPI_Comm comm); int SMPI_Reduce(const void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, int root, MPI_Comm comm); -} +#ifdef __cplusplus +} #endif + +#endif /* ADIOS2_HELPER_MPIWRAP_H_ */