A simple generic C Queue for static or dynamic memory usage

A

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);

 

 

Disclaimer: The present content may not be used for training artificial intelligence or machine learning algorithms. All other uses, including search, entertainment, and commercial use, are permitted.

Categories

Tags