Re: [LAD] Realtime inter-thread communication

From: Paul Davis <paul@email-addr-hidden>
Date: Tue Mar 01 2016 - 17:54:33 EET

On Tue, Mar 1, 2016 at 10:12 AM, Sebastian Gesemann <s.gesemann@email-addr-hidden>
wrote:

> Thank you all for the responses!
>
> On Mon, Feb 29, 2016 at 9:05 PM, Harry van Haaren <harryhaaren@email-addr-hidden>
> wrote:
> > On Mon, Feb 29, 2016 at 7:52 PM, Spencer Jackson <ssjackson71@email-addr-hidden>
> > wrote:
> >> > The generic solution for cases like this is a lock-free ringbuffer.
> >> I've also used the jack ringbuffer for this and it was easy enough.
> >
> > Simple tutorial on using JACK ringbuffer and C++ event class here:
> > https://github.com/harryhaaren/realtimeAudioThreading
>
> I've looked into JACK's ringbuffer implementation. It doesn't look too
> complicated. Thank you all for suggesting it! But I'm a little bit
> concerned about ISO standard compliance. According to the
> multi-threading-aware update to the C11 and C++11 memory models, the
> access to the ringbuffer's data (*buf) is technically a data race and
> therefore invokes undefined behaviour. Only read_ptr/write_ptr are
> somewhat protected (volatile). From what I understand, given the
> C11/C++11 memory model, one is supposed to use "atomics" for all
> read/write accesses in such situations (including *buf). But so far, I
> havn't gathered much experience in this kind of lock-free programming.
>

Sadly, you still don't understand how a lock-free ringbuffer works.

The key insight to have is this:

    * the calculation of what can be read and what can be written may, in
fact
      be incorrect due to threading

      BUT

      they are ALWAYS wrong in the "safe" direction. if the calculation is
wrong
      it will ALWAYS underestimate data-to-be-read and space-to-be-written.

that is: you will never attempt to read data that should not be read, and
you will never attempt to write to space that should not be written. This
is true of ALL lock-free ringbuffer designs, not just JACK's. The property
arises from the requirement that they are single-reader/single-writer. If
you violate this (e.g. attempt to move the read-ptr from the write thread
or vice versa), then all bets are off unless you use some higher level
mutual exclusion logic (which has no place in the ringbuffer itself. The
design works because in audio contexts, when you use a ringbuffer, you are
more or less guaranteed to be using a design where you keep reading and
keep writing to the ringbuffer over and over. The design cannot work for
single-shot communication where you must always collect ALL possible data
in a thread-synchronous fashion. This is not the case for audio work.

Now, that said, there are some under-the-hood issues with the actual JACK
ringbuffer code, but they have absolutely nothing to do with the high level
semantics, and that is what you're relying on. Those issues concern the use
of memory barriers, and are thus related to code-reordering not to
atomicity. Although a clean fix/patch for this would still be a good thing,
the ringbuffer's are used widely and they function as intended in almost
all situations. You need not concern yourself with this issue if you are
just starting out.

_______________________________________________
Linux-audio-dev mailing list
Linux-audio-dev@email-addr-hidden
http://lists.linuxaudio.org/listinfo/linux-audio-dev
Received on Tue Mar 1 20:15:02 2016

This archive was generated by hypermail 2.1.8 : Tue Mar 01 2016 - 20:15:02 EET