The Message Exchange

The Message Queue

Robos messages as such are not placed in the message queue. Instead, a message queue entry comprises just the two pointers, pa and pd. The action part of a message pointed to by pa is a message processing function which resides in its appropriate place in memory. The data part pointed to by pd resides in a portion of dynamically allocated memory which is freed once the message has been dealt with.

This regime makes the message queue compact and easy to handle. A message queue entry is thus defined in 'C' as follows:

struct msg_queue_entry {
  void(*pa)(void *);       //pointer to the appropriate MPF
  void *pd;                //pointer to the message data
};
*pa points to a void function whose single input parameter is a pointer to an as yet undetermined data type. *pd is a pointer-to-void. A 256-entry Message Queue is therefore declared as follows:
struct msg_queue_entry msg_queue[256];
The elements of the msg_queue[] array each contain pointers pa and pd to functions and data buffers. However, further pointers to the elements of the msg_queue[] array itself are needed in order to allow messages to be taken off and put on the message queue. Pointers ps and pf point to the start and finish of the message queue itself - ie the currently occupied part of the message queue array. In fact, to make the program simpler, pf actually points to the next free element after the current end of the queue - ie the place where the next new message entry should be placed. The pointer pt is a constant. It permanently points to the highest (last) element in the message queue array.

The following diagram illustrates how these pointers are used. The shading represents the currently occupied portion of the message queue array.

Note that a 256-entry message queue can hold only 255 messages. At least one element must be considered unoccupied. This is so that ps and pf coincide only when the queue is empty and not when it is full also.

The pointers ps, pf and pt are pointers to msg_queue_entry structures and are defined as follows:

struct msg_queue_entry *ps, *pf, *pt;

Message Queue Declaration

The structure definitions and declarations for the message queue and its associated pointers is as follows.
extern void _far Initialise(void _far *);

#include <stddef.h>            //For NULL pointer definition
struct msg_queue_entry {       //DEFINE A MESSAGE QUEUE ENTRY
  void(_far *pa)(void _far *); //to message processor
  void _far *pd;               //to message data
}
_near msg_queue[256] =         //DECLARE CYCLIC MESSAGE QUEUE
{                              //Place in its first element a
  {Initialise, NULL}           //message instructing the appli-
};                             //cation to initialise itself.

struct msg_queue_entry         //Queue management pointers to:
  _near *pt = msg_queue + 255, //last element of queue array
  _near *ps = msg_queue,       //next message to be processed
  _near *pf = msg_queue + 1;   //where to put next new message

Message Queue Processor

The function main() which expedites and then removes messages from the queue, and the function PutMsg() which puts new messages onto the queue are shown below.
int active = 1;                //main()'s 'on/off' switch

main() {                       //MESSAGE DISPATCHER FUNCTION
  while(active) {              //While '`active' not zeroed
    if(ps != pf) {             //Provided msg queue not empty,
      (*ps->pa)(ps->pd);       //call required msg processor
      if(++ps > pt)            //then advance pointer to next
        ps = msg_queue;        //message in queue ready for 
    }                          //the next pass.
  }
}

int _far PutMsg (              //MESSAGE ENTRY FUNCTION
  void(_far *pa)(void _far *), //points to message action
  void _far *pd                //points to message data
) {
  struct msg_queue_entry _near *p = pf;   //temporary pointer
  if(++p > pt)
    p = msg_queue;             //Advance 'feeler' pointer
  if(p != ps) {                //If room on queue...
    pf->pa = pa;               //Store 'action' pointer
    pf->pd = pd;               //Store 'data' pointer
    pf = p;                    //Advance to next free entry
    return(0);                 //Means 'Message stored OK'
  }
  return(1);                   //'Couldn't store message'
}
If your curiosity persists, you may now go through a detailed explanation of the above source code.
This page's parent within this Web Site. About this Web Site. Its home page. Email its Author.