博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
c语言数据结构实现-数组队列/环形队列
阅读量:4138 次
发布时间:2019-05-25

本文共 2342 字,大约阅读时间需要 7 分钟。

一、背景需求

应用场景是一个生产者一个消费者,两者平均处理速度是相当的,但是有生产峰值速度太快,消费者处理速度跟不上的情况;

这种场景若用单线程处理,则会出现消费速度慢导致拖慢生产者的速度;

若使用双线程处理,一个生产线程一个消费线程,这个时候就能用到队列/环形队列了。

二、相关知识

队列的数据结构其实非常简单,实现方式主要为动态的链式结构或者为静态的数组结构,本文介绍一种静态的数组结构;
所示,入列时插入队列尾,出列时由队列头弹出,用下标值进行位置标识。
约束是用户数据必须是定长的数据,才能用静态数组结构去标识。

三、实现

创建队列,需要确定队列大小以及每个用户数据的长度
int bufqueue_create(bufqueue_t *phead, size_t nmemb, size_t item_size){    int ix = 0;    if ( !phead ) {        return FAILURE;    }#define __ISPOWER(_num_) ((_num_ ^ (_num_ - 1)) == (((_num_ - 1) << 1) + 1))    if ( !__ISPOWER(nmemb) ) {        return FAILURE;    }    /* Refree queue */    FREE_POINTER(phead->queue);    phead->queue = (bufqueue_item *)calloc(nmemb, sizeof(bufqueue_item));    if ( !phead->queue ) {        return FAILURE;    }    for ( ix = 0; ix < nmemb; ix++ ) {        phead->queue[ix].pitem = calloc(1, item_size);        if ( !phead->queue[ix].pitem ) {            return FAILURE;        }    }    phead->item_size = item_size;    phead->size = nmemb;    phead->mask = nmemb - 1;    phead->head = 0;    phead->tail = 0;    phead->used = 0;    printf("Queue alloc success, size: %zd ( Bytes )\n",            sizeof(bufqueue_t) + nmemb * item_size);    return SUCCESS;}
入列操作,分为获取队列尾,返回数据的指针给生成者,生产者生产数据后,更新队列尾操作
void* bufqueue_tail(bufqueue_t *phead){    if ( SUCCESS == bufqueue_isfull(phead) ) {        return NULL;    }    return (phead->queue[phead->tail].pitem);}
int bufqueue_push(bufqueue_t *phead){    phead->used++;    phead->tail = (phead->tail + 1) & phead->mask;    return SUCCESS;}
出列,消费者调用该接口直接获取到数据指针,注意外部并不需要释放空间
void* bufqueue_pop(bufqueue_t *phead){    void *pitem = NULL;    if ( phead->tail == phead->head ) {        return NULL;    }    pitem = phead->queue[phead->head].pitem;    phead->head = (phead->head + 1) & phead->mask;    phead->used--;    return (pitem);}
判定队列是否为空
int bufqueue_isempty(bufqueue_t *phead){    if ( phead->tail == phead->head ) {        return SUCCESS;    }    return FAILURE;}
判断队列是否满
int bufqueue_isfull(bufqueue_t *phead){    if ( !phead ) {        return FAILURE;    }    if ( phead->head == ((phead->tail + 1) & phead->mask) ) {        /* Queue is full */        return SUCCESS;    }    return FAILURE;}

四、小结

使用数组队列类似于牺牲空间换时间的方法,实现简单。但要求用户数据必须定长,并且会出现队列满的情况;
但是在索引方面,由于使用了下标法进行定位,可以快速地查找到下一个元素(head=(head + 1)&mask),这个时候也必须保证队列大小为2^N;
同时在一个生产者一个消费者的场景下,使用该队列可以无需上锁,节省锁的开销;
你可能感兴趣的文章
Spring MVC 教程,快速入门,深入分析
查看>>
Android 的source (需安装 git repo)
查看>>
Commit our mod to our own repo server
查看>>
LOCAL_PRELINK_MODULE和prelink-linux-arm.map
查看>>
Simple Guide to use the gdb tool in Android environment
查看>>
Netconsole to capture the log
查看>>
Build GingerBread on 32 bit machine.
查看>>
How to make SD Card world wide writable
查看>>
Detecting Memory Leaks in Kernel
查看>>
Linux initial RAM disk (initrd) overview
查看>>
Timestamping Linux kernel printk output in dmesg for fun and profit
查看>>
There's Much More than Intel/AMD Inside
查看>>
apache和tomcat整合
查看>>
java虚拟机错误问题
查看>>
oracle建立表空间
查看>>
oracle分区表的性能提升
查看>>
"Cannot allocate memory" OutofMemory when call Ant to build Polish project in Tomcat
查看>>
dumpcap抓包(python)
查看>>
查看文件是否被其他进程访问
查看>>
字符编码详解
查看>>