http://blog.csdn.net/csseikocs/article/details/50790085
===== ring_buffer.h =====
#ifndef __RING_BUFFER_H__
#define __RING_BUFFER_H__
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <assert.h>
#include <string.h>
#include <inttypes.h>
#include <pthread.h>
typedef struct ringbuffer_s
{
int64_t mBufferSize;
char *mBuffer;
char *mBuffer_end;
char *wp;
char *rp;
pthread_mutex_t *mLock;
} ringbuffer_t;
ringbuffer_t* init_ringbuffer(int buff_size);
void free_ringbuffer(ringbuffer_t *rb);
int write_ringbuffer(ringbuffer_t *rb, uint8_t *buf, int size);
int read_ringbuffer(ringbuffer_t *rb, uint8_t *buf, int size);
int64_t space_ringbuffer(ringbuffer_t *rb);
void reset_ringbuffer(ringbuffer_t *rb);
#endif
===== ring_buffer.c
#include "ring_buffer.h"
//#define min(x, y) ({ \
// typeof(x) _min1 = (x); \
// typeof(y) _min2 = (y); \
// (void) (&_min1 == &_min2); \
// _min1 < _min2 ? _min1 : _min2; })
#define min(a, b) (((a) < (b)) ? (a) : (b))
pthread_mutex_t fastmutex = PTHREAD_MUTEX_INITIALIZER;
ringbuffer_t* init_ringbuffer(int buff_size)
{
ringbuffer_t *rb = (ringbuffer_t *)malloc(sizeof(ringbuffer_t));
if (NULL == rb) {
LOGE("err: %s(),%d \n", __FUNCTION__, __LINE__);
return NULL;
}
memset(rb, 0, sizeof(ringbuffer_t));
rb->mBufferSize = buff_size;
rb->mBuffer = (char *) malloc(rb->mBufferSize);
if (NULL == rb->mBuffer) {
free(rb);
LOGE("err: %s(),%d \n", __FUNCTION__, __LINE__);
return NULL;
}
LOGV("===== RingBuffer: Allocated %lld - %08X(bytes) for ring buffer pool\n", rb->mBufferSize, rb->mBufferSize);
rb->mBuffer_end = rb->mBuffer + rb->mBufferSize;
rb->wp = rb->rp = rb->mBuffer;
rb->mLock = &fastmutex;
return rb;
}
void free_ringbuffer(ringbuffer_t *rb)
{
if (rb && rb->mBuffer) {
free(rb->mBuffer);
free(rb);
}
}
void reset_ringbuffer(ringbuffer_t *rb)
{
LOGV("RingBuffer: reset()\n");
pthread_mutex_lock(rb->mLock);
rb->rp = rb->mBuffer;
rb->wp = rb->mBuffer;
pthread_mutex_unlock(rb->mLock);
LOGV("RingBuffer: reset() done\n");
}
int64_t space_ringbuffer(ringbuffer_t *rb)
{
if (rb->rp == rb->wp)
return rb->mBufferSize - 1;
else
return ((rb->rp + rb->mBufferSize - rb->wp) % rb->mBufferSize) - 1;
}
int write_ringbuffer(ringbuffer_t *rb, uint8_t *buf, int size)
{
int64_t count = 0;
int64_t space = 0;
pthread_mutex_lock(rb->mLock);
space = space_ringbuffer(rb);
if (space > 0) {
/* OK, space is there, accept something */
count = min((int64_t) size, space);
if (rb->wp >= rb->rp)
count = min(count, (int64_t) (rb->mBuffer_end - rb->wp));
else
count = min(count, (int64_t) (rb->rp - rb->wp - 1));
//LOGV("Going to accept %lld bytes to wp: %d rp: %d", count,
// (size_t) (rb->wp - rb->mBuffer), (size_t)(rb->rp - rb->mBuffer));
memcpy(rb->wp, buf, count);
rb->wp += (size_t) count;
if (rb->wp == rb->mBuffer_end) {
LOGV("[Status]: ring buffer wp wrapped(%lld - %x) count=%lld\n",
(int64_t)(rb->wp - rb->mBuffer), (int64_t)(rb->wp - rb->mBuffer), count);
rb->wp = rb->mBuffer; /* wrapped */
}
}
pthread_mutex_unlock(rb->mLock);
return count;
}
int read_ringbuffer(ringbuffer_t *rb, uint8_t *buf, int size)
{
int64_t count = size;
pthread_mutex_lock(rb->mLock);
if (rb->rp == rb->wp) {
pthread_mutex_unlock(rb->mLock);
//LOGV("Caching: buffer is empty!");
//usleep(DEF_SLEEP_TIME);
return 0;
}
/* OK, data is there, return something */
if (rb->wp > rb->rp)
count = min(count, (int64_t) (rb->wp - rb->rp));
else
count = min(count, (int64_t) (rb->mBuffer_end - rb->rp));
memcpy(buf, rb->rp, count);
rb->rp += count;
if (rb->rp == rb->mBuffer_end) {
LOGV("[Status]: RingBuffer rp wrapped(%lld-%x) count=%lld\n",
(int64_t)(rb->rp - rb->mBuffer),
(int64_t)(rb->rp - rb->mBuffer), count);
rb->rp = rb->mBuffer; /* wrapped */
}
//LOGV("read %d bytes for cache, rp:%d wp:%d",
// count, (size_t)(rb->rp - rb->mBuffer),
// (size_t)(rb->wp - rb->mBuffer));
pthread_mutex_unlock(rb->mLock);
return count;
}