Jack said:
Actually, no, that's not always true. I've seen this done wrong many
times. In fact, I've had to fix other people's code that got this
wrong several times.
The biggest vulnerability, and easiest place to code an error, is when
an index needs to wrap around.
Sure. Below is a sketch of an implementation that doesn't require
disabling interrupts, assuming one read agent and one write agent and
that unsigned is atomic.
Is there a problem with it?
//conventions:
//empty buffer: writex==readx
//full buffer: (writex+1)mod(buffer size) == readx
static volatile unsigned readx, writex; //indexes, init to 0
static unsigned char mybuf[MYSIZE];
static unsigned inx(unsigned x)
{
return (x+1)%MYSIZE;
}
int isempty(void) {unsigned r=readx, w=writex; return r==w;}
int isfull(void) {unsigned r=readx, w=writex; return r==inx(w);}
int readfrombuf(void)
{
if(isempty()) return BUFFER_EMPTY;
unsigned r = readx;
int ret =mybuf[r];
readx = inx(r);
return ret;
}
int writetobuf(unsigned char val)
{
if(isfull()) return BUFFER_FULL;
unsigned w = writex;
mybuf[w] = val;
writex = inx(w);
return BUFFER_OK;
}