• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Blocks & GCD

Blocks & GCD



Introduction talk about Blocks and Grand Central Dispatch, concurrent programming techniques for Mac and iOS

Introduction talk about Blocks and Grand Central Dispatch, concurrent programming techniques for Mac and iOS



Total Views
Views on SlideShare
Embed Views



0 Embeds 0

No embeds



Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
Post Comment
Edit your comment

    Blocks & GCD Blocks & GCD Presentation Transcript

    • ^{ } blocks and Raphael Sebbe creaceed.comcocoaheads.be @rsebbe
    • 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
    • GPU Core SIMD Multi-CloudFarms/ Core Image OpenCL GLSL Data-driven Accelerate Threads Grand Central Dispatch Load CronBalancing Task-driven OpenMP
    • Overview• Blocks & GCD are 2 different beasts • New language feature • Efficiently define tasks, and execute them• They complement each other nicely
    • Blocks• Concept of closure from functional programming Lisp, Caml, Haskell,• Blocks Javascript, etc. • are an extension of C language • store a piece of executable code • capture the execution context • are objects (Obj-C or C-based API)
    • Definition of a Block// Simple onevoid (^myblock)() = ^{! printf(“Hellon”);};myblock();// With one argvoid (^myblock)(int) = ^(int arg){! printf(“Hello arg=%dn”, arg);};myblock(1);// With a return valueint (^myblock)(int) = ^(int arg){! printf(“Hello arg=%dn”, arg);! return arg + 1; ~ anonymous}; function pointerint r = myblock(1);
    • 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 *)matchmatchRequest:(GKMatchRequest *)matchRequestcompletionHandler:(void (^)(NSError *))handler
    • Execution Context (1/3)• Definition of a block captures the execution context• Variable of standard C types are copied int a = 3; // Context is captured at it’s current state void (^myblock)() = ^{ ! printf(“Hello a=%dn”, a); }; a = 5; myblock(); // outputs “Hello a=3”
    • Execution Context (2/3)• Captured objects are retained id dict = [[NSDictionary alloc] init]; // Referenced objects are retained void (^myblock)() = ^{ ! NSLog(“Hello dict=%@n”, dict); }; [dict release]; myblock(); // outputs “Hello dict=....” Remark: For referenced ivar, it’s self that gets retained. Possible retain cycles.
    • Execution Context (3/3)• Shared (R/W) variables with __block __block int a = 3; // Context is captured at it’s current state void (^myblock)() = ^{ ! a += 1; ! printf(“Hello a=%dn”, a); }; a = 5; Remark: myblock(); // outputs “Hello a=6” __block objects (id, etc.) are not retained
    • Block Storage • When defined, blocks are stack objects, only valid in the definition scope • Must be copied to heap if used outside of creation contextif (x) { if (x) {! block = ^{ printf("truen");}; ! block = ^{ printf("truen");};} else { ! block = [block copy];! block = ^{ printf("falsen");}; } else {} ! block = ^{ printf("falsen");};block(); // unsafe!!! ! block = [block copy];Remark: } block(); // safe!!! If your method [block release]; takes a block as arg., always copy it.
    • 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
    • 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.
    • 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
    • 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
    • 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.)
    • GCD Concept• Tasks in Queues Out In In Out Core Q’s are lightweight, have Core as many as you want
    • 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
    • Queue Types• Serial queues: one task at a time Serial Q’s are • User queues themselves sync primitives • Main queue• Concurrent queues: multiple tasks • 3 priority levels Only the global one on 10.6 / iOS4
    • 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);
    • 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 API exists for}); function pointersdispatch_after(when, queue, ^{ too.! // task code});
    • NSOperationQueueCoreCore
    • Adding Operations// Synchronous, blocks until code is executedNSOperationQueue *queue = [[NSOQ alloc] init];!NSBlockOperation *op1 = [NSBlockOperation! blockOperationWithBlock:^{! ! // some code! !! }];NSBlockOperation *op2 = [NSBlockOperation! blockOperationWithBlock:^{ Predates! ! // some code!! }]; GCD, has some! odd APIs. Now built[op2 addDependency:op1];! on top of it.[queue addOperation:op1];[queue addOperation:op2];[queue addOperationWithBlock:^{! // some code! ! You can set}]; the max concurrent ops.
    • 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 Patterns for collections: - (NSArray *)keysSortedByValueUsingComparator: (NSComparator)cmptr enumeration, mutation, tests, comparison // NSRegularExpression - (void)enumerateMatchesInString:(NSString *)string options:(NSMatchingOptions)options range:(NSRange) range usingBlock:(void (^)(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop))block
    • APIs using Blocks (2/2) // ALAssetsLibrary - (void)enumerateGroupsWithTypes:(ALAssetsGroupType) types usingBlock:(ALAssetsLib...ationResultsBlock) enumerationBlock failureBlock: (ALAssetsLib...ssFailureBlock)failureBlock // Game Kit Patterns for accessors: - (void)loadScoresWithCompletionHandler:(void (^) callback / handler (NSArray *scores, NSError *error))completionHandler // AVFoundation, AppKit, many other, etc.
    • Xcode Demo’s• Extending UIAlertView using blocks• Delving inside Elasty video stabilization method
    • 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 • ...
    • 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
    • Thank you! (Q&A?)