[MPI3 Fortran] Fortran extra_state argument to MPI attribute functions

Jeff Squyres jsquyres at cisco.com
Tue May 26 13:52:28 CDT 2009

A thread started on the general MPI-2.2 list a while ago asking about  
the extra_state parameter to the fortran callbacks in the MPI  
attribute functions:

and continued here

Specifically, there is no indication of how the "extra_state"  
parameter is handled when it is passed to callback functions.

Bear with me -- this requires a little explanation...

The issue is this: when you create a "keyval" in MPI, you specify 2  
callback functions and an INTEGER extra_state parameter.  Each of the  
two callback functions has an extra_state parameter; the intent is  
that the extra_state from the keyval creation function is passed as  
the argument to these two callback functions.  Here's a sample keyval  

    ! copy_fn and delete_fn are subroutines
    ! comm is an INTEGER
    INTEGER extra_state
    extra_state = 42
    CALL MPI_Comm_create_keyval(copy_fn, delete_fn, comm, extra_state,  
    extra_state = 17

There are three options for how this extra_state argument is treated:

1. The extra_state that is passed to the callback functions is the  
exact reference that was passed to MPI_Comm_create_keyval().  Hence,  
when copy_fn/delete_fn are invoked (after MPI_Comm_create_keyval()  
returns), they'll get a passed value of 17.

--> This seems to be obviously illegal in Fortran.  If you pass an  
expression as the value of the extra_state argument to  
MPI_Comm_create_keyval, that reference will be out of scope by the  
time the callbacks are invoked.  Unfortunately, some MPI  
implementations (including Open MPI, until version 1.3.3 is released!)  
use this semantic.  Oops.  :-\

2. Copy the value of extra_state during the call to  
MPI_Comm_create_keyval() into internal MPI implementation storage.   
When the callbacks are invoked, pass a reference to this internal  
storage.  Hence, the first callback that is invoked will always  
receive an extra_state value of 42 (not 17).

Note that no INTENT is specified in the MPI document prototypes for  
the copy_fn and delete_fn, so the callback may actually modify the  
extra_state value.

2a. The MPI implementation can always pass the same extra_state  
reference, meaning that all subsequent callback invocations will get  
the most-recently-modified value.  Hence, if one callback modifies  
extra_state to be 94, then the next callback will receive an  
extra_state value of 94.

2b. The MPI implementation can copy the internal storage and give a  
unique copy to each callback invocation so that *all* invocations will  
always get the original extra_state value (42), even if extra_state is  
modified during the callback.

Now that explanation is over, let me explain the intent of this  
interface from the C side; I believe it gives insight into what should  
happen on the Fortran side.

The C prototype for the callback functions have (void*) extra_state  
arguments.  The intent for them is just like many other C interfaces  
with extra_state arguments: they can be anything, to include pointers  
into much larger / external data instances.  Hence, it's not the  
*value* of the extra_state that is overly important -- that value is  
usually a pointer to something else.

The people who made the MPI interface for the callbacks intended that  
the Fortran extra_state parameter should be used in the same way.   
With Fortran 77, you could just pass my_array(1) as the extra_state  
argument, and then your extra_state argument in the callback would  
effectively be a reference to the whole my_array array.  Ugly, but it  
worked.  :-\  With tighter bindings from F90 and onward, this abuse is  
clearly not possible (which is a Good Thing!).

However, the original intent is somewhat lost here -- since the  
MPI_COMM_CREATE_KEYVAL interface specifies that the EXTRA_STATE  
parameter is an integer, how can you pass a reference to a larger /  
external structure?  This seems somewhat broken / inconsistent with  
the intent from the C interface.

Of course, you *could* pass an INTEGER EXTRA_STATE value that is an  
index into a global array in the application that contains some  
reference to an external data instance -- but that seems fairly  
manual.  Is there a better way?

How are such things normally done in Fortran?  (meaning: what *should*  
we do here?)

As an aside: I think that the above case means that we should go with  
option 2b (meaning: we need to add text to MPI 3.0 indicating that 2b  
semantics must be observed).  Indeed, this would be like most other C  
(void*) extra state interfaces: the value that is passed is *always*  
the same as the original value (42), regardless of whether one of the  
callbacks changed the value locally or not.  The fact that Fortran  
passes parameters by reference and passes by value means that if we  
want the C semantics, we need to use option 2b.

Jeff Squyres
Cisco Systems

More information about the mpiwg-fortran mailing list