zoukankan      html  css  js  c++  java
  • 循环缓冲实现(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
  • 相关阅读:
    1053: 正弦函数
    1052: 数列求和4
    1051: 平方根的和
    1050: 阶乘的累加和
    POJ 1321 棋盘问题(搜索的方式)
    HDU 1176 免费馅饼
    BZOJ 2423 (求LCS的长度和种类数)
    HDU 2612 (2次BFS,有点小细节)
    POJ 1088 滑雪(模板题 DFS+记忆化)
    HRBUST 1186 青蛙过河 (思路错了)
  • 原文地址:https://www.cnblogs.com/eric-geoffrey/p/3772779.html
Copyright © 2011-2022 走看看