Thursday, April 07, 2011

WWDC2010 Session206 Introducing Blocks and Grand Central Dispatch (2)

Grand Central Dispatch

With GCD, you can make your app responsive. Threading is hard. Using GCD makes it simple and fun. You need not do explicit thread management. Cool!

Keeping your app responsive:

1. Do not block the main thread

2. Move work to another thread

3. Update UI back on main threaad

Code without GCD:

- (void)addTweetWithMsg:(NSString*)msg url:(NSURL*)url {

  // Controller UI callback on main thread

  DTweet *tw = [[DTweet alloc] initWithMsg:msg];

  [tweets addTweet:tw display:YES];

  tw.img = [imageCache getImgFromURL:url];//bottle neck

  [tweets updateTweet:tw display:YES];

  [tw release];

}

Code with GCD:

- (void)addTweetWithMsg:(NSString*)msg url:(NSURL*)url {

  // Controller UI callback on main thread

  DTweet *tw = [[DTweet alloc] initWithMsg:msg];

  [tweets addTweet:tw display:YES];

  dispatch_async(image_queue, ^{

    tw.img = [imageCache getImgFromURL:url];

    dispatch_async(main_queue, ^{

      [tweets updateTweet:tw display:YES];

    });

  });

  [tw release];

}

GCD Queues

1. Lightweight list of blocks

2. Enqueue/dequeue is FIFO

3. Enqueue with dispatch_async()

4. Dequeue by automatic thread or main thread

Main Queue

1. Executes blocks one at a time on main thread

2. Cooperates with the UIKit main run loop

3. dispatch_get_main_queue()

Creating your own queues

1. Execute blocks one at a time

2. On automatic helper thread

3. “Queue up” background work

dispatch_queue_t queue;

queue = dispatch_queue_create(“com.example.purpose”, NULL);

dispatch_release(queue);

Queues Instead of Locks

1. Enqueuing is thread-safe.

2. Execution is serial

3. Protect access to shared data

4. Queues are lightweight

Managing Queue Lifetime

1. Queues are reference counted. dispatch_retain() / dispatch_release()

2. GCD retains parameters to dispatch API as necessary

3. Ensure correct queue lifetime across asynchronous operations

4. Ensure objects captured by blocks are valid when blocks are executed

5. Objective-c objects are auto-retained/released

6 Other objects must be retained by your code. CFRetain() / CFRelease()

- (void)asyncParseData:(NSData *)date

          queue:(dispatch_queue_t)queue

          block:(void (^)(id result))block {

  dispatch_retain(queue);

  dispatch_async(self.parse_queue, ^{

    id result = [self parseData:data];

    dispatch_async(queue, ^{

      block(result);

    });

    dispatch_release(queue);

  });

}

App Design with Queues

Demo app tasks

1. Receive and parse network stream

2. Maintain message history

3. Fetch and cache images

4. Display user interface

Without GCD

  NSData *d = [twitterStream receiveData];

  DTweet *tw = [[DTweet alloc] initWithData:d];

  [[tweets addTweet:tw];

  [viewController displayTweet:tw]; });

  tw.img = [imageCache getImgFromURL:tw.url];

  [viewController updateTweetDisplay:tw];

  [tw release];

With GCD

dispatch_async(network_queue, ^{

  NSData *d = [twitterStream receiveData];

  DTweet *tw = [[DTweet alloc] initWithData:d];

  dispatch_async(tweets_queue, ^{

   [[tweets addTweet:tw];

   dispatch_async(main_queue, ^{

   [viewController displayTweet:tw]; });

   });

   dispatch_async(image_queue, ^{

   tw.img = [imageCache getImgFromURL:tw.url];

   dispatch_async(main_queue, ^{

   [viewController updateTweetDisplay:tw];

   });

   });

  });

  [tw release];

});

Pitfalls

1. Avoid blocking per-subsystem queues

2. Be careful when waiting. (deadlock)

3. Blocked worker threads consume resources

Responding to External Events

Dispatch sources

1. Monitor external events

- Files, Network Sockets, Directories, Timers

2. Event handlers can be delivered to any queue

3. Use sources to replace polling or blocking API calls

4. See session 211:

Simplifying iPhone App Development with Grand Central Dispatch

Where do I find GCD?

1. GCD is part of libSystem.dylib

2. #include <dispatch/dispatch.h>


WWDC2010 Session206 Introducing Blocks and Grand Central Dispatch on iPhone

Author: Kevin van Vechten - Manager, Core OS

No comments: