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

James Morris jwm.art.net at gmail.com
Fri Jul 8 11:24:01 UTC 2011


On 8 July 2011 01:50, James Morris <jwm.art.net at gmail.com> wrote:
> On 7 July 2011 13:10, James Morris <jwm.art.net at gmail.com> wrote:
>> 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.
>>
>
> I didn't have time to test it before going to work, when posting
> earlier, but was hoping someone who might see something immediately
> wrong with it might comment. I'm mainly posting back to say it doesn't
> work.
>
> It does mostly work, but not always, which is as good as not working
> at all. It looses the occasional write. For example my test program
> has two threads and two buffers. The first buffer is used for thread 1
> to send data to thread 2, and the second is used to send it back
> again. With 70 items originating in thread 1, and both buffers large
> enough to hold 32 items, 1 item is lost perhaps 1 in 7 program
> executions.
>
> I thought a "lock-free" ring buffer was supposed to be the easy solution!

I've just realized the problem was an error in the testing code. The
2nd thread would read an item from the 1st buffer, and then try to
write it to the 2nd buffer. When the test code failed to handle a
write failure (when both r/w ptrs of the 2nd buffer pointed to same
location *and* both were attempting to simultaneously access that same
location) it's loop back to read again, consequently discarding the
item that failed to write.

So I changed my test code thread loop and the problem goes away. The
loop has to stop reading when a write fails.

While I thought my rbuf was broken I read about how lock-free code is
not really lock-free, it just uses very fine grained locking.
http://stackoverflow.com/questions/2528969/lock-free-multi-threading-is-for-real-threading-experts/2530082#2530082

I'm still uncertain about the reliability of pointer operations being
atomic (otherwise why would glib provide atomic pointer ops?). I
currently assume it can't be guaranteed, which is why I wanted to use
the GCC atomic operations for reading/writing to the read/write
pointers.

So back to the fine grained (b)locking, I decided to count the noof
times it failed to write... I was going to provide counts of failures,
averages etc, but... Well, the counts seemed to increase the more
effort the code put into gathering statistics about failures.

So I'd thought I'd compare the execution time of 7000 items passing
through the two 32-item ring buffers, with the execution time 7000
items passing though 32-item jack-ringbuffers. details to come,
probably to throw all this out the window.



More information about the Linux-audio-dev mailing list