头文件ring_buffer.h
#ifndef _RING_BUF_H_
#define _RING_BUF_H_
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#define MAX_SIZE 200
/* ring buffer structure */
struct ring_buf
{
size_t depth ; /* maximum element number */
size_t width ; /* sizeof each element */
size_t read;
size_t write;
size_t r_msb;
size_t w_msb;
void *buf;
};
typedef struct ring_buf ring_buf_t;
typedef struct ring_buf* ring_buf_p;
bool ring_buf_init (ring_buf_p rbuf, size_t depth, size_t width);
void ring_buf_free (ring_buf_p rbuf);
void ring_buf_clear(ring_buf_p rbuf);
bool ring_buf_full (ring_buf_p rbuf);
bool ring_buf_empty(ring_buf_p rbuf);
bool ring_buf_write(ring_buf_p rbuf, void *wr_data);
bool ring_buf_read (ring_buf_p rbuf, void *rd_data);
void *ring_buf_get(ring_buf_p rbuf);
void ring_buf_commit_read(ring_buf_p rbuf);//必须和ring_buf_get连着用,减少一次数据拷贝
#endif
ring_buffer.c源文件
#include "ring_buffer.h"
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <act_debug.h>
bool ring_buf_init(ring_buf_p rbuf, size_t depth, size_t width)
{
assert(depth > 0 && depth <= MAX_SIZE && width > 0);
rbuf->depth = depth;
rbuf->width = width;
rbuf->read = 0;
rbuf->write = 0;
rbuf->r_msb = 0;
rbuf->w_msb = 0;
rbuf->buf = calloc(depth, width);
return rbuf->buf != NULL;
}
void ring_buf_free(ring_buf_p rbuf)
{
free(rbuf->buf);
rbuf->buf = NULL;
}
void ring_buf_clear(ring_buf_p rbuf)
{
rbuf->read = 0;
rbuf->write = 0;
rbuf->r_msb = 0;
rbuf->w_msb = 0;
}
bool ring_buf_is_empty(ring_buf_p rbuf)
{
return rbuf->read == rbuf->write && rbuf->r_msb == rbuf->w_msb;
}
bool ring_buf_is_full(ring_buf_p rbuf)
{
return rbuf->read == rbuf->write && rbuf->r_msb != rbuf->w_msb;
}
inline void ring_buf_incr(ring_buf_p rbuf, size_t *p_idx,size_t *msb)
{
*p_idx = *p_idx + 1;
if (*p_idx == rbuf->depth) {
*msb ^= 1;
*p_idx = 0;
}
}
bool ring_buf_write(ring_buf_p rbuf, void *wr_data)
{
//printf("ring_buf_write\n");
if (ring_buf_is_full(rbuf)) {
print_dbg("ring buffer is full\n");
return false;
}
else {
//print_dbg("ring_buf_write %d\n",rbuf->width);
memcpy(rbuf->buf + rbuf->write * rbuf->width, wr_data, rbuf->width);
ring_buf_incr(rbuf, &rbuf->write,&rbuf->w_msb);
return true;
}
}
bool ring_buf_read(ring_buf_p rbuf, void *rd_data)
{
if (ring_buf_is_empty(rbuf)) {
print_dbg("ring buffer is empty\n");
return false;
}
else {
memcpy(rd_data, rbuf->buf + rbuf->read * rbuf->width, rbuf->width);
ring_buf_incr(rbuf, &rbuf->read,&rbuf->r_msb);
return true;
}
}
void *ring_buf_get(ring_buf_p rbuf)
{
//printf("ring_buf_get\n");
void *buffer = NULL;
if (ring_buf_is_empty(rbuf)) {
print_dbg("ring buffer is empty\n");
return NULL;
}
else {
//print_dbg("ring_buf_get %d\n",rbuf->width);
buffer = rbuf->buf + rbuf->read* rbuf->width;
return (void *)buffer;
}
}
void ring_buf_commit_read(ring_buf_p rbuf)
{
//printf("ring_buf_commit_read \n");
ring_buf_incr(rbuf, &rbuf->read,&rbuf->r_msb);
return;
}
使用实例main.c
#include <stdio.h>
#include "ring_buffer.h"
int main()
{
static ring_buf_t rb;
char *buf;
if(ring_buf_init(&rb,MAX_SIZE,SIMPLE_SIZE*sizeof(short)) == false)
{
printf("ring buffer init fail\n");
return NULL;
}
/*可以在一个线程中不停的往ring-buffer中写数据*/
// 从data_buffer中读取数据到rb
if(ring_buf_write(&rb,data_buffer) == false)
{
printf("ring_buffer is full1!\n")
}
/*可以在另一个线程中不停地从ring-buffer读数据*/
while(true)
{
buf = ring_buf_get(&rb);//从ring_buffer中读数据出来
if(buf == NULL) {
usleep(10);
continue;
}
ring_buf_commit_read(&rb);
}
//if(rb.buf)
//ring_buf_clear(&rb); //清空ring_buffer
//使用完记得释放资源
ring_buf_free(&rb);
}