In this post i publish a simple modular queue written in C which can be used either by assigning a static space for the elements of a dynamic one (malloc etc). Queue is a particular kind of abstract data type or collection in which the entities in the collection are kept in order. The only requirement is that the memory space which will hold the queue items have to be allocated in prior.
Below is the header/source pair:
/****************************************************************************** * SOF - Header | By: Io.D ******************************************************************************/ #ifndef LIBRARIES_IQUEUE_H_ /****************************************************************************** * Definitions ******************************************************************************/ #define LIBRARIES_IQUEUE_H_ /****************************************************************************** * Includes ******************************************************************************/ #include <stdint.h> #include <string.h> /****************************************************************************** * Enumerations, structures & External Variables ******************************************************************************/ typedef enum { I_OK = 0x00, I_ERROR = 0x01, I_FULL = 0x60, I_EMPTY = 0x61 }I_Status_Queue; typedef struct { volatile void * storage; volatile void * first; volatile void * next; volatile size_t element_size; volatile uint32_t max_elements; } iqueue_t; /****************************************************************************** * Public Functions (API) ******************************************************************************/ I_Status_Queue iqueue_init (iqueue_t * _queue, int _max_elements, size_t _element_size, void * _storage); I_Status_Queue iqueue_enqueue(iqueue_t * _queue, void * _element); I_Status_Queue iqueue_dequeue(iqueue_t * _queue, void * _element); I_Status_Queue iqueue_size (iqueue_t * _queue, uint32_t * _size); /****************************************************************************** * EOF - Header ******************************************************************************/ #endif
/****************************************************************************** * SOF - Source | By: Io.D ******************************************************************************/ /****************************************************************************** * Includes ******************************************************************************/ #include "iqueue.h" /****************************************************************************** * Declarations ******************************************************************************/ /****************************************************************************** * Public functions ******************************************************************************/ I_Status_Queue iqueue_init(iqueue_t * _queue, int _max_elements, size_t _element_size, void * _storage) { if (_queue == NULL) return I_ERROR; memset(_storage, 0x00, _element_size*_max_elements); _queue->element_size = _element_size; _queue->max_elements = _max_elements; _queue->first = (void *)0; _queue->next = _queue->storage = _storage; return I_OK; } I_Status_Queue iqueue_enqueue(iqueue_t * _queue, void * _element) { if (_queue->first == _queue->next) return I_FULL; memmove((void*)_queue->next, (void*)_element, _queue->element_size); _queue->first = _queue->first == (void*)0 ? _queue->next : _queue->first; _queue->next = (uint8_t *)_queue->next + _queue->element_size == (uint8_t *)_queue->storage + (_queue->element_size*_queue->max_elements) ? _queue->storage : (uint8_t *)_queue->next + _queue->element_size; return I_OK; } I_Status_Queue iqueue_dequeue(iqueue_t * _queue, void * _element) { if (_queue->first == (void*)0) return I_EMPTY; memmove((void*)_element, (void*)_queue->first, _queue->element_size); memset((uint8_t*)_queue->first, 0x00, _queue->element_size); _queue->first = (uint8_t *)_queue->first + _queue->element_size == (uint8_t *)_queue->storage + (_queue->element_size*_queue->max_elements) ? _queue->storage : (uint8_t *)_queue->first + _queue->element_size; _queue->first = _queue->first == _queue->next ? (void*)0 : _queue->first; return I_OK; } I_Status_Queue iqueue_size(iqueue_t * _queue, uint32_t * _size) { *_size = _queue->first == (void*)0 ? 0 : _queue->first < _queue->next ? ((uintptr_t)_queue->next - (uintptr_t)_queue->first) / _queue->element_size : _queue->max_elements - (((uintptr_t)_queue->first - (uintptr_t)_queue->next) / _queue->element_size); return I_OK; } /****************************************************************************** * Static functions ******************************************************************************/ /****************************************************************************** * EOF - Source ******************************************************************************/
Usage
// Create a queue handle iqueue_t queue; // Set a memory space to save the elements uint32_t storage[5]; // Initialize the queue iqueue_init(&queue, 5, sizeof(uint32_t), storage); .. .. // Add an element uint32_t element = 31; if (iqueue_enqueue(&queue, &element) == I_FULL) { // Queue is full condition } .. .. // Retrieve an element uint32_t element; if (iqueue_dequeue(&queue, &element) == I_EMPTY) { // Queue is full empty } .. .. // Get the size uint32_t size; iqueue_size(&queue, &size);