• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
CocoaHeads Rennes #1 : Grand Central Dispatch
 

CocoaHeads Rennes #1 : Grand Central Dispatch

on

  • 1,981 views

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

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

Statistics

Views

Total Views
1,981
Views on SlideShare
1,980
Embed Views
1

Actions

Likes
0
Downloads
35
Comments
0

1 Embed 1

http://www.verious.com 1

Accessibility

Categories

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.

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

    CocoaHeads Rennes #1 : Grand Central Dispatch CocoaHeads Rennes #1 : Grand Central Dispatch Presentation Transcript

    • A la découverte deGrand Central Dispatch Pierre Duchêne Thomas Dupont
    • Sommaire• Blocks ➡ Exemples ➡ Syntaxe et utilisation ➡ Gestion mémoire ➡ Bonus• Grand Central Dispatch ➡ Introduction ➡ libdispatch ➡ API haut niveau
    • BlocksThomas Dupont
    • 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;}
    • 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; }];
    • 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];}
    • Exemples[UIView animateWithDuration: 0.6 animations:^{ myView.alpha = 0; } completion:^(BOOL finished){ [myView removeFromSuperview]; }];
    • Exemples[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notifReceived:) name:@"MyNotif" object:nil ];...- (void)notifReceived:(NSNotification*)notif{ /* doing some stuff */}
    • Exemples[[NSNotificationCenter defaultCenter] addObserverForName: @"MyNotif" object: queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification* notif) { /* doing some stuff */ }];
    • 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
    • Syntaxe et utilisation ^ void (void) { NSLog(@"Hello World"); };<=> ^ (void) { NSLog(@"Hello World"); };<=> ^ { NSLog(@"Hello World"); };
    • Syntaxe et utilisationvoid (*myFunction)(int);void (^myBlock )(int);myBlock = ^(int i){ ... };
    • Syntaxe et utilisation void (^(^(myBlock)(void (^)(void)))(void);<=> typedef void (^aBlock)(void); aBlock (^myBlock)(aBlock);
    • Syntaxe et utilisationmyBlock();myBlockwithParam(2);int i = myBlockWithReturn();
    • 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
    • Syntaxe et utilisation Capturer une variable __block garde sa référence__block int a = 3;void (^incrementA)(void) = ^{ a++; };incrementA(); Référence
    • 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
    • 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
    • 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
    • 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
    • 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]; }];}];
    • BonusUIAlertView* alert = [[UIAlertView alloc] init... delegate: nil ...];[alert showWithCompletion:^(NSInteger index) { if (index == 1) { [UIApplication openURL:myURL]; }}];[alert release]; N’existe pas! Codons le
    • Bonus@interface BlockAlertView : UIAlertView <UIAlertViewDelegate> { void (^completionBlock_)(NSInteger);}- (void)showWithCompletion:(void (^)(NSInteger index))completion;@end
    • 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
    • Grand Central DispatchPierre Duchêne
    • Introduction• Nouveaux éléments de langage (Blocks)• Une bibliothèque de fonctions (libdispatch) • Amélioration et simplification de la gestion de la concurrence
    • Introduction - Pourquoi GCD• Complexité du multi-threading• Multiplication des Cores sur toutes les plateformes• Mauvaise gestion des ressources
    • Introduction - GCD c’est quoi?• Gestion des threads au niveau du système• Gestion des problématiques de concurrence (lock, semaphore...)
    • 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
    • Queues• Trois types de Queues : • Main Queue (Main Thread) • Private Dispatch Queue (exécution série) • Global Dispatch Queue (exécution parallèle)
    • 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
    • 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
    • Queues• Deux types d’exécution: • Synchrone • Asynchrone
    • libdispatch - import• Comment utiliser libdispatch dans son projet? #import <dispatch/dispatch.h>
    • 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);
    • 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);
    • 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]; });
    • 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]; }
    • 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
    • libdispatch - deadlock• Attention aux deadlock dispatch_sync(queue, ^{ // Some code ! dispatch_sync(queue, ^{ // Another block }); }); Block 2 ! Block 1 Private queue Other Thread
    • API haut niveau• Grand Central Dispatch ajoute à l’existant • NSOperation • NSOperationQueue
    • API haut niveau• NSBlockOperation • Classe concrête de NSOperation • Gère l’exécution en parallèle de un ou plusieurs Blocks
    • API haut niveau• NSOperationQueue • C’est elle qui gère l’exécution des opérations • Peut être configurée
    • 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];
    • API haut niveau - dépendance• Comment indiquer des dépendances entre opérations? NSBlockOperation* op1 = ...: NSBlockOperation* op2 = ...: [op2 addDependencie:op1];
    • API haut niveau - iOS Sur iOS les NSOperationQueue! n’utilisent pas Grand Central Dispatch
    • Références http://developer.apple.com http://thirdcog.eu/pwcblocks/Contacts pierre.duchene@niji.fr thomas.dupont@niji.fr
    • 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