1. 背景
数组当作队列来用的时候,传统的队列设计方法在判空和判满的时候会损失一个Item,这种在Item占用的内存比较大的情况下比较浪费资源,这里介绍一种能将数组成员全部利用起来的方法。
2. 任务需求
将一个大小为5的数组设计成一个队列,数组成员的数据类型如下:
//结构体类型
typedef queue
{
u_int8 write_index;
u_int8 read_index;
u_int8 queue_size;
}t_queue_stg;
#define QUEUE_SIZE 0x05
u_int8 g_global_arr[QUEUE_SIZE] = {0};
t_queue_stg g_queue_stg = {0};
3. 队列设计
设计原理:
将队列的内存想象成数组g_global_queue产生无数个副本铺开到内存中(实际没有铺开还只是一个数组),如下图。 write_index和read_index不断递增,即使超过了数组的范围。
但是需要访问queue成员的时候,就需要通过计算限制到数组长度范围内;
3.1. 队列空的条件
当write_index 和 read_index 相等的时候,认为是空队列;
3.2. 队列满的条件
当write_index和read_index 相差数组长度的时候,认为是满队列;即read_index + QUEUE_SIZE = write_index;
4. 代码实现
#define QUEUE_SIZE 0x05
t_queue_stg g_global_arr[QUEUE_SIZE] = {0};
t_queue_stg g_queue_stg = {0};
//队列初始化
void queue_init(void)
{
g_queue_stg.read_index = 0;
g_queue_stg.write_index = 0;
g_queue_stg.queue_size = QUEUE_SIZE;
}
void queue_in(u_int8 value)
{
if ((g_queue_stg.read_index + g_queue_stg.queue_size) == g_queue_stg.write_index)
{
//full
return;
}
g_queue_arr[g_queue_stg.write_index % g_queue_stg.queue_size] = value;
g_queue_stg.write_index ++;
}
u_int8 queue_out(void)
{
if (g_queue_stg.read_index == g_queue_stg.write_index)
{
//empty
return INVALID_VALUE;
}
return g_queue_arr[(g_queue_stg.read_index ++) % g_queue_stg.queue_size];
}