[LAD] a *simple* ring buffer, comments pls?

James Morris jwm.art.net at gmail.com
Thu Jul 7 12:10:13 UTC 2011


just wondered if any more-experienced-than-i devs might comment on
this. written in c for c (obviously). i realize it's not portable
outside of GNU GCC (regarding the GCC atomic builtin funcs
__sync_***). meant for a single reader thread and a single writer
thread. comments regarding thread safety very much welcome. thanks in
advance.

james.



#include "rng_buf.h" /* only prototypes the public functions and
typedefs the struct */

#include <stdlib.h>
#include <string.h>
#include "debug.h"


struct _RingBuffer
{
    size_t count;

    void** buf;
    void** bufend;

    void** volatile w;
    void** volatile r;
};


RngBuf* rng_buf_new(size_t count)
{
    size_t sz = 1;
    RngBuf* mb = malloc(sizeof(RngBuf));

    if (!mb)
    {
        return 0;
    }

    for (sz = 1; sz < count; sz <<= 1)
        ;

    mb->buf = calloc(sz, sizeof(void*));

    if (!mb->buf)
    {
        free(mb);
        return 0;
    }

    mb->count = sz;
    mb->bufend = mb->buf + mb->count - 1;
    mb->w = mb->buf;
    mb->r = mb->buf;

    return mb;
}


void rng_buf_free(RngBuf* mb)
{
    free(mb->buf);
    free(mb);
}


size_t rng_buf_write(RngBuf* mb, const void* data)
{
    if (__sync_bool_compare_and_swap(mb->w, 0, data))
    {
        if (!(__sync_bool_compare_and_swap(&mb->w, mb->bufend, mb->buf)))
            __sync_add_and_fetch(&mb->w, sizeof(void*));

        return (size_t)1;
    }

    return (size_t)0;
}


void* rng_buf_read(RngBuf* mb)
{
    void* data;

    if ((data = __sync_fetch_and_and(mb->r, 0)))
    {
        if (!__sync_bool_compare_and_swap(&mb->r, mb->bufend, mb->buf))
            __sync_add_and_fetch(&mb->r, sizeof(void*));

        return data;
    }

    return NULL;
}


void rng_buf_reset(RngBuf* mb)
{ /* needs work */
    mb->r = mb->w = mb->buf;
}



More information about the Linux-audio-dev mailing list