C语言实现的一个缓存队列

《缓存循环队列的实现》


使用方法:

队列的创建分两种:

1. 静态创建

/* 队列大小 */
#define QUEUE_SIZE 10

/* 队列数据空间。请使用宏QALIGN4,目的是为了根据队列大小计算实际需要的队列存储空间大小并对齐4字节 */
uint8_t QueueBuffer[QALIGN4(QUEUE_SIZE)];

/* 队列句柄 */
Queue queue;

初始化:

Queue_Init(&queue, QUEUE_SIZE, QueueBuffer);

2.动态创建

创建函数:

QueuePtr Queue_Create(uint32_t size)

销毁函数:

void Queue_Destory(QueuePtr queue)

!!!以上两个函数必须成对使用!!!


头文件

/**
 * @file    queue.h
 * @brief   Create by AnKun on 2019/10/30
 * @version 1.0.0
 */
#ifndef __QUEUE_H_
#define __QUEUE_H_

#ifdef __cplusplus
extern "C"{
#endif // __cplusplus


#include 
#include 
#include 
#include 
#include 

/// 队列控制结构体
typedef struct
{
    uint32_t read;			///< 读指针
    uint32_t write;			///< 写指针
    uint32_t size;			///< 队列大小(字节)
    uint8_t* payload;		///< 队列负载数据
}Queue, *QueuePtr;

uint32_t Queue_GetSize(const QueuePtr queue);
uint32_t Queue_GetUsed(const QueuePtr queue);
uint32_t Queue_GetFree(const QueuePtr queue);
uint32_t Queue_Write(QueuePtr queue, const void* buf, uint32_t length);
uint32_t Queue_Read(QueuePtr queue, void* buf, uint32_t length);
void Queue_Clear(QueuePtr queue);
void Queue_ErrBack(QueuePtr queue, uint32_t len);
void Queue_Init(QueuePtr queue, uint32_t size, void* payload);
void Queue_Destory(QueuePtr queue);
bool Queue_isFull(const QueuePtr queue);
bool Queue_isEmpty(const QueuePtr queue);
QueuePtr Queue_Create(uint32_t size);

#define QALIGN4(size)  (((size + 5) >> 2) << 2)		///< 对齐四字节

#ifdef __cplusplus
}
#endif // __cplusplus

#endif // __QUEUE_H_



源文件

/**
 * @file    queue.c
 * @brief   Create by AnKun on 2019/10/30
 * @version 1.0.0
 */
#include "queue.h"

/**
 * 获得队列使用量
 * @param  queue 队列句柄
 * @return       返回已使用量
 */
uint32_t Queue_GetUsed(const QueuePtr queue)
{
	int len = queue->write - queue->read;

	if (len >= 0)
		return (uint32_t)len;
	else
		return (queue->size + len);
}

/**
 * 获得队列空余空间
 * @param  queue 队列句柄
 * @return       队列空余数
 */
uint32_t Queue_GetFree(const QueuePtr queue)
{
	return queue->size - Queue_GetUsed(queue) - 1;
}

/**
 * 获得队列大小
 * @param  queue 队列句柄
 * @return       队列大小
 */
uint32_t Queue_GetSize(const QueuePtr queue)
{
	return queue->size - 1;
}

/**
 * 检测队列是否满
 * @param  queue
 * @return       true:满    false:非满
 */
bool Queue_isFull(const QueuePtr queue)
{
	if (queue->read == (queue->write + 1) % queue->size)
		return true;
	else
		return false;
}

/**
 * 检测队列是否为空
 * @param  queue
 * @return       true:空    fasle:非空
 */
bool Queue_isEmpty(const QueuePtr queue)
{
	if (queue->read == queue->write)
		return true;
	else
		return false;
}

/**
 * 数据入队
 * @param  queue  队列句柄
 * @param  buf    要入队的数据
 * @param  length 要入队的数据长度
 * @return        返回入队的字节数
 */
