循环缓冲实现(ring buffer/circular buffer)

/****************************************************************************************************
*
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);

ringbuffer.h

#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;
}

ringbuffer.c

循环缓冲实现(ring buffer/circular buffer)

时间: 2024-10-05 06:59:02

循环缓冲实现(ring buffer/circular buffer)的相关文章

C语言创建循环缓冲区(环形缓冲区)-- Circular Buffer(Ring Buffer)

由于嵌入式系统的资源有限性,循环缓冲区数据结构体(Circular Buffer Data Structures)被大量的使用. 循环缓冲区(也称为环形缓冲区)是固定大小的缓冲区,工作原理就像内存是连续的且可循环的一样.在生成和使用内存时,不需将原来的数据全部重新清理掉,只要调整head/tail 指针即可.当添加数据时,head 指针前进.当使用数据时,tail 指针向前移动.当到达缓冲区的尾部时,指针又回到缓冲区的起始位置. 目录: 为什么使用循环缓冲区 C 实例 使用封装 API设计 确认

The Bip Buffer - The Circular Buffer with a Twist

Introduction The Bip-Buffer is like a circular buffer, but slightly different. Instead of keeping one head and tail pointer to the data in the buffer, it maintains two revolving regions, allowing for fast data access without having to worry about wra

Circular buffer

前言: A circular buffer, cyclic buffer or ring buffer is a data structure that uses a single, fixed-size buffer as if it were connected end-to-end. This structure lends itself easily to buffering data streams. Uses The useful property of a circular buf

buffer cache —— buffer busy waits/read by other session

oracle提供非常精确.有效的row level lock机制,多个用户同时修改数据时,为了保护数据,以块为单位挂起锁的情况不会发生.但这不太正确.以块为单位的锁虽然不存在,但正因为oracle I/O以块为单位组成,所以块单位锁是必要的.假设row1.row2两个行位于同一个块内,两名用户(用户1.用户2)各自对row1.row2执行update,逻辑上两个被更新行之间不存在需要相互保护的数据.因为oracle提供row level lock机制,所以修改互相不用的行完全不成问题.但是若两个

insert buffer/change buffer double write buffer,双写 adaptive hash index(AHI) innodb的crash recovery innodb重要参数 innodb监控

https://yq.aliyun.com/articles/41000 http://blog.itpub.net/22664653/viewspace-1163838/ http://www.cnblogs.com/MYSQLZOUQI/p/5602206.html https://yq.aliyun.com/articles/222 主从不一致性的3种可能原因1.binlog format是不是row2.session级关闭binlog3.人工在slave修改数据 set sql_log_

dtrace.org

http://dtrace.org/blogs/rm/2016/09/15/turtles-on-the-wire-understanding-how-the-os-uses-the-modern-nic/ Turtles on the Wire: Understanding how the OS uses the Modern NIC The modern networking card (NIC) has evolved quite a bit from the simple Etherne

圆形缓冲区(循环buffer)实现

用法 圆形缓冲区的一个有用特性是:当一个数据元素被用掉后,其余数据元素不需要移动其存储位置.相反,一个非圆形缓冲区(例如一个普通的队列)在用掉一个数据元素后,其余数据元素需要向前搬移.换句话说,圆形缓冲区适合实现先进先出缓冲区,而非圆形缓冲区适合后进先出缓冲区. 圆形缓冲区适合于事先明确了缓冲区的最大容量的情形.扩展一个圆形缓冲区的容量,需要搬移其中的数据.因此一个缓冲区如果需要经常调整其容量,用链表实现更为合适. 写操作覆盖圆形缓冲区中未被处理的数据在某些情况下是允许的.特别是在多媒体处理时.

Muduo 设计与实现之一:Buffer 类的设计

[开源访谈]Muduo 作者陈硕访谈实录 http://www.oschina.net/question/28_61182 开源访谈是开源中国推出的一系列针对国内优秀开源软件作者的访谈,以文字的方式记录并传播.我们希望开源访谈能全面的展现国内开源软件.开源软件作者的现状,着实推动国内开源软件的应用与发展. [嘉宾简介] 陈硕 北京师范大学硕士,擅长 C++ 多线程网络编程和实时分布式系统架构.现任职于香港某跨国金融公司 IT 部门,从事实时外汇交易系统开发.编写了开源 C++ 网络库 muduo

如何设定ASH buffer大小

Ash Buffer是SGA里的一块循环使用的内存区域,用于存放MMON捕捉到的active session信息,MMNL每隔60min将Ash buffer的内容经过过滤后dump到AWR,对应的视图是DBA_HIST_ACTIVE_SESS_HISTORY,以腾出Ash buffer空间用于之后的采集.Ash Buffer的大小在instance启动时就已经决定了,并且在instance运行期间不能被动态调整,那么Ash Buffer的大小是由哪些因素决定的? 关于ASH buffer的大小