CocoaHeads Rennes #1 : Grand Central Dispatch

2,154 views

Published on

Slides de la présentation "TA la découverte de Grand Central Dispatch" de la session des CocoaHeads Rennais du 21 avril 2011. Présentation assurée par Pierre Duchêne et Thomas Dupont, ingénieurs chez Niji

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
2,154
On SlideShare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
38
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

CocoaHeads Rennes #1 : Grand Central Dispatch

  1. 1. A la découverte deGrand Central Dispatch Pierre Duchêne Thomas Dupont
  2. 2. Sommaire• Blocks ➡ Exemples ➡ Syntaxe et utilisation ➡ Gestion mémoire ➡ Bonus• Grand Central Dispatch ➡ Introduction ➡ libdispatch ➡ API haut niveau
  3. 3. BlocksThomas Dupont
  4. 4. ExemplesNSArray* sortedArray = [myArray sortedArrayUsingFunction:intSort context:NULL];...NSInteger intSort(id obj1, id obj2, void* context){ int v1 = [obj1 intValue]; int v2 = [obj2 intValue]; if (v1 < v2) return NSOrderedAscending; else if (v1 > v2) return NSOrderedDescending; else return NSOrderedSame;}
  5. 5. ExemplesNSArray* sortedArray = [myArray sortedArrayUsingComparator: ^(id obj1, id obj2) { int v1 = [obj1 intValue]; int v2 = [obj2 intValue]; if (v1 < v2) return NSOrderedAscending; else if (v1 > v2) return NSOrderedDescending; else return NSOrderedSame; }];
  6. 6. Exemples[UIView beginAnimations:@"" context:nil];[UIView setAnimationDuration:0.6];[UIView setAnimationDelegate:self];[UIView setAnimationDidStopSelector: @selector(fadeAnimationDidStop:finished:context:)];myView.alpha = 0;[UIView commitAnimations];...- (void)fadeAnimationDidStop:(NSString*)animId finished:(NSNumber*)finished context:(void*)context{ [myView removeFromSuperview];}
  7. 7. Exemples[UIView animateWithDuration: 0.6 animations:^{ myView.alpha = 0; } completion:^(BOOL finished){ [myView removeFromSuperview]; }];
  8. 8. Exemples[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notifReceived:) name:@"MyNotif" object:nil ];...- (void)notifReceived:(NSNotification*)notif{ /* doing some stuff */}
  9. 9. Exemples[[NSNotificationCenter defaultCenter] addObserverForName: @"MyNotif" object: queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification* notif) { /* doing some stuff */ }];
  10. 10. Syntaxe et utilisation ^ void (void) { NSLog(@"Hello World"); }; t ur ns es re to io trca re ct mè ru ra de st pa pe In sTy de s pe Ty
  11. 11. Syntaxe et utilisation ^ void (void) { NSLog(@"Hello World"); };<=> ^ (void) { NSLog(@"Hello World"); };<=> ^ { NSLog(@"Hello World"); };
  12. 12. Syntaxe et utilisationvoid (*myFunction)(int);void (^myBlock )(int);myBlock = ^(int i){ ... };
  13. 13. Syntaxe et utilisation void (^(^(myBlock)(void (^)(void)))(void);<=> typedef void (^aBlock)(void); aBlock (^myBlock)(aBlock);
  14. 14. Syntaxe et utilisationmyBlock();myBlockwithParam(2);int i = myBlockWithReturn();
  15. 15. Syntaxe et utilisation Capturer une variable en fait une copie constantefloat newAlpha = 1;[UIView animateWithDuration:0.5 delay:1 options:0 animations:^{ myView.alpha = newAlpha; } completion:NULL];newAlpha = 0; Copie constante
  16. 16. Syntaxe et utilisation Capturer une variable __block garde sa référence__block int a = 3;void (^incrementA)(void) = ^{ a++; };incrementA(); Référence
  17. 17. Gestion mémoire Un Block est créé sur la pile et non sur le tas !typedef void (^Block)(void);Block block; int* pInt;if ( ... ) { if ( ... ) { block = ^{ ... }; int a = 1; pInt = &a;} else { <=> } else { block = ^{ ... }; int b = 1; pInt = &b;} }block(); // utilisation de pInt Wrong
  18. 18. Gestion mémoire Copier un Block sur la pile le déplace sur le tas !typedef void (^Block)(void);Block block;if ( ... ) { block = [[^{ ... } copy] autorelease];} else { block = [[^{ ... } copy] autorelease];}block(); Right
  19. 19. Gestion mémoire Capturer un objet le retient !Capturer une variable d’instance retient l’objet auquel elle appartient ! MyClass.h myObjectMyObject* myObject;int myIvar; retain cycle self Block MyClass.mmyObject = [[MyObject alloc] initWithBlock:^{ NSLog(@"%i", myIvar);}]; Wrong
  20. 20. Gestion mémoire Capturer un objet __block ne le retient pas ! MyClass.hMyObject* myObject;int myIvar; MyClass.m__block MyClass* selfBlock = self;myObject = [[MyObject alloc] initWithBlock:^{ NSLog(@"%i", selfBlock-> myIvar);}]; Right
  21. 21. Bonus Effet Bounce des UIAlertViewv.transform = CGAffineTransformMakeScale(0.7, 0.7);v.alpha = 0;[self.view addSubview:v];[UIView animateWithDuration:0.2 animations:^{ v.transform = CGAffineTransformMakeScale(1.25, 1.25); v.alpha = 0.6;} completion:^(BOOL finished) { [UIView animateWithDuration:0.15 animations:^{ v.transform = CGAffineTransformMake(0.85, 0.85); v.alpha = 1; } completion:^(BOOL finished) { [UIView animateWithDuration:0.1 animations:^{ v.transform = CGAffineTransformIdentity; } completion:NULL]; }];}];
  22. 22. BonusUIAlertView* alert = [[UIAlertView alloc] init... delegate: nil ...];[alert showWithCompletion:^(NSInteger index) { if (index == 1) { [UIApplication openURL:myURL]; }}];[alert release]; N’existe pas! Codons le
  23. 23. Bonus@interface BlockAlertView : UIAlertView <UIAlertViewDelegate> { void (^completionBlock_)(NSInteger);}- (void)showWithCompletion:(void (^)(NSInteger index))completion;@end
  24. 24. Bonus@implementation BlockAlertView- (void)showWithCompletion:(void (^)(NSInteger index))completion{ completionBlock_ = [completion copy]; self.delegate = self; [self show];}- (void)alertView:(UIAlertView*)alert clickedButtonAtIndex:(NSInteger)index{ completionBlock_(index); [completionBlock_ release]; completionBlock_ = nil;}- (void)alertViewCancel:(UIAlertView*)alert{ completionBlock_(-1); [completionBlock_ release]; completionBlock_ = nil;}@end
  25. 25. Grand Central DispatchPierre Duchêne
  26. 26. Introduction• Nouveaux éléments de langage (Blocks)• Une bibliothèque de fonctions (libdispatch) • Amélioration et simplification de la gestion de la concurrence
  27. 27. Introduction - Pourquoi GCD• Complexité du multi-threading• Multiplication des Cores sur toutes les plateformes• Mauvaise gestion des ressources
  28. 28. Introduction - GCD c’est quoi?• Gestion des threads au niveau du système• Gestion des problématiques de concurrence (lock, semaphore...)
  29. 29. libdispatch - Queues• Liste FIFO de Blocks à exécuter • Ajout de Block FIFO • Lancement de l’exécution d’un Block FIFO• Gère les threads qui exécutent les Blocks
  30. 30. Queues• Trois types de Queues : • Main Queue (Main Thread) • Private Dispatch Queue (exécution série) • Global Dispatch Queue (exécution parallèle)
  31. 31. Private Dispatch QueueCurrent Thread Block 3 Ajoute Block 1 Block 2 puis Block 2 puis Block 3 Exécute Block 1 Block 1 puis Block 2 puis Block 3 Private queue Other Thread
  32. 32. Global Dispatch Queue Puis Block 3 surCurrent Thread le premier thread qui sera libéré potentiellement avant la fin Block 3 du Block 1 Ajoute Block 1 Block 2 puis Block 2 puis Block 2 puis Block 3 Block 1 Lance Block 1 Global queue Thread Auto Thread Auto
  33. 33. Queues• Deux types d’exécution: • Synchrone • Asynchrone
  34. 34. libdispatch - import• Comment utiliser libdispatch dans son projet? #import <dispatch/dispatch.h>
  35. 35. libdispatch - queue• Comment créer une queue ? dispatch_queue_t main_queue; dispatch_queue_t serial_queue; dispatch_queue_t global_queue; // main queue main_queue = dispatch_get_main_queue(); // private dispatch queue serial_queue = dispatch_queue_create("com.example.myQueue", NULL); // global dispath queue global_queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_release(serial_queue);
  36. 36. libdispatch - étude de cas• Process en background + mise à jour de l’UI dispatch_queue_t background_queue; dispatch_queue_t main_queue; backgroung_queue = dispatch_queue_create("com.example.myQueue", NULL); main_queue = dispatch_get_main_queue(); dispatch_async(background_queue, ^{ int result = hardWorkInBackground(); dispatch_async(main_queue, ^{ updateUIWithData(result); }); }); dispatch_release(background_queue);
  37. 37. libdispatch - étude de cas• Traitement sur les éléments d’un tableau dispatch_queue_t global_queue; global_queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); NSArray* mySudokuGrid = ...; dispatch_apply(nb_iteration,global_queue,^(size_t index){ MyCell* cell = [mySudokuGrid objectAtIndex:index]; [cell computeSolutions]; });
  38. 38. libdispatch - étude de cas• Comment remplacer les locks ? - (void)updateImageCacheWithImage:(UIImage*)img { NSLock* l = self.cacheLock; [l lock]; // Section critique, ne pas ajouter deux fois la même image! if ([self.imageCache containsObj:img]) { [l unlock]; // Surtout ne pas oublier! return; } [self.imageCache addObj:img]; [l unlock]; }
  39. 39. libdispatch - étude de cas• Simplement par une Queue! - (void)updateImageCacheWithImage:(UIImage*)img { dispatch_sync(serial_queue,^{ // Section critique, ne pas ajouter deux fois la même image! if ([self.imageCache containsObj:img]) { return; } [self.imageCache addObj:img]; }); } ou mieux : dispatch_async
  40. 40. libdispatch - deadlock• Attention aux deadlock dispatch_sync(queue, ^{ // Some code ! dispatch_sync(queue, ^{ // Another block }); }); Block 2 ! Block 1 Private queue Other Thread
  41. 41. API haut niveau• Grand Central Dispatch ajoute à l’existant • NSOperation • NSOperationQueue
  42. 42. API haut niveau• NSBlockOperation • Classe concrête de NSOperation • Gère l’exécution en parallèle de un ou plusieurs Blocks
  43. 43. API haut niveau• NSOperationQueue • C’est elle qui gère l’exécution des opérations • Peut être configurée
  44. 44. API haut niveau - base• Créer et lancer une opération via NSOperationQueue : NSOperationQueue* aQueue = [[NSOperationQueue alloc] init]; NSBlockOperation* blockOp = [NSBlockOperation blockOperationWithBlock:^{ // Some Code }]; [aQueue addOperation:blockOp]; ... [aQueue addOperationWithBlock:^{ // Another Block }]; ... [aQueue release];
  45. 45. API haut niveau - dépendance• Comment indiquer des dépendances entre opérations? NSBlockOperation* op1 = ...: NSBlockOperation* op2 = ...: [op2 addDependencie:op1];
  46. 46. API haut niveau - iOS Sur iOS les NSOperationQueue! n’utilisent pas Grand Central Dispatch
  47. 47. Références http://developer.apple.com http://thirdcog.eu/pwcblocks/Contacts pierre.duchene@niji.fr thomas.dupont@niji.fr
  48. 48. CocoaHeads #1 julien@cocoaheads.fr http://cocoaheads.fr thomas.dupont@cocoaheads.frTraduction automatique et intelligente d’applications Cocoa Mail : olivier@foodreporter.net Web : www.foodreporter.fr GitHub : github.com/AliSoftwareA la découverte de Grand Central Dispatch Mail : thomas.dupont@niji.fr Mail : pierre.duchene@niji.fr Web : www.niji.frPartenaire

×