Multithreading: best method for lossy thread notifications in Swift? - swift

I have a high-priority audio thread that runs periodically and should do minimal synchronization.
Sometimes the main thread needs to ensure that at least one audio cycle has passed and certain parameters have been picked up, before sending the next batch of parameters. For example, when disabling an audio node the main thread needs to wait until the next cycle when the disabling command is picked up and the node shuts itself down.
At times it is important for the main thread to wait until the command is fully executed, but other times it's not important, so nobody might be listening to the sync event. Hence the "lossy" scenario.
So what is the best way of notifying other threads about an event with minimal overhead and possibly in a "lossy" way?
Can't think of ways of using a semaphore for this task. Are there any canonical ways of achieving this? Looks like Java's notifyAll() works precisely this way, if so, what synchronization mechanism is used behind notifyAll()?
Edit: been thinking, is there such a thing as "send me a semaphore in a queue and I'll signal it"? Seems a bit too complicated but theoretically it could do the job. Any simpler tools for the same task?

As a rule, you never want to block the main thread (or, at least, for more than a few milliseconds). If the response might ever take longer than that, rather than actually waiting, we would adopt asynchronous patterns, let the main thread proceed. Sure, if you need to prevent user interaction, we’d do that, but we wouldn't block the main thread.
The key concern is that if an app blocks the main thread for too long, you have a bad UX (where the app appears to freeze) and you risk having your app killed by the watchdog process. I would therefore not advise using semaphores (or any other similar mechanisms) to have the main thread wait for something from your audio engine controller.
So, for example, let’s say the main thread wants to tell the audio engine to pause playback, but you want the UI to “wait” for it to be acknowledged and handled. Instead of actually waiting, we would set up some asynchronous pattern where the main thread notifies the audio engine that it wants it to pause, the audio controller would then notify the main thread when that request has been processed via some callback mechanism (e.g., via delegate protocol pattern, completion handler closure, etc.). If you happen to need to prevent user interaction during the intervening time, then you’d disable controller and use some UIActivityIndicatorView (i.e., a spinner) or something like that, something that would be removed when the completion handler is called.
Now, you used the term “lossy”, but that generally conveys that you don't mind the request getting lost. But I’m assuming that is not really the case. I'm assuming that you don't really want the request to be lost, but rather only that the main thread doesn't care about the response, confident that the audio controller will get to it when it can. In that case, you'd probably still give this sort of request to the audio controller a callback mechanism, but the main thread just wouldn’t avail itself of it.
Now if you have a sequence of commands that you want the audio engine to process in order, then the audio controller might have a private, internal queue for these requests, where you’d configure it to not start subsequent request(s) until the prior ones finished. The main thread shouldn't be worried about whether the required audio cycle has processed. It should just send whatever requests are appropriate and the audio controller should handle them in the desired order/timing.

Related

How can one thread determine if a different thread has crashed?

