数据在两个线程之间传递。按说是很简单的功能,但合用的C库还不太好找。
找了一下,看到合适一点的库也是GPL的,不太适合我用在闭源工程中,于是自己重新写了一个简单的,以LGPL方式发行。
功能比较简单,数据分块,每次读或写一个块。
块大小和块数量在ringbuffer初始化时设定。
同时仅支持一个reader和一个writer。
测试环境:
ARM Linux, gcc 4.1.1, uClibc
代码附在后面,其使用方法:
initialize:
rb_t *rbuf = rb_open(chunk_size, chunk_count);
reader:
while(rb_read_ok(rb,buf)==false){
idle_task();
}
writer:
while(rb_write_ok(rb,buf)==false){
idle_task();
}
deinitialize:
rb_close(rbuf);
ringbuf.h:
#pragma once
#include <stdint.h>
#include <stdbool.h>
struct rb_s;
typedef struct rb_s rb_t;
rb_t *rb_open(unsigned int size, unsigned int count);
void rb_reset(rb_t *rb);
void rb_close(rb_t *rb);
bool rb_writable(rb_t *rb);
bool rb_readable(rb_t *rb);
bool rb_write_ok(rb_t *rb, const void *data);
bool rb_read_ok(rb_t *rb, void *buf);
ringbuf.c:
#include <malloc.h>
#include <string.h>
#include "ringbuf.h"
struct rb_s{
unsigned int size;
unsigned int count;
unsigned int rptr, wptr;
unsigned char *buf;
};
rb_t *rb_open(unsigned int size, unsigned int count)
{
rb_t *rb = calloc(1, sizeof(rb_t));
rb->buf = calloc(count, size);
if(rb->buf==NULL){
free(rb);
return NULL;
}
rb->size = size;
rb->count = count;
return rb;
}
void rb_reset(rb_t *rb)
{
rb->wptr = 0;
rb->rptr = 0;
}
void rb_close(rb_t *rb)
{
if(rb){
free(rb->buf);
memset(rb,0, sizeof(rb_t));
free(rb);
}
}
bool rb_writable(rb_t *rb)
{
unsigned int wptr = rb->wptr;
wptr++;
if(wptr>=rb->count) wptr = 0;
if(wptr == rb->rptr) return false;
return true;
}
bool rb_readable(rb_t *rb)
{
if(rb->wptr==rb->rptr) return false;
return true;
}
bool rb_write_ok(rb_t *rb, const void *data)
{
if(rb_writable(rb)){
memcpy(rb->buf+rb->size*rb->wptr,data, rb->size);
rb->wptr++;
if(rb->wptr == rb->count) rb->wptr = 0;
return true;
}
return false;
}
bool rb_read_ok(rb_t *rb, void *buf)
{
if(rb_readable(rb)){
memcpy(buf, rb->buf+rb->size*rb->rptr, rb->size);
rb->rptr++;
if(rb->rptr == rb->count) rb->rptr = 0;
return true;
}
return false;
}
没有评论:
发表评论