SlideShare a Scribd company logo
Blocks
                         and
                 Grand Central Dispatch
                        Matteo Battaglio

                          Pragma Night @ Talent Garden

giovedì 7 febbraio 13
Blocks


                                 Pragma Night
giovedì 7 febbraio 13
What are Blocks?

         Blocks are:
           • 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


                                                              Pragma Night
giovedì 7 febbraio 13
Benefits

           • more functional style of coding
           • less boilerplate code
           • more readable code
           • simplify event-driven scenarios (i.e. callbacks)
           • simplify multi-threading

                                                                Pragma Night
giovedì 7 febbraio 13
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



                                                                  Pragma Night
giovedì 7 febbraio 13
Syntax

          int multiplier = 7;


             Declaration of the variable
                                                           Definition of the variable ‘myBlock’,
                         ‘myBlock’.
                                                                using a block literal.
           The ‘^’ tells that its type is a block.


          int (^myBlock)(int) = ^(int num) { return num * multiplier; };


            Return type          Parameter list
                                                                          Body of the block.

                                                  The parameter is
                                                   named ‘num’.




                                                                                                  Pragma Night
giovedì 7 febbraio 13
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

                                                            Pragma Night
giovedì 7 febbraio 13
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




                                                                            Pragma Night
giovedì 7 febbraio 13
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);
          });

                                          qsort_b() will internally call the block many times, in order
                                                  to compare each pair of cells in the array

          // myCharacters is now { "Charles Condomine", "George", "TomJohn" }




                                                                                                          Pragma Night
giovedì 7 febbraio 13
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)




                                                                                                         Pragma Night
giovedì 7 febbraio 13
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);




                                                                               Pragma Night
giovedì 7 febbraio 13
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

                                                                                        Pragma Night
giovedì 7 febbraio 13
__block
            int myFunction() {

                    __block int i = 0;

                    void (^myBlock)(void) = ^{
                        i++;
                        printf("i has the value %d", i); // prints 'i has the value 1'
                    };

            }



           • 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
                                                                                         Pragma Night
giovedì 7 febbraio 13
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'

            }




                                                               Pragma Night
giovedì 7 febbraio 13
Information hiding

                                                                    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
          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 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.




                                                                                                                             Pragma Night
giovedì 7 febbraio 13
__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


                                                                    Pragma Night
giovedì 7 febbraio 13
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];

                            }
                        }



                                                               Pragma Night
giovedì 7 febbraio 13
Common scenarios in the SDK
        Collection enumeration

          NSArray *array = [NSArray arrayWithObjects:@"One", @"Two", @"Three", @“Four”, nil];

                                    It substitutes the for loop.
                        Now the collections can enumerate themselves.

          [array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
              NSLog(@"array[%d] = %@", idx, obj);
          }];                                                    Setting *stop to YES inside the
                                                                block will stop the enumeration



          [array enumerateObjectsWithOptions: NSEnumerationConcurrent usingBlock:
              ^(id obj, NSUInteger idx, BOOL *stop) {
                  NSLog(@"array[%d] = %@", idx, obj);
              }                                              Making an enumeration concurrent
          ];                                                    is a matter of adding an option!




                                                                                                   Pragma Night
giovedì 7 febbraio 13
Common scenarios in the SDK
         View animations
          - (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];
                      }
                  }];
          }




                                                                       Pragma Night
giovedì 7 febbraio 13
Common scenarios in the SDK
        Notification observers

            NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
            NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];

            [center addObserverForName:SomeNotificationName
                                object:nil
                                 queue:mainQueue
                            usingBlock:^(NSNotification *note) {
                                           NSLog(@"Notification received");
                                       }];




                                                                                   Pragma Night
giovedì 7 febbraio 13
Common scenarios in the SDK
        Operations queues
            NSOperationQueue *queue = [[NSOperationQueue alloc] init];

            [queue addOperationWithBlock:^{
                NSLog(@"This block is run in the operation");
            }];
                                                  Wraps the block inside a NSOperation


                         A single NSBlockOperation can execute multiple blocks concurrently

            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");
            }];


                                                                                              Pragma Night
giovedì 7 febbraio 13
Grand Central Dispatch


                         Pragma Night
