multi thread et accés via un controleur
GG
Membre
Bonsoir,
je cherche à voir comment je peux gérer des NSthread.
Si dans une classe, j'utilise des NSthread qui sont détachés du thread principal, et que je dois les abandonner depuis ma classe contrôleur, comment puis acceder à ces nsthread depuis ma classe contrôleur.
Et le cas échéant, comment les arrêter ?
Depuis ma classe qui détache les nsthreads, je peux connaitre le nombre de threads en cours par :
Mais comment connaitre leur adresse et les arrêter depuis la classe contrôleur (de manière propre ).
je cherche à voir comment je peux gérer des NSthread.
Si dans une classe, j'utilise des NSthread qui sont détachés du thread principal, et que je dois les abandonner depuis ma classe contrôleur, comment puis acceder à ces nsthread depuis ma classe contrôleur.
Et le cas échéant, comment les arrêter ?
Depuis ma classe qui détache les nsthreads, je peux connaitre le nombre de threads en cours par :
<br />[[[NSThread currentThread] threadDictionnary] count];<br />
Mais comment connaitre leur adresse et les arrêter depuis la classe contrôleur (de manière propre ).
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
On pourrait pas faire un
?
Autrement comment récupérer les NSAppleEventManagerSuspensionID via NSAppleEventManagerHandlingStack (c'est une pile il doit contenir ces classes NSAppleEventManagerSuspensionID) non ?
Ce sont des questions naà¯ves mais j'aimerai comprendre pourquoi on ne pourrait pas récupérer des informations sur ces threads de manière propre.
Mais si tu arrives à tuer proprement un thread de l'extérieur, ça m'intéresse aussi :P
Concrètement, lorsque j'affiche le contenu du dictionnaire du thread courant il me sort qu'il est de type NSAppleEventManagerHandlingStack.
Donc je suis allé chercher dans la doc ce que c'était (rien dans la doc officielle, mais il y existe les NSAppleEventManager), et il existe une méthode qui permet d'arrêter ces events resumeWithSuspensionID.
Je me dis (peut être à tort), que si je pouvais récupérer ces NSAppleEventManagerSuspensionID par le biais de la pile, je pourrai tuer proprement les threads.
Voila c'est tout, je suis en état de recherche actuellement .
Je prospecte encore et je vous tiens au jus .
Je crois pas que ça ait à voir avec le fonctionnement inhérent aux threads.
Regarde du côté de pthread ("man pthread"), il y a une fonction (pthread_cancel) qui permet de tuer un thread de l'extérieur, mais le gros problème, c'est la mémoire ! Il faut à tout prix éviter les leaks.
Mais comment fais tu pour connaitre les adresses des nsthreads lancés détachés du nsthread principal ? (je parle au sein de la classe où ils sont été lancés).
Avec le wrapper NSThread qu'Apple a créé autour des fonctions de "phtread", c'est impossible !
Il faut que les threads l'envoient au thread principal via une variable partagée ([NSThread currentThread])
Mais attention, l'adresse du NSThread, n'est pas l'adresse du thread handler qu'on peut utiliser avec pthread_cancel !
Comment peut on accéder à ces threads via le NSthread currentthread ?
Tutut, il n'y a pas de fork, un thread est au sein du même processus, et il partage les mêmes variables !
Pour ce qui est d'accéder à l'adresse du "pthread_t", c'est encapsulé dans leur classe NSThread, c'est impossible.
Et quand bien même tu pourrais, tu ferais comment pour être sûr qu'il n'y a pas de leak en envoyant pthread_cancel ?
Regarde ce sujet, beaucoup de grosses pointures en programmation de Macbidouille y ont participé :P
http://forum.macbidouille.com/index.php?showtopic=154181&hl=NSThread
En général par exemple pour un thread qui est sensé faire une action en boucle, dans la méthode que l'on fait executer par le thread (le selecteur qu'on indique dans le detachThread), on met une RunLoop, du genre boucle while, et la condition de sortie de la boucle est la condition qui te permet de sortir du thread, donc de l'arrêter.
Si c'est un thread qui ne fait pas un truc en boucle mais juste une action longue que tu veux paralléliser, il suffit de mettre des tests à divers endroits de ton code (qui en général, long comme il est dans ce cas, est divisé en étapes de toute façon). Donc en gros tu crées des points de sortie.
Après pour signaler au thread que tu veux sortir, donc pour modifier la valeur de la variable que tu testes pour savoir si tu dois sortir ou pas, il y a plusieurs solutions : soit une variable partagée entre ton thread et le thread principal, soit utiliser les systèmes de communication inter-thread pour envoyer un message au thread lui demandant de sortir dès que possible (donc de mettre son flag bMustExit à YES en gros)... Ceci dit dans ce genre de cas (variable partagée entre threads) il faut absolument protéger les accès à ces variables (via des @synchronized par exemple, ou même mieux les NSLock) pour éviter que tu lises la variable pendant que ton thread principal la modifie par exemple. (c'est pour ça qu'une gestion par envoi de messages, laissant le thread modifier lui-même la variable que tu testes pour sortir de ta RunLoop, est plus sympa que d'utiliser une variable partagée accessible par plusieurs threads)
Communication inter-threads avec les distributed objects : comment gérer les RunLoops et permettre au thread principal de demander à un autre thread de s'arrêter
Apparemment on peut faire joujou avec la runLoop du thread (s'il en a une !)... Après, faut voir ce qu'on peut en faire.
Mais je déconseille vraiment de récupérer cette valeur et d'envoyer un pthread_cancel ! (rapport à la mémoire, et à la gestion multithreadée de Cocoa)
La bibliothèque POSIX pthread de gestion de threads est basée sur la bibliothèque du noyau (mach) il me semble, et NSThread est basé sur la bibliothèque POSIX pthread...
Si tu veux travailler directement avec les threads du noyau -> <mach/mach.h> (/usr/include/mach/i386/thread_act.h ou /usr/include/mach/ppc/thread_act.h)
un objet partagé entre le controleur et le thread
c'est aussi "simple" que ca
ou je n'ai pas compri la question :-\\
Oui et non... C'est une solution (celle que j'avais finalement gardée n'en ayant pas trouvé de meilleure), mais elle n'est pas idéale.
Pour qu'elle le soit, il faudrait un test à chaque instruction du thread.
C'est là que le C++ a un gros avantage sur l'Objective-C : on peut définir des objets qui gèrent la mémoire, et dont le destructeur sera appelé quoi qu'il arrive (exception, fin de thread...).
join() (par exemple) ou a travers l'objet partagé
non?
De toute façon tout est indiqué dans la doc Apple : les différentes façons d'utiliser des threads. Et à mon avis le plus simple est quand même d'utiliser le système de threads Cocoa (NSThreads) que de descendre au niveau des pthreads POSIX et de gérer tout soi-même.
Et pour le coup de la runLoop, voir encore la doc Apple et "Configuring Your Run Loop"...
Si, on peut tuer un thread... "pthread_cancel" est là pour ça. Le vrai problème c'est la mémoire gérée ! ("pthread_cleanup_pop" et "pthread_cleanup_push" dans la bibliothèque POSIX)
C'est pour ça que je disais que c'était déconseillé à cause de la gestion multithreadée de Cocoa... Il y a plusieurs choses à faire quand on veut gérer ses threads directement avec la bibliothèque POSIX avec Cocoa !
Mais "pthread_cancel" est très propre ! C'est juste dommage qu'ils n'aient pas implémenté ça dans NSThread...
En gros, à chaque fois qu'on alloue des ressources, on fait un "pthread_cleanup_push" avec un pointeur de fonction censé relâcher ces ressources, et quand on fait "pthread_cancel", tous les "pthread_cleanup_pop" sont appelés, et le thread s'arrête très proprement.
C'est LE truc qui manque à leur wrapper NSThread (parce que bon, les conditions de sortie à tous les endroits stratégique, c'est tout sauf léger !)
bon, disons que dans mon application cela ne me pose pas de probleme, traitement interrompu par une horloge (temps epuisé) ou par le controleur (mauvaise hypothese de depart).
l'implémentation de sa propre runLoop permet juste de communiquer avec les thread s distribués ?
En gros en implémentant cette méthode, on peut à tout moment arrêter ces threads via une boucle loop runMode:beforeDate: ?
Bien sûr que c'est une solution valableÂ
Je dis juste qu'il pourrait y avoir mieux !
NSThread n'a pas toute la flexibilité de la bibliothèque POSIX...
D'ailleurs, ils le disent texto dans leur doc :
Moi je me méfierais beaucoup de ce genre de considérations... Je ne sais pas si on peut le faire, mais ça me semble assez dangereux d'essayer en tout cas (surtout que c'est du non documenté !)
2 solutions sont peut-être envisageables : le releasePool et les NSZones.
Dans le premier cas, il s'agit de contrôler la destruction d'un releasePool après un pthread_cancel(), moyennant de devoir faire attention à ce que tous les objets crées dans le thread soient bien placés dans ce pool :
La seconde méthode repose sur les NSZones.
Le principe est identique au releasePool (création d'un NSZone dont le pointeur est en globale, puis destruction de ce NSZone après le pthread_cancel). Dans ce cas, les objets doivent être créés via un allocWithZone:. L'inconvénient de cette dernière méthode est que la destruction du NSZone ne fait pas d'appel aux release des objets qui y sont contenus, ce qui peut être facheux pour certaines classes.
.
Là tu le crées dans un thread secondaire, et tu le détruits dans un thread principal ; j'avais testé, c'est le leak assuré :-\\
Mais je suis content que la discussion reprenne ici, ça met un peu de sang neuf au problème
Ca expliquerait en tout cas que ça ne soit pas implémenté dans le wrapper NSThread
Mon idée initiale était de si jamais je dois relancer la classe qui lance ces threads détachés du principal, alors que les précédents n'ont pas terminés, j'arrête les précédents de manière propre.
En C++ avec Boost on peut faire du multi-thread via des templates, qui nous donnent accès à ces threads, et donc de pouvoir les arrêter correctement, sans fuite mémoire. c'est quand même marrant, que cocoa permettent de lancer ces multi-threads mais ne nous donne pas les moyens de les contrôler.
Je suis en train de faire des tests dessus, mais je n'arrive pas à faire fonctionner "PTHREAD_CANCEL_ASYNCHRONOUS" >:(
Par contre, "PTHREAD_CANCEL_DEFERRED" avec des "pthread_testcancel" dans le code fonctionne très bien.
piges pas, a quoi peut servir (de facon un peu serieuse) cette classe?
a ton acces a l'implementation de cette classe? (curiosité)
comme le dit Apple pour les application un peu plus "pointues" utiliser les thread posix
ps : a quoi peu bien servir la methode currentThread qui retourne un NSThread* si on ne peut pas manipuler le thread a partir d'un pointeur