Slide 1

Slide 1 text

Programación concurrente con grand central dispatch xavier jurado ( @ xavierjurado ) iván Leider ( @ileider )

Slide 2

Slide 2 text

Agenda - El problema: programación concurrente - Una solución: Grand Central Dispatch - Bloques - GCD: Runtime Engine (libdispatch) - GCD: API - Demo PROGRAMACIÓN CONCURRENTE CON GCD - XAVIER JURADO E IVÁN LEIDER

Slide 3

Slide 3 text

El Problema - La programación concurrente es compleja - Race conditions - Deadlocks - La programación concurrente es necesaria - I/O (disco, red, dispositivos externos) - Threads - El futuro ya está aquí - Multicore: iPad 2, iPhone 4S, MacBooks, etc - Pero no solo multicore PROGRAMACIÓN CONCURRENTE CON GCD - XAVIER JURADO E IVÁN LEIDER

Slide 4

Slide 4 text

La Solución - ¿Qué es Grand Central Dispatch? - API en C de bajo nivel para manejar tareas concurrentes - Runtime engine - Extensión del lenguaje C (bloques) - Transfiere el manejo de threads de las aplicaciones al sistema operativo - Maneja dinámicamente los recursos por nosotros - Disponible desde Snow Leopard y iOS 4 - Apple está migrando a GCD (APIs, Operations, etc) PROGRAMACIÓN CONCURRENTE CON GCD - XAVIER JURADO E IVÁN LEIDER

Slide 5

Slide 5 text

Bloques - AKA Closures, Lambda, etc - Función + entorno - Aceptan parámetros y devuelven valores - Extensión del lenguaje C/C++/Objective-C - ^{…} - First Class Objects - Se pueden pasar como parámetro - Pueden ser el valor de retorno - Pueden ser retained / released / copied PROGRAMACIÓN CONCURRENTE CON GCD - XAVIER JURADO E IVÁN LEIDER

Slide 6

Slide 6 text

Bloques II PROGRAMACIÓN CONCURRENTE CON GCD - XAVIER JURADO Y IVÁN LEIDER - (NSInteger) add:(NSInteger)param1 to:(NSInteger)param2 { return param1 + param2; } [self add:1 to:2]; Implementación de un método en Objective C

Slide 7

Slide 7 text

Bloques III PROGRAMACIÓN CONCURRENTE CON GCD - XAVIER JURADO Y IVÁN LEIDER NSInteger add(NSInteger param1, NSInteger param2) { return param1 + param2; } add(1, 2); Implementación de una función en C

Slide 8

Slide 8 text

Bloques IV PROGRAMACIÓN CONCURRENTE CON GCD - XAVIER JURADO Y IVÁN LEIDER NSInteger (^add)(NSInteger, NSInteger) = ^(NSInteger param1, NSInteger param2) { return param1 + param2; }; add(1, 2); Implementación de un bloque Retorno Bloque Firma (parámetros) Argumentos Cuerpo del bloque

Slide 9

Slide 9 text

Bloques IV PROGRAMACIÓN CONCURRENTE CON GCD - XAVIER JURADO Y IVÁN LEIDER Implementación de un bloque (con estilo) Retorno Bloque Firma (parámetros) Argumentos Cuerpo del bloque typedef NSInteger(^AddBlock)(NSInteger, NSInteger); AddBlock add = ^(NSInteger param1, NSInteger param2){ return 0; }; add(1,2);

Slide 10

Slide 10 text

Bloques V PROGRAMACIÓN CONCURRENTE CON GCD - XAVIER JURADO Y IVÁN LEIDER [UIView animateWithDuration:0.2f delay:0.0f options:0 animations:^(void) { self.countdownView.transform = CGAffineTransformMakeScale(4.0f, 4.0f); self.countdownView.alpha = 0.0f; } completion:^(BOOL finished) { [self.countdownView removeFromSuperview]; self.countdownView = nil; [self start]; }]; Bloque inline

Slide 11

Slide 11 text

