ringQueue.h
#ifndef RINGQUEUE_H
#define RINGQUEUE_H
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdbool.h>
#include <pthread.h>
#include <stdint.h>
typedef struct rQueue_data
{
void *buffer;
uint32_t len;
} rQueue_data;
typedef struct ringQueue
{
uint32_t front; // 头指针
uint32_t rear; // 尾指针,若队列不空,指向队列尾元素的下一个位置
pthread_mutex_t mutex;
uint32_t max_queueLen; // 队列的最大长度
uint32_t max_dataLen; // 数据的最大长度
rQueue_data data[]; // 存储空间
} ringQueue;
/**
* @description: 初始化队列,分配内存
* @param max_qLen 队列的最大长度
* @param max_dLen 数据的最大长度,即rQueue_data->buffer分配的内存大小,单位:字节
* @return 队列指针
*/
ringQueue *rQueue_init(uint32_t max_qLen, uint32_t max_dLen);
/**
* @description: 入队
* @param *q 队列指针
* @param *e 入队元素
* @return 成功:0 失败:-1
*/
int rQueue_en(ringQueue *q, const rQueue_data *e);
/**
* @description: 出队
* @param *q 队列指针
* @param *e 出队元素,e->buffer需要在外部申请内存,e->len需要初始化为e->buffer的内存大小
* 出队成功,e->len会被赋值为实际出队的数据大小,出队失败,e->len会被赋值为0
* @return 成功:0 失败:-1
*/
int rQueue_de(ringQueue *q, rQueue_data *e);
// 返回队列的元素个数,也就是队列的当前长度
/**
* @description: 返回队列的当前长度
* @param *q 队列指针
* @return 成功:队列长度,失败:-1
*/
int rQueue_length(ringQueue *q);
/**
* @description: 判断队列是否为空
* @param *q 队列指针
* @return true: 队列为空或q为NULL false: 非空
*/
bool rQueue_isEmpty(ringQueue *q);
/**
* @description: 清空队列
* @param *q 队列指针
* @return 成功:0 失败:-1
*/
int rQueue_clear(ringQueue *q);
/**
* @description: 销毁队列
* @param **q 队列指针的指针
* @return
*/
void rQueue_destroy(ringQueue **q);
#ifdef __cplusplus
}
#endif
#endif /* RINGQUEUE_H */
ringQueue.c
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "ringQueue.h"
ringQueue *rQueue_init(uint32_t max_qLen, uint32_t max_dLen)
{
size_t n = sizeof(ringQueue) + sizeof(rQueue_data) * max_qLen;
ringQueue *q = (ringQueue *)malloc(n);
if (q == NULL)
{
printf("%d: rQueue_init err, malloc fail\n", __LINE__);
return NULL;
}
memset(q, 0, n);
for (uint32_t i = 0; i < max_qLen; i++)
{
q->data[i].buffer = malloc(max_dLen);
if (q->data[i].buffer == NULL)
{
printf("%d: rQueue_init err, malloc fail\n", __LINE__);
// 释放前面已经申请的内存
for (uint32_t j = 0; j < i; j++)
{
free(q->data[j].buffer);
}
free(q);
return NULL;
}
memset(q->data[i].buffer, 0, max_dLen);
q->data[i].len = 0;
}
q->max_queueLen = max_qLen;
q->max_dataLen = max_dLen;
pthread_mutex_init(&q->mutex, NULL);
return q;
}
int rQueue_en(ringQueue *q, const rQueue_data *e)
{
int ret = -1;
pthread_mutex_lock(&q->mutex);
if (q == NULL || e == NULL || e->buffer == NULL)
{
goto end;
}
if ((q->rear + 1) % q->max_queueLen == q->front) // 队列满的判断
{
printf("queue is full\n");
goto end;
}
if (e->len > q->max_dataLen)
{
printf("rQueue_en err, e->len is too large, e->len: %d byte, max: %d byte\n",
e->len, q->max_dataLen);
goto end;
}
memcpy(q->data[q->rear].buffer, e->buffer, e->len);
q->data[q->rear].len = e->len;
q->rear = (q->rear + 1) % q->max_queueLen; // rear 指针向后移一位置,若到最后则转到数组头部
ret = 0;
end:
pthread_mutex_unlock(&q->mutex);
return ret;
}
// 出队
int rQueue_de(ringQueue *q, rQueue_data *e)
{
int ret = -1;
pthread_mutex_lock(&q->mutex);
if (q == NULL || e == NULL || e->buffer == NULL)
{
goto end;
}
if (q->front == q->rear) // 队列空的判断
{
printf("queue is empty\n");
goto end;
}
if (e->len < q->data[q->front].len)
{
printf("rQueue_de err, e->len is too small, e->len: %d byte, min: %d byte\n",
e->len, q->data[q->front].len);
goto end;
}
memcpy(e->buffer, q->data[q->front].buffer, q->data[q->front].len);
e->len = q->data[q->front].len;
memset(q->data[q->front].buffer, 0, q->max_dataLen);
q->data[q->front].len = 0;
q->front = (q->front + 1) % q->max_queueLen; // front 指针向后移一位置,若到最后则转到数组头部
ret = 0;
end:
if (ret == -1)
{
e->len = 0;
}
pthread_mutex_unlock(&q->mutex);
return ret;
}
int rQueue_length(ringQueue *q)
{
pthread_mutex_lock(&q->mutex);
if (q == NULL)
{
pthread_mutex_unlock(&q->mutex);
return -1;
}
int len = (q->rear - q->front + q->max_queueLen) % q->max_queueLen;
pthread_mutex_unlock(&q->mutex);
return len;
}
bool rQueue_isEmpty(ringQueue *q)
{
bool ret = false;
pthread_mutex_lock(&q->mutex);
if (q == NULL)
{
printf("rQueue_isEmpty err, q is NULL\n");
pthread_mutex_unlock(&q->mutex);
return true;
}
if (q->front == q->rear)
{
ret = true;
}
pthread_mutex_unlock(&q->mutex);
return ret;
}
int rQueue_clear(ringQueue *q)
{
pthread_mutex_lock(&q->mutex);
if (q == NULL)
{
pthread_mutex_unlock(&q->mutex);
return -1;
}
for (uint32_t i = 0; i < q->max_queueLen; i++)
{
memset(q->data[i].buffer, 0, q->max_dataLen);
q->data[i].len = 0;
}
q->front = 0;
q->rear = 0;
pthread_mutex_unlock(&q->mutex);
return 0;
}
void rQueue_destroy(ringQueue **q)
{
if (q == NULL)
{
return;
}
for (uint32_t i = 0; i < (*q)->max_queueLen; i++)
{
free((*q)->data[i].buffer);
}
pthread_mutex_destroy(&((*q)->mutex));
free(*q);
*q = NULL;
}
测试:
#include <stdio.h>
#include <string.h>
#include "ringQueue.h"
int main(void)
{
ringQueue *q;
q = rQueue_init(5, 10);
if (q == NULL)
{
printf("rQueue_init fail.\n");
return -1;
}
char str[10] = "";
for (int i = 0; i < 4; i++)
{
char temp[2];
rQueue_data e;
sprintf(temp, "%d", i);
strcat(str, temp);
printf("str: %s\n", str);
e.buffer = str;
e.len = strlen(str) + 1;
rQueue_en(q, &e);
}
printf("rQueue_length: %d\n", rQueue_length(q));
//rQueue_clear(q);
if (rQueue_isEmpty(q))
{
printf("queue empty\n");
}
else
{
printf("queue not empty\n");
}
memset(str, 0, sizeof(str));
for (int i = 0; i < 4; i++)
{
rQueue_data e;
e.buffer = str;
e.len = sizeof(str);
rQueue_de(q, &e);
printf("e.buffer: %s e.len: %d\n", (char *)e.buffer, e.len);
}
rQueue_destroy(&q);
if(q == NULL)
{
printf("queue destroy success.\n");
}
return 0;
}
输出结果:
str: 0
str: 01
str: 012
str: 0123
rQueue_length: 4
queue not empty
e.buffer: 0 e.len: 2
e.buffer: 01 e.len: 3
e.buffer: 012 e.len: 4
e.buffer: 0123 e.len: 5
queue destroy success.