Monday, July 15, 2013

Asynchronous Synchronization - A Warning !

In my last post, Asynchronous Synchronization, I explained how to wait for an I/O process to finish before resuming your app.

This works fine, unless you're working with false assumptions.
And that's what I'm writing about today.

Taking the same code sample as in Asynchronous Synchronization:

 - (void)actionOnDocument:(void (^)(PDFDocument *pdfDoc))actionHandler  
 {  
   __block bool isFileOpened = NO;  
   [doc openWithCompletionHandler:^(BOOL success) {  
     if (success) {  
       actionHandler(doc.data);  
       // save and close  
       [doc saveWithCompletion:^(BOOL success) {  
         isFileOpened = YES;  
       }];  
     }  
     else {  
       actionHandler(nil);  
       isFileOpened = YES;  
     }  
   }];  
   // loop-lock  
   while(!isFileOpened){  
     [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];  
   }  
 }  

Now the problem: What if the local 'doc' variable turns out to be NIL ???

I had this issue today. After hours of hunting for memory problems, this was the problem.

What happens when doc is nil:

1 - doc is nil
2 - openWithCompletionHandler is called on a nil-object (i.e. nothing happens)
3 - the completion handler is never called
4 - isFileOpened remains NO forever
5 - the app remains in the while-loop forever
6 - we have a memory problem ;)

In this case the solution was simple. Encapsulate the whole function in a if(doc){...} caption, and we're safe.

This reminds me of why while(...) loops are so dangerous ;)


Have Fun & Keep Koding!  
Freek Sanders.
MakeMeBlue









No comments:

Post a Comment