循环队列及C语言实现三

在之前的博客中给出了设计循环队列的思路以及源码,这些可都是经过我长期大数据测试的验证哦。当然,现在的很多开源项目和一些封装好的类或接口也都有类似的队列实现方法,之所以我还在使用自己写的这一套方法,主要是因为灵活性较大,我可以定制出适合自己的接口。而且在其上的操作逻辑和结果我也心知肚明。
好了,之所以隔了这么久写这个第三篇文章,主要是考虑到以下因素:
<1> 队列并发操作的同步问题;(安全性)
<2> 部分情况下,希望在读取队列后进行队列回写操作。(比如进行数据分析按一帧一帧进行解析的时候,发现队列里缓存数据不足一帧,此时就需要回写,等再有数据保存到队列)

下面先提出 <1> 的解决方法,使用互斥锁和信号量,给出简单例子:

Exp1:

pthread_mutex_init(&mutex);thread1:...pthread_mutex_lock(&mutex);WriteQueue(q, wbuf, writelen);pthread_mutex_unlock(&mutex);...thread2:...pthread_mutex_lock(&mutex);ReadQueue(q, rbuf, &readlen);pthread_mutex_unlock(&mutex);...

Exp2:

sem_init(&sem);thread1:...sem_wait(&sem);WriteQueue(q, wbuf, writelen);sem_post(&sem);...thread2:...sem_wait(&sem);ReadQueue(q, rbuf, &readlen);sem_post(&sem);...

其他的方式还有很多啦,就不一一列举了,小型项目开发应该是足够了。

至于方案 <2> 的解决方法,在 queue.c 中添加一个回写函数就好啦,原理也很简单,把读指针移动到之前的位置就可以啦。需要考虑的就是回写的长度大于队列当前读指针距离队列头的位置时的处理,详细可以参见我下面的代码:

unsigned int RecoverReadQueue(Queue *q, unsigned int len)
{unsigned int ret = 0;unsigned int rest = q->read;if (rest >= len){q->read -= len;}else{q->read = q->size - (len - rest);}q->space -= len;return ret;
}

为了防止部分读者忽略了之前文章,我还是把最新的源码贴出来以供参考:

queue.h

#ifndef _QUEUE_H
#define _QUEUE_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>/*** Queue - queue structure* @buf: queue buffer* @read: position of read* @write: position of write* @size: buffer size* @space: writable buffer size*/
typedef struct {unsigned char *buf;unsigned int read;unsigned int write;unsigned int size;unsigned int space;bool OverFlow;
} Queue;#define Avail(q) (q->size - q->space)extern bool Queue_Empty(Queue *q);
extern bool Queue_Full(Queue *q);
extern unsigned int RecoverReadQueue(Queue *q, unsigned int len);
extern void Queue_Init(Queue *q, int size);
extern void Queue_Destroy(Queue *q);
extern bool AddQueue(Queue *q, unsigned char val);
extern bool DelQueue(Queue *q, unsigned char *val);
extern unsigned int WriteQueue(Queue *q, unsigned char *buf, unsigned int len);
extern unsigned int ReadQueue(Queue *q, unsigned char *buf, unsigned int len);#endif

queue.c