uint32_t Queue_Write(QueuePtr queue, const void* buf, uint32_t length)
{
	uint8_t *dataptr = (uint8_t *)buf;
	uint32_t offset = 0;
	uint32_t nwrite = 0;
	uint32_t nfree = 0;

	/* 传入的数据长度为0, 直接返回 */
	if (length == 0)		return 0;

	/* 队列没有空间, 直接返回 */
	if ((nfree = Queue_GetFree(queue)) == 0)		return 0;

	/* 计算实际能够入队的数据长度 */
	nwrite = nfree >= length ? length : nfree;

	/* 判断队列是否跨尾 */
	offset = queue->size - queue->write;
	if (offset >= nwrite)
	{
		memcpy(queue->payload + queue->write, dataptr, nwrite);
		queue->write += nwrite;
	}
	else
	{
		memcpy(queue->payload + queue->write, dataptr, offset);
		memcpy(queue->payload, dataptr + offset, nwrite - offset);
		queue->write = nwrite - offset;
	}
	return nwrite;
}

/**
 * 数据出队
 * @param  queue  队列句柄
 * @param  buf    存放出队的数据
 * @param  length 出队的数据长度
 * @return        返回出队字节数
 */
uint32_t Queue_Read(QueuePtr queue, void* buf, uint32_t length)
{
	uint8_t *dataptr = (uint8_t *)buf;
	uint32_t offset = 0;
	uint32_t nused = 0;
	uint32_t nread = 0;

	/* 出队数据长度为0, 直接返回 */
	if (length == 0)		return 0;

	/* 计算实际能够出队的数据长度 */
	if ((nused = Queue_GetUsed(queue)) == 0)		return 0;

	/* 计算实际能够读到的数据长度 */
	nread = nused >= length ? length : nused;

	/* 判断要读的数据是否跨尾 */
	offset = queue->size - queue->read;
	if ( offset >= nread)
	{
		memcpy(dataptr, queue->payload + queue->read, nread);
		queue->read += nread;
	}
	else
	{
		memcpy(dataptr, queue->payload + queue->read, offset);
		memcpy(dataptr + offset, queue->payload, nread - offset);
		queue->read = nread - offset;
	}

	return nread;
}

/**
 * 初始化一个队列
 * @param queue   队列句柄
 * @param size    队列大小
 * @param payload 队列缓存地址
 */
void Queue_Init(QueuePtr queue, uint32_t size, void* payload)
{
	queue->read = 0;
	queue->write = 0;
	queue->payload = (uint8_t *)payload;
	queue->size = size + 1;
}

/**
 * 清空队列
 * @param queue 队列句柄
 */
void Queue_Clear(QueuePtr queue)
{
	queue->read = queue->write;
}

/**
 * 动态创建一个队列
 * @param  size 队列大小
 * @return      成功返回队列对象指针, 失败返回NULL
 */
QueuePtr Queue_Create(uint32_t size)
{
	QueuePtr queue = NULL;

	if ((queue = (QueuePtr)malloc(sizeof(Queue))) == NULL)
		return NULL;

	queue->size = size + 1;
	queue->read = 0;
	queue->write = 0;
	queue->payload = NULL;

	if ((queue->payload = (uint8_t *)malloc(QALIGN4(size))) == NULL)
	{
		free(queue);
		return NULL;
	}

	return queue;
}

/**
 * 对于动态创建的队列进行清理工作
 * @param queue 队列句柄
 */
void Queue_Destory(QueuePtr queue)
{
	free(queue->payload);
	free(queue);
	queue = NULL;
}

/**
 * 读指针退后len个字节,!!!慎用!!!
 * @param queue 队列句柄
 * @param len   要退后的字节数
 */
void Queue_ErrBack(const QueuePtr queue, uint32_t len)
{
	int tmp = queue->read - len;
	queue->read = tmp < 0 ? ((uint32_t)(tmp + queue->size)) : ((uint32_t)tmp);
}

你可能感兴趣的:(C/C++)