On 11 July 2011 20:19, Olivier Guilyardi <list(a)samalyse.com> wrote:
Good catch... Multi-core ARM devices are actually
arriving massively. With
Android, there's the Motorola Atrix, the Samsung Galaxy S II, etc..
What about my toaster? :-P
I've ended up going back to Fons's pragmatism. If
non-blocking/lock-free programming is so impossibly difficult,
requiring intimate hardware knowledge of numerous different
architectures then there's only one solution available to people like
me, and that's to code for AMD64/Intel and use the existing ringbuffer
implementations.
I'd be interested though if my usage of __sync_bool_compare_and_swap
and __sync_fetch_and_and improves the ring buffer at all? I like the
fact the implementation I'm using is so simple. Trouble is, using the
GCC builtins instead of volatile slows it down. Guess that means it's
duff.
James.
----------------8<-------------------------
#include "rng_buf.h"
#include <stdlib.h>
#include <string.h>
struct _RingBuffer
{
void** buf;
void** bufend;
void** w;
void** 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->bufend = mb->buf + sz - 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))
{
mb->w = (mb->w == mb->bufend) ? mb->buf : mb->w + 1;
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)))
{
mb->r = (mb->r == mb->bufend) ? mb->buf : mb->r + 1;
return data;
}
return NULL;
}
----------------8<-------------------------