Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Threading in iOS / Cocoa Touch

3,822 views

Published on

Karol Kozimor talking at Cracow.mobi 2011

Published in: Technology, Education
  • Be the first to comment

Threading in iOS / Cocoa Touch

  1. 1. simply mobile
  2. 2. About MeUsed to be a Linux kernel developerCurrently developing hardware accessories for iOS © 2011
  3. 3. What this talk isn’t about © 2011
  4. 4. What this talk isn’t aboutHardware accessories © 2011
  5. 5. What this talk isn’t aboutHardware accessoriesApp Store overnight success © 2011
  6. 6. What this talk isn’t aboutHardware accessoriesApp Store overnight successPOSIX threads © 2011
  7. 7. 150% thread content © 2011
  8. 8. Plan1. Why we love and hate threads2. Grand Central Dispatch3. NSThread class © 2011
  9. 9. Threading © 2011
  10. 10. ThreadingNot only for multi-core chips © 2011
  11. 11. ThreadingNot only for multi-core chipsResponsiveness is the king © 2011
  12. 12. ThreadingNot only for multi-core chipsResponsiveness is the king“The snappy” © 2011
  13. 13. ThreadingNot only for multi-core chipsResponsiveness is the king“The snappy”Asynchronicity © 2011
  14. 14. Half-measuresAsynchronous I/OCoreDataNotifications and KVO © 2011
  15. 15. General solutionThreads © 2011
  16. 16. DownsidesOverheadEspecially on embedded systems#1 issue: threads are difficult © 2011
  17. 17. Really?Thread managementIPC, messaging, synchronizationLockingReentrancy??? © 2011
  18. 18. SolutionGrand Central Dispatch © 2011
  19. 19. Grand Central DispatchLanguage featuresRuntime librariesSystem enhancements © 2011
  20. 20. TogetherAutomate thread management © 2011
  21. 21. Language features: blocksSmall, self-contained pieces of codeAnonymous, inline collection of codeAvailable: Snow Leopard, iOS 4.0 © 2011
  22. 22. Blocks featuresTyped argumentsReturn valueAccess (and modify) variables © 2011
  23. 23. Mainly useful asCallbacksSelf-contained units of work © 2011
  24. 24. SyntaxBOOL (^block)(void);BOOL areKittensCute = YES;block = ^{ return areKittensCute; }; © 2011
  25. 25. Example- (void)blink:(UIColor *)color{ self.view.backgroundColor = color; [UIView animateWithDuration:1.0animations:^{self.view.backgroundColor = [UIColordarkGrayColor];}];} © 2011
  26. 26. Grand Central APIGCD provides FIFO queues for blocksThree types: Main Concurrent Serial © 2011
  27. 27. Concurrent queuesBlocks dequeued in FIFO order… but run concurrently if resources allowFinish in any orderCreated automatically © 2011
  28. 28. Serial queuesUseful for serialization of tasksCreated manuallydispatch_queue_create(“com.yourname.queue”, NULL); © 2011
  29. 29. Really?Thread managementIPC, messaging, synchronizationLockingReentrancy??? © 2011
  30. 30. When queues are not enough Dispatch sources © 2011
  31. 31. Dispatch source APIC-level APICan monitor for events (signals, data) and dispatchhandlers to appropriate queuesLow-level, useful for OS X but maybe not for iOS © 2011
  32. 32. Back to square oneNSThread class © 2011
  33. 33. The real thingCost of threads:Creation timeMemory footprint (512 kB)Design overhead © 2011
  34. 34. Conclusion — Don’t use threads! © 2011
  35. 35. … unless you have no other choiceHigh level event monitoring © 2011
  36. 36. Thread lifecycle1. Initialize2. Start 1. Create autorelease pool, setup sources 2. Do work3. Cancel4. Drain pool © 2011
  37. 37. Thread initnewThread = [[NSThread alloc] initWithTarget:selfselector:@selector(newThreadEntryPoint:) object:nil]; © 2011
  38. 38. Entry point- (void)newThreadEntryPoint:(id)param{ …} © 2011
  39. 39. Thread start[newThread start]; © 2011
  40. 40. Housekeeping- (void)newThreadEntryPoint:(id)param{ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init]; …} © 2011
  41. 41. Get to workTwo options: Execute a predefined workset Monitor for eventsRun loop © 2011
  42. 42. Event sourcesNSInputStream *catnipStream;[catnipStream setDelegate:self];[catnipStream scheduleInRunLoop:[NSRunLoop currentRunLoop]forMode:NSDefaultRunLoopMode];[catnipStream open]; © 2011
  43. 43. Running the loopdo {[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopModebeforeDate:[NSDate distantFuture]]; } while (!done); © 2011
  44. 44. The whole package- (void)runThread{ newThread = [[NSThread alloc] initWithTarget:self selector:@selector(newThreadEntryPoint:)object:nil]; [newThread start];}- (void)newThreadEntryPoint:(id)param{ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; [catnipStream setDelegate:self]; [catnipStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; [catnipStream open]; do { [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; } while (!done);} © 2011
  45. 45. Reuse & recycleWhat if I need on-demand threads? © 2011
  46. 46. Run loop maintenancedo { [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];} while (!done); © 2011
  47. 47. Run loop maintenancedo { [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];} while ([[NSThread currentThread] isCancelled] == NO); © 2011
  48. 48. Run loop maintenancedo { [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:5]];} while ([[NSThread currentThread] isCancelled] == NO); © 2011
  49. 49. Clean up![catnipStream close];[catnipStream removeFromRunLoop:[NSRunLoop currentRunLoop]forMode:NSDefaultRunLoopMode];[catnipStream setDelegate:nil]; © 2011
  50. 50. A lot of code? - (void)runThread{ newThread = [[NSThread alloc] initWithTarget:self selector:@selector(newThreadEntryPoint:)object:nil]; [newThread start];}- (void)newThreadEntryPoint:(id)param{ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; [catnipStream setDelegate:self]; [catnipStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; [catnipStream open]; do { [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDatedateWithTimeIntervalSinceNow:5]]; } while ([[NSThread currentThread] isCancelled] == NO); [catnipStream close]; [catnipStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; [catnipStream setDelegate:nil]; [pool drain];} © 2011
  51. 51. More maintenance Consider draining the autorelease pool from within the loop if the thread will be running for a long time do { [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDatedateWithTimeIntervalSinceNow:5]]; [pool drain]; pool = [[NSAutoreleasePool alloc] init]; } while ([[NSThread currentThread] isCancelled] == NO); © 2011
  52. 52. How to quit?[newThread cancel];Safe to use from any thread © 2011
  53. 53. ConclusionsiOS applications are heavily threaded internallyMain thread, web rendering thread etc.GCD is also implemented via threads © 2011
  54. 54. CaveatsKey-value observers are always executed in thecurrent thread contextWhat happens when KVO from secondary threads isused to handle or update UI outlets? © 2011
  55. 55. SolutionperformSelectorOnMainThread:(SEL)aSelectorwithObject:(id)arg waitUntilDone:(BOOL)wait(on secondary thread)[selfperformSelectorOnMainThread:@selector(updateFields:) withObject:data waitUntilDone:YES]; © 2011
  56. 56. Why?Responsiveness! © 2011
  57. 57. Questions? Karol Kozimorkarol.kozimor@iosyn.com © 2011
  58. 58. More infoConcurrency Programming Guide Operation QueuesThreading Programming GuideWWDC 2011: Blocks and Grand Central Dispatch inPractice © 2011

×