Notification from background thread in C callback - objective-c

As my first Mac application, I'm building an app that displays incoming MIDI timecode.
Therefore, I am having an instance of the RtMidi "library" which wraps the MIDI in and out stuff.
The Mac OS Core MIDI callback is in blank C and is called on multiple threads internally. The RtMidi stuff in in C++ and forwards this multi-threaded call to one single (the main) thread.
As I need a Cocoa function to notify other classes that a new MIDI timecode has arrived ( which happens about every 7-9 ms ), I implemented a Singleton which all necessary classes observe.
So, the order in which the functions are called is :
Core MIDI callback -> RtMidi function -> user callback -> Notification ( via Singleton )
Basically, this works!
The problem is that I right now have everything on the same thread ( the main thread). If I post a notification from the MIDI callback and the called functions take longer to complete than the above mentioned 7-9 ms, the Core MIDI callback gets blocked which causes the whole application to freeze.
I tried debugging and it seems that there is some kind of deadlock occurring.
Anyone has some directions on how to implement multithreading in this case?
As I also do UI updating in the notification observers, I would need all notifications to appear on the main thread. What I don't understand is how everything goes with C / C++ / Objective-C in this particular case.

I would suggest that at the stage that you forward your call from your background thread to the main thread that you do so in a non-blocking manner, if possible. For example, you could use performSelectorOnMainThread:withObject:waitUntilDone:, passing NO for the last argument, or some other mechanism like dispatch_async(dispatch_get_main_queue(), ^{ ... }). This will prevent your background thread from getting blocked, and allow the UI to be updated whenever it has time to do so.

Related

Objective-C NSRunLoop & NotificationCenterDelegate not functional when spawned on Rust worker thread

