Queues

A queue is a first-in first-out (FIFO) collection of objects. Objects can be inserted or removed from a queue from both a thread or an ISR. A queue supports the ability to block a calling thread when either the queue is full or when it is empty depending on the call.

Use QUEUE_Create() to create and initialize a queue. When creating a queue, it is required to provide an allocated array of slots that are used by the queue to reference (pointers) each of the objects contained within the queue. By providing slots during the creation of the queue, it keeps each queue and it's memory requirements completely independent from one another.

To insert an object into a queue, use QUEUE_Enqueue(). An object can be inserted from either a thread or an ISR. If from a thread, use the timeout parameter to block and wait for a free slot if the queue happens to be full. Since the queue does not copy the object into the queue, it is required that the object remains valid during the entire time it is referenced from a queue (i.e. not created on stack memory that is lost on breaking scope).

To remove an object from a queue, use QUEUE_Dequeue(). An object can be removed from either a thread or an ISR. If from a thread, use the timeout parameter to block and wait for an object to arrive if the queue happens to be empty.

Basic Usage

When creating a queue, an array of slots must be provided that are used to reference (pointers) each object contained within the queue. By providing the slots during creation, each queue can have a unique maximum capacity and there is no worst-case allocation occurring within the kernel.

#include "Kernel/kernel_queue.h"
#include <assert.h>

static QUEUE queue;                 /* Allocate a queue */

void APP_Example(void)
{
    static QUEUESLOT slots[10];     /* Allocate the slots to be used by the queue */
    STATUS status;


    status = QUEUE_Create(&queue,   /* Create the queue */
                          slots,    /* Provide a pointer to the slots for the queue */
                          10);      /* The max capacity for the queue  (should match number of slots) */

    assert(status == SUCCESS);
}

A queue only contains a reference (pointer) to each object contained within the queue and therefore it is important that each object remains valid during the entire time the object is contained within the queue. The example snippet below allocates an object (type MYSAMPLE) using a memory pool and places the sample into a queue to be processed later.

#include "Kernel/kernel_queue.h"
#include <assert.h>

/* An application-defined object */
typedef struct MYSAMPLE {
    UINT32 timestamp;
    UINT32 value;
} MYSAMPLE;

void APP_TakeSample(void)
{
    MYSAMPLE* sample;
    STATUS status;


    sample = POOL_Alloc(&pool, INFINITE);           /* Allocate a sample object */
    if (sample) {                                   /* Successfully allocated? */

        sample->timestamp = KERNEL_Timestamp();     /* Timestamp the sample */
        sample->value = APP_TakeMeasurement();      /* Make some measurement for example */

        status = QUEUE_Enqueue(&queue,              /* Place the sample into the queue */
                               sample,              /* A pointer to the object to be placed into the queue */
                               INFINITE);           /* Amount of time to block if the queue is full */

        assert(status == SUCCESS);
    }
}

Continuing from the code snippet above, the snippet below shows a thread that is blocked indefinitely waiting for the sample objects to arrive within the queue to be processed. If a sample is received, the thread can process the sample and then when finished, it returns the sample back to the memory pool in which it was allocated.

void APP_ExampleThread(void* arg)
{
    MYSAMPLE* sample;


    for(;;) {
	
        sample = QUEUE_Dequeue(&queue, INFINITE);   /* Wait indefinitely for a sample to arrive */
        if (sample) {                               /* Verify a valid object */

            APP_ProcessSample(sample);              /* Process the received sample */
            POOL_Free(&pool, sample);               /* Return the memory back to the pool */
        }
    }
}

API Reference

STATUS QUEUE_Create(QUEUE* queue, const CHAR* name, QUEUESLOT* slots, UINT32 capacity)
Creates and initializes a queue.
PARAMETERS
queue A pointer to a caller allocated queue to be intialized.
name A pointer to a NULL terminated string that represents a name for the queue.
slots A pointer to a caller allocated array of slots used to reference the objects contained within the queue.
capacity The maximum number of objects that can be contained within the queue. Must be larger than zero.
RETURNS
SUCCESS The queue was created and initialized.
ERR_NULLREFERENCE The argument 'q' or 'slots' was found to be NULL.
ERR_INVALIDCONTEXT The operation is not supported from the context of an interrupt service routine (ISR).
ERR_INVALIDARGUMENT The argument 'capacity' was invalid. Must be larger than zero.
ERR_ALREADYINITIALIZED The specified queue has already been created and initialized.
REMARKS
The caller allocated array of slots must be able to contain the maximum capacity for the queue.
STATUS QUEUE_Destroy(QUEUE* queue)
Destroys and removes a queue from the kernel. Any threads that are currently blocked waiting to read or write the queue will be released with the ERR_DESTROYED status code.
PARAMETERS
queue A pointer to a queue to be destroyed.
RETURNS
SUCCESS The queue was destroyed and removed from the kernel.
ERR_NULLREFERENCE The argument 'queue' was found to be NULL.
ERR_INVALIDCONTEXT The operation is not supported from the context of an interrupt service routine (ISR).
ERR_NOTINITIALIZED The specified queue has not been created and initialized.
STATUS QUEUE_Clear(QUEUE* queue)
Clears and removes all objects from a queue.
PARAMETERS
queue A pointer to the queue to be cleared.
RETURNS
SUCCESS The queue has been cleared.
ERR_NULLREFERENCE The argument 'queue' was found to be NULL.
ERR_NOTINITIALIZED The specified queue has not been created and initialized.
STATUS QUEUE_Enqueue(QUEUE* queue, void* obj, UINT32 timeout)
Inserts an object into a queue.
PARAMETERS
queue A pointer to the target queue to receive the object.
obj A pointer to the object to be placed into the queue.
timeout The maximum amount of time, in kernel ticks, to block and wait for the object to be inserted if the queue happens to be full. Use '0' to return immediately without blocking. Use 'INFINITE' to block indefinitely.
RETURNS
SUCCESS The object was successfully inserted into the queue.
ERR_NULLREFERENCE The argument 'queue' or 'obj' was found to be NULL.
ERR_NOTINITIALIZED The specified queue has not been created and initialized.
ERR_TIMEOUT The timeout interval elapsed before the queue acquired an available slot for the object.
REMARKS
Can be called from ISR, but cannot block if the queue is full (timeout is ignored).
void* QUEUE_Dequeue(QUEUE* queue, UINT32 timeout)
Inserts an object into a queue.
PARAMETERS
queue A pointer to the queue that contains the object to be removed.
timeout The maximum amount of time, in kernel ticks, to block and wait for an object to arrive if the queue happens to be empty. Use '0' to return immediately without blocking. Use 'INFINITE' to block indefinitely.
RETURNS
A pointer to the object that has been removed from the queue, if any; otherwise NULL.
REMARKS
Can be called from ISR, but cannot block if the queue is full (timeout is ignored).
void* QUEUE_Peek(QUEUE* queue, UINT32 idx)
Reads and returns an object from a queue without removing the object from the queue.
PARAMETERS
queue A pointer to the queue that contains the object to be returned.
idx The zero based index of the object to be returned.
RETURNS
A pointer to the object at the specified index, if any; otherwise NULL.
void* QUEUE_Count(QUEUE* queue)
Returns the number of objects currently contained within a queue.
PARAMETERS
queue A pointer to the target queue.
RETURNS
The total number of objects currently within the given queue.