/** Queue operation API - 1.1** Copyright (C) 2016 SoldierJazz (SoldierJazz@163.com)** This program is free software; you can redistribute it and/or* modify it. **/#include "queue.h"/*** Queue_Init - init a queue* @q: pointer of queue* @size: size of buffer in queue** Must be called when started. */
void Queue_Init(Queue *q, int size)
{q->buf = (unsigned char *)malloc(sizeof(unsigned char) * size);memset(q->buf, 0x00, size);q->read = 0;q->write = 0;q->size = size;q->space = size;q->OverFlow = false;
}/*** Queue_Destroy - destroy a queue* @q: pointer of queue*/
void Queue_Destroy(Queue *q)
{free(q->buf);
}/*** Queue_Empty - tests whether a queue is empty* @q: the queue to test*/
bool Queue_Empty(Queue *q) 
{
    return (q->space == q->size);
}/*** Queue_Full - tests whether a queue is full* @q: the queue to test*/
bool Queue_Full(Queue *q)
{
    return (q->space == 0);
}/*** AddQueue - add a byte to queue* @q: the queue to add to* @val: the char to add*/
bool
bool AddQueue(Queue *q, unsigned char val)
{if (!Queue_Full(q)) {q->buf[q->write] = val;q->write = (q->write + 1) % q->size;q->space--;
        return true;} 
    return false;
}/*** DelQueue - delete a byte from queue* @q: the queue to delete from* @val: the char deleted*/
bool DelQueue(Queue *q, unsigned char *val)
{if (!Queue_Empty(q)) {*val = q->buf[q->read];q->read = (q->read + 1) % q->size;q->space++;
        return true;}
    return false;
}/*** WriteQueue - write buffers to queue* @q: the queue to write in* @buf: pointer of write buffer* @len: length of write buffer*/
unsigned int WriteQueue(Queue *q, unsigned char *buf, unsigned int len)
{unsigned int ret = 0;unsigned int rest = q->size - q->write;if (!Queue_Full(q)) {if (q->space >= len) {ret = len;if (rest >= len) {memcpy(q->buf + q->write, buf, len);q->write = (q->write + len) % q->size;q->space -= len;} else {memcpy(q->buf + q->write, buf, rest);q->write = 0;memcpy(q->buf, buf + rest, len - rest);q->write = len -rest;q->space -= len;}} else {ret = q->space;if (rest >= q->space) {memcpy(q->buf + q->write, buf, q->space);q->write = (q->write + q->space) % q->size;q->space = 0;} else {memcpy(q->buf + q->write, buf, rest);q->write = 0;memcpy(q->buf, buf + rest, q->space - rest);q->write = q->space -rest;q->space = 0;}}   } 
    return ret;
}/*** RecoverReadQueue - recover len of buffer from queue* @q: the queue to recover from* @len: recover length*/
unsigned int RecoverReadQueue(Queue *q, unsigned int len)
{unsigned int ret = 0;unsigned int rest = q->read;if (rest >= len){q->read -= len;}else{q->read = q->size - (len - rest);}q->space -= len;
return ret;
}/*** ReadQueue - read buffers from queue* @q: the queue to read from* @buf: pointer of read buffer* @len: read length*/
unsigned int ReadQueue(Queue *q, unsigned char *buf, unsigned int len)
{unsigned int rest = q->size - q->read;unsigned int ret = 0;if (!Queue_Empty(q)) {if (Avail(q) >= len) {ret = len;if (rest >= len) {memcpy(buf, q->buf + q->read, len);q->read = (q->read + len) % q->size;q->space += len;} else {memcpy(buf, q->buf + q->read, rest);q->read = 0;memcpy(buf + rest, q->buf, len - rest);q->read = len -rest;q->space += len;}
            return len;} else {ret = Avail(q);if (rest >= Avail(q)) {memcpy(buf, q->buf + q->read, Avail(q));q->read = (q->read + Avail(q)) % q->size;q->space = q->size;} else {memcpy(buf, q->buf + q->read, rest);q->read = 0;memcpy(buf + rest, q->buf, Avail(q) - rest);q->read = Avail(q) -rest;q->space = q->size;}}} 
    return ret;
}

关于循环队列主题的系列文章,可移步至以下链接:
1. 《循环队列及C语言实现<一>》
2. 《循环队列及C语言实现<二>》
3. 《循环队列及C语言实现<三>》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/403269.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【转】提高PHP性能的53个技巧

PHP技巧汇总:提高PHP性能的53个技巧用单引号代替双引号来包含字符串&#xff0c;这样做会更快一些。因为PHP会在双引号包围的字符串中搜寻变量&#xff0c;单引号则不会&#xff0c;注意&#xff1a;只有echo能这么做&#xff0c;它是一种可以把多个字符串当作参数的函数译注&a…

