CoreData Multithreading Proper Store Deletion - objective-c

Ok, here's my situation:
I've got an app which requires a user-account.
While you're doing stuff like writing new comments, creating new Posts or reading a thread, every call to the server runs on a separate thread.
More specifically: A new thread is created, makes a call to the server, gets an answer from the server and saves the items from the answer to the Core Data Store.
In order to do this, every thread creates his own insertionContext, but they all share the same storeCoordinator.
But there's one Problem:
When someone does a logout from his account, I have to delete the store,
so if he logs in with another account, the stuff from the other account isn't in the coreDataStorage anymore.
But in Order to delete the Store, I have to make sure that there aren't any background Threads running anymore, because once they try to to save their stuff, they are sure to crash the app, since the store isn't valid anymore.
To clarify: these background threads are NSOperations which are put in an NSOperationQueue and executed from there.
Now CoreData gives the NSOperationQueue a function called "cancelAllOperations" but according to the Documentation, running Operations aren't killed, but only send a cancel message...
How do I use this cancel Message o_O
So far i'm checking at some points whether my thread is canceled and if it is, I don't execute other stuff, but if I do stuff like:
NSError *saveError = nil;
if(!self.isCanceled)
[insertionContext save:&saveError];
There is still the possibility that the Thread is being canceled between the if-check and the save.
So my question:
How do I handle this properly? Is it a question of properly canceling the thread?

I think you should not cancel any operations since it does not kill the thread immediately. Why don't you manage all operations that are currently being executed? This way you can postpone persistent store deletion until all tasks complete (or delete it immediately if there are no operations in progress).

Related

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.

Synchronizing dependent asychnronized functions Objective C

So I am running into a race condition and I have a few solutions on how to fix the issue. I am new to threading so obviously, my opinion and research is limited. I have a large amount of asynchronization calls that can happen if a user receives certain messages from server. Thus, my design is poor due to the dependent nature of my objects.
Lets say I have a function called
adduser:(NSString s){
does some asynchronize activity
}
Messageuser:(NSString s)
{
Does some more asychronize activity
}
if a user were to recieve a message telling it to addUser "Ryan". he would than create a thread and proceed with looking up Ryan and storing him. However, if the user has the application in suspended mode, and in the buffered of messages waiting to be recieved there is a addUser request and a MessageUser request, a race condition occures because it takes longer to complete Adduser than it does to complete MessageUser. Thus, If messageUser is called , and (in our example) "Ryan" has not been fully added, it throws an error.
What would be a possible solution to this issue. I looked into locks and semaphores, and what I am trying to do is, when MessageUser recieves a call, check to make sure there is no thread currently proccessing addUser. If there is none, proceed. Else wait, than proceed after it has finished.
Well it depends on how the messages are being issued in the first place and what the async response events are.
If the operations have dependencies (ordering requirements) then perhaps a background serial queue would be appropriate? That is a simple way to ensure the messages are processed in order.
If the async operations take completion blocks, then you could have the completion block issue the request for the next operation to be performed, though you may not know about that ahead of time.
If you need to solve this in a more general way then you need some kind of system for tracking prerequisites so you can skip work items that don't have their prerequisites met yet. That probably means your own background thread that monitors a list of waiting tasks and receives notification of all task completions so it can scan for items waiting on that completion and issue them.
It seems really complicated though... I suspect you don't really have such strong async parallel processing requirements and a much simpler design would be just as effective. Given your situation where you are receiving messages from a server, I think a serial queue would be the best option. Then you can process messages in the order the server sent them and keep things simple.
//do this once at app startup
dispatch_queue_t queue = dispatch_queue_create("com.example.myapp", NULL);
//handle server responses
dispatch_async(queue, ^{
//handle server message here, one at a time
});
In reality, depending on how you connect to your server you might be able to just move the entire connection handling to the background queue and communicate with it via messages from the UI, and update the UI by dispatching to the dispatch_get_main_queue() which will be the UI thread.

Saving managed object context creates deadlock in iOS 5's performBlock

