1. 程式人生 > >循環緩沖實現(ring buffer/circular buffer)

循環緩沖實現(ring buffer/circular buffer)

得到 讀取數據 增加 下標 emp pty 既然 destroy div

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

循環緩沖實現(ring buffer/circular buffer)