-
Notifications
You must be signed in to change notification settings - Fork 10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Usage of non atomic operations between threads in LinkHut #18
Comments
Oh, err. never mind, I was looking at an older version of LinkHut 👍 it seems the newer version has a spinlock. |
Hmm, I don't think it's a good idea to use locks on the audio thread! Better to use atomic operations and memory barriers, or something like AEMessageQueue from TheAmazingAudioEngine. |
I'd love a definitive answer on the locks front. You've got Michael (TAAE) along with many people on the CA list saying "don't use them at all". Then you've got Gabor (Superpowered) saying you can use them as long as you know the operations they're wrapping will complete rapidly. LinkHut seems to be in the camp that they can be used. Atomic op's and memory barriers feels like the safer option, but I don't know whether there really are cases where a lock is safe to use, too. |
It's impossible to know that an operation on another thread will complete rapidly. For example, the audio thread is waiting on the lock while the main thread is holding it. but before main thread is done with the operation, it might be preempted by some other thread, etc. This creates "priority inversion": the audio thread effectively got only main-thread priority. For a single demo-app this might not be very relevant, but devs might copy the LinkHut example. The audio thread is a global shared resource, if every music app currently running would use locks in their audio threads (waiting for each apps low-priority main threads, etc) there would be very high risk of glitches and buffer drops. |
It's also not just me and other third parties saying don't use locks, Obj-C or malloc - this comes from the Core Audio team itself. I'd back that up with a reference but I'm on my phone =) Sent from my iPhone
|
The goal of LinkHut is to demonstrate the usage of LinkKit, so we tried to make it as small and clear as possible. In the first version we didn't synchronize the data at all between the threads for this reason. After getting several questions about the validity of this, we added the spin lock to at least make it thread safe. But still this is not ideal, as has been pointed out above. Another constraint with LinkHut is that we want it to be completely standalone and not require any additional dependencies to build and run. Otherwise, we would use a lock free queue from AAE or some other library. I think we didn't realize that people would take this as a sort of "app template" or an example of how to do things in an iOS audio app. We probably should have invested more time in making it worthy of this, but were focused on the interaction with the ABLLink library. We will do another iteration on this and try to make a better model for iOS apps. I'm open for suggestions as to what would be the most idiomatic way of handling this without any external libraries. If we're limited to just what's available with |
Maybe something along the lines of this: put all state that needs to be communicated in a struct typedef. main thread: if(old) free(old); audio thread: if(new), read its state and compare-and-swap to move it to old. Not sure of the details, I simply use AEMessageQueue myself :) Cheers On Tue, Mar 22, 2016 at 3:14 PM, Brent Shields notifications@github.com
/Jonatan |
@lijon Thanks Jonatan, that's roughly what I meant by double-buffering. As for bundling AEMessageQueue, that's another thing to consider. |
Thanks. I’ve never seen the use of a spin lock in a core audio thread before, I always just used ring buffers to communicate, but your post makes it clear exactly why they are a bad idea.
|
Fix comment for ABLLinkSetIsPlaying
The method used in LinkHut to communicate info to and from the audio thread, are not atomic and will break sometimes on 32 bit platforms with torn writes. It happens when a Float64 or UInt64 value is half written then the other thread reads the value.
The text was updated successfully, but these errors were encountered: