#include "rb.h"
enum rb_state
{
RINGBUFFER_EMPTY,
RINGBUFFER_FULL,
RINGBUFFER_HALFFULL, /* half full is neither full nor empty */
};
// 获取 ringbuff 的状态
enum rb_state rb_status(ringbuff *rb) {
if (rb->read_index == rb->write_index)
{
if (rb->read_mirror == rb->write_mirror)
return RINGBUFFER_EMPTY;
else
return RINGBUFFER_FULL;
}
return RINGBUFFER_HALFFULL;
}
// 获取 ringbuff 中数据的长度
uint16 rb_data_len(ringbuff *rb) {
switch (rb_status(rb)) {
case RINGBUFFER_EMPTY:
return 0;//空就返回 0
case RINGBUFFER_FULL:
return rb->size;// 满就返回缓冲区的大小
case RINGBUFFER_HALFFULL:// 半满
default:
if (rb->write_index > rb->read_index) // 如果在同一镜像
return rb->write_index - rb->read_index; // 返回下标差
else
return rb->size - (rb->read_index - rb->write_index); // 如果不在同一镜像,通过计算获取数据的长度
};
}
// 缓冲区初始化
void rb_init(ringbuff *rb,uint8 *pool,uint16 size){
/* initialize read and write index */
rb->read_mirror = rb->read_index = 0;
rb->write_mirror = rb->write_index = 0;
/* set buffer pool and size */
rb->buffer_ptr = pool;
rb->size = DATA_ALIGN_DOWN(size, DATA_ALIGN_SIZE);
}
// 创建一个ringbuff
ringbuff* rb_create(uint16_t size) {
ringbuff *rb;
uint8_t *pool;
size = DATA_ALIGN_DOWN(size, DATA_ALIGN_SIZE);// 大小做字节对齐
rb = (ringbuff *)malloc(sizeof(ringbuff));// 申请内存
if (rb == NULL)
goto exit;
pool = (uint8_t *)malloc(size);// 申请数据缓冲区内存
if (pool == NULL) {
free(rb);
rb = NULL;
goto exit;
}
rb_init(rb, pool, size);// 初始化 ringbuff
exit:
return rb;
}
// 往 ringbuff 写入数据
uint16 rb_put(ringbuff *rb,const uint8 *ptr,uint16 length) {
uint16 size = 0;
/* whether has enough space */
size = rb_space_len(rb);// 获取 ring_buff 中可用空间的大小
/* no space */
if (size == 0)
return 0;// 如果空间不够 直接返回
/* drop some data */
if (size < length) // 如果缓存区的空间不够保存这一次数据, 则把能够写入的这一部分数据写进去
length = size;
/* One-time write */
if (rb->size - rb->write_index > length)
{
/* read_index - write_index = empty space */
memcpy(&rb->buffer_ptr[rb->write_index], ptr, length);
/* this should not cause overflow because there is enough space for
* length of data in current mirror */
rb->write_index += length;
return length;// 返回写入数据的长度
}
/* two-time write */
memcpy(&rb->buffer_ptr[rb->write_index],
&ptr[0],
rb->size - rb->write_index);
memcpy(&rb->buffer_ptr[0],
&ptr[rb->size - rb->write_index],
length - (rb->size - rb->write_index));
/* we are going into the other side of the mirror */
rb->write_mirror = ~rb->write_mirror;
rb->write_index = length - (rb->size - rb->write_index);
return length;
}
// 强制往 ringbuff 写入数据
uint16 rb_put_force(ringbuff *rb,const uint8 *ptr,uint16 length) {
uint16 space_length = 0;
space_length = rb_space_len(rb);
// cout<<"ptr: "<<ptr<<endl;
// cout<<"space_length: "<<space_length<<endl;
// cout<<"length: "<<length<<endl;
if (length > space_length) {
ptr = &ptr[length - rb->size];
length = rb->size;
}
// cout<<"ptr: "<<ptr<<endl;
// cout<<"length: "<<length<<endl;
if (rb->size - rb->write_index > length)
{
// cout<<"lailailailai"<<endl;
/* read_index - write_index = empty space */
memcpy(&rb->buffer_ptr[rb->write_index], ptr, length);
/* this should not cause overflow because there is enough space for
* length of data in current mirror */
rb->write_index += length;
if (length > space_length)
rb->read_index = rb->write_index;
return length;
}
memcpy(&rb->buffer_ptr[rb->write_index],
&ptr[0],
rb->size - rb->write_index);
memcpy(&rb->buffer_ptr[0],
&ptr[rb->size - rb->write_index],
length - (rb->size - rb->write_index));
/* we are going into the other side of the mirror */
rb->write_mirror = ~rb->write_mirror;
rb->write_index = length - (rb->size - rb->write_index);
if (length > space_length)
{
rb->read_mirror = ~rb->read_mirror;
rb->read_index = rb->write_index;
}
return length;
}
// 从 ringbuff 获取数据
uint16 rb_get(ringbuff *rb,uint8 *ptr,uint16 length) {
uint16 size = 0;
/* The length of the existing data in the buffer */
size = rb_data_len(rb);
/* no data */
if (size == 0)
return 0;
/* less data */
if (size < length)
length = size;
cout<<"size: "<<size<<" < "<<"length: " << length<<(size < length)<<endl;
if (rb->size - rb->read_index > length)
{
/* copy all of data */
memcpy(ptr, &rb->buffer_ptr[rb->read_index], length);
/* this should not cause overflow because there is enough space for
* length of data in current mirror */
rb->read_index += length;
return length;
}
memcpy(&ptr[0],
&rb->buffer_ptr[rb->read_index],
rb->size - rb->read_index);
memcpy(&ptr[rb->size - rb->read_index],
&rb->buffer_ptr[0],
length - (rb->size - rb->read_index));
/* we are going into the other side of the mirror */
rb->read_mirror = ~rb->read_mirror;
rb->read_index = length - (rb->size - rb->read_index);
return length;
}
// 往 ringbuff 中写入一个字符
uint16 rb_putchar(ringbuff *rb, const uint8 ch) {
/* whether has enough space */
if (!rb_space_len(rb)) // 没有足够的空间就直接返回了
return 0;
rb->buffer_ptr[rb->write_index] = ch;// 把这个字符写入到缓冲区的指定位置
/* flip mirror */
if (rb->write_index == rb->size-1) {// 检查写入这个字符后,当前镜像是否写满
rb->write_mirror = ~rb->write_mirror;// 翻转镜像
rb->write_index = 0;// 设置下标为0
}else{
rb->write_index++; // 下标加1
}
return 1;// 写入一个字符,返回 1
}
// 往 ringbuff 强制写入一个字符
uint16 rb_putchar_force(ringbuff *rb, const uint8 ch) {
enum rb_state old_state = rb_status(rb);// 获取状态
rb->buffer_ptr[rb->write_index] = ch;// 写入数据
/* flip mirror */
if (rb->write_index == rb->size-1) {// 检查当前镜像是不是满了
rb->write_mirror = ~rb->write_mirror; // 翻转写镜像
rb->write_index = 0;// 翻转之后设置下标为 0
if (old_state == RINGBUFFER_FULL) {// 如果 ringbuff 的状态是满
rb->read_mirror = ~rb->read_mirror; // 翻转读镜像
rb->read_index = rb->write_index; // 设置读下标和写下标一致
}
}else{
rb->write_index++; // 写下标加1
if (old_state == RINGBUFFER_FULL)
rb->read_index = rb->write_index;// 如果满,设置读下标等于写下标
}
return 1; // 写入一个字符,返回1
}
// 从ringbuff 获取一个字符
uint16 rb_getchar(ringbuff *rb,uint8 *ch) {
/* ringbuffer is empty */
if (!rb_data_len(rb)) // 检查 ringbuff 是否为空
return 0;
/* put character */
*ch = rb->buffer_ptr[rb->read_index];// 获取当前读下标的数据
if (rb->read_index == rb->size-1) {// 如果
RT-Thread 环形缓冲区
需积分: 0 87 浏览量
更新于2023-08-22
收藏 4KB RAR 举报
镜像指示位:缓冲区的长度如果是n,逻辑地址空间则为0至n-1;那么,规定n至2n-1为镜像逻辑地址空间。本策略规定读写指针的地址空间为0至2n-1,其中低半部分对应于常规的逻辑地址空间,高半部分对应于镜像逻辑地址空间。当指针值大于等于2n时,使其折返(wrapped)到ptr-2n。使用一位表示写指针或读指针是否进入了虚拟的镜像存储区:置位表示进入,不置位表示没进入还在基本存储区。
在读写指针的值相同情况下,如果二者的指示位相同,说明缓冲区为空;如果二者的指示位不同,说明缓冲区为满。这种方法优点是测试缓冲区满/空很简单;不需要做取余数操作;读写线程可以分别设计专用算法策略,能实现精致的并发控制。缺点是读写指针各需要额外的一位作为指示位。
如果缓冲区长度是2的幂,则本方法可以省略镜像指示位。如果读写指针的值相等,则缓冲区为空;如果读写指针相差n,则缓冲区为满,这可以用条件表达式(写指针==(读指针异或缓冲区长度))来判断。
----(来自百度百科)
呵呵哒( ̄▽ ̄)"
- 粉丝: 2w+
- 资源: 12
最新资源
- python进阶篇27-高性能的多线程网络资源访问.avi
- 利用WIFI实现数据的高速分享APP-毕业设计.zip
- python进阶篇28-高性能的多线程网络资源访问第二节.avi
- python进阶篇29-http相关讲解.avi
- 2006-2020年各省单位GDP能耗增速数据
- python进阶篇30-wsgi讲解.avi
- 英语学习 App 毕业设计.zip
- python进阶篇32-综合习题讲解.avi
- abaqus PCB板钻削加工仿真 铜箔+纤维复合材料+铜箔建模 铜箔采用J-C本构 纤维复合材料可采用二维壳单元hashin准则 也可以采用三维hashin子程序,实体单元
- python进阶篇33-进阶项目讲解第二节.avi
- python进阶篇34-项目讲解第三节.avi
- python语言toutiao爬虫程序代码QZQ.txt
- python语言tukutupian爬虫程序代码QZQ.txt
- python语言gushi爬虫程序代码QZQ.txt
- python语言wenbenxiaoshuo爬虫程序代码QZQ1.txt
- python语言wenbenxiaoshuo爬虫程序代码QZQ.txt