博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
循环缓冲实现(ring buffer/circular buffer)
阅读量:4318 次
发布时间:2019-06-06

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

/****************************************************************************************************

* buf : 存放数据的缓冲区地址
* size: 缓冲区的大小(必须是2的幂)
* in :写指针下标
* out :读指针下标
* 缓冲区模型如下:size固定大小,in的值始终大于等于out的值
* 先从ringbuf->in到缓冲区末端写数据,如果还没写完,再从缓冲区头开始写入剩下的,从而实现了循环缓冲。
* +--------------+(in)-----------------+(size)
* +
* +-----+(out)-------------------------+
* 那么可用的缓冲空间大小就是(size - in + out)
* 所以写数据时
* 1.先从length和(ringbuf->size - ringbuf->in + ringbuf->out)之间取一个较小的值赋给length
* 2.再判断缓冲区的末端(buffer->size - (buffer->in & (buffer->size - 1)))大小是否够保存length的数据给len
* 3.拷贝len长度的数据到缓冲区的末端 memcpy(buffer->buf + (buffer->in & (buffer->size - 1)), data, len);
* 4.再拷贝剩下的数据到缓冲区的前端 memcpy(buffer->buf, data + len, length - len); 如果length - len为0则无操作。
* 5.写指针的下标增加length长度。
* 6.返回实际写入缓冲区的长度。
*
* 读取数据:
* 1.数据量的大小由(buffer->in - buffer->out)决定
* amount和(buffer->in - buffer->out)取小值给amount,作为一次读取的数据大小
* 2.尾部缓冲数据大小由(buffer->size - (buffer->out & (buffer->size - 1)))决定
* 判断尾部数据和总需求数据大小,取小值给len
* 3.先拷贝尾部缓冲的数据到目的memcpy(target, buffer->buf + (buffer->out & (buffer->size - 1)), len);
* 4.再拷贝头部缓冲数据 memcpy(target + len, buffer->buf, amount - len); amount - len为0则无操作。
* 5.读指针的下标增加amount大小
* 6.返回实际读取的数据大小。
* 注意:
* 当(ringbuf->in == ringbuf->out + ringbuf->size)即(ringbuf->in == ringbuf->out + ringbuf->size)时,表示缓冲区已满.
* 此时得到的较小值一定是0,后面实际写入的字节数也全为0。
*
* 既然ringbuf->size是2的幂,那么(ringbuf->size-1)也就是一个除最高位为0,其余二进制位都为1的一个数值
* 也就能保证(ringbuf->in & (ringbuf->size - 1))不会超过(ringbuf->size - 1),和(ringbuf->in)%(ringbuf->size - 1)的效果一样
* 从上面可以看出,ringbuf->in的值可以从0变化到超过fifo->size的数值,还要注意的是数据类型的翻转问题
* ringbuf->out也如此,但它们的差不会超过ringbuf->size。
****************************************************************************************************/

可参考文件

 

 

typedef struct cycle_buffer { unsigned char* buf;unsigned int size;unsigned int in;unsigned int out;}RingBuffer;RingBuffer *RingBuffer_create(int length);void RingBuffer_destroy(RingBuffer *buffer);int RingBuffer_read(RingBuffer *buffer, char *target, int amount);int RingBuffer_write(RingBuffer *buffer, char *data, int length);int RingBuffer_empty(RingBuffer *buffer);int RingBuffer_Reset(RingBuffer *buffer);

 

#define min(x, y) ((x) < (y) ? (x) : (y))#define ROUND_UP_2(num) (((num)+1)&~1)#define DEFAULT_BUF_SIZE (2*1024*1024)RingBuffer *RingBuffer_create(int length){unsigned int size = ROUND_UP_2(length);if ( (size&(size-1)) || (size < DEFAULT_BUF_SIZE) ){size = DEFAULT_BUF_SIZE;}RingBuffer *buffer = (RingBuffer *)malloc(sizeof(RingBuffer)); if (!buffer) {return NULL; }memset(buffer, 0, sizeof(RingBuffer)); buffer->size = size; buffer->in = 0;buffer->out = 0; buffer->buf = (unsigned char *)malloc(size); if (!buffer->buf){free(buffer);return NULL;}memset(buffer->buf, 0, size);return buffer;}void RingBuffer_destroy(RingBuffer *buffer){if(buffer) {free(buffer->buf);free(buffer);}}int RingBuffer_Reset(RingBuffer *buffer){if (buffer == NULL){return -1;}buffer->in = 0;buffer->out = 0;memset(buffer->buf, 0, buffer->size);return 0;}int RingBuffer_empty(RingBuffer *buffer){return buffer->in == buffer->out;}int RingBuffer_write(RingBuffer *buffer, char *data, int length){unsigned int len = 0;length = min(length, buffer->size - buffer->in + buffer->out); len = min(length, buffer->size - (buffer->in & (buffer->size - 1)));memcpy(buffer->buf + (buffer->in & (buffer->size - 1)), data, len);memcpy(buffer->buf, data + len, length - len);buffer->in += length;return length;}int RingBuffer_read(RingBuffer *buffer, char *target, int amount){unsigned int len = 0;amount = min(amount, buffer->in - buffer->out);len = min(amount, buffer->size - (buffer->out & (buffer->size - 1)));memcpy(target, buffer->buf + (buffer->out & (buffer->size - 1)), len);memcpy(target + len, buffer->buf, amount - len);buffer->out += amount;return amount;}

 

转载于:https://www.cnblogs.com/citroen/p/9955972.html

你可能感兴趣的文章
记一次CentOS7进单用户模式修改密码的失败经历(faild to load SELinux policy freezing)...
查看>>
shh整合后web.xml、spring配置文件和struts.xml的内容
查看>>
ExportToExcel SharePointSolutionInstaller
查看>>
C# 发送邮件内容嵌入图片
查看>>
HMACSHA512
查看>>
C#实现office文档转换为PDF或xps
查看>>
关于MVC整理
查看>>
etcd使用经历
查看>>
力扣 报错 runtime error: load of null pointer of type 'const int'
查看>>
angular_directive的controllerAs
查看>>
Ubuntu下修改为永久DNS的方法
查看>>
BabeLua常见问题
查看>>
Javascript 中 == 和 === 区别是什么?
查看>>
conductor 事件处理程序
查看>>
C#设计模式——小结
查看>>
文件修改等
查看>>
阅读后提问
查看>>
SQL 基本(Head First)
查看>>
由函数clock想到的
查看>>
SQL Server常用语句
查看>>