环形缓冲队列(RingBuffer),自己写的靠谱的代码

===== ring_buffer.h =====

#ifndef __RING_BUFFER_H__
#define __RING_BUFFER_H__


#include
#include
#include
#include
#include
#include
#include


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

你可能感兴趣的:(C语言基础工具)