Bloques VI PROGRAMACIÓN CONCURRENTE CON GCD - XAVIER JURADO Y IVÁN LEIDER - (void)generateThumbnailWithCompletionHandler:(void (^)(CGImageRef))block { CGImageRef image; // Hacemos los cálculos pertinentes para obtener una imagen // ... block(image); } Bloque como parámetro

Slide 12

Slide 12 text

BLOQUES: scope - Variables locales ~ Objective C - En el caso de bloques inline, las variables locales también comprenden las variables definidas en el scope que contiene el bloque (el método en el que es implementado) - No hace falta pasar ningún “contexto” - Los bloques inline pueden escribir en las variables definidas dentro de su scope, pero no en las variables definidas en el método que las contiene. Salvo que estas últimas estén definidas con el modificador __block - También se puede acceder a las propiedades y variables de instancia del objeto dentro el cual fue implementado el bloque PROGRAMACIÓN CONCURRENTE CON GCD - XAVIER JURADO E IVÁN LEIDER

Slide 13

Slide 13 text

Bloques: scope II PROGRAMACIÓN CONCURRENTE CON GCD - XAVIER JURADO E IVÁN LEIDER bool rev = arg; __block int cnt = 0; sort(array, ^(int a, int b) { cnt++; if(rev) return b - a; else return a - b; }); NSLog(@"Count: %d", cnt);

Slide 14

Slide 14 text

gestión de memoria - Ojo! Es muy fácil provocar memory leaks/retain cycles - Si accedemos a un objeto, es retenido automáticamente - Excepto si usamos __block - Si accedemos a una variable de instancia, self es retenido - Gestión Pre ARC - Block_copy() / (id)copy; - Block_release() / (void)release; - (id)autorelease - @property (nonatomic, copy) BlockType block; PROGRAMACIÓN CONCURRENTE CON GCD - XAVIER JURADO E IVÁN LEIDER

Slide 15

Slide 15 text

Grand Central Dispatch PROGRAMACIÓN CONCURRENTE CON GCD - XAVIER JURADO E IVÁN LEIDER

Slide 16

Slide 16 text

RUNTIME ENGINE - Dispatch Queues - Pools of Threads - Manejados por GCD a nivel de sistema operativo - Main Queue: ejecuta en el “Main Thread” - Se usa sobre todo para tareas de UI - Concurrent Queues: ejecutan tareas sincronizadas o no sincronizadas - Serial Queues: ejecutan tareas sincronizadas o no sincronizadas como una cola “FIFO” PROGRAMACIÓN CONCURRENTE CON GCD - XAVIER JURADO E IVÁN LEIDER

Slide 17

Slide 17 text

API Main Queue PROGRAMACIÓN CONCURRENTE CON GCD - XAVIER JURADO E IVÁN LEIDER dispatch_queue_t mainQueue = dispatch_get_main_queue(); dispatch_async(mainQueue, ^(void) { [[[UIAlertView alloc] initWithTitle:@"GCD" message:@"GCD is amazing!" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] show]; });

Slide 18

Slide 18 text

API II Tareas sincronizadas PROGRAMACIÓN CONCURRENTE CON GCD - XAVIER JURADO E IVÁN LEIDER void (^printFrom1To1000)(void) = ^{ for (int i = 1;i <= 1000; i++){ NSLog(@"Counter = %d", i); } }; dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_sync(concurrentQueue, printFrom1To1000); dispatch_sync(concurrentQueue, printFrom1To1000);

Slide 19

Slide 19 text

API III Tareas no sincronizadas PROGRAMACIÓN CONCURRENTE CON GCD - XAVIER JURADO E IVÁN LEIDER void (^printFrom1To1000)(void) = ^{ for (int i = 1;i <= 1000; i++){ NSLog(@"Counter = %d", i); } }; dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_async(concurrentQueue, printFrom1To1000); dispatch_async(concurrentQueue, printFrom1To1000);

Slide 20

Slide 20 text

API IV - Otras APIs - Ejecutar una tarea después de un lapso: dispatch_after - Ejecutar una tarea a lo sumo una vez: dispatch_once - Inicialización - True singleton - Ejecutar grupos de tareas: dispatch_group_create, dispatch_group_async, dispatch_group_notify, dispatch_release PROGRAMACIÓN CONCURRENTE CON GCD - XAVIER JURADO E IVÁN LEIDER

Slide 21

Slide 21 text

API V Crear Dispatch Queues PROGRAMACIÓN CONCURRENTE CON GCD - XAVIER JURADO E IVÁN LEIDER dispatch_queue_t firstSerialQueue = dispatch_queue_create("org.nscoders.serialQueue", 0); dispatch_async(firstSerialQueue, ^{ for (int i = 1;i <= 1000; i++){ NSLog(@"Counter = %d", i); }}); dispatch_async(firstSerialQueue, ^{ for (int i = 1;i <= 1000; i++){ NSLog(@"Counter = %d", i); }});

Slide 22

Slide 22 text

Demo PROGRAMACIÓN CONCURRENTE CON GCD - XAVIER JURADO E IVÁN LEIDER https://github.com/NSCoderNightBCN/ GLKitHelloWorld/tree/gcd

Slide 23

Slide 23 text

^{ GRACIAS! }