Idle thread approach in iOS - objective-c

I'm trying to set up a thread that stays idle until new data it's available. What it's the best approach for this in Objective-C? Till now I tried to make a simple run loop
while(YES) {
if(isDataAvailable) {
//process data
}
}
However this has an huge impact on performance, my FPS drops from 40 to 20 and the interface becomes unusable (even if the actual data process happens once in a second or so and it's not very intense for the CPU. I tried to add [NSThread sleepForTimeInterval:0.01] at the end, but this way I lose data packages ('process data' refers to some streaming related operations, queue and unqueue data packages), however the FPS returns to normal.
I'm fair new in Objective-C and I was thinking maybe there is a better way to do this? I also had a look over NSRunLoop, but didn't manage to make it work as a run loop :), only attached a timer to it that doesn't do more than my [NSThread sleepForTimeInterval:0.01] thing.
Any help it's highly appreciated:D

If you need to keep the seconary thread alive, you definitely want to use a real runloop:
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Multithreading/RunLoopManagement/RunLoopManagement.html#//apple_ref/doc/uid/10000057i-CH16-SW1
Basically, just create and start your thread, set up an autorelease pool, then run your runloop for some set time amount. When the time expires, you check to see if you should exit your thread, or enter into the runloop again.
As Marcelo points out though, there are more modern approaches to achieve concurrency (GCD and async dispatch being a couple of examples) so maybe investigate other forms of concurrency as well.

Related

Is it okay to call [NSProcessInfo beginActivityWithOptions] and [NSProcessInfo endActivity] on a per-thread basis?

I've got a MacOS/X app which in general is not averse to app-napping, but sometimes it will spawn one or more child threads to do timing-sensitive networking tasks, which do need to avoid being app-napped.
The elegant thing to do would be to have each of these threads call [[NSProcess processInfo] beginActivityWithOptions [...]] when it starts, and also call [[NSProcess processInfo] endActivity [...]] just before it exits, which would (hopefully) have the effect of avoiding app-nap on my process (or at least on those particular threads) only when one or more of these network-threads is running.
My question is, is this a legal/acceptable calling pattern, or is NSProcessInfo more of a per-process-only kind of API that doesn't implement the thread-safe reference-counting logic that would be necessary to reliably yield the expected behavior if I call it from multiple threads? (if it's the latter, I can implement that logic myself, but I'd rather not reinvent the wheel here)
This API is considered like process-wide, to report that your entire Application is doing the specific kind of job, which should be or should not be affected by power saving heuristics (which are, again, per-process, not per-thread).
The best way to use it would be to begin one activity before all your background threads started, and finish it after all your important background threads finished.
You can do it with DispatchGroup or any other instrument you wish.
That is not the only way though.
beginActivityWithOptions would return the _NSActivityAssertion, which is not generally aware of threads. You could bring your own thread sync mechanism to this party.
Calling this API several times would create several _NSActivityAssertion objects, which is definetely redundant but should work, if you will properly end each of them.
First of all this API should be or should not be affected by power-saving heuristics.
The best way to use it would be to use it with a dispatch group

Detect when block is added to Grand Central Dispatch?

