The MPI::Comm class hierarchy makes explicit the different kinds of communicators implicitly defined by MPI and allows them to be strongly typed. Since the original design of MPI defined only one type of handle for all types of communicators, the following clarifications are provided for the C++ design.
Types of communicators There are five different types of communicators: MPI::Comm, MPI::Intercomm, MPI::Intracomm, MPI::Cartcomm, and MPI::Graphcomm. MPI::Comm is the abstract base communicator class, encapsulating the functionality common to all MPI communicators. MPI::Intercomm and MPI::Intracomm are derived from MPI::Comm. MPI::Cartcomm and MPI::Graphcomm are derived from MPI::Intracomm.
Advice to users.
Initializing a derived class with an instance of a base class is not legal in C++. For instance, it is not legal to initialize a Cartcomm from an Intracomm. Moreover, because MPI::Comm is an abstract base class, it is non-instantiable, so that it is not possible to have an object of class MPI::Comm. However, it is possible to have a reference or a pointer to an MPI::Comm.
Example
The following code is erroneous.
Intracomm intra = MPI::COMM_WORLD.Dup(); Cartcomm cart(intra); // This is erroneous( End of advice to users.)
MPI::COMM_NULL The specific type of MPI::COMM_NULL is implementation dependent. MPI::COMM_NULL must be able to be used in comparisons and initializations with all types of communicators. MPI::COMM_NULL must also be able to be passed to a function that expects a communicator argument in the parameter list (provided that MPI::COMM_NULL is an allowed value for the communicator argument).
Rationale.
There are several possibilities for implementation of
MPI::COMM_NULL. Specifying its required behavior, rather
than its realization, provides maximum flexibility to implementors.
( End of rationale.)
Example
The following example demonstrates the behavior of assignment and
comparison using MPI::COMM_NULL.
MPI::Intercomm comm; comm = MPI::COMM_NULL; // assign with COMM_NULL if (comm == MPI::COMM_NULL) // true cout << "comm is NULL" << endl; if (MPI::COMM_NULL == comm) // note -- a different function! cout << "comm is still NULL" << endl;
Dup() is not defined as a member function of MPI::Comm, but it is defined for the derived classes of MPI::Comm. Dup() is not virtual and it returns its OUT/ parameter by value.
MPI::Comm::Clone() The C++ language interface for MPI includes a new function Clone(). MPI::Comm::Clone() is a pure virtual function. For the derived communicator classes, Clone() behaves like Dup() except that it returns a new object by reference. The Clone() functions are prototyped as follows:
Comm& Comm::Clone() const = 0
Intracomm& Intracomm::Clone() const
Intercomm& Intercomm::Clone() const
Cartcomm& Cartcomm::Clone() const
Graphcomm& Graphcomm::Clone() const
Rationale.
Clone() provides the ``virtual dup'' functionality that is
expected by C++ programmers and library writers. Since
Clone() returns a new object by reference, users are
responsible for eventually deleting the object. A new name is
introduced rather than changing the functionality of Dup().
( End of rationale.)
Advice
to implementors.
Within their class declarations, prototypes for Clone() and
Dup() would look like the following:
namespace MPI { class Comm { virtual Comm& Clone() const = 0; }; class Intracomm : public Comm { Intracomm Dup() const { ... }; virtual Intracomm& Clone() const { ... }; }; class Intercomm : public Comm { Intercomm Dup() const { ... }; virtual Intercomm& Clone() const { ... }; }; // Cartcomm and Graphcomm are similarly defined };Compilers that do not support the variable return type feature of virtual functions may return a reference to Comm. Users can cast to the appropriate type as necessary. ( End of advice to implementors.)