Blocks & variables
Sébastien M.
Membre
Bonjour tout le monde.
Je commence le développement d'un petit outil de messagerie instantané. Un des buts de son développement est de toucher à de nouveau concepts que je n'ai encore jamais eu l'occasion d'utiliser. Ainsi, je viens de faire la connaissance de "Grand Central Dispatch" ainsi que des blocks.
Malgré la lecture de la documentation à propos des blocks, j'ai un peu de mal à comprendre leurs comportements avec les variables. Si j'ai bien compris la documentation, lors de la création d'un block, toutes les variables utilisées par celui-ci sont copiées en mémoire. Ainsi la modification d'une variable à partir du block n'impacte pas le reste du scope et vice-et-versa. Ce comportement peut cependant être changé grâce au symbole "__block".
Cependant, même avec le mot clef "__block", je n'arrive pas à manipuler les attributs de mon objet "self" à partir du block. Est-il possible de le faire ? Y a-t-il une copie complète de mon objet en mémoire ? Dois utiliser des outils du type mutex ?
Merci d'avance de vos réponses !
Je commence le développement d'un petit outil de messagerie instantané. Un des buts de son développement est de toucher à de nouveau concepts que je n'ai encore jamais eu l'occasion d'utiliser. Ainsi, je viens de faire la connaissance de "Grand Central Dispatch" ainsi que des blocks.
Malgré la lecture de la documentation à propos des blocks, j'ai un peu de mal à comprendre leurs comportements avec les variables. Si j'ai bien compris la documentation, lors de la création d'un block, toutes les variables utilisées par celui-ci sont copiées en mémoire. Ainsi la modification d'une variable à partir du block n'impacte pas le reste du scope et vice-et-versa. Ce comportement peut cependant être changé grâce au symbole "__block".
Cependant, même avec le mot clef "__block", je n'arrive pas à manipuler les attributs de mon objet "self" à partir du block. Est-il possible de le faire ? Y a-t-il une copie complète de mon objet en mémoire ? Dois utiliser des outils du type mutex ?
Merci d'avance de vos réponses !
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Si un block fait référence à self, alors un retain est fait sur self, et non une copie. C'est d'ailleurs le cas pour tout objet utilisé dans le block. Une copie du pointeur est effectuée mais un retain est également fait sur l'objet (et un release une fois le block supprimé).
__block n'est utile que pour modifier les variables (primitives ou pointeurs) de méthodes. Pour les variables de classes, ce n'est pas nécessaire.
Si ça ne fonctionne pas, le problème est autre. Quelle est donc l'erreur exactement ?
Aurais-tu un morceau des code à nous montrer pour qu'on voit ce que tu as essayé de faire et qu'on voit ce qui fait que d'après toi ça ne marche pas ?
Il semblerait que j'étais fatigué hier soir... Après avoir refait quelques tests j'arrive en effet aux résultats attendus !
Cependant, dans le cas des blocks avec GCD, dois-je utiliser un mécanisme de mutex pour la modification de valeur de variables ? Pour mes blocks de code à verrouiller, me conseillez-vous plutôt les NSLock ou les @synchronize ?
Merci.
Au final dans l'ensemble en général quand tu utilises GCD tu as peu à te soucier de cela. Je dis pas que tout est automatique, en effet il faut y faire attention et c'est une bonne habitude de ta part. Mais cela est grandement simplifié tout de même. Du moment que tu utilises à bon escient dispatch_sync ou dispatch_async en fonction du besoin, et une dispatch_queue concurrent ou serial selon les contraintes voulues, et que tu passes par des property atomic pour être sûr.
Après il y a des cas plus alambiqués où tu peux avoir besoin de mutex ou de locks en effet. Mais dans ce cas, utilise ceux fournis par GCD, qui sont bien plus rapides (et en plus sont des double-check-locks donc moins consommateurs) que des NSLocks ou autre @synthesize. Je te laisse potasser la doc pour ces cas-là , qui restent assez rares en pratique de mon expérience.
PS : Autres lectures intéressantes en plus du Concurrency Programming Guide & co : http://www.mikeash.com/pyblog/friday-qa-2009-08-28-intro-to-grand-central-dispatch-part-i-basics-and-dispatch-queues.html
Concrètement, je suis en train de coder une encapsulation asynchrone des sockets en Objective-C. Je sais que cela a déjà été fait de nombreuses fois, mais c'est dans l'objectif d'apprendre de nouveaux concepts.
Lorsque je veux écrire une donnée sur une socket, mon thread principale ajoute un NSData dans un NSMutableArray. Dans un autre thread/une autre queue, une boucle vérifie le contenu du NSMutableArray : s'il n'est pas vide, il écrit sur la socket.
Du coup, il suffirait de déclarer le NSMutableArray comme atomic grâce a un @property et cela fonctionnerait correctement, c'est bien cela ?
Cependant, cela ne permettrait pas alors à n'importe quel autre objet d'accéder directement à mon NSMutableArray ? Ne vaut-il pas mieux alors mettre manuellement le @synchronise ?
Merci !
Donc globalement, il vaut mieux utiliser les OSSpinLock. Les autres ont-il des avantages ?
Dans ton code tu inclus :
Vu le nom, je suppose que c'est quelque chose d'assez bas niveau. Celui-ci ne fonctionnerait-il pas uniquement sur OSX (dans le man, j'ai une référence à Darwin) ?
Le coe“ur du système est donc le même (sauf, bien entendu, si des nouveauté sont introduites dans OS X et que le noyau d'iOS n'a pas encore été mis-à -jours.)
Il faut donc juste faire attention à ne pas utiliser cela si on compile de l'Objective-C sur un linux ! ;-)
Merci à tous pour vos réponses.