el-table列宽设置百分比无效;el-table使用min-width设置百分比;el-table百分比设置无效;

废话不多说&#xff0c;直接给每个el-table-column&#xff0c;设置 width"auto" min-width"25%"即可。 总的百分比还是要等于100%哈。 点赞收藏吧 感谢 代码可以直接复制使用&#xff1a; <template><div style"width:1300px;">&…

Anonymous Inner Class (匿名内部类) 是否可以extends(继承)其它类,是否可以implements(实现)interface(接口)?...

http://blog.csdn.net/fhm727/article/details/5220003 1、什么是匿名内部类&#xff1f; 内部类&#xff0c;存在于另一个类内部的类&#xff0c;而匿名内部类&#xff0c;顾名思义&#xff0c;就是没有名字的内部类。 2、为什么需要匿名内部类&#xff1f; 每个inner clas…

VIM使用系统剪切板

在 Linux 终端模式下使用 vim 编辑器时发现经常需要在vim打开的文本文档进行复制粘贴&#xff0c;那么下面就跟着我的思路一步步往下走吧。 一、首先确认当前 vim 配置是不是支持系统剪切板&#xff0c;可以在终端模式下输入命令&#xff1a; vim --version | grep clipboard…

AndroidManifest.xml清单文件要点

AndroidManifest.xml AndroidManifest.xml清单文件通常包括如下内容&#xff1a; 应用程序的包名&#xff0c;该包名作为该应用的唯一标识。应用包含的组件&#xff0c;如Activity,Service,Broadcastreceiver和ContentProvider.应用程序使用系统所需的权限声明。其他程序访问该…

python操作Excel读写--使用xlrd

From: http://www.cnblogs.com/lhj588/archive/2012/01/06/2314181.html 一、安装xlrd模块 到python官网下载http://pypi.python.org/pypi/xlrd模块安装&#xff0c;前提是已经安装了python 环境。 也可以在命令行执行&#xff1a;easy_install xlrd (注意权限) 二、使用介绍…

el-table自动充满,且无滚动条;el-table某列的列宽自适应,其他列按比例分配。

情景一&#xff1a;例如首列按照内容自适应展开&#xff0c;其余列有各自的比例。这样设置&#xff0c;就不会出现滚动条。 注意点&#xff1a; 给需要自适应展开的列加 :width"flexColumnWidth"计算方法 就可以自适应展开需要给余下所有的列都设置 width“auto” mi…

DataGridView控件中显示图片及其注意事项 【z】

windows Forms编程里面有一个DataGridView控件&#xff0c;它不光是可以显示数据&#xff0c;可以显示按钮&#xff0c;复选框&#xff0c;甚至还可以显示图片。这些图片可以来自于数据库&#xff08;用二进制的方式存储的&#xff09;&#xff0c;也可以来自文件系统。下面是一…

在winform上内嵌入其它的程序

这段代码很有意义,用于把一个程序的界面嵌入到我们自己程序的某个指定窗体上. 比如在某个项目里,我需要把基恩士的激光扫描轮廓显示给客户看,但是激光的DLL中并没有这种功能提供. 于是我想先启动激光的官方程序用以显示轮廓, 然后再把这种显示界面嵌入到我自己程序的界面上指定…

SPI总线时序

SPI&#xff0c;是一种高速的&#xff0c;全双工&#xff0c;同步的通信总线&#xff0c;并且在芯片的管脚上只占用四根线&#xff0c;节约了芯片的管脚&#xff0c;同时为PCB的布局上节省空间&#xff0c;提供方便&#xff0c;正是出于这种简单易用的特性&#xff0c;现在越来…

js计算浮点数出现小数;解决js计算小数问题;js数组相加出现小数;

