Jack Klein wrote:
Quote:
On Sun, 28 Oct 2007 03:11:15 GMT, Ark Khasin
<akhasin@macroexpressions.comwrote in comp.lang.c:
>
Quote:
>CBFalconer wrote:
Quote:
>>Sven wrote:
>>>Can someone point out source code for a safe circular buffer
>>>receiver transmitter? It's for sending and receiving bytes via
>>>RS232.
>>All you need to do is disable interrupts (or their equivalents)
>>before altering the counters and flags.
>>>
>In fact, you don't, if volatile (and of course atomic) read and write
>indexes are modified exclusively by the read routine and the write
>routine respectively. Good encapsulation saves messing with disabling
>interrupts.
>
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;
}
--
Ark