When a message arrives at a processor, it triggers the execution of a handler function, not unlike a UNIX signal handler. The handler function receives, as an argument, a pointer to the message. The message itself specifies which handler function is to be called when the message arrives. Messages are contiguous sequences of bytes. The message has two parts: the header, and the data. The data may contain anything you like. The header contains a handler number, which specifies which handler function is to be executed when the message arrives. Before you can send a message, you have to define the handler numbers.
CONVERSE maintains a table mapping handler numbers to function pointers. Each processor has its own copy of the mapping. There is a caution associated with this approach: it is the user's responsibility to ensure that all processors have identical mappings. This is easy to do, nonetheless, and the user must be aware that this is (usually) required.
The following functions are provided to define the handler numbers:
typedef void (*CmiHandler)(void *)
Functions that handle CONVERSE messages must be of this type.
int CmiRegisterHandler(CmiHandler h)
This represents the standard technique for associating numbers
with functions. To use this technique, the CONVERSE user registers
each of his functions, one by one, using CmiRegisterHandler. One must
register exactly the same functions in exactly the same order on all
processors. The system assigns monotonically increasing numbers to
the functions, the same numbers on all processors. This insures
global consistency. CmiRegisterHandler returns the number which was
chosen for the function being registered.
int CmiRegisterHandlerGlobal(CmiHandler h)
This represents a second registration technique. The CONVERSE
user registers his functions on processor zero, using
CmiRegisterHandlerGlobal. The CONVERSE user is then responsible for
broadcasting those handler numbers to other processors, and installing
them using CmiNumberHandler below. The user should take care not to
invoke those handlers until they are fully installed.
int CmiRegisterHandlerLocal(CmiHandler h)
This function is used when one wishes to register functions
in a manner that is not consistent across processors. This function
chooses a locally-meaningful number for the function, and records it
locally. No attempt is made to ensure consistency across processors.
void CmiNumberHandler(int n, CmiHandler h)
Forces the system to associate the specified handler number n
with the specified handler function h. If the function number
n was previously mapped to some other function, that old mapping
is forgotten. The mapping that this function creates is local to the
current processor. CmiNumberHandler can be useful in combination with
CmiRegisterGlobalHandler. It can also be used to implement
user-defined numbering schemes: such schemes should keep in mind that
the size of the table that holds the mapping is proportional to the
largest handler number -- do not use big numbers!
(Note: Of the three registration methods, the CmiRegisterHandler method is by far the simplest, and is strongly encouraged. The others are primarily to ease the porting of systems that already use similar registration techniques. One may use all three registration methods in a program. The system guarantees that no numbering conflicts will occur as a result of this combination.)
June 29, 2008
Converse Homepage
Charm Homepage