<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Mar 1, 2016 at 10:12 AM, Sebastian Gesemann <span dir="ltr"><<a href="mailto:s.gesemann@gmail.com" target="_blank">s.gesemann@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Thank you all for the responses!<br>
<span class=""><br>
On Mon, Feb 29, 2016 at 9:05 PM, Harry van Haaren <<a href="mailto:harryhaaren@gmail.com">harryhaaren@gmail.com</a>> wrote:<br>
> On Mon, Feb 29, 2016 at 7:52 PM, Spencer Jackson <<a href="mailto:ssjackson71@gmail.com">ssjackson71@gmail.com</a>><br>
> wrote:<br>
>> > The generic solution for cases like this is a lock-free ringbuffer.<br>
>> I've also used the jack ringbuffer for this and it was easy enough.<br>
><br>
> Simple tutorial on using JACK ringbuffer and C++ event class here:<br>
> <a href="https://github.com/harryhaaren/realtimeAudioThreading" rel="noreferrer" target="_blank">https://github.com/harryhaaren/realtimeAudioThreading</a><br>
<br>
</span>I've looked into JACK's ringbuffer implementation. It doesn't look too<br>
complicated. Thank you all for suggesting it! But I'm a little bit<br>
concerned about ISO standard compliance. According to the<br>
multi-threading-aware update to the C11 and C++11 memory models, the<br>
access to the ringbuffer's data (*buf) is technically a data race and<br>
therefore invokes undefined behaviour. Only read_ptr/write_ptr are<br>
somewhat protected (volatile). From what I understand, given the<br>
C11/C++11 memory model, one is supposed to use "atomics" for all<br>
read/write accesses in such situations (including *buf). But so far, I<br>
havn't gathered much experience in this kind of lock-free programming.<br></blockquote><div><br></div><div>Sadly, you still don't understand how a lock-free ringbuffer works.<br><br></div><div>The key insight to have is this:<br><br></div><div>    * the calculation of what can be read and what can be written may, in fact<br></div><div>      be incorrect due to threading<br>      <br></div><div>      BUT<br>   <br></div><div>      they are ALWAYS wrong in the "safe" direction. if the calculation is wrong<br></div><div>      it will ALWAYS underestimate data-to-be-read and space-to-be-written.<br></div><div><br></div><div>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.<br></div><div><br>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.<br></div><div><br><br></div><div> <br></div></div></div></div>