RingBuffer的快速上手使用方法
一、前言(ring buffer使用的原因)
ring buffer:环形buffer,用于多个线程之间传递数据,是标准的先入先出FIFO模型。一般解决多个线程同时访问共享数据,需要使用互斥量锁。使用互斥锁能解决共享资源不会同时被多个线程所访问的问题,然而mutex的使用也带来了额外开销。ring buffer的引入就是为了有效解决互斥访问问题,又有效节省了开销。
二、ring buffer的实现原理
环形缓冲区通常有一个读指针和一个写指针。读指针指向缓冲区中的可读的数据,写指针指向环形缓冲区中可写的缓冲区。通过移动读指针和写指针就可以实现缓冲区的数据读取与写入。在通常情况下,如果只有一个用户读和一个用户写,那么就不需要添加互斥机制。如果有多个用户读写缓冲区,就必须添加互斥保护机制。
1.定义数据结构
typedef struct
{
uint32_t PCBuffer; //缓冲区的起始地址
uint16_t Front; //头指针
uint16_t Rear; //尾指针
uint16_t Maxsize;//buffer大小
} attribute((packed)) PCRingBufferType;
ST_PL2PS_Pkt PointCloudReceived_Buffer[PointCloudReceived_RingBuffer_Maxsize + 5] attribute((aligned(64)));
PCRingBufferType PCReceived_RingBuffer;
2.初始化RingBuffer
/******************************************************************************
*函数名 :PC_RingBuffer_Init
*函数功能 :构造一个空环形缓冲区
*输入参数 : Q环形缓冲区控制块
PcBuffer Q控制块基址
Maxsize Q控制块大小
*返回值 :0表示成功
****************************************************************************/
int PC_RingBuffer_Init(PCRingBufferType Q,INTPTR PcBuffer,uint16_t Maxsize)
{
Q->Front=0;
Q->Rear=0;
Q->Maxsize=Maxsize;
Q->PCBuffer=PcBuffer;
return 0;
}
3.获取RingBuffer是否为空
/******************************************************************************
*函数名 :PC_IsEmptyQueue
*函数功能 :判断RingBuffer是否为空
*输入参数 : Q环形缓冲区控制块
*返回值 :1表示空
*****************************************************************************/
bool PC_IsEmptyQueue(PCRingBufferType *Q)
{
return (Q->Front == Q->Rear);
}
4.获取RingBuffer是否为满
/******************************************************************************
*函数名 :PC_IsEmptyQueue
*函数功能 :判断RingBuffer是否为空
*输入参数 : Q环形缓冲区控制块
*返回值 :1表示满
*****************************************************************************/
bool PC_IsFullQueue(PCRingBufferType *Q)
{
return (Q->Front == (Q->Rear + 1) % Q->Maxsize);
}
获取RingBuffer已经占用多少个元素
/******************************************************************************
*函数名 :PC_QueueUsedSize
*函数功能 :获取RingBuffer已经占用多少个元素
*输入参数 : Q环形缓冲区控制块
*返回值 :占用元素的个数
*****************************************************************************/
uint16_t PC_QueueUsedSize(PCRingBufferType *Q)
{
return (((Q->Rear + Q->Maxsize) - Q->Front) % Q->Maxsize);
}
5.获取RingBuffer已经占用多少个元素
/******************************************************************************
*函数名 :PC_QueueFreeSize
*函数功能 :获取RingBuffer空闲多少个元素
*输入参数 : Q环形缓冲区控制块
*返回值 :空闲元素的个数
*****************************************************************************/
uint16_t PC_QueueFreeSize(PCRingBufferType *Q)
{
return ((Q->Front + Q->Maxsize - 1) - Q->Rear) % Q->Maxsize;
}
6.获取RingBuffer出栈的bufferline是否再队列里面
/******************************************************************************
*函数名 :PC_IsWithinQue
*函数功能 :获取RingBuffer出栈的bufferline是否再队列里面
*输入参数 : Q环形缓冲区控制块
BufferLine buffer的行号
*返回值 :true 在buffer里面 f
*****************************************************************************/
bool PC_IsWithinQue(PCRingBufferType *Q, uint16_t BufferLine)
{
return (((Q->Rear + Q->Maxsize) - Q->Front) % Q->Maxsize) >= (((Q->Rear + Q->Maxsize) - BufferLine) % Q->Maxsize) && Q->Rear != BufferLine;
}
7.获取RingBuffer 入队一个元素的运行状态
/******************************************************************************
*函数名 :PC_Enqueue
*函数功能 :获取入队元素的运行状态
并且将队尾加1
*输入参数 : Q环形缓冲区控制块
*返回值 :false 表示入队列失败 ,true表示入队列成功
****************************************************************************/
bool PC_Enqueue(PCRingBufferType Q)
{
if(PC_IsFullQueue(Q))
return false;
else
{
Q->Rear=(Q->Rear+1)%Q->Maxsize;
return true;
}
}
8.获取RingBuffer 入队N个元素的运行状态
/******************************************************************************
*函数名 :PC_Enqueue
*函数功能 :获取入队元素的运行状态
并且将队尾加N个元素
*输入参数 : Q环形缓冲区控制块
Num 入栈元素的个数
*返回值 :false 表示入队列失败 ,true表示入队列成功
*****************************************************************************/
bool PC_EnqueueNum(PCRingBufferType *Q, uint16_t Num)
{
if (PC_QueueFreeSize(Q) <= Num)
{
return false;
}
else
{
Q->Rear = (Q->Rear + Num) % Q->Maxsize;
return true;
}
}
9.获取入栈RingBuffer 的地址
/******************************************************************************
*函数名 :PC_PreEnqueueAddr
*函数功能 :获取RingBuffer入栈的地址
*输入参数 : Q环形缓冲区控制块
UnitLength 元素的大小
*返回值 :入栈元素元素的地址
*****************************************************************************/
INTPTR PC_PreEnqueueAddr(PCRingBufferType* Q,uint32_t UnitLength)
{
return Q->PCBuffer+(Q->Rear)*UnitLength;
}
10.获取RingBuffer 出队一个元素的运行状态
/******************************************************************************
*函数名 :PC_Dequeue
*函数功能 :获取RingBuffer出队一个元素的运行状态
并且将队首加1
*输入参数 : Q环形缓冲区控制块
*返回值 :入栈元素元素的地址
*****************************************************************************/
bool PC_Dequeue(PCRingBufferType *Q)
{
if (PC_IsEmptyQueue(Q))
{
return false;
}
else
{
/the Data should Dequeue to network,so Add network PointCloud operation here/
Q->Front = (Q->Front + 1) % Q->Maxsize;
return true;
}
}
11.获取RingBuffer 出队一个元素的运行状态
/******************************************************************************
*函数名 :PC_DequeueNum
*函数功能 :获取出栈元素的状态,若占用的元素大于出栈元素的个数将返回一个true,
若占用的元素小于出栈元素的个数,将不断的返回true
*输入参数 : Q环形缓冲区控制块true
*返回值 :true :
*****************************************************************************/
bool PC_DequeueNum(PCRingBufferType *Q, uint16_t Num)
{
if (PC_QueueUsedSize(Q) > Num)
{
Q->Front = (Q->Front + Num) % Q->Maxsize;
return true;
}
else
{
uint16_t l_QueueUsedSize = PC_QueueUsedSize(Q);
Q->Front = (Q->Front + l_QueueUsedSize) % Q->Maxsize;
}
return true;
}
三、ring buffer的使用
1.初始化buffer
输入参数 : Q环形缓冲区控制块
PcBuffer Q控制块基址
Maxsize Q控制块大小
PC_RingBuffer_Init(&PCReceived_RingBuffer,(INTPTR)PointCloudReceived_Buffer,PointCloudReceived_RingBuffer_Maxsize);
2.获取RingBuffer 入队N个元素的运行状态
*输入参数 : Q环形缓冲区控制块
Num 入栈元素的个数
*返回值 :false 表示入队列失败 ,true表示入队列成功
PC_EnqueueNum(&PCReceived_RingBuffer,DMA_RX_SAMPLE_NUMBER_OF_PACKAGE);
3.获取入栈基址
Status = XAxiDma_SimpleTransfer(&axidmaPtr, PC_PreEnqueueAddr(&PCReceived_RingBuffer,sizeof(ST_PL2PS_Pkt)),DMA_RX_SAMPLE_DATA_LENGTH*DMA_RX_SAMPLE_NUMBER_OF_PACKAGE, XAXIDMA_DEVICE_TO_DMA);
*输入参数 : Q环形缓冲区控制块
UnitLength 元素的大小
*返回值 :入栈元素元素的地址
PC_PreEnqueueAddr(&PCReceived_RingBuffer,sizeof(ST_PL2PS_Pkt)
4.发送一包点云数据
PCPreProF_SendtoRcore((char *)((ST_PL2PS_Pkt *)PCReceived_RingBuffer.PCBuffer + PCReceived_RingBuffer.Front), 1248u);
5.出栈一包数据
*函数功能 :获取RingBuffer出队一个元素的运行状态
并且将队首加1
*输入参数 : Q环形缓冲区控制块
PC_Dequeue(&PCReceived_RingBuffer);
RingBuffer的快速上手使用方法相关推荐
- objective-c 2.0编程语言,Objective-C 2.0编程快速上手 EXE版[12MB]
Objective-C 2.0编程快速上手 内容简介: <Objective-C 2.0编程快速上手>是介绍Objective-C编程的基础教程.全书采用实例讲解.按部就班的方式,全面详细 ...
- 使用Yolov5训练自己制作的数据集,快速上手
总结了快速上手Yolov5训练自己制作的数据集的方法,步骤都很详细,学者耐心看. 文章目录 一.准备好Yolov5框架 二.关于数据集的问题 三.VOC格式数据集转yolo格式数据集 四.训练模型 五 ...
- 普通人快速上手编程的三个方法
这个时代,编程已经变得像基础计算机技能一样,这不仅体现在随着python等语言兴起使得学习编程更加简单,还体现在编程在各行各业都具有非常高效的作用. 我妈是怎么学会编程的 举个例子,我妈是一个小学老师 ...
- 【零基础上手JavaWeb】07 快速上手 XML解析方法
写在前面,大家好!我是[跨考菌],一枚跨界的程序猿,专注于后台技术的输出,目标成为全栈攻城狮!这博客是对我跨界过程的总结和思考.如果你也对Java.后端技术感兴趣,抑或是正在纠结于跨界,都可以关注我的 ...
- 微信小程序运营和推广方法 新手如何快速上手去找新用户
微信小程序线上入口众多,且基于微信这个社交大平台,但对于一个专注线下的刚刚上线的实体店小程序,没有流量.没有用户,该如何去做推广呢? 作为一个运营者或者商家来说,我们应该要怎么去运营小程序?其实小程序 ...
- 【转】Vue.js 2.0 快速上手精华梳理
Vue.js 2.0 快速上手精华梳理 Sandy 发掘代码技巧:公众号:daimajiqiao 自从Vue2.0发布后,Vue就成了前端领域的热门话题,github也突破了三万的star,那么对于新 ...
- 『转载』Debussy快速上手(Verdi相似)
『转载』Debussy快速上手(Verdi相似) Debussy 是NOVAS Software, Inc(思源科技)发展的HDL Debug & Analysis tool,这套软体主要不是 ...
- [转载]ESFramework 4.0 快速上手(15) -- 客户端登录验证
ESFramework 4.0 快速上手(15) -- 客户端登录验证 在之前版本的Rapid引擎中,是没有提供客户端登陆验证的机制的,如果要验证用户的帐号密码信息,我们只有自己手动通过自定义信息来实 ...
- WijmoJS 2019V1正式发布:全新的在线 Demo 系统,助您快速上手,开发无忧
2019独角兽企业重金招聘Python工程师标准>>> 下载WijmoJS 2019 v1 WijmoJS是为企业应用程序开发而推出的一系列包含HTML5和JavaScript的开发 ...
- react 快速上手开发_React中测试驱动开发的快速指南
react 快速上手开发 by Michał Baranowski 通过MichałBaranowski React中测试驱动开发的快速指南 (A quick guide to test-driven ...
最新文章
- 马斯克活猪脑机接口试验成功!多芯片植入,硬币大小,实时读取脑电波,已被批准人脑实验...
- 易生信-扩增子教程02-真菌引物选择
- 大话中文文本分类之TextRCNN
- Netflix网关zuul(1.x和2.x)全解析
- 怎样用MATLAB画二次函数曲线,MATLAB 二次函数的画图.doc
- 验证码 -图形图像识别的算法。http://blog.csdn.net/xtalk2008/archive/2007/11/01/1861310.aspx...
- 8-[多线程] 进程池线程池
- 骚年快答 | 为何微服务项目都使用单体代码仓库?
- 9、java中的异常处理机制
- 矢量图标库如何引入html,Iconfont矢量图标库在网站中的使用方法
- Java笔记11-【异常、线程】
- 201673020127 词频统计软件项目报告
- GBK与UNICODE编码互转
- Flash Cs4 安装之后打不开
- 正则表达式:提取数字和小数点
- python程序实现分析_Python编程快速上手——疯狂填词程序实现方法分析
- 【题解】洛谷P1328[NOIP2014]生活大爆炸版石头剪刀布 模拟
- 美食杰项目-登录注册
- 霍兰德人格分析雷达图——python实现
- 【个人C++学习日记】
热门文章
- UnityEngine.Quaternion.LookRotation的使用(感觉这个用着还不错做一个笔记)
- u盘制作启动盘后容量变小
- Model-Free Adaptive Predictive Control
- 2018年1月西邻雪山自驾游攻略
- Go异常处理——defer、panic、recover
- 如何防范计算机安全,计算机安全风险及防范措施
- 登陆apple pay显示无法登录服务器,apple pay无法添加卡怎么办?未能连接到apple pay的解决方法...
- 为什么我的iPhone上的某些iMessages绿色和某些蓝色?
- 【寒江雪】点到直线的最短距离
- 怎么测试网站访问速度?