- Back to Home »
- Programming techniques »
- Ring buffer
Sunday, June 28, 2015
1. Cấu trúc
2. Nguyên lý làm việc
3. Cách sử dụng
A single process/thread to process/thread buffer use case
Multiple processes/thread to process/thread use case
Single process/thread to multiple processes/thread use case
Single process/thread to multiple process/thread use case using a dispatcher and multiple queues
4. Source code sample
ringbufer.h
#ifndef RINGBUFFER_H
#define RINGBUFFER_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stddef.h>
#include <stdbool.h>
/*
* ringbuffer.h - C ring buffer (FIFO) interface.
*/
typedef struct ringbuffer_t
{
void *buffer; // data buffer
void *buffer_end; // end of data buffer
size_t capacity; // maximum number of items in the buffer
size_t count; // number of items in the buffer
size_t sz; // size of each item in the buffer
void *head; // pointer to head
void *tail; // pointer to tail
} ringbuffer_t;
bool ring_init(ringbuffer_t *cb, size_t capacity, size_t sz);
bool ring_free(ringbuffer_t *cb);
bool ring_push_head(ringbuffer_t *cb, const void *item);
bool ring_pop_tail(ringbuffer_t *cb, void *item);
#ifdef __cplusplus
}
#endif
#endif /* RINGBUFFER_H */
ringbuffer.c
#include "ringbuffer.h"
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
bool ring_init(ringbuffer_t *cb, size_t capacity, size_t sz)
{
cb->buffer = malloc(capacity * sz);
if(cb->buffer == NULL){
printf("ring_init FAIL ! \n");
return false;
}
cb->buffer_end = (char *)cb->buffer + capacity * sz;
cb->capacity = capacity;
cb->count = 0;
cb->sz = sz;
cb->head = cb->buffer;
cb->tail = cb->buffer;
return true;
}
bool ring_free(ringbuffer_t *cb)
{
if(cb->buffer){
free(cb->buffer);
cb->buffer = NULL;
}else{
return false;
}
return true;
}
bool ring_push_head(ringbuffer_t *cb, const void *item)
{
if(cb->count == cb->capacity){
printf("Ringbuffer is Full ! \n");
return false;
}
memcpy(cb->head, item, cb->sz);
cb->head = (char*)cb->head + cb->sz;
if(cb->head == cb->buffer_end)
cb->head = cb->buffer;
cb->count++;
return true;
}
bool ring_pop_tail(ringbuffer_t *cb, void *item)
{
if(cb->count == 0){
printf("Ringbuffer is Empty ! \n");
return false;
}
memcpy(item, cb->tail, cb->sz);
cb->tail = (char*)cb->tail + cb->sz;
if(cb->tail == cb->buffer_end)
cb->tail = cb->buffer;
cb->count--;
return true;
}
ringbuffer_test.c
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "ringbuffer.h"
#define CAPACITY 10
typedef struct data_t{
int idata;
float fdata;
}data_t;
ringbuffer_t ringbf;
int main(int argc, char **argv)
{
ring_init(&ringbf, CAPACITY, sizeof(data_t));
int i;
data_t tmpdata;
for(i = 0; i < CAPACITY; i++){
tmpdata.idata = i;
tmpdata.fdata = i+1;
ring_push_head(&ringbf, (void*)&tmpdata);
printf("number of items: %d \n", ringbf.count);
}
for(i = 0; i < CAPACITY; i++){
ring_pop_tail(&ringbf, (void*)&tmpdata);
printf("number of items: %d, idata: %d, fdata: %f \n", ringbf.count, tmpdata.idata, tmpdata.fdata);
}
ring_free(&ringbf);
return 0;
}
Good jpb
ReplyDelete