Top Banner
^{ } and Raphael Sebbe creaceed.com @rsebbe cocoaheads.be blocks
32

Blocks & GCD

Jan 15, 2015

Download

Technology

rsebbe

Introduction talk about Blocks and Grand Central Dispatch, concurrent programming techniques for Mac and iOS
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Blocks & GCD

^{ } and

Raphael Sebbe [email protected]

blocks

Page 2: Blocks & GCD

Ways to Get More

• We can’t get more GHz out of silicon

• Parallelism is the solution

• Nowadays, multi-core systems is the rule

• On it’s way to mobile devices (iPad2)

• Specialized hardware, like GPU, too

• Already there on mobile

Page 3: Blocks & GCD

SIMD

GPU

Multi-Core

Farms/Cloud

Data-driven Task-driven

Ope

nCL

Gra

nd

Cen

tral

D

ispa

tch

GLS

L

Acc

eler

ate

Load

Ba

lanc

ing

Thr

eads

Cro

n

Ope

nMP

Cor

e Im

age

Page 4: Blocks & GCD

Overview

• Blocks & GCD are 2 different beasts

• New language feature

• Efficiently define tasks, and execute them

• They complement each other nicely

Page 5: Blocks & GCD

Blocks• Concept of closure from functional

programming

• Blocks

• are an extension of C language

• store a piece of executable code

• capture the execution context

• are objects (Obj-C or C-based API)

Lisp, Caml, Haskell, Javascript, etc.

Page 6: Blocks & GCD

Definition of a Block// Simple onevoid (^myblock)() = ^{! printf(“Hello\n”);};myblock();

// With one argvoid (^myblock)(int) = ^(int arg){! printf(“Hello arg=%d\n”, arg);};myblock(1);

// With a return valueint (^myblock)(int) = ^(int arg){! printf(“Hello arg=%d\n”, arg);! return arg + 1;};int r = myblock(1);

~ anonymous function pointer

Page 7: Blocks & GCD

Typedef’ing a Block// Typedef of a block typetypedef void (^MyBlockType)(NSURL *assetURL, NSError *error);