giovedì 7 febbraio 13
What is Grand Central Dispatch?
          Grand Central Dispatch (GCD) is:
           • 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)



                                                                Pragma Night
giovedì 7 febbraio 13
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


                                                               Pragma Night
giovedì 7 febbraio 13
Implementation


           • dispatch queues
           • dispatch sources
           • dispatch groups
           • dispatch semaphores

                                         Pragma Night
giovedì 7 febbraio 13
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
                                                             Pragma Night
giovedì 7 febbraio 13
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

                                                             Pragma Night
giovedì 7 febbraio 13
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();




                                                                                     Pragma Night
giovedì 7 febbraio 13
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

                                                        Pragma Night
giovedì 7 febbraio 13
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);




                                                                                     Pragma Night
giovedì 7 febbraio 13
Using queues

           • 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


                                                                    Pragma Night
giovedì 7 febbraio 13
Using queues
       • 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

                                                                       Pragma Night
giovedì 7 febbraio 13
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

                                                                 Pragma Night
giovedì 7 febbraio 13
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);
              }
      }



                                                                                      Pragma Night
giovedì 7 febbraio 13
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



                                                                Pragma Night
giovedì 7 febbraio 13
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);




                                                                                   Pragma Night
giovedì 7 febbraio 13
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);




                                                                                       Pragma Night
giovedì 7 febbraio 13
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

                                                                   Pragma Night
giovedì 7 febbraio 13
Thank You!

                        matteo.battaglio@pragmamark.org
                                                          Pragma Night
giovedì 7 febbraio 13

More Related Content

PDF
Blocks & GCD
PPTX
Grand Central Dispatch
KEY
Grand Central Dispatch Design Patterns
PPTX
Pune-Cocoa: Blocks and GCD
PDF
GCD and OperationQueue.
PPTX
Effective java - concurrency
PDF
Java Concurrency Gotchas
PPTX
The Java memory model made easy
Blocks & GCD
Grand Central Dispatch
Grand Central Dispatch Design Patterns
Pune-Cocoa: Blocks and GCD
GCD and OperationQueue.
Effective java - concurrency
Java Concurrency Gotchas
The Java memory model made easy

What's hot (20)

PPTX
Дмитрий Нестерук, Паттерны проектирования в XXI веке
PPT
PDF
Java Concurrency in Practice
PDF
Ppl for students unit 4 and 5
PDF
camel-scala.pdf
PPT
Clojure concurrency
KEY
Automatic Reference Counting
KEY
Know yourengines velocity2011
PDF
Java Concurrency Idioms
PPTX
Building High Perf Web Apps - IE8 Firestarter
PDF
Fast as C: How to Write Really Terrible Java
PDF
Let'swift "Concurrency in swift"
PPT
Stoop 305-reflective programming5
PDF
Loom and concurrency latest
PPT
iOS Development with Blocks
PDF
2008 07-24 kwpm-threads_and_synchronization
PPTX
これからのPerlプロダクトのかたち(YAPC::Asia 2013)
ODP
Asynchronous I/O in NodeJS - new standard or challenges?
PPT
Behavioral Reflection
PDF
[JavaOne 2011] Models for Concurrent Programming
Дмитрий Нестерук, Паттерны проектирования в XXI веке
Java Concurrency in Practice
Ppl for students unit 4 and 5
camel-scala.pdf
Clojure concurrency
Automatic Reference Counting
Know yourengines velocity2011
Java Concurrency Idioms
Building High Perf Web Apps - IE8 Firestarter
Fast as C: How to Write Really Terrible Java
Let'swift "Concurrency in swift"
Stoop 305-reflective programming5
Loom and concurrency latest
iOS Development with Blocks
2008 07-24 kwpm-threads_and_synchronization
これからのPerlプロダクトのかたち(YAPC::Asia 2013)
Asynchronous I/O in NodeJS - new standard or challenges?
Behavioral Reflection
[JavaOne 2011] Models for Concurrent Programming
Ad

Viewers also liked (18)

PPTX
Objective C Tricks
PDF
Tech Talk #4 : Multi - threading and GCD ( grand central dispatch ) in iOS - ...
PPT
iOS Multithreading
PPTX
iOS Developer Interview Questions
PDF
Grand Central Dispatch - iOS Conf SG 2015
PPTX
Programação Assíncrona com C# 5
PPTX
GCD of n Numbers
PDF
TDC 2012 Goiânia: Trilha .NET - Novidades do .NET Framework 4.5
PDF
IAsyncResult Pattern ou Asynchronous Programming Model (APM)
PDF
Programação assíncrona com C# 5 no Visual Studio 2013 [MVP ShowCast 2013 - DE...
PDF
Android Application Development at JFokus 2011
PDF
iOS 入門教學
PPTX
iOS Application Lifecycle
PDF
Multithreading on iOS
PDF
AnsibleFest 2014 - Role Tips and Tricks
PPTX
Euclid's Algorithm for Greatest Common Divisor - Time Complexity Analysis
PPTX
IBDesignable & IBInspectible
PDF
Programação assíncrona com C#
Objective C Tricks
Tech Talk #4 : Multi - threading and GCD ( grand central dispatch ) in iOS - ...
iOS Multithreading
iOS Developer Interview Questions
Grand Central Dispatch - iOS Conf SG 2015
Programação Assíncrona com C# 5
GCD of n Numbers
TDC 2012 Goiânia: Trilha .NET - Novidades do .NET Framework 4.5
IAsyncResult Pattern ou Asynchronous Programming Model (APM)
Programação assíncrona com C# 5 no Visual Studio 2013 [MVP ShowCast 2013 - DE...
Android Application Development at JFokus 2011
iOS 入門教學
iOS Application Lifecycle
Multithreading on iOS
AnsibleFest 2014 - Role Tips and Tricks
Euclid's Algorithm for Greatest Common Divisor - Time Complexity Analysis
IBDesignable & IBInspectible
Programação assíncrona com C#
Ad

Similar to Objective-C Blocks and Grand Central Dispatch (20)

PDF
Blocks and GCD(Grand Central Dispatch)
PPTX
Unit 1
PPTX
OOP, API Design and MVP
PDF
Functions
PDF
Oh Crap, I Forgot (Or Never Learned) C! [CodeMash 2010]
PDF
Smalltalk, the dynamic language
PDF
codeblocks-instructions.pdf
PPTX
Functions
PDF
Introduction to Compiler Development
PPTX
Solid OOPS
PPTX
User defined functions
PDF
C++primer
PPT
funcrttionadl asfkjoefweno alsdfjoweefwf
PDF
C reference manual
PPTX
SWIFT 3
PPTX
classVII_Coding_Teacher_Presentation.pptx
PDF
The best every notes on c language is here check it out
PPT
L4 functions
PPTX
C language
Blocks and GCD(Grand Central Dispatch)
Unit 1
OOP, API Design and MVP
Functions
Oh Crap, I Forgot (Or Never Learned) C! [CodeMash 2010]
Smalltalk, the dynamic language
codeblocks-instructions.pdf
Functions
Introduction to Compiler Development
Solid OOPS
User defined functions
C++primer
funcrttionadl asfkjoefweno alsdfjoweefwf
C reference manual
SWIFT 3
classVII_Coding_Teacher_Presentation.pptx
The best every notes on c language is here check it out
L4 functions
C language

Objective-C Blocks and Grand Central Dispatch

  • 1. Blocks and Grand Central Dispatch Matteo Battaglio Pragma Night @ Talent Garden giovedì 7 febbraio 13
  • 2. Blocks Pragma Night giovedì 7 febbraio 13
  • 3. What are Blocks? Blocks are: • 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 Pragma Night giovedì 7 febbraio 13
  • 4. Benefits • more functional style of coding • less boilerplate code • more readable code • simplify event-driven scenarios (i.e. callbacks) • simplify multi-threading Pragma Night giovedì 7 febbraio 13
  • 5. 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 Pragma Night giovedì 7 febbraio 13
  • 6. Syntax int multiplier = 7; Declaration of the variable Definition of the variable ‘myBlock’, ‘myBlock’. using a block literal. The ‘^’ tells that its type is a block. int (^myBlock)(int) = ^(int num) { return num * multiplier; }; Return type Parameter list Body of the block. The parameter is named ‘num’. Pragma Night giovedì 7 febbraio 13
  • 7. 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 Pragma Night giovedì 7 febbraio 13
  • 8. 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 Pragma Night giovedì 7 febbraio 13
  • 9. 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); }); qsort_b() will internally call the block many times, in order to compare each pair of cells in the array // myCharacters is now { "Charles Condomine", "George", "TomJohn" } Pragma Night giovedì 7 febbraio 13
  • 10. 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) Pragma Night giovedì 7 febbraio 13
  • 11. 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); Pragma Night giovedì 7 febbraio 13
  • 12. 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 Pragma Night giovedì 7 febbraio 13
  • 13. __block int myFunction() { __block int i = 0; void (^myBlock)(void) = ^{ i++; printf("i has the value %d", i); // prints 'i has the value 1' }; } • 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 Pragma Night giovedì 7 febbraio 13
  • 14. 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' } Pragma Night giovedì 7 febbraio 13
  • 15. Information hiding 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 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 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. Pragma Night giovedì 7 febbraio 13
  • 16. __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 Pragma Night giovedì 7 febbraio 13
  • 17. 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]; } } Pragma Night giovedì 7 febbraio 13
  • 18. Common scenarios in the SDK Collection enumeration NSArray *array = [NSArray arrayWithObjects:@"One", @"Two", @"Three", @“Four”, nil]; It substitutes the for loop. Now the collections can enumerate themselves. [array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { NSLog(@"array[%d] = %@", idx, obj); }]; Setting *stop to YES inside the block will stop the enumeration [array enumerateObjectsWithOptions: NSEnumerationConcurrent usingBlock: ^(id obj, NSUInteger idx, BOOL *stop) { NSLog(@"array[%d] = %@", idx, obj); } Making an enumeration concurrent ]; is a matter of adding an option! Pragma Night giovedì 7 febbraio 13
  • 19. Common scenarios in the SDK View animations - (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]; } }]; } Pragma Night giovedì 7 febbraio 13
  • 20. Common scenarios in the SDK Notification observers NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; NSOperationQueue *mainQueue = [NSOperationQueue mainQueue]; [center addObserverForName:SomeNotificationName object:nil queue:mainQueue usingBlock:^(NSNotification *note) { NSLog(@"Notification received"); }]; Pragma Night giovedì 7 febbraio 13
  • 21. Common scenarios in the SDK Operations queues NSOperationQueue *queue = [[NSOperationQueue alloc] init]; [queue addOperationWithBlock:^{ NSLog(@"This block is run in the operation"); }]; Wraps the block inside a NSOperation A single NSBlockOperation can execute multiple blocks concurrently 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"); }]; Pragma Night giovedì 7 febbraio 13
  • 22. Grand Central Dispatch Pragma Night giovedì 7 febbraio 13
  • 23. What is Grand Central Dispatch? Grand Central Dispatch (GCD) is: • 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) Pragma Night giovedì 7 febbraio 13
  • 24. 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 Pragma Night giovedì 7 febbraio 13
  • 25. Implementation • dispatch queues • dispatch sources • dispatch groups • dispatch semaphores Pragma Night giovedì 7 febbraio 13
  • 26. 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 Pragma Night giovedì 7 febbraio 13
  • 27. 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 Pragma Night giovedì 7 febbraio 13
  • 28. 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(); Pragma Night giovedì 7 febbraio 13
  • 29. 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 Pragma Night giovedì 7 febbraio 13
  • 30. 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); Pragma Night giovedì 7 febbraio 13
  • 31. Using queues • 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 Pragma Night giovedì 7 febbraio 13
  • 32. Using queues • 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 Pragma Night giovedì 7 febbraio 13
  • 33. 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 Pragma Night giovedì 7 febbraio 13
  • 34. 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); } } Pragma Night giovedì 7 febbraio 13
  • 35. 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 Pragma Night giovedì 7 febbraio 13
  • 36. 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); Pragma Night giovedì 7 febbraio 13
  • 37. 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); Pragma Night giovedì 7 febbraio 13
  • 38. 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 Pragma Night giovedì 7 febbraio 13
  • 39. Thank You! matteo.battaglio@pragmamark.org Pragma Night giovedì 7 febbraio 13