Pragma Night @ Talent Garden
Blocks
and
Grand Central Dispatch
Matteo Battaglio
giovedì 7 febbraio 13
Pragma Night
Blocks
giovedì 7 febbraio 13
Pragma Night
What are Blocks?
• an extension to the C language and its derivatives
Objective-C and C++, introduced by Apple
• available in iOS SDK since version 4.0
• already used by plenty of iOS frameworks’ APIs
Blocks are:
giovedì 7 febbraio 13
Pragma Night
Benefits
• more functional style of coding
• less boilerplate code
• more readable code
• simplify event-driven scenarios (i.e. callbacks)
• simplify multi-threading
giovedì 7 febbraio 13
Pragma Night
Definition
• ‘block’ is the name Objective-C gives to the
concept of closure, that is:
• a pointer to a function
• a copy of some of the local variables of its
higher-order function
giovedì 7 febbraio 13
Pragma Night
Syntax
int multiplier = 7;
int (^myBlock)(int) = ^(int num) { return num * multiplier; };
Declaration of the variable
‘myBlock’.
The ‘^’ tells that its type is a block.
Return type Parameter list
Definition of the variable ‘myBlock’,
using a block literal.
The parameter is
named ‘num’.
Body of the block.
giovedì 7 febbraio 13
Pragma Night
Key features
• allow code to be passed around for later
execution
• access to the local variables of the function they
were declared in
• mantain a state among calls
giovedì 7 febbraio 13
Pragma Night
Code example #1
int multiplier = 7;
// Declaring a block and assigning it to the variable ‘myBlock’
int (^myBlock)(int) = ^(int num) { return num * multiplier; };
// Calling the block
printf(myBlock(3)); // prints '21'
Calling a block in no different
than calling a function
giovedì 7 febbraio 13
Pragma Night
Code example #2
// Inline use of a block literal (as an actual parameter of a function)
char *myCharacters[3] = { "TomJohn", "George", "Charles Condomine" };
qsort_b(myCharacters, 3, sizeof(char *), ^(const void *l, const void *r) {
char *left = *(char **)l;
char *right = *(char **)r;
return strncmp(left, right, 1);
});
// myCharacters is now { "Charles Condomine", "George", "TomJohn" }
qsort_b() will internally call the block many times, in order
to compare each pair of cells in the array
giovedì 7 febbraio 13
Pragma Night
Code example #3
// Declaring a function that takes a block as parameter
void myFunction(int (^aBlock)(void *, void *));
// Declaring a function that returns a block
void (^myFunction(int a, int b))(double, double);
Function name Function parameters The function’s return type is a block with signature
void (^)(double, double)
giovedì 7 febbraio 13
Pragma Night
Code example #4
// Defining a custom name for our block type to improve code style
typedef void (^MyBlockType)(double, double);
// Variable and function declarations now look much more readable
MyBlockType myBlock = ^(double a, double b) { printf("hey!"); };
MyBlockType myFunction(int a, int b, MyBlockType aBlock);
giovedì 7 febbraio 13
Pragma Night
Variables caveats
• non-local variables in blocks are constant and
read-only
Trying to modify ‘i’ from inside the block
results in a compilation error.
• in order to make them ‘live’ and writable the
__block type specifier must be added to their
declaration
giovedì 7 febbraio 13
Pragma Night
__block
• what __block does is:
• pass the variable by reference - rather than by
value - to the block
• create a strong (as opposed to weak) reference
to that variable
int myFunction() {
__block int i = 0;
void (^myBlock)(void) = ^{
i++;
printf("i has the value %d", i); // prints 'i has the value 1'
};
}
giovedì 7 febbraio 13
Pragma Night
State representation
• blocks can use variables marked with __block to
keep a state among calls
int myFunction() {
__block int i = 0;
void (^myBlock)(void) = ^{
i++;
printf("i has the value %d", i);
};
myBlock(); // prints 'i has the value 1'
myBlock(); // prints 'i has the value 2'
}
giovedì 7 febbraio 13
Pragma Night
Information hiding
int array[] = {4, 5, 2, 6, 1};
qsort_b(array, 5, sizeof(int), ^(void) {
__block int sum = 0;
return ^(const void *a, const void *b) {
sum += (int)a;
return a - b;
};
}());
The outer block defines a local variable that is used inside the
inner block to mantain a state: this way we are keeping the sum
variable hidden to the rest of the program
The inner block is what gets passed to the qsort_b() function
These parentheses tell us that the outer block is
executed, and not passed to qsort_b.
giovedì 7 febbraio 13
Pragma Night
__block implications
• variables marked with __block are shared
between their lexical scope and all blocks and
block copies declared or created within that scope
• multiple blocks can simultaneously use a shared
variable
• when a block is copied (i.e. it is moved from the
stack to the heap), they survive the destruction
of their stack frame
giovedì 7 febbraio 13
Pragma Night
Memory concerns
• a block is allowed to access self
• self is passed as a strong reference
• this could lead to a ‘retain cicle’
• trick: define a __weak reference to self
int myFunction() {
__weak MyObject weakSelf = self;
void (^myBlock)(void) = ^{
[weakSelf someMethod];
}
}
giovedì 7 febbraio 13
Pragma Night
Common scenarios in the SDK
NSArray *array = [NSArray arrayWithObjects:@"One", @"Two", @"Three", @“Four”, nil];
[array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSLog(@"array[%d] = %@", idx, obj);
}];
[array enumerateObjectsWithOptions: NSEnumerationConcurrent usingBlock:
^(id obj, NSUInteger idx, BOOL *stop) {
NSLog(@"array[%d] = %@", idx, obj);
}
];
It substitutes the for loop.
Now the collections can enumerate themselves.
Collection enumeration
Setting *stop toYES inside the
block will stop the enumeration
Making an enumeration concurrent
is a matter of adding an option!
giovedì 7 febbraio 13
Pragma Night
Common scenarios in the SDK
- (void)animateView:(UIView*)view {
CGRect cacheFrame = [view frame];
[UIView animateWithDuration:1.5 animations:
^{
CGRect newFrame = [view frame];
newFrame.origin.y = newFrame.origin.y + 250.0;
[view setFrame:newFrame];
[view setAlpha:0.5];
}
completion:
^(BOOL finished) {
if (finished) {
sleep(1);
[view setFrame:cacheFrame];
[view setAlpha:1.0];
}
}];
}
View animations
giovedì 7 febbraio 13
Pragma Night
Common scenarios in the SDK
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];
[center addObserverForName:SomeNotificationName
object:nil
queue:mainQueue
usingBlock:^(NSNotification *note) {
NSLog(@"Notification received");
}];
Notification observers
giovedì 7 febbraio 13
Pragma Night
Common scenarios in the SDK
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperationWithBlock:^{
NSLog(@"This block is run in the operation");
}];
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"This block is run in the operation");
}];
[operation addExecutionBlock:^{
NSLog(@"NSBlockOperations can execute multiple blocks ");
}];
[operation setCompletionBlock:^{
NSLog(@"This Code Runs Once The Operation Has Finished");
}];
Operations queues
Wraps the block inside a NSOperation
A single NSBlockOperation can execute multiple blocks concurrently
giovedì 7 febbraio 13
Pragma Night
Grand Central Dispatch
giovedì 7 febbraio 13
Pragma Night
What is Grand Central Dispatch?
• a set of language features and libraries to improve
and simplify the act of writing concurrent code
• more efficient than threads
• implemented at all levels of APIs in iOS (BSD
subsystem, CoreFoundation, Cocoa)
Grand Central Dispatch (GCD) is:
giovedì 7 febbraio 13
Pragma Night
Concept
• GCD is based on the Thread Pool pattern
• a (small) number of threads is created
• (possibly lots of) tasks are added to queues in
order to be executed
• an algorithm handles the creation/destruction of
threads, and the scheduling of tasks
giovedì 7 febbraio 13
Pragma Night
Implementation
• dispatch queues
• dispatch sources
• dispatch groups
• dispatch semaphores
giovedì 7 febbraio 13
Pragma Night
Dispatch queues
• execute tasks always in a first-in, first-out order
• 2 types:
• serial queues (aka private dispatch queues)
• one and only one task running at a time
• the main dispatch queue is a peculiar one
• concurrent queues (aka global dispatch queues)
• tasks started in order but run concurrently
• four such queues, differing only by priority level,
are made available by the os
giovedì 7 febbraio 13
Pragma Night
Serial queues
• one and only one task running at a time
• the main dispatch queue is serial
• tied to the main thread and application’s run loop
• interleaves queued tasks with other event
sources
• often used as the key synchronization point for
the application
giovedì 7 febbraio 13
Pragma Night
Creating serial queues
// Creating a serial dispatch queue
dispatch_queue_t queue;
queue = dispatch_queue_create("com.example.MyQueue", NULL);
// Getting the dispatch queue on which the currently executing block is running
dispatch_queue_t current_queue;
current_queue = dispatch_get_current_queue();
// Getting the main dispatch queue
dispatch_queue_t main_queue;
main_queue = dispatch_get_main_queue();
giovedì 7 febbraio 13
Pragma Night
Concurrent queues
• tasks are started in order but run concurrently
• the system provides four concurrent queues
• they are global to the application
• they differ only by priority level
giovedì 7 febbraio 13
Pragma Night
Creating concurrent queues
// Getting one of the four global dispatch queues
dispatch_queue_t global_queue;
global_queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// The four priority levels, ranked high to low, are
DISPATCH_QUEUE_PRIORITY_HIGH
DISPATCH_QUEUE_PRIORITY_DEFAULT
DISPATCH_QUEUE_PRIORITY_LOW
DISPATCH_QUEUE_PRIORITY_BACKGROUND
// Creating a concurrent dispatch queue
dispatch_queue_t queue;
queue = dispatch_queue_create("com.example.MyQueue", DISPATCH_QUEUE_CONCURRENT);
giovedì 7 febbraio 13
Pragma Night
•dispatch_async(queue, block)
• submits a block for asynchronous execution on
a dispatch queue and returns immediately
•dispatch_sync(queue, block)
• submits a block object for execution on a
dispatch queue and waits until that block
completes
Using queues
giovedì 7 febbraio 13
Pragma Night
•dispatch_after(when, queue, block)
• enqueue a block for execution at the specified time
•dispatch_apply(iterations, queue, block)
• submits a block to a dispatch queue for multiple
invocations
•dispatch_once(queue, block)
• executes a block object once and only once for the
lifetime of an application
Using queues
giovedì 7 febbraio 13
Pragma Night
Dispatch sources
• allow the client to register blocks or functions to
execute asynchronously upon system events
• unlike manually-put tasks, they remain attached to
their queue, and submit their associated task to it
whenever the corresponding event occurs
• to prevent backlogging, they can coalesce events
• types of sources: signal, timer, descriptor, process,
Mach port, custom
giovedì 7 febbraio 13
Pragma Night
Dispatch source example
dispatch_source_t CreateDispatchTimer(uint64_t interval,
uint64_t leeway,
dispatch_queue_t queue,
dispatch_block_t block) {
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER,
0, 0, queue);
if (timer) {
dispatch_source_set_timer(timer, dispatch_walltime(NULL, 0), interval, leeway);
dispatch_source_set_event_handler(timer, block);
dispatch_resume(timer);
}
return timer;
}
void MyCreateTimer() {
dispatch_source_t aTimer = CreateDispatchTimer(30ull * NSEC_PER_SEC,
1ull * NSEC_PER_SEC,
dispatch_get_main_queue(),
^{ MyPeriodicTask(); });
// Store it somewhere for later use.
if (aTimer) {
MyStoreTimer(aTimer);
}
}
giovedì 7 febbraio 13
Pragma Night
Dispatch groups
• are objects that allow several tasks to be grouped
for later joining.
• a task can be added to a queue as a member of a
group, and then the client can use the group object
to wait until all of the tasks in that group have
completed
giovedì 7 febbraio 13
Pragma Night
Dispatch group example
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_t group = dispatch_group_create();
// Add a task to the group
dispatch_group_async(group, queue, ^{
// Some asynchronous work
});
//
// Do some other work while the tasks execute...
//
// When you cannot make any more forward progress,
// wait on the group to block the current thread.
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
// Release the group when it is no longer needed.
dispatch_release(group);
giovedì 7 febbraio 13
Pragma Night
Dispatch semaphores
• useful for regulating the use of finite resources
// Example: limiting the number of file descriptors open concurrently
// 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);
giovedì 7 febbraio 13
Pragma Night
References
• WWDC 2011 - session 308:
Blocks and Grand Central Dispatch in Practice
• Apple documentation
• Blocks Programming Topics
• Concurrency Programming Guide
• Grand Central Dispatch (GCD) Reference
• Book: Pro Multithreading and Memory Management
for iOS and OS X: with ARC, Grand Central
Dispatch, and Blocks
giovedì 7 febbraio 13
Pragma Night
Thank You!
matteo.battaglio@pragmamark.org
giovedì 7 febbraio 13

Blocks and GCD(Grand Central Dispatch)

  • 1.
    Pragma Night @Talent Garden Blocks and Grand Central Dispatch Matteo Battaglio giovedì 7 febbraio 13
  • 2.
  • 3.
    Pragma Night What areBlocks? • an extension to the C language and its derivatives Objective-C and C++, introduced by Apple • available in iOS SDK since version 4.0 • already used by plenty of iOS frameworks’ APIs Blocks are: giovedì 7 febbraio 13
  • 4.
    Pragma Night Benefits • morefunctional style of coding • less boilerplate code • more readable code • simplify event-driven scenarios (i.e. callbacks) • simplify multi-threading giovedì 7 febbraio 13
  • 5.
    Pragma Night Definition • ‘block’is the name Objective-C gives to the concept of closure, that is: • a pointer to a function • a copy of some of the local variables of its higher-order function giovedì 7 febbraio 13
  • 6.
    Pragma Night Syntax int multiplier= 7; int (^myBlock)(int) = ^(int num) { return num * multiplier; }; Declaration of the variable ‘myBlock’. The ‘^’ tells that its type is a block. Return type Parameter list Definition of the variable ‘myBlock’, using a block literal. The parameter is named ‘num’. Body of the block. giovedì 7 febbraio 13
  • 7.
    Pragma Night Key features •allow code to be passed around for later execution • access to the local variables of the function they were declared in • mantain a state among calls giovedì 7 febbraio 13
  • 8.
    Pragma Night Code example#1 int multiplier = 7; // Declaring a block and assigning it to the variable ‘myBlock’ int (^myBlock)(int) = ^(int num) { return num * multiplier; }; // Calling the block printf(myBlock(3)); // prints '21' Calling a block in no different than calling a function giovedì 7 febbraio 13
  • 9.
    Pragma Night Code example#2 // Inline use of a block literal (as an actual parameter of a function) char *myCharacters[3] = { "TomJohn", "George", "Charles Condomine" }; qsort_b(myCharacters, 3, sizeof(char *), ^(const void *l, const void *r) { char *left = *(char **)l; char *right = *(char **)r; return strncmp(left, right, 1); }); // myCharacters is now { "Charles Condomine", "George", "TomJohn" } qsort_b() will internally call the block many times, in order to compare each pair of cells in the array giovedì 7 febbraio 13
  • 10.
    Pragma Night Code example#3 // Declaring a function that takes a block as parameter void myFunction(int (^aBlock)(void *, void *)); // Declaring a function that returns a block void (^myFunction(int a, int b))(double, double); Function name Function parameters The function’s return type is a block with signature void (^)(double, double) giovedì 7 febbraio 13
  • 11.
    Pragma Night Code example#4 // Defining a custom name for our block type to improve code style typedef void (^MyBlockType)(double, double); // Variable and function declarations now look much more readable MyBlockType myBlock = ^(double a, double b) { printf("hey!"); }; MyBlockType myFunction(int a, int b, MyBlockType aBlock); giovedì 7 febbraio 13
  • 12.
    Pragma Night Variables caveats •non-local variables in blocks are constant and read-only Trying to modify ‘i’ from inside the block results in a compilation error. • in order to make them ‘live’ and writable the __block type specifier must be added to their declaration giovedì 7 febbraio 13
  • 13.
    Pragma Night __block • what__block does is: • pass the variable by reference - rather than by value - to the block • create a strong (as opposed to weak) reference to that variable int myFunction() { __block int i = 0; void (^myBlock)(void) = ^{ i++; printf("i has the value %d", i); // prints 'i has the value 1' }; } giovedì 7 febbraio 13
  • 14.
    Pragma Night State representation •blocks can use variables marked with __block to keep a state among calls int myFunction() { __block int i = 0; void (^myBlock)(void) = ^{ i++; printf("i has the value %d", i); }; myBlock(); // prints 'i has the value 1' myBlock(); // prints 'i has the value 2' } giovedì 7 febbraio 13
  • 15.
    Pragma Night Information hiding intarray[] = {4, 5, 2, 6, 1}; qsort_b(array, 5, sizeof(int), ^(void) { __block int sum = 0; return ^(const void *a, const void *b) { sum += (int)a; return a - b; }; }()); The outer block defines a local variable that is used inside the inner block to mantain a state: this way we are keeping the sum variable hidden to the rest of the program The inner block is what gets passed to the qsort_b() function These parentheses tell us that the outer block is executed, and not passed to qsort_b. giovedì 7 febbraio 13
  • 16.
    Pragma Night __block implications •variables marked with __block are shared between their lexical scope and all blocks and block copies declared or created within that scope • multiple blocks can simultaneously use a shared variable • when a block is copied (i.e. it is moved from the stack to the heap), they survive the destruction of their stack frame giovedì 7 febbraio 13
  • 17.
    Pragma Night Memory concerns •a block is allowed to access self • self is passed as a strong reference • this could lead to a ‘retain cicle’ • trick: define a __weak reference to self int myFunction() { __weak MyObject weakSelf = self; void (^myBlock)(void) = ^{ [weakSelf someMethod]; } } giovedì 7 febbraio 13
  • 18.
    Pragma Night Common scenariosin the SDK NSArray *array = [NSArray arrayWithObjects:@"One", @"Two", @"Three", @“Four”, nil]; [array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { NSLog(@"array[%d] = %@", idx, obj); }]; [array enumerateObjectsWithOptions: NSEnumerationConcurrent usingBlock: ^(id obj, NSUInteger idx, BOOL *stop) { NSLog(@"array[%d] = %@", idx, obj); } ]; It substitutes the for loop. Now the collections can enumerate themselves. Collection enumeration Setting *stop toYES inside the block will stop the enumeration Making an enumeration concurrent is a matter of adding an option! giovedì 7 febbraio 13
  • 19.
    Pragma Night Common scenariosin the SDK - (void)animateView:(UIView*)view { CGRect cacheFrame = [view frame]; [UIView animateWithDuration:1.5 animations: ^{ CGRect newFrame = [view frame]; newFrame.origin.y = newFrame.origin.y + 250.0; [view setFrame:newFrame]; [view setAlpha:0.5]; } completion: ^(BOOL finished) { if (finished) { sleep(1); [view setFrame:cacheFrame]; [view setAlpha:1.0]; } }]; } View animations giovedì 7 febbraio 13
  • 20.
    Pragma Night Common scenariosin the SDK NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; NSOperationQueue *mainQueue = [NSOperationQueue mainQueue]; [center addObserverForName:SomeNotificationName object:nil queue:mainQueue usingBlock:^(NSNotification *note) { NSLog(@"Notification received"); }]; Notification observers giovedì 7 febbraio 13
  • 21.
    Pragma Night Common scenariosin the SDK NSOperationQueue *queue = [[NSOperationQueue alloc] init]; [queue addOperationWithBlock:^{ NSLog(@"This block is run in the operation"); }]; NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"This block is run in the operation"); }]; [operation addExecutionBlock:^{ NSLog(@"NSBlockOperations can execute multiple blocks "); }]; [operation setCompletionBlock:^{ NSLog(@"This Code Runs Once The Operation Has Finished"); }]; Operations queues Wraps the block inside a NSOperation A single NSBlockOperation can execute multiple blocks concurrently giovedì 7 febbraio 13
  • 22.
    Pragma Night Grand CentralDispatch giovedì 7 febbraio 13
  • 23.
    Pragma Night What isGrand Central Dispatch? • a set of language features and libraries to improve and simplify the act of writing concurrent code • more efficient than threads • implemented at all levels of APIs in iOS (BSD subsystem, CoreFoundation, Cocoa) Grand Central Dispatch (GCD) is: giovedì 7 febbraio 13
  • 24.
    Pragma Night Concept • GCDis based on the Thread Pool pattern • a (small) number of threads is created • (possibly lots of) tasks are added to queues in order to be executed • an algorithm handles the creation/destruction of threads, and the scheduling of tasks giovedì 7 febbraio 13
  • 25.
    Pragma Night Implementation • dispatchqueues • dispatch sources • dispatch groups • dispatch semaphores giovedì 7 febbraio 13
  • 26.
    Pragma Night Dispatch queues •execute tasks always in a first-in, first-out order • 2 types: • serial queues (aka private dispatch queues) • one and only one task running at a time • the main dispatch queue is a peculiar one • concurrent queues (aka global dispatch queues) • tasks started in order but run concurrently • four such queues, differing only by priority level, are made available by the os giovedì 7 febbraio 13
  • 27.
    Pragma Night Serial queues •one and only one task running at a time • the main dispatch queue is serial • tied to the main thread and application’s run loop • interleaves queued tasks with other event sources • often used as the key synchronization point for the application giovedì 7 febbraio 13
  • 28.
    Pragma Night Creating serialqueues // Creating a serial dispatch queue dispatch_queue_t queue; queue = dispatch_queue_create("com.example.MyQueue", NULL); // Getting the dispatch queue on which the currently executing block is running dispatch_queue_t current_queue; current_queue = dispatch_get_current_queue(); // Getting the main dispatch queue dispatch_queue_t main_queue; main_queue = dispatch_get_main_queue(); giovedì 7 febbraio 13
  • 29.
    Pragma Night Concurrent queues •tasks are started in order but run concurrently • the system provides four concurrent queues • they are global to the application • they differ only by priority level giovedì 7 febbraio 13
  • 30.
    Pragma Night Creating concurrentqueues // Getting one of the four global dispatch queues dispatch_queue_t global_queue; global_queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); // The four priority levels, ranked high to low, are DISPATCH_QUEUE_PRIORITY_HIGH DISPATCH_QUEUE_PRIORITY_DEFAULT DISPATCH_QUEUE_PRIORITY_LOW DISPATCH_QUEUE_PRIORITY_BACKGROUND // Creating a concurrent dispatch queue dispatch_queue_t queue; queue = dispatch_queue_create("com.example.MyQueue", DISPATCH_QUEUE_CONCURRENT); giovedì 7 febbraio 13
  • 31.
    Pragma Night •dispatch_async(queue, block) •submits a block for asynchronous execution on a dispatch queue and returns immediately •dispatch_sync(queue, block) • submits a block object for execution on a dispatch queue and waits until that block completes Using queues giovedì 7 febbraio 13
  • 32.
    Pragma Night •dispatch_after(when, queue,block) • enqueue a block for execution at the specified time •dispatch_apply(iterations, queue, block) • submits a block to a dispatch queue for multiple invocations •dispatch_once(queue, block) • executes a block object once and only once for the lifetime of an application Using queues giovedì 7 febbraio 13
  • 33.
    Pragma Night Dispatch sources •allow the client to register blocks or functions to execute asynchronously upon system events • unlike manually-put tasks, they remain attached to their queue, and submit their associated task to it whenever the corresponding event occurs • to prevent backlogging, they can coalesce events • types of sources: signal, timer, descriptor, process, Mach port, custom giovedì 7 febbraio 13
  • 34.
    Pragma Night Dispatch sourceexample dispatch_source_t CreateDispatchTimer(uint64_t interval, uint64_t leeway, dispatch_queue_t queue, dispatch_block_t block) { dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue); if (timer) { dispatch_source_set_timer(timer, dispatch_walltime(NULL, 0), interval, leeway); dispatch_source_set_event_handler(timer, block); dispatch_resume(timer); } return timer; } void MyCreateTimer() { dispatch_source_t aTimer = CreateDispatchTimer(30ull * NSEC_PER_SEC, 1ull * NSEC_PER_SEC, dispatch_get_main_queue(), ^{ MyPeriodicTask(); }); // Store it somewhere for later use. if (aTimer) { MyStoreTimer(aTimer); } } giovedì 7 febbraio 13
  • 35.
    Pragma Night Dispatch groups •are objects that allow several tasks to be grouped for later joining. • a task can be added to a queue as a member of a group, and then the client can use the group object to wait until all of the tasks in that group have completed giovedì 7 febbraio 13
  • 36.
    Pragma Night Dispatch groupexample dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_group_t group = dispatch_group_create(); // Add a task to the group dispatch_group_async(group, queue, ^{ // Some asynchronous work }); // // Do some other work while the tasks execute... // // When you cannot make any more forward progress, // wait on the group to block the current thread. dispatch_group_wait(group, DISPATCH_TIME_FOREVER); // Release the group when it is no longer needed. dispatch_release(group); giovedì 7 febbraio 13
  • 37.
    Pragma Night Dispatch semaphores •useful for regulating the use of finite resources // Example: limiting the number of file descriptors open concurrently // 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); giovedì 7 febbraio 13
  • 38.
    Pragma Night References • WWDC2011 - session 308: Blocks and Grand Central Dispatch in Practice • Apple documentation • Blocks Programming Topics • Concurrency Programming Guide • Grand Central Dispatch (GCD) Reference • Book: Pro Multithreading and Memory Management for iOS and OS X: with ARC, Grand Central Dispatch, and Blocks giovedì 7 febbraio 13
  • 39.