Does an NSTimer with a small duration cause any problems like the event queue filling up with unprocessed messages?
Nope, NSTimer won't try to call your callback more often than it's able to. It's very good about keeping up, though; ask for a timer that fires at 60hz, and it will in fact fire at 60hz most of the time.
If you call an NSTimer with a RIDICULOUSLY high rate, like thousands of fires per second, you will eventually reach a point where the event queue has so many timer fire messages in it that desirable messages (usually "touch end") are dropped. However, this is a rare event and not a killer. (As long as you have not written your game to assume that all touches which begin eventually end. DON'T EVER ASSUME THIS.)
Average Software recommends an NSTimer with a duration of 0.0. According to the documentation, the interval of a timer is defined as: "The number of seconds between firings of the timer. If seconds is less than or equal to 0.0, this method chooses the nonnegative value of 0.1 milliseconds instead." However I would say that "fire this every 0.1 seconds" is a good proxy for "run whenever idle".
CADisplayLink is what you want if you want to just say "wake me up when it is time to display a frame". I do not think it is the correct solution to the specific problem gothica suggests?
I
think there's some way to actually tell the cocoa event loop "call me whenever you're not doing anything else". I find this suggestion of how to do this using GCD:
http://stackoverflow.com/questions/7356820/specify-to-call-someting-when-main-thread-is-idle but do not know if this truly works.
However: Technogothica, I do not think you are going about this in the right way to begin with. You usually do not need to write a "run when idle" handler yourself; rather what you really want is to engineer your program such that the Apple-provided run loop is doing the things you wanted your 'run when idle' loop to do, for you. This should always be possible. (Among other things, if you are truly running "whenever idle" then you are going to be 100%ing the CPU and people with laptops with loud fans will hate you.)
In particular, you say "The idle processing I want to add is to poll the state of background threads synchronously with user interface updates". What I would suggest is that instead of polling, when the background thread must communicate something to the main thread, it "push" by calling performSelector:onThread:withObject:waitUntilDone: (there is also a performSelectorOnMainThread).
http://cocoawithlove.com/2009/08/safe-threaded-design-and-inter-thread.htmlThis will cause the requested method to be invoked on the desired thread on the next visit to that thread's "run loop".
Aside from this, what I would suggest is that you research
GCD. It's quick to learn and allows you to perform all kinds of elaborate and really neat tricks. GCD is like NSOperation/NSOperationQueue but more cleanly designed. It's also what the "run loop" in newer versions of OS X / iOS is based on, which means if you're using GCD you're effectively being given access to the primitives of the os x/ios run loop, and it is expressive enough I think it mops up the use cases where performSelector:onThread: isn't so hot. Using this you could do something like signal from a secondary thread like "schedule this function to run on the main thread's event loop, but only do so with the lowest possible priority". You can also use this to perform performSelector:onThread:-like messaging from non-objective-c code, and receive these sorts of inter-thread "messages" on threads which do not actually have a cocoa run loop.