A message queue is a structure that enables tasks to post and receive messages. A message is a generic (void) pointer and as such can be used to send data that will fit into a pointer type (2 or 4 bytes depending upon processor word size) or can be used to pass a pointer to a block of memory. The message queue has a buffer that enables a number of posts to be completed without receives occuring. The buffer keeps the posted messages in a fifo order so the oldest message is received first. When the buffer isn’t full a post will put the message at the back of the queue and the calling task continues execution. When the buffer is full a post will block the calling task until there is room for the message. When the buffer isn’t empty a receive will return the message from the front of the queue and continue execution of the calling task. When the buffer is empty a receive will block the calling task until a message is posted.

You allocate a message queue by declaring it as a C variable

    CTL_MESSAGE_QUEUE_t m1;

A message queue is initialised using the ctl_message_queue_init function.

    void *queue[20];
    …
    ctl_message_queue_init(&m1, queue, 20);

This example uses an 20 element array for the message queue. Note that the array is a `void *` which enables pointers to memory or (cast) integers to be communicated via a message queue.

You can post a message to a message queue with an optional timeout using the ctl_message_queue_post function.

    ctl_message_queue_post(&m1, (void *)45, 0, 0);

This example posts the integer `45` onto the message queue.

    if (ctl_message_queue_post(&m1, (void *)45, 1, ctl_get_current_time()+1000) == 0)
      {
        // timeout occured
      }

This example uses a timeout and tests the return result to see if the timeout occured.

If you want to post a message and you don’t want to block (e.g from an interrupt service routine) you can use the ctl_message_queue_post_nb function.

    if (ctl_message_queue_post_nb(&m1, (void *)45)==0)
      {
        // queue is full
      }

This example tests the return result to see if the post failed.

You can receive a message with an optional timeout using the ctl_message_queue_receive function.

    void *msg;
      ctl_message_queue_receive(&m1, &msg, 0, 0);

This example receives the oldest message in the message queue.

    if (ctl_message_queue_receive(&m1, &msg, 1, ctl_get_current_time()+1000) == 0)
      {
        // timeout occured
      }

This example uses a timeout and tests the return result to see if the timeout occured.

If you want to receive a message and you don’t want to block (e.g from an interrupt service routine) you can use the ctl_message_queue_receive_nb function.

    if (ctl_message_queue_receive_nb(&m1, &msg)==0)
      {
        // queue is empty
      }

##### Example

The following example illustrates usage of a message queue to implement the producer-consumer problem.

    CTL_MESSAGE_QUEUE_t m1;
    void *queue[20];

    void task1(void)
    {
      …
      ctl_message_queue_post(&m1, (void *)i, 0, 0);
      …
    }

    void task2(void)
    {
      void *msg;
      …
      ctl_message_queue_receive(&m1, &msg, 0, 0);
      …
    }

    int
    main(void)
    {
      …
      ctl_message_queue_init(&m1, queue, 20);
      …
    }