I've been looking for a solution for this problem for a long time and have yet reached one.
I'm developing an iOS app with core data. I've created two managed object contexts (MOC) which point to the same persistent store coordinator. One MOC (referred as self.moc) is initiated with main queue concurrency whereas the other mov (referred as self.bmoc) is initiated with private queue concurrency. I've made sure that self.moc only runs on the main thread and self.bmoc only runs within its performBlock or performBlockAndWait block.
However, I've encountered this strange situation where my app freezes on the [self.bmoc save:nil] line. Since the save action is executed within the performBlock block, I don't see a reason for it to reach a deadlock. Since it freezes on that line, I can't receive an error even if I use [self.bmoc save:&error] rather than nil.
Below is the code which will reproduce the problem. Although I have many functions similar to the one below, only this one creates the problem. I fail to figure the cause of the problem and any insight is greatly appreciated. Thank you!
-(void)createEmptyUserData {
[self.bmoc performBlock:^{
User* user = [NSEntityDescription insertNewObjectForEntityForName:#"User" inManagedObjectContext:self.bmoc];
/* sets user object */
[self.bmoc save:nil];
}];
}
Note: This piece of code is executed in main thread.
There are two basic reasons for you to get a "hang" in that situation.
You have a nested call to performBlockAndWait or some other synchronous thread/queue call.
One of your blocks is not returning, and running forever.
Both of these can be easily seen by looking at the stacks of each running thread at the time of the "hang."
performBlock simply takes the execution block and adds it to a queue, then it returns immediately. Some other thread is then popping execution blocks off the queue and executing them.
performBlockAndWait executes in the context of the calling thread. Basically, it waits for currently enqueued execution blocks to run, then it runs the requested code on the current thread.
It des not return until the call is complete.
So, I'd bet you either have multiple nested calls to performBlockAndWait OR one of your asynchronous execution blocks is not completing.
Look at the stack at the time of the hang...
Alternatively, log your block execution, so you can see when each block starts and exits.

Exiting application iOS

When my application loads, using the didFinishLaunchingWithOptionsi parse data from the internet to nsarrays. My question is, when the user exists the application by using the 'home' button, and then loads the application again how can the data be re-loaded? (because if the data does not reload - if there are any updates on websites, the new updates will not be seen).
Add an applicationWillEnterForeground method to your app delegate. Load the data there, or start a thread to load it if you like.
You should probably also periodically check for new data even while the app remains open, because the user could go idle for a long time.
As an aside, you shouldn't do anything which might block in applicationDidFinishLaunchingWithOptions. If you are using synchronous NSURLConnection APIs there is a danger the OS might kill your app for taking too long to launch. Best to either use the asynchronous/NSURLConnectionDelegate APIs or do the networking on a background thread and call back to the main thread when you need to update UI (UIKit does NOT like being called from background threads, as it is not thread safe. It might appear to work sometimes, but it will come back to bite you sooner or later).

Matching CoreData save notifications for callbacks

I'd like to pick someone's brain on this. I have a dedicated save NSManagedObjectContext and GCD queue from which I operate on it. And whenever new data comes into my app I save it on that context and merge the changes into the main context. My problem arises in telling the main thread what just happened. Right after I call save my current context is now up-to-date, but if I fire a method in the main context it's context isn't. If I wait for the NSManagedObjectContextDidSave notification, and I save three times, I now have three queued delegate calls but no way to match them to the notifications coming in. Does anyone know of a good way to get around this?
EDIT
What I ended up doing was creating a new context for each save operation and attaching a block to be called when the save notification arrived. It looks like this, http://pastie.org/2068084
From your answer to my comment above, I see that you pass along the managedObjectContext in the notification. I'm not that confident about asynchronous stuff yet, but I do think that you're violating some concurrency rule, if I correctly interpret this quote from the NSManagedObjectContext Class Reference:
Concurrency
Core Data uses thread (or serialized queue) confinement to protect managed objects and managed object contexts (see “Concurrency with Core Data”). A consequence of this is that a context assumes the default owner is the thread or queue that allocated it—this is determined by the thread that calls its init method. You should not, therefore, initialize a context on one thread then pass it to a different thread. Instead, you should pass a reference to a persistent store coordinator and have the receiving thread/queue create a new context derived from that.
I'd say, try passing along the persistent store coordinator in the notification and recreate the managed object context in the block.
I'm not sure what you mean by, " ...if I fire a method in the main context it's context isn't. If I wait for the NSManagedObjectContextDidSave..." That implies that you are not waiting until the contexts have been merged. If so, that is why you can't access the data, it's just not in the front context.
Do you call mergeChangesFromContextDidSaveNotification: from the front context after it receives the notification?