环形队列实现
1.说明:
完成一个通用型的环形队列,通用型表现为
(1)随时需要,随时创建;
(2)需要多大的队列长度、需要多大的单条消息长度都可以在创建时候指定(一次性申请的而非每有数据再申请);
(3)采用了顺序存储结构而不是链式存储结构,所以速度运行速度还可以。
2.需要的运行条件:
作者是在STM32F103里面运行的。
3.程序实现:
(1)结构体的抽象;
typedef struct _QUEUE{
char name[10]; //队列名
/* 操作函数 */
int (* readData)(struct _QUEUE *queue,void * data);
int (* writeData)(struct _QUEUE *queue,void * data);
int (* getcnt)(struct _QUEUE *queue);
int (* is_full)(struct _QUEUE *queue);
int (* is_empty)(struct _QUEUE *queue);
int (* free)(struct _QUEUE *queue);
int msg_len; //队列长度
int queue_len; //队列有效长度
int queue_max; //队列最大长度
int read,write; //读写指针
void *data; //用户数据
}QUEUE,*qQUEUE;
操作函数和普通的环形队列基本上差不多。
这个数据结构能兼容所有的数据类型(包括用户自定义数据类型)的关键在于定义了指针类型的数据,这个指针所指向的地址就是存放用户的数据。
定义成(void *)是为了兼容所有的数据类型输入,不用去刻意转换,我们把转换放在函数内部完成。
4.所有代码展示:
.c文件:
#include "queue.h"
#include "stdlib.h"
#include "string.h"
#include "stdio.h"
/*
*队列是否满
*/
static int queue_is_full(qQUEUE queue)
{
return ( (queue->write+1)%queue->queue_max == queue->read );
}
/*
*队列是否空
*/
static int queue_is_empty(qQUEUE queue)
{
return ( queue->read == queue->write );
}
/*
*读队列
*/
static int queue_read(qQUEUE queue,void * data)
{
if( queue_is_empty(queue) )
{
/* 队空,无法读取 */
DBG("Empty\r\n");
return 1;
}
/* 类型转换,因为void *类型的指针偏移大小无法被编译器所识别,所以统一为char * */
char *tmp = (char *)(&queue->data)+(queue->msg_len * queue->read);
memcpy(data,tmp,queue->msg_len);
queue->read = ( queue->read+1)%queue->queue_max ;
return 0;
}
/*
*写队列
*/
static int queue_write(qQUEUE queue,void * data)
{
if( queue_is_full(queue) )
{
/* 队满,无法写入 */
DBG("Full\r\n");
return 1;
}
/* 类型转换,因为void *类型的指针偏移大小无法被编译器所识别,所以统一为char * */
char *tmp = (char *)(&queue->data)+(queue->msg_len * queue->write);
memcpy(tmp,data,queue->msg_len);
queue->write = ( queue->write+1)%queue->queue_max;
return 0;
}
/*
*队列元素个数
*/
static int queue_get_cnt(qQUEUE queue)
{
return ( (queue->write+queue->queue_max-queue->read)%queue->queue_max );
}
/*
*队列内存释放
*/
static int queue_free(qQUEUE queue)
{
free(queue);
return 0;
}
/*
*创建一个队列
*/
qQUEUE create_new_queue(int msg_len,int queue_len,char *name)
{
/* 分配内存 */
/* 计算方法:
队列的有效长度 = 队列最大长度 - 1
内存总长度 = 单消息长度*(队列最大长度)+ QUEUE结构体长度 - 1条单消息长度
即,内存总长度 = 单消息长度*(队列的有效长度)+ QUEUE结构体长度
*/
int q_len = msg_len*(queue_len)+sizeof(QUEUE);
qQUEUE q = malloc(q_len);
/* 创建一个队列 */
if(!q)
{
DBG("q NULL\r\n");
return NULL;
}
/* 赋值 */
q->write = q->read = 0;
q->msg_len = msg_len;
q->queue_len = queue_len;
q->queue_max = queue_len+1;
strcpy(q->name,name);
/* 函数调用 */
q->readData = queue_read;
q->writeData= queue_write;
q->getcnt = queue_get_cnt;
q->is_empty = queue_is_empty;
q->is_full = queue_is_full;
q->free = queue_free;
return q;
}
.h文件
#ifndef __QUEUE__H_
#define __QUEUE__H_
#define DBG printf
/* 定义一个队列 */
typedef struct _QUEUE{
char name[10]; //队列名
/* 操作函数 */
int (* readData)(struct _QUEUE *queue,void * data);
int (* writeData)(struct _QUEUE *queue,void * data);
int (* getcnt)(struct _QUEUE *queue);
int (* is_full)(struct _QUEUE *queue);
int (* is_empty)(struct _QUEUE *queue);
int (* free)(struct _QUEUE *queue);
int msg_len; //队列长度
int queue_len; //队列有效长度
int queue_max; //队列最大长度
int read,write; //读写指针
void *data;
}QUEUE,*qQUEUE;
qQUEUE create_new_queue(int msg_len,int queue_len,char *name);
#endif