On 8 July 2011 01:50, James Morris <jwm.art.net(a)gmail.com> wrote:
On 7 July 2011 13:10, James Morris
<jwm.art.net(a)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…
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.