Commit f7fec28f authored by Brad King's avatar Brad King
Browse files

core: Refactor ADIOS factory to use Comm encapsulation

Implement the Comm encapsulation by moving MPI code out of the factory.
parent a9a46ce9
...@@ -59,10 +59,9 @@ namespace core ...@@ -59,10 +59,9 @@ namespace core
ADIOS::ADIOS(const std::string configFile, MPI_Comm mpiComm, ADIOS::ADIOS(const std::string configFile, MPI_Comm mpiComm,
const bool debugMode, const std::string hostLanguage) const bool debugMode, const std::string hostLanguage)
: m_ConfigFile(configFile), m_DebugMode(debugMode), m_HostLanguage(hostLanguage) : m_ConfigFile(configFile), m_DebugMode(debugMode),
m_HostLanguage(hostLanguage), m_Comm(helper::Comm::Duplicate(mpiComm))
{ {
SMPI_Comm_dup(mpiComm, &m_MPIComm);
if (!configFile.empty()) if (!configFile.empty())
{ {
if (configFile.substr(configFile.size() - 3) == "xml") if (configFile.substr(configFile.size() - 3) == "xml")
...@@ -90,17 +89,7 @@ ADIOS::ADIOS(const bool debugMode, const std::string hostLanguage) ...@@ -90,17 +89,7 @@ ADIOS::ADIOS(const bool debugMode, const std::string hostLanguage)
{ {
} }
ADIOS::~ADIOS() ADIOS::~ADIOS() = default;
{
// Handle the case where MPI is finalized before the ADIOS destructor is
// called, which happens, e.g., with global / static ADIOS objects
int flag;
MPI_Finalized(&flag);
if (!flag)
{
SMPI_Comm_free(&m_MPIComm);
}
}
IO &ADIOS::DeclareIO(const std::string name) IO &ADIOS::DeclareIO(const std::string name)
{ {
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include "adios2/common/ADIOSMPI.h" #include "adios2/common/ADIOSMPI.h"
#include "adios2/common/ADIOSTypes.h" #include "adios2/common/ADIOSTypes.h"
#include "adios2/core/Operator.h" #include "adios2/core/Operator.h"
#include "adios2/helper/adiosComm.h"
namespace adios2 namespace adios2
{ {
...@@ -39,7 +40,7 @@ public: ...@@ -39,7 +40,7 @@ public:
const bool m_DebugMode = true; const bool m_DebugMode = true;
/** Get the communicator passed to constructor for parallel case. */ /** Get the communicator passed to constructor for parallel case. */
MPI_Comm GetComm() const { return m_MPIComm; } MPI_Comm GetComm() const { return m_Comm; }
/** Changed by language bindings in constructor */ /** Changed by language bindings in constructor */
const std::string m_HostLanguage = "C++"; const std::string m_HostLanguage = "C++";
...@@ -184,8 +185,8 @@ public: ...@@ -184,8 +185,8 @@ public:
void RemoveAllIOs() noexcept; void RemoveAllIOs() noexcept;
private: private:
/** Passed from parallel constructor, MPI_Comm is a pointer itself. */ /** Communicator given to parallel constructor. */
MPI_Comm m_MPIComm; helper::Comm m_Comm;
/** XML File to be read containing configuration information */ /** XML File to be read containing configuration information */
const std::string m_ConfigFile; const std::string m_ConfigFile;
......
...@@ -8,12 +8,54 @@ ...@@ -8,12 +8,54 @@
#include "adiosComm.h" #include "adiosComm.h"
#include "adiosComm.tcc" #include "adiosComm.tcc"
#include <ios> //std::ios_base::failure
#include "adios2/common/ADIOSMPI.h"
namespace adios2 namespace adios2
{ {
namespace helper namespace helper
{ {
Comm::~Comm() = default; Comm::Comm() = default;
Comm::Comm(MPI_Comm mpiComm) : m_MPIComm(mpiComm) {}
Comm::~Comm()
{
// Handle the case where MPI is finalized before the ADIOS destructor is
// called, which happens, e.g., with global / static ADIOS objects
int flag;
MPI_Finalized(&flag);
if (!flag)
{
if (m_MPIComm != MPI_COMM_NULL && m_MPIComm != MPI_COMM_WORLD &&
m_MPIComm != MPI_COMM_SELF)
{
SMPI_Comm_free(&m_MPIComm);
}
}
}
Comm::Comm(Comm &&comm) : m_MPIComm(comm.m_MPIComm)
{
comm.m_MPIComm = MPI_COMM_NULL;
}
Comm &Comm::operator=(Comm &&comm)
{
Comm(std::move(comm)).swap(*this);
return *this;
}
void Comm::swap(Comm &comm) { std::swap(this->m_MPIComm, comm.m_MPIComm); }
Comm Comm::Duplicate(MPI_Comm mpiComm)
{
MPI_Comm newComm;
SMPI_Comm_dup(mpiComm, &newComm);
return Comm(newComm);
}
} // end namespace helper } // end namespace helper
} // end namespace adios2 } // end namespace adios2
...@@ -8,6 +8,8 @@ ...@@ -8,6 +8,8 @@
#ifndef ADIOS2_HELPER_ADIOSCOMM_H_ #ifndef ADIOS2_HELPER_ADIOSCOMM_H_
#define ADIOS2_HELPER_ADIOSCOMM_H_ #define ADIOS2_HELPER_ADIOSCOMM_H_
#include "adios2/common/ADIOSMPI.h"
namespace adios2 namespace adios2
{ {
namespace helper namespace helper
...@@ -17,7 +19,66 @@ namespace helper ...@@ -17,7 +19,66 @@ namespace helper
class Comm class Comm
{ {
public: public:
/**
* @brief Default constructor. Produces an empty communicator.
*
* An empty communicator may not be used for communcation.
*/
Comm();
/**
* @brief Move constructor. Moves communicator state from that given.
*
* The moved-from communicator is left empty and may not be used for
* communication.
*/
Comm(Comm &&);
/**
* @brief Deleted copy constructor. A communicator may not be copied.
*/
Comm(Comm const &) = delete;
~Comm(); ~Comm();
/**
* @brief Move assignment. Moves communicator state from that given.
*
* The moved-from communicator is left empty and may not be used for
* communication.
*/
Comm &operator=(Comm &&);
/**
* @brief Deleted copy assignment. A communicator may not be copied.
*/
Comm &operator=(Comm const &) = delete;
/**
* @brief Swap communicator state with another.
*/
void swap(Comm &comm);
// FIXME: Remove conversion after clients transition to encapsulation.
/** Convert to a concrete MPI communicator. */
operator MPI_Comm() const { return m_MPIComm; }
/**
* @brief Create a communicator by duplicating a MPI communicator.
*/
static Comm Duplicate(MPI_Comm mpiComm);
private:
/**
* @brief Construct by taking ownership of a MPI communicator.
*
* This is a private implementation detail used by static
* methods like Duplicate.
*/
explicit Comm(MPI_Comm mpiComm);
/** Encapsulated MPI communicator instance. */
MPI_Comm m_MPIComm = MPI_COMM_NULL;
}; };
} // end namespace helper } // end namespace helper
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment