305. Semantics


Up: C++ Next: C++ Datatypes Previous: Class Member Functions for MPI

The semantics of the member functions constituting the C++ language binding for MPI are specified by the MPI function description itself. Here, we specify the semantics for those portions of the C++ language interface that are not part of the language binding. In this subsection, functions are prototyped using the type MPI::<CLASS> rather than listing each function for every MPI class; the word <CLASS> can be replaced with any valid MPI class name (e.g., Group), except as noted.

Construction / Destruction The default constructor and destructor are prototyped as follows:

{ MPI::<CLASS>() (binding deprecated, see Section Deprecated since MPI-2.2 ) }
{ MPI::<CLASS>() (binding deprecated, see Section Deprecated since MPI-2.2 ) }

In terms of construction and destruction, opaque MPI user level objects behave like handles. Default constructors for all MPI objects except MPI::Status create corresponding MPI::*_NULL handles. That is, when an MPI object is instantiated, comparing it with its corresponding MPI::*_NULL object will return true. The default constructors do not create new MPI opaque objects. Some classes have a member function Create() for this purpose.


Example In the following code fragment, the test will return true and the message will be sent to cout.


void foo() 
{ 
  MPI::Intracomm bar; 
 
  if (bar == MPI::COMM_NULL)  
    cout << "bar is MPI::COMM_NULL" << endl; 
} 

The destructor for each MPI user level object does not invoke the corresponding MPI_*_FREE function (if it exists).


Rationale.

MPI_*_FREE functions are not automatically invoked for the following reasons:

    1. Automatic destruction contradicts the shallow-copy semantics of the MPI classes.


    2. The model put forth in MPI makes memory allocation and deallocation the responsibility of the user, not the implementation.


    3. Calling MPI_*_FREE upon destruction could have unintended side effects, including triggering collective operations (this also affects the copy, assignment, and construction semantics). In the following example, we would want neither foo_comm nor bar_comm to automatically invoke MPI_*_FREE upon exit from the function.

    void example_function()  
    { 
      MPI::Intracomm foo_comm(MPI::COMM_WORLD), bar_comm; 
      bar_comm = MPI::COMM_WORLD.Dup(); 
      // rest of function 
    } 
    
( End of rationale.)

Copy / Assignment The copy constructor and assignment operator are prototyped as follows:

{ MPI::<CLASS>(const MPI::<CLASS>& data) (binding deprecated, see Section Deprecated since MPI-2.2 ) }
{ MPI::<CLASS>& MPI::<CLASS>::operator=(const MPI::<CLASS>& data) (binding deprecated, see Section Deprecated since MPI-2.2 ) }

In terms of copying and assignment, opaque MPI user level objects behave like handles. Copy constructors perform handle-based (shallow) copies. MPI::Status objects are exceptions to this rule. These objects perform deep copies for assignment and copy construction.


Advice to implementors.

Each MPI user level object is likely to contain, by value or by reference, implementation-dependent state information. The assignment and copying of MPI object handles may simply copy this value (or reference). ( End of advice to implementors.)

Example Example using assignment operator. In this example, MPI::Intracomm::Dup() is not called for foo_comm. The object foo_comm is simply an alias for MPI::COMM_WORLD. But bar_comm is created with a call to MPI::Intracomm::Dup() and is therefore a different communicator than foo_comm (and thus different from MPI::COMM_WORLD). baz_comm becomes an alias for bar_comm. If one of bar_comm or baz_comm is freed with MPI_COMM_FREE it will be set to MPI::COMM_NULL. The state of the other handle will be undefined --- it will be invalid, but not necessarily set to MPI::COMM_NULL.


  MPI::Intracomm foo_comm, bar_comm, baz_comm; 
 
  foo_comm = MPI::COMM_WORLD; 
  bar_comm = MPI::COMM_WORLD.Dup(); 
  baz_comm = bar_comm; 

Comparison

The comparison operators are prototyped as follows:

{ bool MPI::<CLASS>::operator==(const MPI::<CLASS>& data) const (binding deprecated, see Section Deprecated since MPI-2.2 ) }
{ bool MPI::<CLASS>::operator!=(const MPI::<CLASS>& data) const (binding deprecated, see Section Deprecated since MPI-2.2 ) }

The member function operator==() returns true only when the handles reference the same internal MPI object, false otherwise. operator!=() returns the boolean complement of operator==(). However, since the Status class is not a handle to an underlying MPI object, it does not make sense to compare Status instances. Therefore, the operator==() and operator!=() functions are not defined on the Status class.

Constants Constants are singleton objects and are declared const. Note that not all globally defined MPI objects are constant. For example, MPI::COMM_WORLD and MPI::COMM_SELF are not const.



Up: C++ Next: C++ Datatypes Previous: Class Member Functions for MPI


Return to MPI-2.2 Standard Index
Return to MPI Forum Home Page

(Unofficial) MPI-2.2 of September 4, 2009
HTML Generated on September 10, 2009