[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