一、前言(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的快速上手使用方法相关推荐

  1. objective-c 2.0编程语言,Objective-C 2.0编程快速上手 EXE版[12MB]

    Objective-C 2.0编程快速上手 内容简介: <Objective-C 2.0编程快速上手>是介绍Objective-C编程的基础教程.全书采用实例讲解.按部就班的方式,全面详细 ...

  2. 使用Yolov5训练自己制作的数据集,快速上手

    总结了快速上手Yolov5训练自己制作的数据集的方法,步骤都很详细,学者耐心看. 文章目录 一.准备好Yolov5框架 二.关于数据集的问题 三.VOC格式数据集转yolo格式数据集 四.训练模型 五 ...

  3. 普通人快速上手编程的三个方法

    这个时代,编程已经变得像基础计算机技能一样,这不仅体现在随着python等语言兴起使得学习编程更加简单,还体现在编程在各行各业都具有非常高效的作用. 我妈是怎么学会编程的 举个例子,我妈是一个小学老师 ...

  4. 【零基础上手JavaWeb】07 快速上手 XML解析方法

    写在前面,大家好!我是[跨考菌],一枚跨界的程序猿,专注于后台技术的输出,目标成为全栈攻城狮!这博客是对我跨界过程的总结和思考.如果你也对Java.后端技术感兴趣,抑或是正在纠结于跨界,都可以关注我的 ...

  5. 微信小程序运营和推广方法 新手如何快速上手去找新用户

    微信小程序线上入口众多,且基于微信这个社交大平台,但对于一个专注线下的刚刚上线的实体店小程序,没有流量.没有用户,该如何去做推广呢? 作为一个运营者或者商家来说,我们应该要怎么去运营小程序?其实小程序 ...

  6. 【转】Vue.js 2.0 快速上手精华梳理

    Vue.js 2.0 快速上手精华梳理 Sandy 发掘代码技巧:公众号:daimajiqiao 自从Vue2.0发布后,Vue就成了前端领域的热门话题,github也突破了三万的star,那么对于新 ...

  7. 『转载』Debussy快速上手(Verdi相似)

    『转载』Debussy快速上手(Verdi相似) Debussy 是NOVAS Software, Inc(思源科技)发展的HDL Debug & Analysis tool,这套软体主要不是 ...

  8. [转载]ESFramework 4.0 快速上手(15) -- 客户端登录验证

    ESFramework 4.0 快速上手(15) -- 客户端登录验证 在之前版本的Rapid引擎中,是没有提供客户端登陆验证的机制的,如果要验证用户的帐号密码信息,我们只有自己手动通过自定义信息来实 ...

  9. WijmoJS 2019V1正式发布:全新的在线 Demo 系统,助您快速上手,开发无忧

    2019独角兽企业重金招聘Python工程师标准>>> 下载WijmoJS 2019 v1 WijmoJS是为企业应用程序开发而推出的一系列包含HTML5和JavaScript的开发 ...

  10. react 快速上手开发_React中测试驱动开发的快速指南

    react 快速上手开发 by Michał Baranowski 通过MichałBaranowski React中测试驱动开发的快速指南 (A quick guide to test-driven ...

最新文章

  1. 马斯克活猪脑机接口试验成功!多芯片植入,硬币大小,实时读取脑电波,已被批准人脑实验...
  2. 易生信-扩增子教程02-真菌引物选择
  3. 大话中文文本分类之TextRCNN
  4. Netflix网关zuul(1.x和2.x)全解析
  5. 怎样用MATLAB画二次函数曲线,MATLAB 二次函数的画图.doc
  6. 验证码 -图形图像识别的算法。http://blog.csdn.net/xtalk2008/archive/2007/11/01/1861310.aspx...
  7. 8-[多线程] 进程池线程池
  8. 骚年快答 | 为何微服务项目都使用单体代码仓库?
  9. 9、java中的异常处理机制
  10. 矢量图标库如何引入html,Iconfont矢量图标库在网站中的使用方法
  11. Java笔记11-【异常、线程】
  12. 201673020127 词频统计软件项目报告
  13. GBK与UNICODE编码互转
  14. Flash Cs4 安装之后打不开
  15. 正则表达式:提取数字和小数点
  16. python程序实现分析_Python编程快速上手——疯狂填词程序实现方法分析
  17. 【题解】洛谷P1328[NOIP2014]生活大爆炸版石头剪刀布 模拟
  18. 美食杰项目-登录注册
  19. 霍兰德人格分析雷达图——python实现
  20. 【个人C++学习日记】

热门文章

  1. UnityEngine.Quaternion.LookRotation的使用(感觉这个用着还不错做一个笔记)
  2. u盘制作启动盘后容量变小
  3. Model-Free Adaptive Predictive Control
  4. 2018年1月西邻雪山自驾游攻略
  5. Go异常处理——defer、panic、recover
  6. 如何防范计算机安全,计算机安全风险及防范措施
  7. 登陆apple pay显示无法登录服务器,apple pay无法添加卡怎么办?未能连接到apple pay的解决方法...
  8. 为什么我的iPhone上的某些iMessages绿色和某些蓝色?
  9. 【寒江雪】点到直线的最短距离
  10. 怎么测试网站访问速度?