3. GCD: An Overview
Concurrency
do multiple things simultaneously
take advantage of multiple cores
Traditional way: create multiple threads
not efficiently: unused or overused cores
low-level, waste time to create and destroy thread
thread programming is hard
Modern way: Grand Central Dispatch (GCD)
4. GCD: An Overview
easier, more modern and efficient than threads
high-level, move thread management down to system level
define tasks and add them to an appropriate dispatch queues
task management and execution is more efficient than threads
new concepts: task and dispatch queues
5. GCD: An Overview
in waiting
a queue - FIFO
put task into queue dequeued tasks
to execute are being executed
if there are some queues, they could still execute tasks concurrently
6. Blocks
blocks
task is defined by using block
blocks are an extension of C language
encapsulate code like a function by using ^{ … }
define blocks
// Simple one
void (^myblock)() = ^{
printf(“Hellon”);
};
myblock(); //executing block
7. Blocks (cont.)
with arguments
void (^myblock)(int) = ^(int arg){
printf(“Helloarg=%dn”,arg);
};
myblock(1);
with return value
int (^myblock)(int) = ^(int arg){
printf(“Hello arg=%dn”,arg);
return arg+1;
};
int r = myblock(1);
http://developer.apple.com/library/ios/#documentation/cocoa/Conceptual/Blo
cks/Articles/bxGettingStarted.html#//apple_ref/doc/uid/TP40007502-CH7-SW1
8. Dispatch Queues
Overview
dispatch queues
C based, procedural programming
easy way to perform tasks asynchronously and concurrently
add a task into the queues to perform it
3-types of dispatch queues
serial (private dispatch queue) execute one task at a time
concurrent (global dispatch queue) execute one or more task concurrently
main dispatch queues execute task on main thread
9. Dispatch Queues
Creating dispatch queues
dispatch_queue_t queue;
// Main (serial) queue
queue = dispatch_get_main_queue();
// User (serial) queue
queue = dispatch_queue_create(“com.mycompany.qname”, NULL);
// Global (concurrent) queue, with priority
queue = dispatch_get_global_queue(
DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
notes:
there are 3 global queues by priority: HIGH, DEFAULT, LOW
you can create as many serial queue as you need
10. Dispatch Queues
Adding tasks to a queue
synchronous
// Synchronous, blocks until code is executed
dispatch_sync(queue, ^{
//taskcode
});
asynchronous
// Asynchronous, returns immediately to caller
dispatch_async(queue, ^{
//taskcode
});
dispatch_after(when, queue, ^{
//taskcode
});
11. Dispatch Queues
more
suspend a queue
dispatch_suspend(queue);
resume a queue
dispatch_resume(queue);
memory management
Dispatch queues are reference-counted data types.When you create a serial
dispatch queue, it has an initial reference count of 1.You can use the
dispatch_retain and dispatch_release functions to increment
and decrement that reference count as needed. When the reference count of
a queue reaches zero, the system asynchronously deallocates the queue.
13. Operation Queues
Creating operations
by selector
NSInvocationOperation* theOp = [[NSInvocationOperation alloc]
initWithTarget:self selector:@selector(myTaskMethod:) object:data];
by block
NSBlockOperation *operation = [NSBlockOperation
blockOperationWithBlock:^{
NSLog(@"Doing something...");
}];
//you can add more blocks
[operation addExecutionBlock:^{
NSLog(@"Another block");
}];
[operation setCompletionBlock:^{
NSLog(@"Doing something once the operation has finished");
}];
14. Operation Queues
Executing operations
adding operation to NSOperationQueue
NSOperationQueue* aQueue = [[NSOperationQueue alloc] init];
[aQueue addOperation:anOp]; // Add a single operation
// Add multiple operations
[aQueue addOperations:anArrayOfOps waitUntilFinished:NO];
[aQueue addOperationWithBlock:^{
/* Do something. */
}];
You can execute operations manually by reading document from:
http://developer.apple.com/library/ios/#documentation/General/
Conceptual/ConcurrencyProgrammingGuide/OperationObjects/Operation
Objects.html#//apple_ref/doc/uid/TP40008091-CH101-SW1
15. Operation Queues
More
suspending and resuming operation queues
- (void)setSuspended:(BOOL)suspend
cancels all queued and executing operation
- (void)cancelAllOperation
reference links:
https://developer.apple.com/library/mac/#documentation/Cocoa/Refe
rence/NSOperationQueue_class/Reference/Reference.html
https://developer.apple.com/library/mac/#documentation/Cocoa/Refe
rence/NSOperation_class/Reference/Reference.html
16. Dispatch Group
use to group some blocks and track when they all complete
it can be helpful when progress can’t be made until all of the specified
tasks are complete
dispatch_queue_t queue = dispatch_get_global_queue(0,0);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group,queue,^{
NSLog(@"Block 1");
});
dispatch_group_async(group,queue,^{
NSLog(@"Block 2");
});
dispatch_group_notify(group,queue,^{
NSLog(@"Final block is executed last after 1 and 2");
});
17. Dispatch Semaphore
In computer science, a semaphore is a variable or abstract data type that provides
a simple but useful abstraction for controlling access by multiple processes to a
common resource in a parallel programming or multi user environment.
(wikipedia)
use a dispatch semaphore to regulate the number of tasks simultaneously
accessing some resources
// Create the semaphore, specifying the initial pool size
dispatch_semaphore_t fd_sema = dispatch_semaphore_create
(getdtablesize() / 2);
// Wait for a free file descriptor
dispatch_semaphore_wait(fd_sema, DISPATCH_TIME_FOREVER);
fd = open("/etc/services", O_RDONLY);
// Release the file descriptor when done
close(fd);
dispatch_semaphore_signal(fd_sema);
18. Examples
Example 1: Download Image with dispatch queue
dispatch_queue_t queue = dispatch_queue_create(”image_queue”
, NULL);
//dispatch_async to get the image data
dispatch_async(queue, ^{
NSData *data = [NSData dataWithContentsOfURL:
[NSURL URLWithString:url]];
UIImage *anImage = [UIImage imageWithData:data];
[self.images setValue:anImage forKey:userID];
UITableViewCell *cell = [self.tableView
cellForRowAtIndexPath:indexPath];
//dispatch_async on the main queue to update the UI
dispatch_async(dispatch_get_main_queue(), ^{
cell.imageView.image = anImage;
});
});
run a heavy work on background and update GUI on main thread
19. Examples
Example 2: Callback block
#import "ASIHTTPRequest.h”
- (void)getImage {
__block ASIHTTPRequest *request = [ASIHTTPRequest
requestWithURL:sourceURL];
[request setCompletionBlock:^{
NSLog(@"Image downloaded.");
NSData *data = [request responseData];
image = [[UIImage alloc] initWithData:data];
}];
[request setFailedBlock:^{
NSLog(@"Error downloading image");
}];
[request startAsynchronous];
}
the OS will automatically run the code to download the image on a
background thread, and call one of the callback blocks when it completes or fails!
Our topic today is Grand Central Dispatch.It takes about 15 minutes to covers all issues
Here are contents of my presentation
Firstly, I want to talk about an overview of GCDGCD is a new technology to perform concurrent programming.As you know, creating multiple threads is traditional way to do this.Assume, if you want to download a file in background, you will have to create a thread and attach this work on this thread.But threading is not efficient because it doesn’t take advantage of multiple core efficiently.
So that apple has invented GCD to do concurrency easier, more modern and efficient.It moves thread management down to system level.All you have to do is only creating tasks and putting them into dispatch queues.
You can see it more “ro rang” in this picture.Two steps to perform concurrently a task. Defines a task and put it into the dispatch queues.
Let’s go to step 1.You define a task by using block.Blocks are an extension of C language.To define a block you simply “wraps” code in ^{ .. }