Re: AU Threading Question
Re: AU Threading Question
- Subject: Re: AU Threading Question
- From: Stephen Blinkhorn <email@hidden>
- Date: Fri, 08 Apr 2011 14:16:20 -0600
Hi Gregory,
On 8 Apr 2011, at 11:22, Gregory Wieber wrote:
Not sure if you're aware, but the GUI stuff should ALWAYS run from
the main thread.
Could you expand on this a little?
Stephen
On Fri, Apr 8, 2011 at 10:03 AM, Stephen Blinkhorn <email@hidden
> wrote:
Thanks for your comprehensive answer Brian.
On 8 Apr 2011, at 02:54, Brian Willoughby wrote:
Or is it possible that the Render method will have to wait for the
GetProperty()read to finish before writing new values?
As far as the processor is concerned, the entire array is just
separate memory locations that can be read or written in any order
at any time, and threading will allow them to be written by one
thread in the middle of being read by another thread. In other
words, nothing is going to automatically make the Render thread stop
while some other thread is reading these values. No part of the
code is aware of the special purpose of these memory locations, or
the tie-in between the writer (producer) and reader (consumer).
You, as the programmer, must establish the rules and enforce them.
OK, that's what I was asking really.
I would like to ask you to step back for a moment and consider what
your program is doing, as designed at the moment.
It appears that you are updating the peak meter levels on every
Render call (or at least you haven't specified any mechanism in your
code to limit how frequently these values are updated). With
typical buffer sizes, this represents an update rate of maybe 10
times per second (4096 frames per buffer @ 44,100 frames per second)
to as high as maybe 345 times per second (128 frames per buffer @
44,100 frames per second). With low latency and high sample rates,
which are quite popular these days, you could easily have hundreds
or thousands of updates per second.
At the same time, you have an NSTimer polling your data - hopefully
at a more sensible rate like 24 Hz or so, certainly less than 60 Hz
at the most. But that NSTimer is not synchronized with the Render
updates, and if your Render thread is updating the values hundreds
or thousands of times per second it's highly likely that an update
will change part of the array in the middle of your Cocoa view
copying the values. This is a textbook example of a race condition.
A better approach would be to reduce the update rate so that it is
as slow as the display rate, and then you'd have much less
likelihood of hitting that race condition. Also, instead of polling
the data for changes at a rate that is not synchronized to the
updates, why not just have the Render thread tell the Cocoa view
that something has changed? This avoids polling entirely, and
should eliminate the race condition unless the Cocoa view is so slow
to respond that it catches the next update (if your Cocoa view is
too slow to keep up, then you should slow the update rate anyway).
The Render thread updates the peak meter values at the same refresh
rate as the GUI (which as you pointed out is usually several or more
blocks of data) so it stores peak values across render calls until
it knows what the real peak value is. At the same time I set/unset a
flag so that the render method can see if a GUI read has occurred
and the GUI can ascertain if there is fresh data to display. So it's
all in sync.
I don't really like the NSTimer approach and I did switch to using a
PropertyChanged mechanism at one point but the overall effect wasn't
as 'smooth' from the user's point of view. I might try that again
quickly as on paper it seems like a better approach.
My apologies if I misunderstood your question or if you already knew
all of this.
No apology required Brian, many thanks for the answers!
My main concern is that I'm experiencing occasional audio glitches
and stuttering (although no one else has ever complained about
this). I've taken care to make sure I'm not doing any memory
allocation via malloc or new during render calls (I use placement
new using a preallocated memory block) but I've noticed that the GUI
also tends to 'hang' during these periods of glitching/stuttering
and I'll get a CPU spike.
So the reason I asked the original question was to get a better
understanding of how threading works in an audiounit/host context
and to make sure that I'm not doing anything via the GUI that could
cause the Render thread to block.
To confirm I'm not totally off the mark; When the GUI thread calls
GetProperty() the GetProperty() call is executed on the GUI thread
and in my case accesses data shared between threads? Is that correct?
Thanks,
Stephen
Brian Willoughby
Sound Consulting
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Coreaudio-api mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Coreaudio-api mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden