Message Board API Routines

Functions

int MB_Env_Init (void)
 Initialises the libmboard environment.
int MB_Env_Finalise (void)
 Finalises the libmboard environment.
int MB_Env_Initialised (void)
 Indicates whether MB_Env_Init() has been called successfully.
int MB_Env_Finalised (void)
 Indicates whether MB_Env_Finalise() has been called.
int MB_Create (MBt_Board *mb_ptr, size_t msgsize)
 Instantiates a new Message Board object.
int MB_SetAccessMode (MBt_Board mb, int MODE)
 Sets access mode of the Message Board.
int MB_SetSyncPattern (MBt_Board mb, unsigned int *sync_matrix)
 Sets sync pattern of the Message Board.
int MB_AddMessage (MBt_Board mb, void *msg)
 Adds a message to the Message Board.
int MB_Clear (MBt_Board mb)
 Clears the Message Board.
int MB_Delete (MBt_Board *mb_ptr)
 Deletes a Message Board.
int MB_Iterator_Create (MBt_Board mb, MBt_Iterator *itr_ptr)
 Creates a new Iterator for accessing messages in board mb.
int MB_Iterator_CreateSorted (MBt_Board mb, MBt_Iterator *itr_ptr, int(*cmpFunc)(const void *msg1, const void *msg2))
 Creates a new Iterator for accessing sorted messages in board mb.
int MB_Iterator_CreateFiltered (MBt_Board mb, MBt_Iterator *itr_ptr, int(*filterFunc)(const void *msg, const void *params), void *filterFuncParams)
 Creates a new Iterator for accessing a selection of messages in board mb.
int MB_Iterator_CreateFilteredSorted (MBt_Board mb, MBt_Iterator *itr_ptr, int(*filterFunc)(const void *msg, const void *params), void *filterFuncParams, int(*cmpFunc)(const void *msg1, const void *msg2))
 Instantiates a new Iterator for accessing a sorted selection of messages in board mb.
int MB_Iterator_Delete (MBt_Iterator *itr_ptr)
 Deletes an Iterator.
int MB_Iterator_GetMessage (MBt_Iterator itr, void **msg_ptr)
 Returns next available message from Iterator.
int MB_Iterator_Rewind (MBt_Iterator itr)
 Rewinds an Iterator.
int MB_Iterator_Randomise (MBt_Iterator itr)
 Randomises the order of entries in an Iterator.
int MB_SyncStart (MBt_Board mb)
 Synchronises the content of the board across all processes.
int MB_SyncTest (MBt_Board mb, int *flag)
 Inspects the completion status of a board synchronisation.
int MB_SyncComplete (MBt_Board mb)
 Completes the synchronisation of a board.
int MB_Filter_Create (MBt_Filter *fh_ptr, int(*filterFunc)(const void *msg, int pid))
 Creates a filter object.
int MB_Filter_Assign (MBt_Board mb, MBt_Filter fh)
 Assigns a filter handle to a message board.
int MB_Filter_Delete (MBt_Filter *fh_ptr)
 Deallocates a registered function.
int MB_IndexMap_Create (MBt_IndexMap *im_ptr, const char *name)
 Instantiates a new Index Map object.
int MB_IndexMap_Delete (MBt_IndexMap *im_ptr)
 Deletes an Index Map.
int MB_IndexMap_AddEntry (MBt_IndexMap im, int value)
 Adds an entry into the Index Map.
int MB_IndexMap_Sync (MBt_IndexMap im)
 Distributes/gathers the map content across/from all processors.
int MB_IndexMap_MemberOf (MBt_IndexMap im, int pid, int value)
 Query the map to determine if a value exists on a particular processor.

Detailed Description

Routines to create and use Message Boards


Function Documentation

MB_Env_Init ( void   ) 

Initialises the libmboard environment.

This routine must be called before any other libmboard routines (apart for MB_Env_Initialised() and MB_Env_Finalised()). It launches the communication thread and initialises all internal data structures required by the library.

The libmboard environment should be initialised only once, and never re-initialised once it has been finalised (using MB_Env_Finalise()).

Possible return codes:

MB_Env_Finalise ( void   ) 

Finalises the libmboard environment.

This should be the last libmboard routine called within a program (apart for MB_Env_Initialised() and MB_Env_Finalised()). It deallocates all internal data structures and terminates the communication thread.

It is erroneous to finalise the environment while there are pending board synchronisations, i.e. all MB_SyncStart() must be completed with a matching MB_SyncComplete() (or successful MB_SyncTest()).

Possible return codes:

MB_Env_Initialised ( void   ) 

Indicates whether MB_Env_Init() has been called successfully.

This routine will return MB_SUCCESS if the environment has been initialised, or MB_ERR_ENV otherwise.

Possible return codes:

  • MB_SUCCESS
  • MB_ERR_ENV (libmboard environment was not successfully set up, or, has already been finalised)
MB_Env_Finalised ( void   ) 

Indicates whether MB_Env_Finalise() has been called.

This routine will return MB_SUCCESS if the environment has been finalised, or MB_ERR_ENV otherwise.

Possible return codes:

MB_Create ( MBt_Board mb_ptr,
size_t  msgsize 
)

Instantiates a new Message Board object.

Parameters:
[out] mb_ptr Address of Message Board handle
[in] msgsize Size of message that this Message Board will be used for

Creates a new board for storing messages of size msgsize and returns a handle to the board via mb_ptr .

In the parallel debug version, this routine is blocking and will return when all processes have issued and completed the call. This effectively synchronises all processes. It is the users' responsibility to ensure that all processes issue the call (with the same values of msgsize) to prevent deadlocks.

If this routine returns with an error, mb_ptr will be set to MB_NULL_MBOARD.

Note:
We currently support up to 4096 boards.

Possible return codes:

Usage example:

/* Datatype for message */
typedef struct {
    double x;
    double y;
    int    value;
} MyMessageType;

/* some function somewhere */
void func_harimau(void) {
    
    int rc;
    MBt_Board myboard;
    
    /* create the message board */
    rc = MB_Create(&myboard, sizeof(MyMessageType));
    if ( rc != MB_SUCCESS )
    {
        fprintf(stderr, "Message board creation failed!\n");
        
        /* check valur of rc to determine reason of failure. Handle error */
        /* don't continue if error can't be handled */
        exit(1);
    }
    
    /* .... more code .... */

}
MB_SetAccessMode ( MBt_Board  mb,
int  MODE 
)

Sets access mode of the Message Board.

Parameters:
[in] mb Message Board handle
[in] MODE Access mode identifier

Sets the access mode of the board to allow the board synchronisation process to be optimised.

This routine is collective and must be called on all MPI processes. The mode applies only to the calling MPI process hence can be set to a different value on different processes.

When a non-readable mode is set, all MB_Iterator_*() will be disabled. Similarly, when a non-writeable mode is set, MB_AddMessage() will be disabled.

MB_MODE_READWRITE is the default mode of all newly created boards.

The following MODE values can be used:

This routine can only be called when the message board is empty and not locked.

Warning:
It is recommended that you never call this routine when there any synchronisation in progress. MB_SetAccessMode() calls MPI routines which may interfere with the synchronisation process if the underlying MPI library is not thread compliant.

Possible return codes:

Usage example: (to be included)

MB_SetSyncPattern ( MBt_Board  mb,
unsigned int *  sync_matrix 
)

Sets sync pattern of the Message Board.

Parameters:
[in] mb Message Board handle
[in] sync_matrix Integer array representing board communication matrix

Sets the access pattern of the board to allow the board synchronisation process to be optimised.

This routine is collective and must be called on all MPI processes. However, only the master node (MPI rank == 0) needs to provide a valid sync_matrix. The sync_matrix parameter will be ignored on all other nodes.

The sync_matrix array must be an element count equal to the square of the number of nodes. It is the users responsibility to provide a non-NULL sync_matrix which points to an array of apropriate size.

Warning:
If an invalid sync_matrix is provided by the master node, the routine may terminate or return errorneously, leaving the other nodes waiting for further instrustions from the master node hence causing a deadlock.

The sync_matrix will be processed as an NxN matrix (where N is the number of nodes), whereby the row i will represent the amount of communication from all node to node i. A zero value will indicate no communication.

When a node does not read from any proc including itself (all zeros in row i), it will be set to a non-reader and all MB_Iterator_*() routines will be disabled.

Similarly, when a node does not send to any other proc including itself, (add zeros in column i) it will be set to a non-writer and MB_AddMessage() will be disabled.

This routine can only be called when the message board is empty and not locked.

Warning:
It is recommended that you never call this routine when there any synchronisation in progress. MB_SetSyncPattern() calls MPI routines which may interfere with the synchronisation process if the underlying MPI library is not thread compliant.

Possible return codes:

Usage example: (to be included)

MB_AddMessage ( MBt_Board  mb,
void *  msg 
)

Adds a message to the Message Board.

Parameters:
[in] mb Message Board handle
[in] msg Address of the message to be added

Messages added to the board must be of the size specified during the creation of the board. Adding messages of a different size may not cause an error code to be returned, but will lead to unexpected behavior and possible segmentation faults.

The message data addressed by msg is cloned and stored in the message board. Users are free to modify, reuse, or deallocate their copy of the message after this routine has completed.

It this routine returns with an error, the access mode of mb will remain unchanged.

Possible return codes:

Usage example:

/* some function somewhere */
void func_kucing(void) {

    int rc;
    MBt_Board myboard;
    myMessageType staticMsg;
    myMessageType dynamicMsg;

    /* create board to store myMessageType messages */
    rc = MB_Create(&myboard, sizeof(myMessageType));
    
    /* create messages to add to board */
    staticMsg.value = 200;
    dynamicMsg = (myMessageType *)malloc(sizeof(myMessageType));
    dynamicMsg->value = 100;
    
    if ( MB_AddMessage(myboard, (void *)&staticMsg) != MB_SUCCESS )
    {
        fprintf(stderr, "Error adding message to board\n");
        
        /* check valur of rc to determine reason of failure. Handle error */
        /* don't continue if error can't be handled */
        exit(1);
    }
    
    if ( MB_AddMessage(myboard, (void *)dynamicMsg) != MB_SUCCESS )
    {
        fprintf(stderr, "Error adding message to board\n");
        
        /* check valur of rc to determine reason of failure. Handle error */
        /* don't continue if error can't be handled */
        exit(1);
    }
    
    /* it is safe to modify message memory once it has been added to the board.
     * Value in the board will not be modified.
     */
    staticMsg.value = 42;
    
    /* it is safe to deallocate message memory once it has been added to message board */
    free(dynamicMsg);

    /* ... more code ... */
}
MB_Clear ( MBt_Board  mb  ) 

Clears the Message Board.

Parameters:
[in] mb Message Board handle

Deletes all messages from the board. The board can be reused for adding more messages of the same type.

Once a board is cleared, all Iterators associated with the board is no longer valid and has to be recreated. It is the users' responsibility to ensure that invalidated Iterators are never used.

MB_Clear() can be asked not to deallocate memory. The allocated memory will then be reuse when the board is later populated. This therefore increases the amount of memory used by the simulation in exchange for a shorter runtime. This can ge done by setting the following environment variable: MBOARD_MEMPOOL_RECYCLE=1

Possible return codes:

Usage example:

/* some function somewhere */
void func_semut(void) {
    
    MBt_Board myboard;
    
    /* board created */
    rc = MB_Create(&myboard, sizeof(myMessageType));
    
    /* .... more code that uses the board .... */
    
    /* clear the board */
    if ( MB_Clear(myboard) != MB_SUCCESS )
    {
        fprintf(stderr, "Could not clear message board\n");
        
        /* check valur of rc to determine reason of failure. Handle error */
        /* don't continue if error can't be handled */
        exit(1);
    }

    /* ... board can be reused here ... */
    /* Don't forget to delete the board when done */
    
}
MB_Delete ( MBt_Board mb_ptr  ) 

Deletes a Message Board.

Parameters:
[in,out] mb_ptr Address of Message Board handle

Upon successful deletion, the handle referenced by mb_ptr will be set to MB_NULL_MBOARD.

If an error occurs, this routine will return an error code, and mb_ptr will remain unchanged.

If a null board (MB_NULL_MBOARD) is given, the routine will return immediately with MB_SUCCESS

Once a board is deleted, all Iterators associated with the board is no longer valid. It is the users' responsibility to ensure that invalidated Iterators are never used.

Possible return codes:

Usage example:

/* some function somewhere */
void func_belut(void) {
    
    MBt_Board myboard;
    
    /* board created */
    rc = MB_Create(&myboard, sizeof(myMessageType));
    
    /* .... more code that uses the board .... */
    
    /* when done, delete the board */
    if ( MB_Delete(&myboard) != MB_SUCCESS )
    {
        fprintf(stderr, "Could not delete message board\n");
        
        /* check valur of rc to determine reason of failure. Handle error */
        /* don't continue if error can't be handled */
        exit(1);
    }
    
    /* ... more code ... */
}
MB_Iterator_Create ( MBt_Board  mb,
MBt_Iterator itr_ptr 
)

Creates a new Iterator for accessing messages in board mb.

Parameters:
[in] mb Message Board handle
[out] itr_ptr Address of Iterator Handle

Upon successful creation of the Iterator, the routine returns a handle to the Iterator via itr_ptr .

Attempts to create an Iterator against a null board (MB_NULL_MBOARD) will result in an MB_ERR_INVALID error.

If this routine returns with an error, itr_ptr will remain unchanged.

Warning:
The Iterator will remain valid as long as the board it was created for is not modified, cleared or deleted. Reading messages from an invalid Iterator will lead to undefined behaviour and possible segmentation faults. It is the users' responsibility to ensure that only valid Iterators are used.

Possible return codes:

Usage example:

/* some function somewhere */
void func_siput(void) {
    
    MBt_Board myboard;
    MBt_Iterator iterator;
    
    /* .... more code that creates and populate myboard .... */
    
    rc = MB_Iterator_Create(myboard, &iterator);
    if ( rc != MB_SUCCESS )
    {
        fprintf(stderr, "Error while creating Iterator\n");
        
        /* check valur of rc to determine reason of failure. Handle error */
        /* don't continue if error can't be handled */
        exit(1);
    }
    
    /* iterator ready to be used */
    /* ... more code ... */
}
MB_Iterator_CreateSorted ( MBt_Board  mb,
MBt_Iterator itr_ptr,
int(*)(const void *msg1, const void *msg2)  cmpFunc 
)

Creates a new Iterator for accessing sorted messages in board mb.

Parameters:
[in] mb Message Board handle
[out] itr_ptr Address of Iterator Handle
[in] cmpFunc Pointer to user-defined comparison function

Creates a new Iterator for accessing messages in board mb, and returns a handle to the iterator via itr_ptr. This Iterator will allow users to retrieve ordered messages from mb without modifying the board itself.

The user-defined comparison function (cmpFunc) must return an integer less than, equal to, or greater than zero if the first message is considered to be respectively less than, equal to, or greater than the second. In short:

  • 0 if (msg1 == msg2)
  • < 0 if (msg1 < msg2)
  • > 0 if (msg1 > msg2)

If two members compare as equal, their order in the sorted Iterator is undefined.

Attempts to create an Iterator against a null board (MB_NULL_MBOARD) will result in an MB_ERR_INVALID error.

If this routine returns with an error, itr_ptr will remain unchanged.

Warning:
The Iterator will remain valid as long as the board it was created for is not modified, cleared or deleted. Reading messages from an invalid Iterator will lead to undefined behaviour and possible segmentation faults. It is the users' responsibility to ensure that Iterators are not invalidated before they are used.

Possible return codes:

Usage example:

/* our message datatype */
typedef struct {
    int id;
    double price;
    double value;
} myMessageType;

/* to be used for sorting myMessageType based on 'price' */
int mycmp(const void *msg1, const void *msg2) {
    myMessageType *m1, *m2;

    /* cast messages to proper type */
    m1 = (myMessageType*)msg1;
    m2 = (myMessageType*)msg2;

    if (m1->price == m2->price)
    {
        return 0;
    }
    else if (m1->price > m2->price) {
    {
        return 1;
    }
    else
    {
        return -1;
    }
}

/* some function somewhere */
void func_siamang(void) {

    MBt_Iterator iterator;
    
    /* assuming myboard has been created and populated */
    
    rc = MB_Iterator_CreateSorted(myboard, &iterator, &mycmp);
    if ( rc != MB_SUCCESS )
    {
        fprintf(stderr, "Error while creating Sorted Iterator\n");
        
        /* check valur of rc to determine reason of failure. Handle error */
        /* don't continue if error can't be handled */
        exit(1);
    }

    /* ... more code ... */
}
MB_Iterator_CreateFiltered ( MBt_Board  mb,
MBt_Iterator itr_ptr,
int(*)(const void *msg, const void *params)  filterFunc,
void *  filterFuncParams 
)

Creates a new Iterator for accessing a selection of messages in board mb.

Parameters:
[in] mb Message Board handle
[out] itr_ptr Address of Iterator Handle
[in] filterFunc Pointer to user-defined filter function
[in] filterFuncParams Pointer to input data that will be passed into filterFunc

Creates a new Iterator for accessing messages in board mb, and returns a handle to the iterator via itr_ptr. This Iterator will allow users to retrieve a filtered selection of messages from mb without modifying the board itself.

The user-defined filter function (filterFunc) must return 0 if a message is to be rejected by the filter, or 1 if it is to be accepted.

The filterFuncParam argument allows users to pass on additional information to filterFunc (see example code below). Users may useNULL in place of filterFuncParam if filterFunc does not require additional information.

Attempts to create an Iterator against a null board (MB_NULL_MBOARD) will result in an MB_ERR_INVALID error.

If this routine returns with an error, itr_ptr will remain unchanged.

Warning:
The Iterator will remain valid as long as the board it was created for is not modified, cleared or deleted. Reading messages from an invalid Iterator will lead to undefined behaviour and possible segmentation faults. It is the users' responsibility to ensure that Iterators are not invalidated before they are used.

Possible return codes:

Usage example:

/* our message datatype */
typedef struct {
    int id;
    double price;
    double value;
} myMessageType;

/* parameter datatype for myFilter */
typedef struct {
    double minPrice;
    double maxPrice;
} myFilterParams;

/* to be used for filtering myMessageType  */
int myFilter(const void *msg, const void *params) {
    myMessageType *m;
    myFilterParams *p;

    /* cast data to proper type */
    m = (myMessageType*)msg;
    p = (myFilterParams*)params;

    if (m1->price > p->maxPrice)
    {
        return 0; /* reject */
    }
    else if (m1->price < p->minPrice) {
    {
        return 0; /* reject */
    }
    else
    {
        return 1; /* accept */
    }
}

/* some function somewhere */
void func_monyet(void) {
    
    MBt_Iterator iterator;
    myFilterParam params;
    
    /* assuming myboard has been created and populated */
    
    params.minPrice = 10.5;
    params.maxPrice = 58.3;
    rc = MB_Iterator_CreateFiltered(myboard, &iterator, &myFilter, &params);
    if ( rc != MB_SUCCESS )
    {
        fprintf(stderr, "Error while creating Filtered Iterator\n");
        
        /* check valur of rc to determine reason of failure. Handle error */
        /* don't continue if error can't be handled */
        exit(1);
    }
    
    /* ... more code ... */
}
MB_Iterator_CreateFilteredSorted ( MBt_Board  mb,
MBt_Iterator itr_ptr,
int(*)(const void *msg, const void *params)  filterFunc,
void *  filterFuncParams,
int(*)(const void *msg1, const void *msg2)  cmpFunc 
)

Instantiates a new Iterator for accessing a sorted selection of messages in board mb.

Parameters:
[in] mb Message Board handle
[out] itr_ptr Address of Iterator Handle
[in] filterFunc Pointer to user-defined filter function
[in] filterFuncParams Pointer to input data that will be passed into filterFunc
[in] cmpFunc Pointer to user-defined compariosn function

Creates a new Iterator for accessing messages in board mb, and returns a handle to the iterator via itr_ptr. This Iterator will allow users to retrieve a filtered selection of ordered messages from mb without modifying the board itself.

The user-defined filter function (filterFunc) must return 0 if a message is to be rejected by the filter, or 1 if it is to be accepted.

The filterFuncParam argument allows users to pass on additional information to filterFunc (see example code below). Users may useNULL in place of filterFuncParam if filterFunc does not require additional information.

The user-defined comparison function (cmpFunc) must return an integer less than, equal to, or greater than zero if the first message is considered to be respectively less than, equal to, or greater than the second. In short:

  • 0 if (msg1 == msg2)
  • < 0 if (msg1 < msg2)
  • > 0 if (msg1 > msg2)

Attempts to create an Iterator against a null board (MB_NULL_MBOARD) will result in an MB_ERR_INVALID error.

If this routine returns with an error, itr_ptr will remain unchanged.

Warning:
The Iterator will remain valid as long as the board it was created for is not modified, cleared or deleted. Reading messages from an invalid Iterator will lead to undefined behaviour and possible segmentation faults. It is the users' responsibility to ensure that Iterators are not invalidated before they are used.

Possible return codes:

Usage example:

/* our message datatype */
typedef struct {
    int id;
    double price;
    double value;
} myMessageType;

/* parameter datatype for myFilter */
typedef struct {
    double minPrice;
    double maxPrice;
} myFilterParams;

/* to be used for filtering myMessageType  */
int myFilter(const void *msg, const void *params) {
    myMessageType *m;
    myFilterParams *p;

    /* cast data to proper type */
    m = (myMessageType*)msg;
    p = (myFilterParams*)params;

    if (m1->price > p->maxPrice)
    {
        return 0; /* reject */
    }
    else if (m1->price < p->minPrice) {
    {
        return 0; /* reject */
    }
    else
    {
        return 1; /* accept */
    }
}

/* to be used for sorting myMessageType based on 'price' */
int mycmp(const void *msg1, const void *msg2) {
    myMessageType *m1, *m2;

    /* cast messages to proper type */
    m1 = (myMessageType*)msg1;
    m2 = (myMessageType*)msg2;

    if (m1->price == m2->price)
    {
        return 0;
    }
    else if (m1->price > m2->price) {
    {
        return 1;
    }
    else
    {
        return -1;
    }
}

/* some function somewhere */
void func_beruk(void) {
        
    MBt_Iterator iterator;
    myFilterParam params;
    
    /* assuming myboard has been created and populated */
    
    params.minPrice = 10.5;
    params.maxPrice = 58.3;
    rc = MB_Iterator_CreateFilteredSorted(myboard, &iterator, &myFilter, &params, &mycmp);
    if ( rc != MB_SUCCESS )
    {
        fprintf(stderr, "Error while creating Filtered+Sorted Iterator\n");
        
        /* check valur of rc to determine reason of failure. Handle error */
        /* don't continue if error can't be handled */
        exit(1);
    }
    
    /* ... more code ... */
}
MB_Iterator_Delete ( MBt_Iterator itr_ptr  ) 

Deletes an Iterator.

Parameters:
[in,out] itr_ptr Address of Iterator Handle

Upon successful deletion, the handle referenced by itr_ptr will be set to MB_NULL_ITERATOR.

If an error occurs, itr_ptr will remain unchanged.

If a null Iterator (MB_NULL_ITERATOR) is passed in, the routine will return immediately with MB_SUCCESS

Possible return codes:

Usage example:

/* some function somewhere */
void func_lipan(void) {

    MBt_Board myboard;
    MBt_Iterator iterator;
    
    /* .... more code that creates and populate myboard .... */
    
    rc = MB_Iterator_Create(myboard, &iterator);
    /* .... more code .... */
    
    rc = MB_Iterator_Delete(&iterator);
    if ( rc != MB_SUCCESS )
    {
        fprintf(stderr, "Unable to delete Iterator\n");
        
        /* check valur of rc to determine reason of failure. Handle error */
        /* don't continue if error can't be handled */
        exit(1);
    }

    /* ... more code ... */
}
MB_Iterator_GetMessage ( MBt_Iterator  itr,
void **  msg_ptr 
)

Returns next available message from Iterator.

Parameters:
[in] itr Iterator Handle
[out] msg_ptr Address where pointer to message will be written to

After a successful call to the routine, msg_ptr will be assigned with a pointer to a newly allocated memory block containing the message data. It is the user's responsibility to free the memory associated with the returned msg.

When there are no more messages to return, msg_ptr will be assigned with NULL and the routine shall complete with the MB_SUCCESS return code.

Any attempts to retrieve a message from a null Iterator (MB_NULL_ITERATOR) will result in an MB_ERR_INVALID error.

In the event of an error, msg will be assigned NULL and the routine shall return with an appropriate error code.

Warning:
If the given Iterator is invalidated due to a deletion or clearance of the target board, calling this routine on the invalid board may result in either an undefined block of data or a segmentation fault.

Possible return codes:

Usage example:

/* some function somewhere */
void func_ayam(void) {
    
    int rc;
    MyMessageType *msg = NULL;
    MBt_Iterator  iterator;
    
    /* assuming myboard has been created and populated */
    
    /* create and iterator myBoard */
    MB_Iterator_Create(myBoard, &iterator);
    
    rc = MB_Iterator_GetMessage(iterator, (void **)&msg);
    while (msg) /* loop till end of Iterator */
    {
        do_something_with_message(msg);
        free(msg); /* free allocated message */
        
        /* get next message from iterator */
        rc = MB_Iterator_GetMessage(iterator, (void **)&msg);
        
        if (rc != MB_SUCCESS)
        {
            fprintf(stderr, "Oh no! Error while traversing iterator.\n");
            
            /* check valur of rc to determine reason of failure. Handle error */
            /* don't continue if error can't be handled */
            exit(1);
        }
    }

}
MB_Iterator_Rewind ( MBt_Iterator  itr  ) 

Rewinds an Iterator.

Parameters:
[in] itr Iterator Handle

Resets the internal counters such that the next MB_Iterator_GetMessage() call on the given Iterator will obtain the first message in the list (or NULL if the Iterator is empty).

Rewinding a null Iterator (MB_NULL_ITERATOR) will result in an MB_ERR_INVALID error.

Possible return codes:

Usage example:

/* some function somewhere */
void func_itik(void) {
    
    MyMessageType *msg1, *msg2;
    MBt_Iterator  iterator;
    
    /* assuming myboard has been created and populated */
    
    /* create and iterator myBoard */
    MB_Iterator_Create(myBoard, &iterator);
    
    /* get a message */
    MB_Iterator_GetMessage(iterator, (void *)msg1); 
    
    /* rewind the iterator */
    MB_Iterator_Rewind(iterator);
    
    /* get another message */
    MB_Iterator_GetMessage(iterator, (void *)msg2);
    
    /* msg1 and msg2 will be pointers to different blocks of data, but
     * both blocks will contain the same data
     */
    
    /* ... more ... */
    
    free(msg1);
    free(msg2);
}
MB_Iterator_Randomise ( MBt_Iterator  itr  ) 

Randomises the order of entries in an Iterator.

Parameters:
[in] itr Iterator Handle

Apart from randomising the order of entries in the Iterator, this routine will also reset the internal counters leading to an effect similar to that of MB_Iterator_Rewind().

Randomising a null Iterator (MB_NULL_ITERATOR) will result in an MB_ERR_INVALID error.

Possible return codes:

Usage example:

/* some function somewhere */
void func_angsa(void) {

    MyMessageType *msg1, *msg2, *msg3, *msg4;
    MBt_Iterator  iterator;
    
    /* assuming myboard has been created and populated */
    
    /* create and iterator myBoard */
    MB_Iterator_Create(myBoard, &iterator);
    
    /* ... fill up board ... */
    
    /* get messages */
    MB_Iterator_GetMessage(iterator, (void *)msg1); 
    MB_Iterator_GetMessage(iterator, (void *)msg2); 
    MB_Iterator_GetMessage(iterator, (void *)msg3); 
    MB_Iterator_GetMessage(iterator, (void *)msg4); 
    /* ... more ... */
    
    /* .... process messages .... */
    
    free(msg1);
    free(msg2);
    free(msg3);
    free(msg4);
    
    /* randomise the iterator (rewind was done automatically) */
    MB_Iterator_Randomise(iterator);
    
    /* messages should now be returned in a randomised order */
    MB_Iterator_GetMessage(iterator, (void *)msg1); 
    MB_Iterator_GetMessage(iterator, (void *)msg2); 
    MB_Iterator_GetMessage(iterator, (void *)msg3); 
    MB_Iterator_GetMessage(iterator, (void *)msg4); 
    /* ... more ... */
    
    free(msg1);
    free(msg2);
    free(msg3);
    free(msg4);

}
MB_SyncStart ( MBt_Board  mb  ) 

Synchronises the content of the board across all processes.

Parameters:
[in] mb Message Board Handle

This is a non-blocking routine which returns immediately after locking the message board and intialising the synchronisation process. The board should not be modified, cleared, or deleted until the synchronisation process is completed using MB_SyncComplete() (or until MB_SyncTest() results in a MB_TRUE flag).

In the serial version, this routine will do nothing apart from locking the message board.

Synchronisation of a null board (MB_NULL_MBOARD) is valid, and will return immediately with MB_SUCCESS

Note:
Multiple synchronisations of a board is supported but perhaps not in the way that you might expect. Subsequent synchronisations will only consider messages that were added after the previous synchronisation, which means that messages that were excluded (by filters) in previous syncs will not be considered in following ones.

Possible return codes:

Usage example:

int rc;
int flag;
MBt_Board myboard;
myMessageType staticMsg;
/* .... more code .... */

rc = MB_Create(&myboard, sizeof(myMessageType));
/* .... more code .... */

/* create messages to add to board */
staticMsg.value = 200;


if ( MB_AddMessage(myboard, (void *)&staticMsg) != MB_SUCCESS )
{
    fprintf(stderr, "Error adding message to board\n");
    
    /* check valur of rc to determine reason of failure. Handle error */
    /* don't continue if error can't be handled */
    exit(1);
}

if ( MB_SyncStart(myboard) != MB_SUCCESS )
{
    fprintf(stderr, "Unable to begin synchronisation\n");
    
    /* check valur of rc to determine reason of failure. Handle error */
    /* don't continue if error can't be handled */
    exit(1);
}

/* check if synchronisation has completed */
MB_SyncTest(myboard, &flag);
if (flag == MB_TRUE) 
{
    printf("synchronisation has completed\n");
    
    /* a successful call to MB_SyncTest would already complete
     * the communication and unlock the board. MB_SyncComplete()
     * is not needed.
     */
    process_message_board();
}
else
{
    printf("synchronisation still in progress\n");
    
    do_something_else_first();
    
    if ( MB_SyncComplete(myboard) != MB_SUCCESS ) /* wait till sync done */
    {
        fprintf(stderr, "Unable to begin synchronisation\n");
        
        /* check valur of rc to determine reason of failure. Handle error */
        /* don't continue if error can't be handled */
        exit(1);
    }
    
    process_message_board();
}

/* .... rest of program .... */
MB_SyncTest ( MBt_Board  mb,
int *  flag 
)

Inspects the completion status of a board synchronisation.

Parameters:
[in] mb Message Board Handle
[out] flag address where return value will be written to

This routine is non-blocking, and will return after setting the flag value to either MB_TRUE or MB_FALSE depending on the synchronisation completion status.

If synchronisation has completed, the MB_TRUE flag is returned, and the board is unlocked. The synchronisation process is considered to be completed, and users no longer need to call MB_SyncComplete() on this board.

Testing a null board (MB_NULL_MBOARD) will always return with the MB_TRUE flag and MB_SUCCESS return code.

Testing a board that is not being synchronised is invalid, and will return with the MB_FALSE flag and MB_ERR_INVALID return code.

In the serial version, this routine will always return MB_TRUE as synchronisation is assumed to be completed immediately after it started.

Possible return codes:

Usage example: see MB_SyncStart()

MB_SyncComplete ( MBt_Board  mb  ) 

Completes the synchronisation of a board.

Parameters:
[in] mb Message Board Handle

This routine will block until the synchronisation of the board has completed. Upon successful execution of this routine, the board will be unlocked and ready for access.

In the serial version, this routine will do nothing apart from unlocking the message board.

Synchronisation of a null board (MB_NULL_MBOARD) is valid, and will return immediately with MB_SUCCESS

Completing synchronisation a board that is not being synchronised is invalid, and will return with the MB_ERR_INVALID error code.

Possible return codes:

Usage example: see MB_SyncStart()

MB_Filter_Create ( MBt_Filter fh_ptr,
int(*)(const void *msg, int pid)  filterFunc 
)

Creates a filter object.

Parameters:
[out] fh_ptr Address to write Filter Handle to
[in] filterFunc Pointer to user-defined function

Introduced in version 0.2.0.

Registers a filter function and returns a handle to the filter via ft_ptr. The handle is unique to that function and is recognised across all processing nodes.

Registered filters can be assigned to message boards using MB_Filter_Assign() to act as a filtering mechanism when retrieving messages from remote nodes during a synchronisation. This reduces the number of messages that need to be transferred and stored on each node.

If this routine returns with an error, fh_ptr will be set to :: MB_NULL_FILTER.

In the parallel debug version, this routine is blocking and will return when all processes have issued and completed the call. This effectively synchronises all processing nodes. It is the users' responsibility to ensure that all processing nodes issue the call (with the same values for filterFunc) to prevent deadlocks.

Possible return codes:

Usage example:

/* our message datatype */
typedef struct {
    int id;
    double price;
    double value;
} myMessageType;

/* to be used for filtering myMessageType  */
int myFilter(const void *msg, int pid) {
    myMessageType *m;

    /* cast data to proper type */
    m = (myMessageType*)msg;

    if (m->price < 0) return 0; /* reject */
    else return 1; /* accept */

}
    
/* some function somewhere */
void func_beruang(void) {

    int rc;
    MBt_Filter f_handle;
    
    /* register the function */
    rc = MB_Fitler_Create(&f_handle, &myFilter);
    if ( rc != MB_SUCCESS )
    {
        fprintf(stderr, "Error while creating filter\n");
        
        /* check valur of rc to determine reason of failure. Handle error */
        /* don't continue if error can't be handled */
        exit(1);
    }
    
    /* assign function to board, assuming myboard has been created */
    rc = MB_Filter_Assign(mboard, f_handle);
    if ( rc != MB_SUCCESS )
    {
        fprintf(stderr, "Error while assigning filter to board\n");
        
        /* check valur of rc to determine reason of failure. Handle error */
        /* don't continue if error can't be handled */
        exit(1);
    }
    
    /* ... more code that adds messages to myboard ... */
    
    /* assign params for filtering messages during sync */
    MB_SyncStart(myboard); /* you should check the return code */
    do_something_else();
    MB_SyncComplete(myboard); /* you should check the return code */
    
    /* we should now have messages from other processing nodes, but
     * only those that passes the filter function myFilter()
     */
    
    /* ... do stuff ... */
    
    rc = MB_Filter_Delete(&f_handle);
    if ( rc != MB_SUCCESS )
    {
        fprintf(stderr, "Error while deleting filter\n");
        
        /* check valur of rc to determine reason of failure. Handle error */
        /* don't continue if error can't be handled */
        exit(1);
    }
    
}
MB_Filter_Assign ( MBt_Board  mb,
MBt_Filter  fh 
)

Assigns a filter handle to a message board.

Parameters:
[in] mb Message Board Handle
[in] fh Filter Handle

Introduced in version 0.2.0.

This routine assigns a registered filter to a Message Board. The associated filter function will act as a filtering mechanism when retrieving messages from remote nodes during a synchronisation. This reduces the number of messages that need to be transferred and stored on each node.

For efficiency, boards must be assigned with the same fh on all MPI processes. It is left to the user to ensure that this is so.

fh can be MB_NULL_FILTER, in which case mb will be deassociated with any function that it was previously assigned with.

Possible return codes:

Usage example: see MB_Filter_Create()

MB_Filter_Delete ( MBt_Filter fh_ptr  ) 

Deallocates a registered function.

Parameters:
[in,out] fh_ptr Address of Filter Handle

Introduced in version 0.2.0.

The filter function associated with fh_ptr will be deregistered, and fh_ptr will be set to MB_NULL_FILTER.

Deleting a filter that is assigned to a board will result in an error if the board is synchronised. It is the users' responsibility to ensure that this does not happen.

If an invalid handle is give, the routine will end with MB_ERR_INVALID and fh_ptr will not be modified.

If MB_NULL_FILTER is entered via fh_ptr, the routine will end immediately with MB_SUCCESS.

Possible return codes:

Usage example: see MB_Filter_Create()

MB_IndexMap_Create ( MBt_IndexMap im_ptr,
const char *  name 
)

Instantiates a new Index Map object.

Parameters:
[in] name Unique string identifying the map (max of 127 chars)
[out] im_ptr Address of Index Map handle

Introduced in version 0.2.0.

Creates a new Index Map and returns a handle to the map via im_ptr .

name should be a string that uniquely identifies the map and can contain up to 127 characters. If the given string is longer than 127 characters the routine will quit and return with MB_ERR_OVERFLOW.

In the parallel debug version, this routine is blocking and will return when all processes have issued and completed the call. This effectively synchronises all processes. It is the users' responsibility to ensure that all processes issue the call (in the same order if multiple maps are created).

If this routine returns with an error, im_ptr will be set to MB_NULL_INDEXMAP.

Possible return codes:

Usage example:

MBt_IndexMap map_id;
/* our message datatype */
typedef struct {
    int recipient_id;
    double price;
    double value;
} myMessageType;

/* some function somewhere */
void func_itik(void) {

    int i, rc;
    
    /* create a map of agent IDs available on this processor */
    rc = MB_IndexMap_Create(&map_id, "Agent ID");
    assert(rc == MB_SUCCESS);
    
    /* loop thru local agents and add their IDs to map */
    for (i = 0; i < agents_in_this_proc; i++)
    {
        rc = MB_IndexMap_AddEntry(map_id, agent[i].id);
        assert(rc == MB_SUCCESS);
    }
    /* map_id should now know which agents are in out local proc */
    
    /* sync so it also knows which agents are in all remote procs */
    rc = MB_IndexMap_Sync(map_id);
    assert(rc == MB_SUCCESS);
    
    /* map is not ready to be used in agent filter functions */
    /* see filter_by_target_agents() */
    
    /* .... other stuff ... */
    
    
    /* Delete map when done */
    rc = MB_IndexMap_Delete(&map_id);
    assert(rc == MB_SUCCESS);
}

/* example filter function that uses the IndexMap. This fucntion can
 * be registered using MB_Filter_Create() and assigned to boards
 * using MB_Filter_Assign()
 */
int filter_by_target_agents(const void *msg, int pid)
{
    /* value of pid will be populated by the board sync mechanism 
     * that runs the filter, and will contain the pid of the
     * target processor
     */
    myMessageType *m = (myMessageType *)msg;
    
    if (MB_IndexMap_MemberOf(map_id, pid, m->recipient_id)) return 1; /*ok*/
    else return 0; /* reject */
}
MB_IndexMap_Delete ( MBt_IndexMap im_ptr  ) 

Deletes an Index Map.

Parameters:
[in,out] im_ptr Address of Index Map handle

Introduced in version 0.2.0.

Upon successful deletion, the handle referenced by im_ptr will be set to MB_NULL_INDEXMAP.

If an error occurs, this routine will return an error code and im_ptr will remain unchanged.

If a null board (MB_NULL_INDEXMAP) is given, the routine will return immediately with MB_SUCCESS

Possible return codes:

Usage example: see MB_IndexMap_Create()

MB_IndexMap_AddEntry ( MBt_IndexMap  im,
int  value 
)

Adds an entry into the Index Map.

Parameters:
[in] im Index Map handle
[in] value Integer value of entry to add into the map

Introduced in version 0.2.0.

Entry will be added to the local map. In the parallel version, this entry will be searchable on other processors after MB_IndexMap_Sync() is called.

Adding an entry that already exists will have no effect on the map and the routine will return successfully.

Possible return codes:

Usage example: see MB_IndexMap_Create()

MB_IndexMap_Sync ( MBt_IndexMap  im  ) 

Distributes/gathers the map content across/from all processors.

Parameters:
[in] im Index Map handle

Introduced in version 0.2.0.

In the serial library, this routine does nothing and returns immediately with MB_SUCCESS. It will however return with an appropriate error code if an invalid or null map is given.

In parallel, this routine is a blocking and collective operation. It is the users' responsibility to ensure that the routine is called on all processors to avoid deadlocks.

Contents of the map is distributed across all processors such that every processor will be able to determine if an entry exists in a map of any other processor using the MB_IndexMap_MemberOf() routine.

This routine should be called after all entries are added to the map (using MB_IndexMap_AddEntry()) and before and queries are made (using MB_IndexMap_MemberOf()).

Warning:
This routine calls MPI Routines and should therefore never be called when there are any Message Board syncs in progress as this will cause problems with MPI Libraries that do not support full threading.

Possible return codes:

Usage example: see MB_IndexMap_Create()

MB_IndexMap_MemberOf ( MBt_IndexMap  im,
int  pid,
int  value 
)

Query the map to determine if a value exists on a particular processor.

Parameters:
[in] im Index Map handle
[in] pid Target processor ID
[in] value Value of entry to query for

Introduced in version 0.2.0.

Returns MB_TRUE or MB_FALSE depending on whether value exists in the map of processor with ID pid.

MB_IndexMap_Sync() must be called on the map before this routine can be used.

In the serial library, pid is ignored and the call to MB_IndexMap_Sync() is not compulsory but advisable.

Warning:
This is the only IndexMap routine that will be called very frequently during the simulation. We want it to be fast fast fast, so all checks are only done in debug mode!!! It is therefore crucial that end-users always test their code with the debug version of libmboard before using it in earnest.

Possible return codes:

Usage example: see MB_IndexMap_Create()


Generated on 1 Oct 2009 for libmboard by  doxygen 1.6.1