I have a background thread that is doing a bunch of work - loading the application. The main thread is displaying progress on a UIProgressView.
The background thread is being spawned with performSelectorInBackground (though, I'm not wed to this method if a different approach makes this problem easier to solve)
[self performSelectorInBackground:#selector(loadAppInBackground) withObject:self];
On a couple occasions a bug has caused the background thread to crash (different bugs as the app evolves) which results in the progress bar stopping, but the user getting no clear indication that anything is wrong.
I'd like to detect this situation and fail more gracefully than simply hanging until the user gives up on waiting.
Because the duration of the load process can vary greatly, simply timing out isn't an ideal option.
What's the best way for the foreground thread to detect that the background thread has failed? Since the foreground thread is busy dealing with the UI, would it require a second background thread to monitor the first? That seems ugly.
Is there some thread-to-thread communication mechanism that could be used to "ping" the background process? Better yet, a low level system mechanism of checking the status of other threads?
The debugger knows about all the threads that are running... and seems to know their status. I'm wondering if there's a call available to my app to do the same.
If the background task runs in some sort of regular cycle (eg, there's a big loop where much of the work gets done), it can set a flag every so often to indicate that it's still alive.
One way to do this is to have background thread store [NSDate timeIntervalSinceReferenceDate] somewhere, and, in your main thread, occasionally (perhaps on a timer) compare that to the current time. If the difference is greater than some reasonable limit you can guess that the background thread has died.
Another way is to have the background thread simply set a Boolean, and have the main thread interrogate that and clear it on some regular basis. If the Boolean doesn't get set again between main thread interrogations you can infer that it has died.
The first technique has the advantage that you can "tune" the "reasonable limit" to tolerate code (in either thread) that is somewhat irregular in it's timing. The second approach generally requires timings that are more predictable.
Of course with either approach you want to somehow avoid "blowing the whistle" if the background thread has just finished up and you simply haven't recognized that yet.
A common technique is to have an extra thread to check for life signs of the thread in question - a so called heartbeat thread. The heartbeat thread polls the thread by checking if it responds in a timely manner, if not, deems the thread dead and terminates it.
A simple heartbeat thread implementation would be to check a counter that is incremented regularly by the other thread, if the counter is not incremented within a certain time it is regarded as dead and then an appropriate action could be taken like restarting thread or killing app. Another more common way is if the hb thread sends messages to the thread and checks for a response with a timeout.
It seems like there is no mechanism in objective c to check the status of a background thread directly. Any of the answers provided are decent options... either timing out, or having the thread create some sort of evidence of its continued existence.
I was hoping for something a little more simple, reliable, and real-time.
I'm going to experiment with catching an exception in the thread and perhaps producing a notification like "BackgroundThreadException" that the foreground thread could listen for and react to.

How NSOperation handle network connection loss while downloading huge data?

In my app created NSOperationQueue of NSOperation to download multiple images in background.I wanted to know what will happen if network connection is lost while downloading data.Whether all those are operations which are still in queue are marked as finished and removed from queue or will remain in queue and again start downloading process when network is established again or something else?
Can anyone explain how NSOperationQueue works in such scenario?
Thanks in advance!
The current NSOperation will continue with whatever logic is left when it receives the failure signal, and then terminate as normal, causing the NSOperationQueue to begin running the next NSOperation. If the internet still isn't back, it'll fail as well, and will just keep moving through the queue whether the network re-connects or not, failing all the connections unless the network reconnects.
There's probably quite a few different ways to handle this, because there's a lot to consider. For instance, you could put some logic in your code to mark an NSOperation as unsuccessful if it fails due to a network drop-out, and re-add failed NSOperations back into the queue. However, what if the network stays down for ages? Would your implementation be okay to keep trying to download images forever, or should you only let it re-try a particular file download a few times before giving up until the next time that feature is used?
You could also use a series of network reachability checks, such as before an NSOperation is added to the queue, before the NSOperation itself launches the NSURLConnection, etc. Should it fail you could have the NSOperation wait around until the network is re-connected and continue. (It's not ideal to do that, but because you're running it on a background thread it won't freeze the app's interface for the user at least).
If you wanted to, you could even implement the functionality you asked about in your question. That is, upon a network drop-out, cancelling all remaining operations in the NSOperationQueue, informing the user they'll have to re-try when the net comes back on. Then the next time the feature is called, re-add all those remaining NSOperations.

How to properly shut down/restart NSThread after applicationDidEnterBackground/applicationWillEnterForeground

For performance reasons, I instantiate a dedicated NSThread to process incoming messages that are streamed from a network server. I use an NSOperation for the purpose of instantiating the connection and receiving incoming data through the NSURLConnection delegates, but as soon as new data comes in and gets parsed, I offload the processing of the message to the dedicated NSThread. The idea is to let one thread focus on receiving incoming messages and let the other thread just do the processing.
What's the proper way to shut down the NSThread when the applicationDidEnterBackground comes in?
Also, how should I restart the NSThread when applicationWillEnterForeground comes in?
Other than the main thread, it seems the state of other background threads is not maintained between going to sleep and restarting.
By the way, I'm all for using NSOperations for most tasks that have a measurable amount of work -- ie, accessing a resource over the network, performing a calculation, etc. However, in this case, I need to process messages on the fly on a long-living dedicated thread that is always there by calling performSelector:onThread:withObject:waitUntilDone: and passing it the target thread. It seems NSOperation isn't a good fit for this.
I would appreciate your input.
"For performance reasons"?
If processing doesn't take much time, run everything (including NSURLConnection) on the main thread. Concurrency bugs are a major pain.
If you want things to run serially, you can emulate a "single thread" with an NSOperationQueue with maxConcurrentOperations = 1. I'm pretty sure that NSOperationQueue uses thread pools (and on 4.0, GCD, which probably uses thread pools), which means you don't need to keep a thread running all the time.
Apart from that, your process is automatically suspended and resumed by the system, so you don't need to kill off threads.
I'm not sure what you mean by "the state of other background threads".

Can I use a continuous background thread to update the iPhone UI without using NSTimer?

Let's say that if I read from www.example.com/number, I get a random number. In my iPhone app, I want to be able to continuously read from that address and display the new number on the screen after each request is finished. Let's also assume that I want this process to start as soon as the view loads. Lastly, as a side-note, I'm using ASIHTTPRequest to simplify the web requests.
Approach 1: In my viewDidLoad method I could synchronously read from the URL in a loop (execution will not continue until I get a response from the HTTP request). Pros: the requests are serial and I have full control to respond to each one. Cons: the UI never gets updated because I never exit the function and give control back to the run time loop. Clearly, this is not a good solution.
Approach 2: In my viewDidLoad method I create a timer which calls a fetchURL function once per second. Pros: each request is in a separate thread, and the UI updates after each request is finished. Cons: the requests are in separate threads, and cannot be controlled well. For example, if there is a connection timeout on the first request, I want to be able to display an error popup, and not have any further requests happen until settings are changed. However, with this approach, if it takes 3 seconds to timeout, two additional requests will have already been started in that time. If I just slow down the timer, then data comes in too slowly when the connection is working well.
It seems like there should be some approach which would merge the benefits of the first two approaches I mentioned. I would like a way that I could decide whether on not to send the next request based on the result of the previous request.
Approach 3: I considered using a timer which fires more quickly (say every .25 seconds), but have the timer's function check a flag to see what to do next. So, if the previous request has finished, it sends a new request (unless there was an error). Otherwise, if the previous request has not finished, the timer's function returns without sending a new request. By firing this timer more quickly, you would get better response time, but the flag would let me get the synchronization I wanted.
It seems like Approach 3 would do what I want, but it also seems a little forced. Does anyone have a suggestion for a better approach to this, or is something like Approach 3 the best way to do it?
You could do this using GCD with less code and using fewer resources. This is how you could do it:
In viewDidLoad call a block asynchronously (using dispatch_async) that does the following:
Load the data with a synchronous call and handle timeouts if it failed.
If successful, inform the main thread to update the UI.
Queue a new block to run after a delay that does the same thing (using dispatch_after).
To call back to the main thread from another thread I can think of these methods:
If you want to update a custom view, you can set setNeedsDisplay from your block
Otherwise, you could queue a block on what's called "main queue", which is a queue running on the main thread. You get this queue by calling dispatch_get_main_queue. and then treat it like any other queue (for example you can add your block by calling dispatch_async).
If you don't want to use blocks you can use the NSObject's performSelectorOnMainThread:withObject:waitUntilDone: method.
See GCD Reference for more details.
That said, you should never keep performing small requests so frequently (unless for specific tasks like fetching game data or something). It will severely reduce battery life by keeping antenna from sleeping.
I believe an NSOperation is what you need. Use the number 1 solution above, but place the code in your NSOperation's main method. Something like this:
The .h file
#interface MyRandomNumberFetcher : NSOperation {
}
#end
The .m file
#implementation MyRandomNumberFetcher
- (void) main {
// This is where you start the web service calls.
}
#end
I'd also recommend adding a reference to the UI controller so your operation queue class can call it back when it's appropriate.
Here's another suggestion. Create an NSOperationQueue that will run your requests on a different thread. If you find you need to refresh the UI call performSelectorOnMainThread. When the request completes create another request and add it to the queue. Set the queue to run only one action at a time.
This way you'll never have two requests running at the same time.

what exactly NSUrlConnection ASynchronous means?

i am getting confused what is the difference between Synchronous NSUrlConnection and ASynchronous NSUrlConnection?is there Synchronous or ASynchronous? if we use detachNewThreadSelector in connectionDidFinishLoading method,is it
ASynchronous NSUrlConnection? which is the best way?any tutorial ...
Synchronous means that you trigger your NSURLConnection request and wait for it to be done.
Asynchronous means that you can trigger the request and do other stuff while NSURLConnection downloads data.
Which is "best"?
Synchronous is very straightforward: you set it up, fire it, and wait for the data to come back. But your application sits there and does nothing until all the data is downloaded, some error occurs, or the request times out. If you're dealing with anything more than a small amount of data, your user will sit there waiting, which will not make for a good user experience.
Asynchronous requires just a little more work, but your user can do other stuff while the request does its thing, which is usually preferable. You set up some delegate methods that let you keep track of data as it comes in, which is useful for tracking download progress. This approach is probably better for most usage cases.
You can do both synchronous and asynchronous requests with NSURLConnection. Apple's documentation provides a clear explanation of the two approaches and delegate methods required for the latter approach.
It seems that you're conflating synchronous/asynchronous connections and threading. In my app I used asynchronous connections as an alternative to threading.
Let's say you want to download a big file without causing the UI to freeze. You have two basic options:
Asynchronous connection. You start with + connectionWithRequest:delegate: (or one of the other non-autorelease options) and it downloads bits of the file, calling your delegate when interesting thing happen. The runloop is still going, so your UI stays responsive. Of course you have to be careful that your delegate don't go out of scope.
Synchronous. You start the connection with + sendSynchronousRequest:returningResponse:error: but the code waits until the download is complete. You'll really need to spawn a new thread (or one of the higher level threading operations that Cocoa supports) or the UI will block.
Which option is "best" or the least painful will depend on the architecture of your application and what you're trying to achieve. If you need to create a thread for a long running process anyway, you might go with the second option. In general I would say the first option is easiest.
It's all pretty well documented on Apple's Developer site.
Something which hasn't been mentioned in the other responses is the size of the request. If you're downloading a large file, for example, then using an asynchronous connection is better. Your delegate will receive blocks of data as they arrive. In comparison, the synchronous method will wait for all the data before making it available to you. The delegate can start processing the response sooner (better user experience), or save save it to a file instead of memory (better resource usage). You also have the option to stop the response without waiting for all the data.
Basically, the asynchronous method gives you more control over the connection but at the cost of complexity. The synchronous method is much simpler, but shouldn't be used on the main UI thread because it blocks.
In response to the other answers regarding the file size: I think file size doesn't matter. If the server responds really slowly and you're loading data synchronous your UI still freezes, even if you're loading a small amount of data, like 3k.
So I'd go for the asynchronous option in every situation, cause you never know what you're going to get with regards to file size, server responsiveness or network speeds.