Chapter 2. Programming Grand Central Dispatch

Grand Central Dispatch, or GCD for short, is a low-level C API that works with block objects. The real use for GCD is to dispatch tasks to multiple cores without making you, the programmer, worry about which core is executing which task. On Mac OS X, multicore devices, including laptops, have been available to users for quite some time. With the introduction of multicore devices such as the iPad 2, programmers can write amazing multicore-aware multithreaded apps for iOS. See the preface for more background on the importance of multicores.

In Chapter 1 we learned how to use block objects. If you have not read that chapter, I strongly suggest that you do straight away, as GCD relies heavily on block objects and their dynamic nature. In this chapter, we will learn about really fun and interesting things that programmers can achieve with GCD in iOS and Mac OS X.

At the heart of GCD are dispatch queues. Dispatch queues, as we will see in Different Types of Dispatch Queues, are pools of threads managed by GCD on the host operating system, whether it is iOS or Mac OS X. You will not be working with these threads directly. You will just work with dispatch queues, dispatching tasks to these queues and asking the queues to invoke your tasks. GCD offers several options for running tasks: synchronously, asynchronously, after a certain delay, etc.

To start using GCD in your apps, you don’t have to import any special library into your project. Apple has already incorporated GCD into various frameworks, including Core Foundation and Cocoa/Cocoa Touch. All methods and data types available in GCD start with a dispatch_ keyword. For instance, dispatch_async allows you to dispatch a task on a queue for asynchronous execution, whereas dispatch_after allows you to run a block of code after a given delay.

Traditionally, programmers had to create their own threads to perform tasks in parallel. For instance, an iOS developer would create a thread similar to this to perform an operation 1000 times:

- (void) doCalculation{

  /* Do your calculation here */

}

- (void) calculationThreadEntry{

  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

  NSUInteger counter = 0;

  while ([[NSThread currentThread] isCancelled] == NO){

    [self doCalculation];

    counter++;

    if (counter >= 1000){
      break;
    }

  }

  [pool release];

}

- (BOOL)              application:(UIApplication *)application
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{

  /* Start the thread */
  [NSThread detachNewThreadSelector:@selector(calculationThreadEntry)
                           toTarget:self
                         withObject:nil];

  // Override point for customization after application launch.
  [self.window makeKeyAndVisible];
  return YES;
}

The programmer has to start the thread manually and then create the required structure for the thread (entry point, autorelease pool, and thread’s main loop). When we write the same code with GCD, we really won’t have to do much:

dispatch_queue_t queue =
  dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

size_t numberOfIterations = 1000;

dispatch_async(queue, ^(void) {
  dispatch_apply(numberOfIterations, queue, ^(size_t iteration){
    /* Perform the operation here */
  });
});

In this chapter, you will learn all there is to know about GCD and how to use it to write modern multithreaded apps for iOS and Mac OS X that will achieve blazing performance on multicore devices such as the iPad 2.