web-dev-qa-db-fra.com

Existe-t-il un identifiant pthread_t non valide?

Je voudrais appeler pthread_join pour un identifiant de thread donné, mais uniquement si ce thread a été démarré. La solution sûre pourrait être d'ajouter une variable pour suivre quel thread a commencé ou non. Cependant, je me demande si la vérification des variables pthread_t est possible, quelque chose comme le code suivant.

pthread_t thr1 = some_invalid_value; //0 ?
pthread_t thr2 = some_invalid_value;

/* thread 1 and 2 are strated or not depending on various condition */
....

/* cleanup */
if(thr1 != some_invalid_value)
    pthread_join(&thr1);

if(thr2 != some_invalid_value)
    pthread_join(&thr2);

Où some_invalid_value pourrait être 0, ou une macro "PTHREAD_INVALID_ID" dépendante de l'implémentation

PS: Mon hypothèse est que les types pthread_t sont comparables et assignables, hypothèse basée sur

PPS: Je voulais le faire, parce que je pensais qu'appeler pthread_join sur un identifiant de thread non valide était un comportement indéfini. Ce n'est pas. Cependant, rejoindre un thread précédemment joint IS comportement indéfini. Supposons maintenant que la "fonction" ci-dessus soit appelée à plusieurs reprises. L'appel inconditionnel de pthread_join et la vérification du résultat peuvent entraîner l'appel de pthread_join sur un thread précédemment joint.

52
shodanex

Votre hypothèse est incorrecte pour commencer. Les objets pthread_t sont opaques. Vous ne pouvez pas comparer les types pthread_t directement en C. Vous devez utiliser pthread_equal à la place.

Une autre considération est que si pthread_create échoue, le contenu de votre pthread_t ne sera pas défini. Il ne peut plus être défini sur votre valeur non valide.

Ma préférence est de conserver les valeurs de retour des appels pthread_create (avec les ID de threads) et de les utiliser pour déterminer si chaque thread a été démarré correctement.

17
qbert220

Comme suggéré par Tony, vous pouvez utiliser pthread_self() dans cette situation.

Mais ne pas comparer thread_ts utilisant == ou !=. Utilisation pthread_equal .

Du pthread_self page de manuel:

Par conséquent, les variables de type pthread_t ne peuvent pas être comparées de manière portable à l'aide de l'opérateur d'égalité C (==); utilisez plutôt pthread_equal (3).

11
Mat

J'ai récemment rencontré ce même problème. Si pthread_create () a échoué, je me suis retrouvé avec une valeur non définie et non valide stockée dans ma structure phtread_t. Par conséquent, je conserve un booléen associé à chaque thread qui est défini sur true si pthread_create () a réussi.

Alors tout ce que je dois faire c'est:

void* status;
if (my_thread_running) {
  pthread_join(thread, &status);
  my_thread_running = false;
}
1
It'sPete

Malheureusement, sur les systèmes où pthread_t Est un pointeur, pthread_equal() peut retourner l'égalité même si les deux arguments font référence à des threads différents, par ex. un thread peut quitter et un nouveau thread peut être créé avec la même valeur de pointeur pthread_t.

1
HavePoopWillStep

Je portais du code qui utilisait pthreads dans une application C++, et j'avais la même question. J'ai décidé qu'il était plus facile de passer à l'objet C++ std::thread, Qui a la méthode .joinable() pour décider de se joindre ou non, c'est-à-dire.

 if (t.joinable()) t.join();

J'ai trouvé que le simple fait d'appeler pthead_join Sur une mauvaise valeur pthread_t (suite à l'échec de pthread_create) Provoquait une erreur de segmentation, pas seulement une valeur de retour d'erreur.

0
Mark Lakata

C'est une excellente question que je souhaite vraiment obtenir plus de discussion dans les classes C++ et les tests de code.

Une option pour certains systèmes - qui peut sembler exagéré pour vous, mais qui m'a été utile - consiste à démarrer un thread qui ne fait rien d'autre qu'attendre efficacement un signal de suppression, puis quitter. Ce thread continue de fonctionner pendant toute la durée de vie de l'application, en descendant très tard dans la séquence d'arrêt. Jusqu'à ce moment, l'ID de ce thread peut être utilisé comme valeur de "thread non valide" - ou, plus probablement, comme sentinelle "non initialisée" - dans la plupart des cas. Par exemple, mes bibliothèques de débogage suivent généralement les threads à partir desquels les mutex ont été verrouillés. Cela nécessite l'initialisation de cette valeur de suivi à quelque chose de sensible. Parce que POSIX a plutôt bêtement refusé d'exiger que les plates-formes définissent un INVALID_THREAD_ID, et parce que mes bibliothèques permettent à main () de verrouiller les choses (rendant les vérifications pthread_self qui sont une bonne solution pthread_create inutilisable pour le suivi des verrous), c'est la solution que j'ai appris à utiliser . Cela fonctionne sur n'importe quelle plate-forme.

Notez, cependant, que vous avez un peu plus de travail de conception à faire si vous souhaitez que cela puisse initialiser les références de thread statiques à des valeurs non valides.

0
breakpoint