Question on xQueuePeek() online example

Hello,

reading the online example for xQueuePeek() - copied below, I don’t understand exactly the point when calling xQueueSend() and xQueuePeek(). In both cases a pointer address (pointer to pointer) is taken, instead of just the pointer, as expected. Please, see below “&pxMessage” and “& (pxRxedMessage)”:

struct AMessage
 {
    char ucMessageID;
    char ucData[ 20 ];
 } xMessage;

 QueueHandle_t xQueue;

 // Task to create a queue and post a value.
 void vATask( void *pvParameters )
 {
 struct AMessage *pxMessage;

    // Create a queue capable of containing 10 pointers to AMessage structures.
    // These should be passed by pointer as they contain a lot of data.
    xQueue = xQueueCreate( 10, sizeof( struct AMessage * ) );
    if( xQueue == 0 )
    {
        // Failed to create the queue.
    }

    // ...

    // Send a pointer to a struct AMessage object.  Don't block if the
    // queue is already full.
    pxMessage = & xMessage;
    xQueueSend( xQueue, ( void * ) &pxMessage, ( TickType_t ) 0 );

    // ... Rest of task code.
 }

 // Task to peek the data from the queue.
 void vADifferentTask( void *pvParameters )
 {
 struct AMessage *pxRxedMessage;

    if( xQueue != 0 )
    {
        // Peek a message on the created queue.  Block for 10 ticks if a
        // message is not immediately available.
        if( xQueuePeek( xQueue, &( pxRxedMessage ), ( TickType_t ) 10 ) )
        {
            // pcRxedMessage now points to the struct AMessage variable posted
            // by vATask, but the item still remains on the queue.
        }
    }

    // ... Rest of task code.
 }

Your Queue is a Queue of Pointers, since the element size is sizeof(structure aMessage*), so the functions take pointer to pointers to pass the address of the place to put the results.

One important thing to note about defining your Queue in this manner, is that the sender shouldn’t change the contents of the message sent until it knows it has been processed by the receiver.

1 Like

Thanks for the explanation!

A way to not use pointer to pointer at all (just as an application exercise, rather than providing an advantage - even because the subject belongs more to the C language than to FreeRTOS) would be to encapsulate the pointer to the structure inside another structure. It ends up being a copy for value. I tested this version on ESP32 with success. It doesn’t use xQueuePeek(), but xQueueReceive() - which is not a problem, since the main subject of the question has changed. I put the main parts below (I took the opportunity to eliminate the restriction of keeping the object untouched until the receiver when using dynamic allocation):

struct Message
{
  char ucMessageID;
  char ucData[20];
};

struct AMessage
{
  struct Message *pxMessage;
};

...

// On main()
xQueue = xQueueCreate(10, sizeof(struct AMessage));

...

// On sending task (vATask)
struct AMessage txedMessage;
txedMessage.pxMessage = (struct Message*) malloc(sizeof(struct Message));
xQueueSend(xQueue, (void *) &txedMessage, portMAX_DELAY);

...

// On receiving task (vADifferentTask)
struct AMessage rxedMessage;
xQueueReceive(xQueue, &rxedMessage, portMAX_DELAY);
// rxedMessage.pxMessage points to user data;
free(rxedMessage.pxMessage);