FM_begin_message(), FM_send_piece(), and
FM_end_message() may be called from within a handler.
FM_receive()'d from a message is discarded.
FM_stream * passed into a handler is live for the entire
execution of the handler. Hence, it is incorrect to recycle that
function parameter by storing the result of an
FM_begin_message() in it, even after the last
FM_receive(). Instead, declare a new FM_stream *
variable within the handler and use that for sending messages.
The biggest caveat when working with handlers in FM is that handlers do not execute atomically with respect to the rest of the computation. In a sense, they are like ultra-lightweight threads. Handlers may interleave arbitrarily with each other and with the main computation. As a result, they must be prepared for two situations:
To handle the first situation, handlers should associate a flag with global data structures to distinguish between consistent and inconsistent states. To handle the second situation, handlers should copy message data to a global buffer and resend the data from the main computation. (Hopefully, this will not happen often in practice.)
The following example illustrates the minimal amount of text that must be present in a handler declaration, commented for clarity.
/* Define an empty handler function called my_handler() */
int my_handler(FM_stream *my_stream, unsigned int my_sender)
{
/* Tell FM_extract() to continue extracting */
return FM_CONTINUE;
}
The following is a slightly more advanced handler, to show some of the additional features:
/* Define a handler that reads a string */
/* string into an array and outputs it */
int outputstring(FM_stream *strm, unsigned int snd)
{
char *buf;
int buflen;
/* Allocate space for a string and receive data into it */
/* NOTE: This handler assumes the message length was sent */
/* as the first part of the message */
FM_receive(&buflen,strm,sizeof(int));
buf = (char *)malloc(buflen+1);
FM_receive(buf,strm,buflen);
/* Output the string to standard output */
printf("%s\n",buf);
/* Clean up */
free(buf);
/* Tell FM_extract() to keep going */
return FM_CONTINUE;
}
Go to the first, previous, next, last section, table of contents.