原博1 原博2 方案1和方案2都是有效的 注意参数一定要是数字 而不能是字符串 否则会计算错误 情景&#xff1a; 在计算浮点数时候&#xff0c;出现多余小数。 例如&#xff1a; 1.11 1 2.1100000000000003 为什么计算小数会出现误差&#xff1f; 浮点数值的最高进度是17位…

Shell脚本中获取本机ip地址的3个方法

From: http://www.jb51.net/article/56585.htm 这篇文章主要介绍了Shell脚本中获取本机ip地址的3个方法,本文直接给出实现代码,需要的朋友可以参考下方法一&#xff1a; 复制代码 代码如下:/sbin/ifconfig -a|grep inet|grep -v 127.0.0.1|grep -v inet6|awk {print $2}|tr -d…

VMware安装系统时没有弹出分区设置

在安装虚拟机系统的时候&#xff0c;有时候会遇到在安装一些镜像时没有弹出分区设置的画面&#xff0c;比如&#xff0c;我在使用 VMware 安装 CentOS 的时候&#xff0c;在选择完镜像&#xff0c;设置好启动安装的时候系统自动为我划分了 3 个分区&#xff1a;/boot、/、swap分…

如何在postgresql中模拟oracle的dual表,来测试数据库最基本的连接功能?

还好&#xff0c;网上弄到的&#xff0c;&#xff0c;没有dual的数据库&#xff0c;可以试图用select函数不带from数据表的方式来实现返回值。 一段测试代码&#xff1a; try:conn psycopg2.connect(databasedb.service_name, userdb.username, passwordpassword, hostdb.ip, …

Linux 系统如何查看硬盘UUID与修改

一、查看 1. sudo blkid 2. ls -l /dev/disk/by-uuid 3. tune2fs -l /dev/sdb 二、修改与恢复 uuidgen 会返回一个合法的 uuid&#xff0c;结合 tune2fs 可以新生成一个 uuid 并写入 ext2,3,4 分区中&#xff1a; 比如新建或改变 sda5 的 uuid &#xff08;需要 root 权限…

vue+element实现树状表格的增删改查;使用el-table树形数据与懒加载实现树状表格增删改查

以下代码可以直接复制使用 一、情景&#xff1a; 列表是一个树状表格&#xff0c;可以无限添加下级&#xff0c;以及对列表的某一行进行增删改查&#xff08;目前查没有写&#xff09;。 原博链接 二、本篇是在原博主的代码基础上添加了部分功能。 功能1&#xff1a; 给树状表格…

定时任务 Crontab命令 详解

From: http://www.centoscn.com/CentOS/help/2014/1030/4025.html 前言 crontab是Unix和Linux用于设置周期性被执行的指令&#xff0c;是互联网很常用的技术&#xff0c;很多任务都会设置在crontab循环执行&#xff0c;如果不使用crontab&#xff0c;那么任务就是常驻程序&…

Web Js 按键事件……Enter提交事件 Enter Js事件

$(document).ready(function(){document.onkeydown function (event){ if (event.keyCode13) //回车键的键值为13 submit();}; });$(document).ready(funtion) 可以简写为 ↓ $(function(){});转载于:https://www.cnblogs.com/blogs2014/p/5789256.html

ISCSI 1-由零开始

iSCSI的概念 iSCSI&#xff0c;即Internet SCSI&#xff0c;是IETF制订的一项标准&#xff0c;用于将SCSI数据块映射为以太网数据包。从根本上说&#xff0c;它是一种基于IP Storage理论的新型存储技术&#xff0c;该技术将存储行业广泛应用的SCSI接口技术与IP网络技术相结合&a…

js获取当前日期并格式化(多种格式)

获取当前日期的格式&#xff1a;2022-01-07 或者 2022/01/07 或者 2022-01-07 12:00:00 或者 2022/01/07 12:00:00 原博链接 方法1&#xff1a; // 对Date的扩展&#xff0c;将 Date 转化为指定格式的String // 月(M)、日(d)、小时(h)、分(m)、秒(s)、季度(q) 可以用 1-2 个…