I have an iOS application using NSThreads for concurrency tasks. I will try to migrate it to be using the Grand Central Dispatch (GCD) for handling concurrency.
The problem is that the app needs information regarding how many threads has been created since a given time. And how many threads that was spawned since that given time is currently running.
At the moment this is done by creating a category that does a method swizzling on the -main method in NSThread. In the new swizzled method it simply increments the total number of threads running and then decrement the same variable before the new swizzled -main method returns.
The problem is that when I use GCD dispatch_async it does not create a NSThread, hence my category approach does not work. How can I achieve the same while using GCD to handle concurrency?
What I would like to detect is when a new block is added to GCD, and when that block has been executed.
Any suggestions on how to achieve the same is very welcome.
EDIT
Many thanks to #ipmcc and #RyanR for helping me out on this. :) I believe I need to tell some more about the background and what I am trying to accomplish.
What I am actually trying is to extend the iOS testing framework Frank. Frank embeds a small web-server within a given app which enables sending HTTP request to the iOS application and thereby simulating events, a swipe or a tap gesture as an example.
I would like to extend it in a way that enables it to wait until all work triggered by a specific simulated event has ended before returning upon a request.
However I found it hard to detect exactly what work was triggered by the received event. And thats how I came to the solution to just reset a thread counter and then increment this counter for all created threads after the event was simulated, and decrement it when the threads are finishing. And then block until threads count became zero again. I know this approach is not perfect either, and it wont work with GCP.
Is there any other way to achieve it? Another possible solution which I have thought of is to specify that everything must run synchronized except the thread handling the HTTP request. However I don't know if this possible.
Any suggestions on how to achieve blocking after each simulated event until work triggered by that event has completed?
The problem is that the app needs information regarding how many
threads has been created since a given time. And how many threads that
was spawned since that given time is currently running.
You will not be able to get this information from GCD. One of the points of GCD is that you do not manage the thread pool. It is opaque. You'll note that even pthreads, the underlying threading library on which NSThread and GCD are built, does not have a (public) means to enumerate all existing threads or get the number of running threads. This is not going to be doable without hard core low level hackery. If you need to control or know the number of threads, then you need to be the one to spawn and manage them, and GCD is the wrong abstraction for you.
At the moment this is done by creating a category that does a method
swizzling on the -main method in NSThread. In the new swizzled method
it simply increments the total number of threads running and then
decrement the same variable before the new swizzled -main method
returns.
Note that this only tells you the number of threads started using NSThread. As mentioned, NSThread is a fairly high level abstraction on top of pthreads. There is nothing to prevent library code from spawning its own threads using the pthreads API that will be invisible to your count.
The problem is that when I use GCD dispatch_async it does not create a
NSThread, hence my category approach does not work. How can I achieve
the same while using GCD to handle concurrency?
In short, you can't. If you want to go forth and patch functions all over the various frameworks, then you should look up a library called mach_override. (But please don't.)
What I would like to detect is when a new block is added to GCD, and
when that block has been executed.
Since GCD uses thread pools, the act of adding a block does not imply a new thread. (And that's sorta the whole point.)
If you have some limited resource whose consumption you need to manage, the traditional way to do that would be with a limiting semaphore, but that is just one option.
This whole question just reeks of a poor design. Like the number of pthreads, GCD's queue widths are opaque/non-public. Your previous solution was not particularly viable (as discussed), and further efforts are likely to yield similarly poor solutions. You should really rethink your architecture such that knowing how many threads are running isn't important.
EDIT: Thanks for the clarification. There's not really a generic way, from the outside, to tell when all the "work" is done. What if an action sets up a timer that won't call back for ten minutes? At the extreme, consider this: the main runloop continues to spin for the entire life of the app, and as long as the main runloop is spinning, "work" could be being done on it.
In order to detect "doneness" your app has to signal doneness. In order to signal doneness, the app has to have some way (internal to itself) to know it's done. Put differently, the app can't tell something else (i.e. Frank) something it doesn't know. One way to go about this would be to encapsulate all the work you do in your app in NSOperations. NSOperation/NSOperationQueue provide good ways of reporting "doneness." At the simplest level, you could wrap the code where you kickoff work in an NSBlockOperation, then add a completion block to that operation that signals something else when it's done, and enqueue it to an NSOperationQueue for execution. (You could also do this with dispatch_group and dispatch_group_notify if you prefer working in the GCD style.)
If you have specific questions about how to package up your app's work into NSOperations, I would suggest starting a new question.
You can hook into the dispatch introspection functions (introspection.h, methods all start with dispatch_introspection), but you have to link with that library which is supposed to be only for debugging. I don't think you can include that in a release build. Your best bet would be to encapsulate GCD into your own object, so all your code submits blocks to execute through that object and it submits them to GCD after tracking whatever you're interested in. You won't be able to track thread consumption though, because GCD intentionally abstracts that and reuses threads.

NSTimer versus separate thread - which one to choose?

Let's assume we have simple UI and for whatever reason, every 5 seconds a UILabel needs to be updated.
I can now either setup an NSTimer which does the job, or create a separate thread which runs endlessly, sleeps 5 seconds, does its thing, sleeps again and so on.
Which one would I choose to go for? What are the differences?
You have to do UI operations on the main thread anyway, so unless your doing some processing prior to setting the label there would be no benefit of using another thread.
The UI can only be updated on the main thread of any program. If you want to do calculations for the label in a separate thread, that's perfectly fine, but the code to update your UI will have to operate on the main thread (or, you can use performSelectorOnMainThread:withObject:waitUntilDone: to call setText: on your label and have it operate correctly).
Use NSTimer.
Why?
As soon as you introduce extra threads, you introduce the possibility of a whole new class of bugs i.e. thread synchronisation issues. These tend to be very hard to diagnose and resolve due to their indeterminate nature.
You have to do UI updates on the main thread anyway. So your thread would have to do -performSelectorOnMainThread:withObject:waitUntilDone: to update the UI.
If the calculations for the label take a while (don't just assume they do, try it the simple way first and see), have your timer kick off an NSOperation to do the calculations and then have the NSOperations call -performSelectorOnMainThread:withObject:waitUntilDone: when it has finished.

What can I do if two detached threads overlap each other? queue

I'm not very 'up' on multi-threading, but I've been using detachNewThreadSelector in a couple of places to access data in a database. Unfortunately, on slower devices the first request may still be happening when I call the second... Which naturally causes a crash because both are calling the same method (which is obviously not thread-safe).
What is the best way to go about sorting a bug like this? Can I somehow queue them so that the second thread doesn't start until the first one has finished?
Thanks!
You may want to have a look at NSOperation and NSOperationQueue which is an abstraction for a queue of tasks that can be run asynchronously from the main thread. If you want the NSOperationQueue to run just a NSOperation at a time (so to wait after the current task is compleate before firing the next one) you can just set the maxConcurrentOperationCount property of the queue to 1
To extend ranos answer a bit, be sure to add operations from the same thread because if you add several NSOperations from several threads, they will run concurrently, even though maxConcurrentOperationCount on NSOperationQueue is set to 1.

How do I terminate a thread waiting on #synchronized objective C

I have some code like this:
doDatabaseFetch {
...
#synchronized(self) {
...
}
}
and many objects that call doDatabaseFetch as the user uses the view.
My problem is, I have an operation (navigate to the next view) that also requires a database fetch. My problem is that it hits the same synchronize block and waits it's turn! I would ideally like this operation to kill all the threads waiting or give this thread a higher priority so that it can execute immediately.
Apple says that
The recommended way to exit a thread is to let it exit its entry point routine normally. Although Cocoa, POSIX, and Multiprocessing Services offer routines for killing threads directly, the use of such routines is strongly discouraged.
So I don't think I should kill the threads... but how can I let them exit normally if they're waiting on a synchronized block? Will I have to write my own semaphore to handle this behavior?
Thanks!
Nick.
The first question to ask here - do you need that big of a critical section so many threads are waiting to enter? What you are doing here is serializing parallel execution, i.e. making your program single-threaded again (but slower.) Reduce the lock scope as much as possible, think about reducing contention at the application level, use appropriate synchronization tools (wait/signal) - you'll find that you don't need to kill threads, pretty much ever. I know it's a very general advise, but it really helps to think that way.
Typically you cannot terminate a thread that is waiting on a synchronized block, if you need that sort of behavior, you should be using a timed wait and signal paradigm so that threads are sound asleep waiting and can be interrupted. Plus if you use a timed wait and signal paradigm, each time the timed wait expires your threads have the opportunity to not go back to sleep but rather to exit or take some other path (ie. even if you don't choose to terminate them).
Synchronized blocks are designed for uncontested locks, on an uncontested lock, the synchronization should be pretty close to a noop, but as soon as the lock becomes contested they have a very detrimental to application performance, moreso than even simply because they are serializing your parallel program.
I'm not an Objective C expert by any means, but I'm sure that there are some more advanced synchronization patterns such as barriers, conditions, atomics, etc.