SlideShare a Scribd company logo
^{ }
        blocks
                   and


                 Raphael Sebbe
                  creaceed.com
cocoaheads.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-



Cloud
Farms/
                 Core Image



                         OpenCL



                                  GLSL
                                         Data-driven




                  Accelerate




             Threads


             Grand
            Central
            Dispatch


  Load
              Cron
Balancing
                                         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 one
void (^myblock)() = ^{
! printf(“Hellon”);
};
myblock();


// With one arg
void (^myblock)(int) = ^(int arg){
! printf(“Hello arg=%dn”, arg);
};
myblock(1);


// With a return value
int (^myblock)(int) = ^(int arg){
! printf(“Hello arg=%dn”, arg);
! return arg + 1;                    ~ anonymous
};                                   function pointer
int r = myblock(1);
Typedef’ing a Block
// Typedef of a block type
typedef 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
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 context
if (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.)
Blocks & GCD
Blocks & GCD
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
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);
Adding Tasks
// Synchronous, blocks until code is executed
dispatch_sync(queue, ^{
! // task code
});

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



// Asynchronous, returns immediately to caller
dispatch_async(queue, ^{
! // task code                                     API exists for
});
                                                 function pointers
dispatch_after(when, queue, ^{                      too.
! // task code
});
NSOperationQueue



Core

Core
Adding Operations
// Synchronous, blocks until code is executed
NSOperationQueue *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
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
 • ...
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?)

More Related Content

Blocks & GCD

  • 1. ^{ } blocks and Raphael Sebbe creaceed.com cocoaheads.be @rsebbe
  • 2. 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
  • 3. GPU Core SIMD Multi- Cloud Farms/ Core Image OpenCL GLSL Data-driven Accelerate Threads Grand Central Dispatch Load Cron Balancing Task-driven OpenMP
  • 4. Overview • Blocks & GCD are 2 different beasts • New language feature • Efficiently define tasks, and execute them • They complement each other nicely
  • 5. 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)
  • 6. Definition of a Block // Simple one void (^myblock)() = ^{ ! printf(“Hellon”); }; myblock(); // With one arg void (^myblock)(int) = ^(int arg){ ! printf(“Hello arg=%dn”, arg); }; myblock(1); // With a return value int (^myblock)(int) = ^(int arg){ ! printf(“Hello arg=%dn”, arg); ! return arg + 1; ~ anonymous }; function pointer int r = myblock(1);
  • 7. Typedef’ing a Block // Typedef of a block type typedef 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
  • 8. 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”
  • 9. 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.
  • 10. 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
  • 11. Block Storage • 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) { 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.
  • 12. 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
  • 13. 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.
  • 14. 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
  • 15. 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
  • 16. 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.)
  • 19. GCD Concept • Tasks in Queues Out In In Out Core Q’s are lightweight, have Core as many as you want
  • 20. 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
  • 21. 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
  • 22. 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);
  • 23. Adding Tasks // Synchronous, blocks until code is executed dispatch_sync(queue, ^{ ! // task code }); dispatch_apply(count, queue, ^(size_t i){ ! // process ith }); // Asynchronous, returns immediately to caller dispatch_async(queue, ^{ ! // task code API exists for }); function pointers dispatch_after(when, queue, ^{ too. ! // task code });
  • 25. Adding Operations // Synchronous, blocks until code is executed NSOperationQueue *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.
  • 26. 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
  • 27. 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.
  • 28. Xcode Demo’s • Extending UIAlertView using blocks • Delving inside Elasty video stabilization method
  • 30. 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 • ...
  • 31. 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