I'm currently trying to use Rust C interop in order to send actional desktop notifications (using a modified version of this lib). The main goal here would be to handle these notification sending events on separate threads like so:
thread::spawn(move || unsafe {
sys::sendNotification(
NSString::from_str(&title).deref(),
NSString::from_str(&message).deref(),
NSString::from_str(&uri).deref(),
NSString::from_str(&img.unwrap_or_default()).deref(),
);
});
This would allow me to have multiple notification 'handlers' running at the same time (vs. just being able to have a single notification displayed at once), and would also allow my main process to run without being blocked. Given the nature of the program (web-scraper), I don't want scraping halted whenever a notification is being displayed.
That said, this approach is somewhat problematic because the underlying obj-c code relies on NSRunLoop to handle click events (e.g., user clicks on the action to open a web page) through the created NotificationCenterDelegate instance. Per my knowledge (feel free to fact-check me on this I'm not familiar with obj-c), NSRunLoops only operate on the main thread and this code is rendered useless if ran on a worker... The notification still sends in this scenario, but events aren't processed.
Is there a way to handle this that is more effective than running my scraping logic on a separate loop and sending notif-send events to the main thread for processing (which will probably be halted by a notification that I hadn't opened)?
Strictly speaking, there is (or can be) one NSRunLoop per thread, not only the main thread. But it's still the case that GUI stuff generally needs to run on the main thread.
I recommend that you take the approach of running scraping on a separate thread. This is generally a good idea for any combination of long-running work and GUI — it ensures that the work cannot cause the UI to hang or hiccup.

GPUImage gpus_ReturnNotPermittedKillClient crash using GPUImageFilter

I'm using GPUImageFilter in a chain, and most of the time it works OK. I've recently come across a few random crashes that match the symptoms in this github issue (albeit I'm using GPUImageFilter not live capture or video). I'm trying to find a suitable method that can ensure I've cleared the frame buffer and any other GPUImage-related activities in willResignActive.
Currently I have:
[[GPUImageContext sharedFramebufferCache] purgeAllUnassignedFramebuffers];
Is this sufficient? Should I use something else instead/in addition to?
As indicated there, seeing gpus_ReturnNotPermittedKillClient in a stack trace almost always is due to OpenGL ES operations being performed while your application is in the background or is just about to go to the background.
To deal with this, you need to guarantee that all GPUImage-related work is finished before your application heads to the background. You'll want to listen for delegate notifications that your application is heading to the background, and make sure all processing is complete before that delegate callback exits. The suggestion there by henryl is one way to ensure this. Add the following near the end of your delegate callback:
runSynchronouslyOnVideoProcessingQueue(^{
// Do some operation
});
What that will do is inject a synchronous block into the video processing pipeline (which runs on a background queue). Your delegate callback will block the main thread at that point until this block has a chance to execute, guaranteeing that all processing blocks before it have finished. That will make sure all pending operations are done (assuming you don't add new ones) before your application heads to the background.
There is a slight chance of this introducing a deadlock in your application, but I don't think any of my code in the processing pipeline calls back into the main queue. You might want to watch out for that, because if I do still have something in there that does that, this will lock your application. That internal code would need to be fixed if so.

Triggering via Asynchronous Callbacks

If an application executes a code block asynchronously and notifies the completion state in a callback, do these all leave execution on the main thread (the callback)?
What is the correct way to handle Core Graphics drawing and file operations in this callback?
I currently have these instructions running in the callback, but would like to trigger a thread to handle these instructions instead.
If you are doing any UI drawing, that has to be on the main thread. If you hvae these asynchronous blocks doing work now (ostensibly in a concurrent dispatch queue), why not just do all the work there, and when you have a finished product to show, only then message back on the main block. If your callback calls other methods in your class, the safest way to deal with concurrency is to define helper objects - small objects that take some input and product an output.
Create the helper, attach whatever data it needs, kick it off in a block on a queue, and when its done it messages back on the main thread that extracts the finished product, renders it, then deletes the helper object.
I dont have much experience in Core Graphics, but I've done a good amount of work on blocks.
In my opinion, if your application executes a code block asynchronously (on a new thread), then it's a good practice to the make callback or notification on the main thread.

App stops receiving data from socket when UI scroll

I have an iPad app that receives data using UDP sockets. And it has a UIWebView to browse webpages.
But while doing scroll in the UIWebView, everything freezes and no data is received.
I've been searching and it has something to do with runloops and threads. But if the UIWebView can't run in another thread other than the main one, how can I receive data while doing scroll? It is critical to keep receiving data.
The project uses the AsyncUdpSocket class from Cocoa AsyncSocket that works quite well. And also the singleton class from Matt Gallagher. Everything is running in the main thread, UDP reception and UI.
Thanks in advance!
When you do a scroll, the runloop enters a different mode (UITrackingRunLoopMode) and stops responding to network activity on the main thread. This is done for performance reasons.
You should be able to schedule those updates on the proper runloop mode (UITrackingRunLoopMode I believe). Though, I wouldn't recommend this.
Instead, try setting up your UDP networking code on another thread (or queue, yay GCD!) and schedule callbacks on the main thread to update the UI. This will guarantee the networking thread has the proper runloop mode when getting data back on the socket.

Background network calls - iOS

I need to implement posting some data to a web server in the background. Just to clarify, by "in the background", I don't mean the normal way of showing a spinning icon and posting data to a web service using something like an AsyncTask or ASIHTTPRequest's [request startAsynchronous] method. I need to maintain a queue of data that a Thread can asychronously start processing and posting to a Web service while the user is working in the application.
I'm looking for some help on designing a queue like that, especially in some edge cases like User receiving a call, logging out of the application while the the post is happening, user leaving the application to goto a different one while a post is happening and the like. How would you handle these cases? Is there any source code you can recommend that does this?
Thanks,
Teja.
I've started using NSOperationQueue in my own work lately, for controlling background network requests. NSOperation deals with most of the boilerplate code necessary for asynchronously running tasks (such as network operations) on threads in the background (or foreground, if necessary for UI updates).
It also allows dependencies across queues; for example, I use two queues in my application:
The first schedules image downloads, at a max concurrency of 2 at a time, in the background. Each image download has a corresponding completion handler (as an NSBlockOperation) that is dependent on the image download completing. These operations sit on the [NSOperationQueue mainQueue], which operates on the main thread, allowing them to update UI (specifically, the corresponding UIImageView).
Note that NSOperation and NSOperationQueue are not for network requests only, but any operation that can be divided into atomic tasks and scheduled concurrently.
Here are Apple's intro docs on the topic.
Having implemented something similar myself, I would recommend using a service and not a thread to do network calls. That way even if your activity gets killed you're sure your network calls will be executed.
Then to implement the queue i suggest you take a look into IntentService (http://developer.android.com/reference/android/app/IntentService.html)
from the docs:
IntentService is a base class for Services that handle asynchronous
requests (expressed as Intents) on demand. Clients send requests
through startService(Intent) calls; the service is started as needed,
handles each Intent in turn using a worker thread, and stops itself
when it runs out of work.
This "work queue processor" pattern is commonly used to offload tasks
from an application's main thread. The IntentService class exists to
simplify this pattern and take care of the mechanics. To use it,
extend IntentService and implement onHandleIntent(Intent).
IntentService will receive the Intents, launch a worker thread, and
stop the service as appropriate.
All requests are handled on a single worker thread -- they may take as
long as necessary (and will not block the application's main loop),
but only one request will be processed at a time.
If your application is simple enough you can use sendBroadCast() to share info and notifications between your activity and the IntentService
Create a singleton that encapsulate a thread :
In the initialisation of your object :
[NSThread detachNewThreadSelector:#selector(mainPosterThread) toTarget:self withObject:nil];
- (void)mainDownloaderThread
{
if( [NSThread respondsToSelector:#selector(setThreadPriority:)] )
{
[NSThread setThreadPriority:0.1];
}
NSString *urlToDownload = nil;
while(shouldRun)
{
// Take next data to post in a queue (lastObject of a NSArray for example)
if( nextDataToPost )
{
// Post
}
else
{
// Sleep for some time.
}
}
}
You can also have methods for stopping / starting the thread while the app go background / foreground on a multitask supported device. If no multitasking supported, save the post data in the queue at stop time (if not too long) and restore them at start. The biggest chalenge is to manage be able to cancel the current upload while app will ends.
This is an issue which I've been perfecting in every new application I write. Basically I wanted network functionality which is asynchronous and which was written by me using native functionality. I'd be happy to show you some of this code if you're interested.
First of all, I suggest that you make all network calls on the main thread asynchronously rather than synchronously, using a delegate. This way serialization/synchronization/concurrency is not an issue. And since classes are network delegates, I'd just set up one class to where a new connection has a new delegate instance.
[[NSURLConnection alloc] initWithRequest:request delegate:del] autorelease];
e.g.
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data