Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Concurrent and Asynchronous Programming with Grand Central Dispatch

Nathan Eror
September 13, 2011

Concurrent and Asynchronous Programming with Grand Central Dispatch

Multicore has officially come to iOS devices, and taking advantage of those cores in your apps is simpler than you might think. Concurrent programming is never easy, but GCD makes it a whole lot easier. In this session, you will learn the ins and outs of GCD and how to use it to effectively. We will cover topics like:

* Concurrent and serial queues
* Creating your own queues
* Synchronizing access to shared memory without locks
* Using semaphores to keep execution under control
* Using dispatch sources for asynchronous data access
* Using Instruments to profile and optimize your concurrent and asynchronous code

Nathan Eror

September 13, 2011
Tweet

More Decks by Nathan Eror

Other Decks in Programming

Transcript

  1. WHO AM I? •iOS and Mac developer, consultant and speaker

    •11+ years experience as a developer •Founded Free Time Studios in early 2009 to focus on iOS app and game developent
  2. BLOCKS • Portable anonymous functions • Defined & implemented inline

    or assigned to a variable • Syntax is similar to C function pointers • Used throughout the Cocoa and Cocoa Touch API’s (usually to implement callbacks) • Used in almost all GCD API calls
  3. DEFINING A BLOCK int (^myBlock)(int) = ^(int num) { return

    num * multiplier; }; Return Type Argument type(s) Variable name Argument list Block Body Literal Block Definition
  4. USING BLOCKS Using a Predefined Block Like a Function int

    multiplier = 7; int (^myBlock)(int) = ^(int num) { return num * multiplier; }; printf("%d", myBlock(3)); // prints "21" Inline Blocks as Method Arguments NSArray *myArray = [NSArray arrayWithObjects:@"One", @"Two", @"Three", nil]; [myArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { NSLog(@"Item %d: %@", idx + 1, obj); }]; //Prints //Item 1: One //Item 2: Two //Item 3: Three
  5. BLOCK STORAGE Using the __block Storage Type __block int x

    = 123; // x lives in block storage void (^printXAndY)(int) = ^(int y) { x = x + y; printf("%d %d\n", x, y); }; printXAndY(456); // prints: 579 456 // x is now 579
  6. CAVEATS •Intended for flow control •Once submitted to a queue,

    a block will execute •Be careful with asynchronous API’s
  7. QUEUE TYPES Global Queues dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0); Main Queue dispatch_get_main_queue(); Serial

    Queues dispatch_queue_create("myQueue", DISPATCH_QUEUE_SERIAL); Concurrent Queues dispatch_queue_create("myQueue", DISPATCH_QUEUE_CONCURRENT);
  8. BARRIER BLOCKS •Will not run until all previously submitted blocks

    are executed •Blocks submitted afterwards will not run until the barrier block has completed •Useful for synchronizing access to shared resources
  9. DISPATCH GROUPS •Groups blocks submitted to queues •Can notify once

    all blocks have executed •Can also block the thread until all blocks have executed
  10. DISPATCH SEMAPHORES •Used to regulate the use of finite resources

    •Just just like a regular semaphore, but faster Using Semaphores dispatch_semaphore_t semaphore = dispatch_semaphore_create(5); dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); // ... DO STUFF ... dispatch_semaphore_signal(semaphore);
  11. DISPATCH ONCE •Guarantees a block is executed only once •Thread

    safe Using dispatch_once for singletons + (MyClass *)sharedInstance { static dispatch_once_t onceToken; static AppDelegate *singleInstance; dispatch_once(&onceToken, ^{ singleInstance = [[MyClass alloc] init]; }); return singleInstance; }