MyBlockType myBlock = ^(NSURL *assetURL, NSError *error) {! // Some code};

// Syntax of untyped block as Obj-C method argument- (void)addPlayersToMatch:(GKMatch *)match matchRequest:(GKMatchRequest *)matchRequest completionHandler:(void (^)(NSError *))handler

Page 8: Blocks & GCD

Execution Context (1/3)

int a = 3;

// Context is captured at it’s current statevoid (^myblock)() = ^{! printf(“Hello a=%d\n”, a);};

a = 5;

myblock(); // outputs “Hello a=3”

• Definition of a block captures the execution context

• Variable of standard C types are copied

Page 9: Blocks & GCD

Execution Context (2/3)

id dict = [[NSDictionary alloc] init];

// Referenced objects are retainedvoid (^myblock)() = ^{! NSLog(“Hello dict=%@\n”, dict);};

[dict release];

myblock(); // outputs “Hello dict=....”

• Captured objects are retained

Remark: For referenced ivar, it’s

self that gets retained. Possible

retain cycles.

Page 10: Blocks & GCD

Execution Context (3/3)• Shared (R/W) variables with __block

__block int a = 3;

// Context is captured at it’s current statevoid (^myblock)() = ^{! a += 1;! printf(“Hello a=%d\n”, a);};

a = 5;

myblock(); // outputs “Hello a=6”Remark:

__block objects (id, etc.) are not

retained

Page 11: Blocks & GCD

Block Storage

if (x) {! block = ^{ printf("true\n");};} else {! block = ^{ printf("false\n");};}block(); // unsafe!!!

• When defined, blocks are stack objects, only valid in the definition scope

• Must be copied to heap if used outside of creation context

if (x) {! block = ^{ printf("true\n");}; ! block = [block copy];} else {! block = ^{ printf("false\n");};! block = [block copy];}block(); // safe!!![block release];

Remark: If your method

takes a block as arg., always copy

it.

Page 12: Blocks & GCD

Blocks Advantages

• Idea: invoke this “block of code” later.

• Callback API are naturally expressed

• Good replacement to your many didEnd: methods

• Task queueing / parallelism much easier

• See GCD

Page 13: Blocks & GCD

Grand Central Dispatch

• Need for parallelism that scales

• Easy to program for wide adoption

• Parallelism examples

• iTunes - Coverflow, downloads...

• iPhoto - import, uploads, preview

• Twitter Profile Pictures, etc.

Page 14: Blocks & GCD

Grand Central Dispatch

• Multi-core needs threads

• Say you have a 4-core machine, you need 4 threads for maximum throughput.

• Well... No.

• This is a pre-emptive world

Page 15: Blocks & GCD

Threads (1/2)

• Optimal number of threads for your app

• Number of (virtual) cores

• Load from other apps

• Thread state (low speed I/O)

• This continuously changes

• Consequences: unused or overused cores

Page 16: Blocks & GCD

Threads (2/2)

• 3 problems with threads:

• Too low-level, you shouldn’t waste your time at this (when to create/destroy them)

• You generally don’t have easy access to global system info

• Thread programming is hard (sync primitives, etc.)

Page 17: Blocks & GCD
Page 18: Blocks & GCD
Page 19: Blocks & GCD

GCD Concept

• Tasks in Queues

Core

Core

In Out

Q’s are lightweight, have as many as you

want

In Out

Page 20: Blocks & GCD

Why Q’s• Goal: Best use of cores

• Let the system create/destroy threads for you

• Write less code: wide adoption

• Better overall user experience (responsiveness)

• Technical: Less contention

• Fewer locks

• Scales much better with

• number of tasks

• number of cores

Page 21: Blocks & GCD

Queue Types

• Serial queues: one task at a time

• User queues

• Main queue

• Concurrent queues: multiple tasks

• 3 priority levels

Serial Q’s are themselves sync

primitives

Only the global one on

10.6 / iOS4

Page 22: Blocks & GCD

Queuesdispatch_queue_t queue;

// Main (serial) queuequeue = dispatch_get_main_queue();

// User (serial) queuequeue = dispatch_queue_create(“com.mycompany.qname”, ! NULL);

// Global (concurrent) queue, with priorityqueue = dispatch_get_global_queue! (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

Page 23: Blocks & GCD

Adding Tasks// Synchronous, blocks until code is executeddispatch_sync(queue, ^{! // task code});

dispatch_apply(count, queue, ^(size_t i){! // process ith});

// Asynchronous, returns immediately to callerdispatch_async(queue, ^{! // task code});

dispatch_after(when, queue, ^{! // task code});

API exists for function pointers

too.

Page 24: Blocks & GCD

NSOperationQueue

Core

Core

Page 25: Blocks & GCD

Adding Operations// Synchronous, blocks until code is executedNSOperationQueue *queue = [[NSOQ alloc] init];!NSBlockOperation *op1 = [NSBlockOperation ! blockOperationWithBlock:^{! ! // some code! !! }];NSBlockOperation *op2 = [NSBlockOperation ! blockOperationWithBlock:^{! ! // some code!! }];![op2 addDependency:op1];![queue addOperation:op1];[queue addOperation:op2];[queue addOperationWithBlock:^{! // some code! !}];

You can set the max concurrent

ops.

Predates GCD, has some odd APIs. Now built

on top of it.

Page 26: Blocks & GCD

APIs using Blocks (1/2)// Collections (NSDictionary / NSArray / NSSet)- (void)enumerateKeysAndObjectsWithOptions:(NSEnumerationOptions)opts usingBlock:(void (^)(id key, id obj, BOOL *stop))block

- (NSSet *)keysOfEntriesPassingTest:(BOOL (^)(id key, id obj, BOOL *stop))predicate

- (NSArray *)keysSortedByValueUsingComparator:(NSComparator)cmptr

// NSRegularExpression- (void)enumerateMatchesInString:(NSString *)string options:(NSMatchingOptions)options range:(NSRange)range usingBlock:(void (^)(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop))block

Patterns for collections: enumeration, mutation, tests, comparison

Page 27: Blocks & GCD

APIs using Blocks (2/2)// ALAssetsLibrary- (void)enumerateGroupsWithTypes:(ALAssetsGroupType)types usingBlock:(ALAssetsLib...ationResultsBlock)enumerationBlock failureBlock:(ALAssetsLib...ssFailureBlock)failureBlock

// Game Kit- (void)loadScoresWithCompletionHandler:(void (^)(NSArray *scores, NSError *error))completionHandler

// AVFoundation, AppKit, many other, etc.

Patterns for accessors: callback / handler

Page 28: Blocks & GCD

Xcode Demo’s

• Extending UIAlertView using blocks

• Delving inside Elasty video stabilization method

Page 29: Blocks & GCD
Page 30: Blocks & GCD

Threads

• Threads are not dead yet, they are just under your feet. (see crashlogs)

• Some uses are well suited at threads

• Real time needs

• OpenGL

• Core Image

• ...

Page 31: Blocks & GCD

What’s Next?

• Check WWDC videos [210, 308, 322]

• Dispatch group (dispatch_group_*)

• Source (dispatch_source_*)

• Semaphores (dispatch_semaphore_*)

• ARC interactions

• File / Memory I/O

• Target queues

Page 32: Blocks & GCD

Thank you!(Q&A?)