Re: [NSSound isPlaying] fails to indicate sound termination in Lion
Re: [NSSound isPlaying] fails to indicate sound termination in Lion
- Subject: Re: [NSSound isPlaying] fails to indicate sound termination in Lion
- From: Charles Srstka <email@hidden>
- Date: Mon, 23 Jul 2012 04:09:24 -0500
On Jul 23, 2012, at 3:27 AM, Jay Reynolds Freeman wrote:
> If it had never worked properly I would have found and fixed the problem during testing under Snow Leopard. The problem is that the 10.6 implementation worked *exactly* as the documentation specifies, but the 10.7 one doesn't. My code didn't rely on undocumented behavior, it relied precisely on what was documented. :-)
The documentation doesn’t say that you can block the main thread and still use the async API. In fact, it doesn’t even say that it will spawn a new thread at all. Of course in practice it would probably use a thread, but strictly going by what’s in the documentation, it could theoretically do all the processing in tiny little slivers on each iteration of the run loop or on an NSTimer on the main thread and still follow that API contract to a tee. Your code is making assumptions about what the API is doing, and this is what has come back to bite you as the undocumented behavior has changed.
If you think about it, it’s not hard to figure out ways that an asynchronous API could fail if the main thread is blocked:
1. If the async API doesn’t use a thread at all, obviously it will fail if the thread is blocked.
2. If the async API calls through to some other, lower-level async API, and *that* API spawns the thread, and the higher-level async API uses either a timer or a notification to detect when the lower-level API finishes, then the higher-level API will never detect the process finishing if the main thread is blocked.
3. If the async API relies on timers or notifications for anything else, it will fail if the main thread is blocked.
4. If the async API uses dispatch_[a]sync, +[NSOperationQueue mainQueue], -[NSObject performSelectorOnMainThread:withObject:waitUntilDone:], or something similar to use a non-thread-safe API as part of what it does, that won’t happen as long as the main thread is blocked.
5. I’ve written async APIs which used the techniques in #4 to set their “finished” properties on the main thread at the end, so that the properties can be observed via KVC without causing all kinds of non-main-thread calls to UI elements. If any API does this, it won’t happen if the main thread is blocked.
Etc., etc. The moral: don’t block the main thread. No Apple asynchronous API is guaranteed to work when you do so. Mac users tend to associate the spinning beachball with a hung app anyways (note how it’s commonly referred to as the beachball of *death*), and if I’m informed correctly, iOS will actually automatically kill any app whose main thread is blocked for a certain amount of time. Either way, it’s bad mojo.
FWIW, I just built a little test app out of curiosity. In my testing, it works exactly the same on Snow Leopard as it does on Lion — the isPlaying property stays true forever if the main thread is blocked — so perhaps even the fact that it worked for you on 10.6 may have been due to some peculiarity of your system. At any rate, it certainly is not something that can be relied upon.
Charles
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden