2013-07-12 4 views

Répondre

3

errno doit être thread-local. Dans chaque thread la valeur de cette variable peut être différente.

qu'il devrait être localement mis en œuvre dans tous les fils

Il n'est pas votre devoir de mettre en œuvre errno comme variables thread_local. C'est un travail pour les développeurs de compilateurs.

De cppreference.com

errno est une macro préprocesseur utilisé pour l'indication d'erreur. Il se développe en une lvalue modifiable locale de type int. (depuis C++ 11)

simplement dans 11 compilateurs C de ce code ne doit jamais affirmer

#include <iostream> 
#include <cerrno> 
#include <thread> 
#include <cassert> 

int g_errno = 0; 

void thread_function() 
{ 
    errno = E2BIG; 
    g_errno = errno; 
} 

int main() 
{ 
    errno = EINVAL; 
    std::thread thread(thread_function); 
    thread.join(); 
    assert(errno != g_errno && "not multithreaded"); 
} 
+0

Mon problème est comment faire cela?la procédure habituelle consiste à inclure l'entête #include et à utiliser directement errno. Comment le rendre local? – WildThing

+0

@WildThing voir la mise à jour de la réponse. – ForEveR

+0

que la référence ci-dessus dit que: ** "Les bibliothèques qui supportent le multi-threading doivent implémenter errno sur une base par thread: avec chaque thread ayant son propre errno local" **. Au niveau de la mise en œuvre À quoi cela ressemble-t-il? – WildThing

0

Cela signifie que chaque fil doit avoir sa propre instance de la errno variables

La mise en œuvre peut facilement atteindre cet objectif en utilisant quelque chose comme:

int __thread errno; 

__thread étant une extension gcc qui garantit que la variable est locale (donc un thread ne peut pas écraser une autre instance threads de la variable)

En tant qu'utilisateur de errno, vous n'avez pas à vous en préoccuper. Vous n'avez même pas à vous inquiéter que errno ait été modifié de manière préventive par un autre thread.

+0

Pouvez-vous décrire cette procédure plus en détail s'il vous plaît? – WildThing

+0

ajouté un peu plus – doron

3

Historiquement, errno était une variable de commune de type int - à savoir tous les modules a sa propre définition, et l'éditeur de liens était responsable de leur fusion. Ainsi, les programmes ont simplement déclaré int errno; globalement et avaient une définition de travail.

Cela se décompose dans les environnements multithread, car il n'y a qu'une seule variable. Ainsi, errno.h doit maintenant définir quelque chose qui est un lvalueint, et les programmes ne doivent pas définir leurs propres errno.

La bibliothèque GNU C par exemple définit quelque chose de similaire à

#define errno (*(__errno_location())) 

__errno_location() est une fonction en ligne qui calcule l'adresse du fil local errno.

Tout cela ne concerne pas l'application, sauf que c'est une erreur de définir la vôtre errno.

+0

Était-ce vraiment une variable commune? Je pensais que c'était une variable externe définie dans libc. –

+0

@Maxim, oui - 'extern int errno;' fonctionne aussi parce que cela peut aussi être utilisé pour faire référence à une définition commune. L'initialisation avec 'int errno = 0;' échoue cependant à lier. –