On Thu, 10 Dec 2015, Will J Godfrey wrote:
On Thu, 10 Dec 2015 06:51:48 -0800 (PST)
Len Ovens <len(a)ovenwerks.net> wrote:
You can check if there are 4 bytes available, if
not don't read (yet).
Normally (at least for anything I have done) the reason I use the ring
buffer is to divorce the data processing from any real time requirement.
So I am reading the ring buffer in a loop, I can check how many bytes are
available. jack_ringbuffer_read_space(buffer) can be used I think.
I'm doing this. My main concern was whether the pointers would be updated in
byte steps or block size steps, and what implications that might have.
I'm quite prepared to believe I might be over-thinking the problem. This has
been known before :)
On the input end of the ringbuffer we put a set number of bytes into the
buffer. This is done during the time our app has it's time to do whatever
it is going to do in that jack period. But this callback might be running
on another core than the rest of the app and so it is possible that the
write event may be only partly done when our app looks at the buffer. That
is why it is not known that if there is data there it has all been
written. However, the call back is a RT thread and so it will finish the
write "real soon". So there should be an event's worth of bytes by the
time you look at it a second time. A time out does not really make sense
that I can see. I don't think the ring buffer is un reliable. But, don't
read till all the bytes are there.
The answer to your question of how the pointer is updated, does't matter
really. What matters is if everything that goes in gets to the output. So
if one checks that the right number of bytes are there before reading, it
doesn't matter. The safe way to do things might be to update the pointer
after each byte written. The least code way/cpu way may be to write n
bytes then update. But Paul's answer seems to indicate the first is
true... but, the buffer can be written to manually too, where the input
manually inserts a byte at a time and updates the pointers after each
byte. The API allows that from what I can tell. In fact, if the calling SW
wanted to, it could write 10 bytes and only update the pointer 3, write
another 3 and then update the pointer 10 (I can't see any sane SW doing
so).
But you have control of both the input and the output, so you can make
sure the event based input API is used rather than a manual method. The
jack ringbuffer does not force you to code in a sane manner, but you can
still choose to code in a sane manner if you want to.
In general, jack does things in chunks. It starts doing things at the
beginning of a period going through all it's call backs and when finished
it does nothing till the beginning of the next period. On a single core
system, it is this time when your application will be looking at the
non-RT end of the ringbuffer. So in general, so long as the RT end can
always access the right number of bytes when it needs to, everything will
work.... nothing will be lost.
Someone will correct all my mistakes I am sure.
My own code, after having thought this through in answer to your question,
does not do enough checks at all :) I need to go back and fix some
things. Oddly enough, it does work :) My particular code is all MIDI
events and so those events are various sizes, not all 4 bytes. I started
off with more than one ringbuffer for each expected event size. This meant
I had to do my sorting in RT, so I have now gone to one buffer and parse
it on the output. With one, two or three byte events, I can easily look
for the right number... I pull one byte, parse it and know I have it all
or expect one or two more. However, I do use sysex events as well so I
have to look for an eox.
Len goes back to redo a big chunk of his code. I must be missing at least
some events.
--
Len Ovens
www.ovenwerks.net